Removed "arch" directory, and "makeflop" & "bootmaker" - they are all no longer in use.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@14587 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,24 +1,7 @@
|
|||||||
SubDir HAIKU_TOP src system boot ;
|
SubDir HAIKU_TOP src system boot ;
|
||||||
|
|
||||||
#SetupIncludes ;
|
|
||||||
#oldccflags = $(CCFLAGS) ;
|
|
||||||
#{
|
|
||||||
# CCFLAGS = ;
|
|
||||||
# local x ;
|
|
||||||
# for x in $(CCFLAGS) {
|
|
||||||
# if $(x) != --nostdinc {
|
|
||||||
# CCFLAGS += $(x) ;
|
|
||||||
# }
|
|
||||||
# }
|
|
||||||
#}
|
|
||||||
|
|
||||||
BuildPlatformMain bootmaker : bootmaker.c ;
|
|
||||||
BuildPlatformMain bin2h : bin2h.c ;
|
BuildPlatformMain bin2h : bin2h.c ;
|
||||||
BuildPlatformMain bin2asm : bin2asm.c ;
|
BuildPlatformMain bin2asm : bin2asm.c ;
|
||||||
BuildPlatformMain makeflop : makeflop.c ;
|
|
||||||
|
|
||||||
#CCFLAGS = $(oldccflags) ;
|
|
||||||
|
|
||||||
SubInclude HAIKU_TOP src system boot arch ;
|
|
||||||
SubInclude HAIKU_TOP src system boot platform ;
|
SubInclude HAIKU_TOP src system boot platform ;
|
||||||
SubInclude HAIKU_TOP src system boot loader ;
|
SubInclude HAIKU_TOP src system boot loader ;
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
SubDir HAIKU_TOP src system boot arch ;
|
|
||||||
|
|
||||||
SubInclude HAIKU_TOP src system boot arch $(TARGET_ARCH) ;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
SubDir HAIKU_TOP src system boot arch alpha ;
|
|
||||||
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
/*
|
|
||||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
|
||||||
** Distributed under the terms of the NewOS License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int _start()
|
|
||||||
{
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
OUTPUT_FORMAT("elf64-alpha", "elf64-alpha", "elf64-alpha")
|
|
||||||
OUTPUT_ARCH(alpha)
|
|
||||||
|
|
||||||
ENTRY(_start)
|
|
||||||
SECTIONS
|
|
||||||
{
|
|
||||||
. = 0x101000 + SIZEOF_HEADERS;
|
|
||||||
|
|
||||||
/* text/read-only data */
|
|
||||||
.text : { *(.text .gnu.linkonce.t.*) }
|
|
||||||
|
|
||||||
__ctor_list = .;
|
|
||||||
.ctors : { *(.ctors) }
|
|
||||||
__ctor_end = .;
|
|
||||||
|
|
||||||
.rodata : { *(.rodata) }
|
|
||||||
|
|
||||||
/* writable data */
|
|
||||||
. = ALIGN(0x1000);
|
|
||||||
__data_start = .;
|
|
||||||
.data : { *(.data .gnu.linkonce.d.*) }
|
|
||||||
|
|
||||||
/* unintialized data (in same segment as writable data) */
|
|
||||||
__bss_start = .;
|
|
||||||
.bss : { *(.bss) }
|
|
||||||
|
|
||||||
. = ALIGN(0x1000);
|
|
||||||
_end = . ;
|
|
||||||
|
|
||||||
/* Strip unnecessary stuff */
|
|
||||||
/DISCARD/ : { *(.comment .note .eh_frame .dtors) }
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
|
|
||||||
STAGE2_DIR = boot/$(ARCH)
|
|
||||||
STAGE2_OBJ_DIR = $(STAGE2_DIR)/$(OBJ_DIR)
|
|
||||||
STAGE2_OBJS = $(STAGE2_OBJ_DIR)/stage2.o
|
|
||||||
DEPS += $(STAGE2_OBJS:.o=.d)
|
|
||||||
|
|
||||||
STAGE2 = $(STAGE2_OBJ_DIR)/stage2
|
|
||||||
|
|
||||||
$(STAGE2): $(STAGE2_OBJS) $(LIBC)
|
|
||||||
$(LD) -dN --script=$(STAGE2_DIR)/stage2.ld -L $(LIBGCC_PATH) $(LIBGCC) $(STAGE2_OBJS) $(LIBC) -o $@
|
|
||||||
|
|
||||||
stage2clean:
|
|
||||||
rm -f $(STAGE2_OBJS) $(STAGE2_ARCH)
|
|
||||||
|
|
||||||
$(STAGE2_OBJ_DIR)/%.o: $(STAGE2_DIR)/%.c
|
|
||||||
@mkdir -p $(STAGE2_OBJ_DIR)
|
|
||||||
$(CC) $(GLOBAL_CFLAGS) -Iinclude -I$(STAGE2_DIR) -c $< -o $@
|
|
||||||
|
|
||||||
$(STAGE2_OBJ_DIR)/%.d: $(STAGE2_DIR)/%.c
|
|
||||||
@mkdir -p $(STAGE2_OBJ_DIR)
|
|
||||||
@echo "making deps for $<..."
|
|
||||||
@($(ECHO) -n $(dir $@);$(CC) $(GLOBAL_CFLAGS) -Iinclude -I$(STAGE2_DIR) -M -MG $<) > $@
|
|
||||||
|
|
||||||
$(STAGE2_OBJ_DIR)/%.d: $(STAGE2_DIR)/%.S
|
|
||||||
@mkdir -p $(STAGE2_OBJ_DIR)
|
|
||||||
@echo "making deps for $<..."
|
|
||||||
@($(ECHO) -n $(dir $@);$(CC) $(GLOBAL_CFLAGS) -Iinclude -I$(STAGE2_DIR) -M -MG $<) > $@
|
|
||||||
|
|
||||||
$(STAGE2_OBJ_DIR)/%.o: $(STAGE2_DIR)/%.S
|
|
||||||
@mkdir -p $(STAGE2_OBJ_DIR)
|
|
||||||
$(CC) $(GLOBAL_CFLAGS) -Iinclude -I$(STAGE2_DIR) -c $< -o $@
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
SubDir HAIKU_TOP src system boot arch m68k ;
|
|
||||||
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
ifneq ($(_BOOT_MAKE),1)
|
|
||||||
_BOOT_MAKE = 1
|
|
||||||
|
|
||||||
# include targets we depend on
|
|
||||||
include lib/lib.mk
|
|
||||||
include kernel/kernel.mk
|
|
||||||
include apps/apps.mk
|
|
||||||
|
|
||||||
BOOT_DIR = boot/$(ARCH)
|
|
||||||
BOOT_OBJ_DIR = $(BOOT_DIR)/$(OBJ_DIR)
|
|
||||||
|
|
||||||
STAGE2_OBJS = \
|
|
||||||
$(BOOT_OBJ_DIR)/stage2.o \
|
|
||||||
$(BOOT_OBJ_DIR)/stage2_asm.o \
|
|
||||||
$(BOOT_OBJ_DIR)/stage2_nextmon.o \
|
|
||||||
$(BOOT_OBJ_DIR)/stage2_text.o \
|
|
||||||
|
|
||||||
DEPS += $(STAGE2_OBJS:.o=.d)
|
|
||||||
|
|
||||||
STAGE2 = $(BOOT_OBJ_DIR)/stage2
|
|
||||||
|
|
||||||
$(STAGE2): $(STAGE2_OBJS) $(KLIBS)
|
|
||||||
$(LD) -dN --script=$(BOOT_DIR)/stage2.ld -L $(LIBGCC_PATH) $(STAGE2_OBJS) $(LINK_KLIBS) $(LIBGCC) -o $@
|
|
||||||
|
|
||||||
stage2: $(STAGE2)
|
|
||||||
|
|
||||||
stage2clean:
|
|
||||||
rm -f $(STAGE2_OBJS) $(STAGE2)
|
|
||||||
|
|
||||||
CLEAN += stage2clean
|
|
||||||
|
|
||||||
SEMIFINAL = $(BOOT_DIR)/final.bootdir
|
|
||||||
|
|
||||||
#$(SEMIFINAL): $(STAGE2) $(KERNEL) $(APPS) tools
|
|
||||||
$(SEMIFINAL): $(STAGE2) tools
|
|
||||||
$(BOOTMAKER) --bigendian $(BOOT_DIR)/config.ini -o $(SEMIFINAL)
|
|
||||||
|
|
||||||
STAGE1_OBJS = \
|
|
||||||
$(BOOT_OBJ_DIR)/stage1.o
|
|
||||||
|
|
||||||
DEPS += $(STAGE1_OBJS:.o=.d)
|
|
||||||
|
|
||||||
FINAL = $(BOOT_DIR)/final
|
|
||||||
|
|
||||||
AWKPROG='\
|
|
||||||
{ \
|
|
||||||
printf "\0\207\01\07"; \
|
|
||||||
printf "\0%c%c%c", $$1 / 65536, $$1 / 256, $$1; \
|
|
||||||
printf "\0%c%c%c", $$2 / 65536, $$2 / 256, $$2; \
|
|
||||||
printf "\0%c%c%c", $$3 / 65536, $$3 / 256, $$3; \
|
|
||||||
printf "\0\0\0\0\04\070\0\0\0\0\0\0\0\0\0\0" \
|
|
||||||
}'
|
|
||||||
|
|
||||||
$(FINAL): $(STAGE1_OBJS)
|
|
||||||
$(LD) -dN --script=$(BOOT_DIR)/stage1.ld $(STAGE1_OBJS) -o $@.elf
|
|
||||||
@${SIZE} $@.elf
|
|
||||||
@${OBJCOPY} -O binary $@.elf $@.raw
|
|
||||||
@(${SIZE} $@.elf | tail +2 | ${AWK} ${AWKPROG} ; cat $@.raw) > $@
|
|
||||||
|
|
||||||
FINAL_ASMINCLUDE = $(BOOT_DIR)/final.asminclude
|
|
||||||
|
|
||||||
$(FINAL_ASMINCLUDE): $(SEMIFINAL) tools
|
|
||||||
$(BIN2ASM) < $(SEMIFINAL) > $(FINAL_ASMINCLUDE)
|
|
||||||
|
|
||||||
finalclean:
|
|
||||||
rm -f $(STAGE1_OBJS) $(FINAL) $(SEMIFINAL) $(FINAL_ASMINCLUDE)
|
|
||||||
|
|
||||||
CLEAN += finalclean
|
|
||||||
|
|
||||||
#
|
|
||||||
$(BOOT_OBJ_DIR)/stage1.o: $(BOOT_DIR)/stage1.S
|
|
||||||
@if [ ! -d $(BOOT_OBJ_DIR) ]; then mkdir -p $(BOOT_OBJ_DIR); fi
|
|
||||||
$(CC) -c $< $(GLOBAL_CFLAGS) -I. -Iinclude -o $@
|
|
||||||
|
|
||||||
$(BOOT_OBJ_DIR)/%.o: $(BOOT_DIR)/%.c
|
|
||||||
@if [ ! -d $(BOOT_OBJ_DIR) ]; then mkdir -p $(BOOT_OBJ_DIR); fi
|
|
||||||
$(CC) -c $< $(GLOBAL_CFLAGS) $(KERNEL_CFLAGS) -Iinclude -Iinclude/nulibc -o $@
|
|
||||||
|
|
||||||
$(BOOT_OBJ_DIR)/%.d: $(BOOT_DIR)/%.c
|
|
||||||
@if [ ! -d $(BOOT_OBJ_DIR) ]; then mkdir -p $(BOOT_OBJ_DIR); fi
|
|
||||||
@echo "making deps for $<..."
|
|
||||||
@($(ECHO) -n $(dir $@);$(CC) $(KERNEL_CFLAGS) -Iinclude -Iinclude/nulibc -M -MG $<) > $@
|
|
||||||
|
|
||||||
$(BOOT_OBJ_DIR)/%.d: $(BOOT_DIR)/%.S
|
|
||||||
@if [ ! -d $(BOOT_OBJ_DIR) ]; then mkdir -p $(BOOT_OBJ_DIR); fi
|
|
||||||
@echo "making deps for $<..."
|
|
||||||
@($(ECHO) -n $(dir $@);$(CC) $(KERNEL_CFLAGS) -Iinclude -Iinclude/nulibc -M -MG $<) > $@
|
|
||||||
|
|
||||||
$(BOOT_OBJ_DIR)/%.o: $(BOOT_DIR)/%.S
|
|
||||||
@if [ ! -d $(BOOT_OBJ_DIR) ]; then mkdir -p $(BOOT_OBJ_DIR); fi
|
|
||||||
$(CC) -c $< $(GLOBAL_CFLAGS) $(KERNEL_CFLAGS) -Iinclude -Iinclude/nulibc -o $@
|
|
||||||
|
|
||||||
endif
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
# ---------------------------------------------------------------
|
|
||||||
# The bootstrap code is where control starts once netboot, boot.com,
|
|
||||||
# etc loads the image. It creates a page table to map the kernel in
|
|
||||||
# at 0x80000000 and then jumps to the kernel entrypoint where things
|
|
||||||
# really start happening. This MUST be the first entry in the .ini
|
|
||||||
#
|
|
||||||
[bootstrap]
|
|
||||||
type=elf32
|
|
||||||
file=boot/m68k/obj.m68k/stage2
|
|
||||||
|
|
||||||
#[kernel]
|
|
||||||
#type=elf32
|
|
||||||
#file=kernel/obj.m68k/system
|
|
||||||
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
** Copyright 2002, Travis Geiselbrecht. All rights reserved.
|
|
||||||
** Distributed under the terms of the NewOS License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define BASE 0x4380000
|
|
||||||
#define BOOTDIR_BASE (BASE + 0x1000)
|
|
||||||
#define STAGE2_BOOTDIR_PAGE (BOOTDIR_BASE + 0x60)
|
|
||||||
#define STAGE2_OFFSET (BOOTDIR_BASE + 0x74)
|
|
||||||
|
|
||||||
.globl _start
|
|
||||||
_start:
|
|
||||||
nop
|
|
||||||
|
|
||||||
/* load the base of the bootdir */
|
|
||||||
movel #BOOTDIR_BASE,%a0
|
|
||||||
|
|
||||||
/* load the offset the stage2 will start into the bootdir */
|
|
||||||
movel (STAGE2_BOOTDIR_PAGE),%d0
|
|
||||||
mulul #4096,%d0
|
|
||||||
movel %d0,%a1
|
|
||||||
|
|
||||||
/* load the offset into that page the stage2 entry point will be */
|
|
||||||
movel (STAGE2_OFFSET),%a2
|
|
||||||
|
|
||||||
/* add them together */
|
|
||||||
addl %a2,%a1
|
|
||||||
addl %a1,%a0
|
|
||||||
|
|
||||||
/* look in the vector table and find the monitor vector */
|
|
||||||
movec %vbr,%a3
|
|
||||||
movel %a3@(4),%sp@-
|
|
||||||
|
|
||||||
/* copy the arg we got */
|
|
||||||
movel %sp@(8),%sp@-
|
|
||||||
|
|
||||||
/* make the call */
|
|
||||||
jsr (%a0)
|
|
||||||
|
|
||||||
addql #8,%sp
|
|
||||||
|
|
||||||
rts
|
|
||||||
|
|
||||||
.align 4
|
|
||||||
tempstack:
|
|
||||||
.skip 0x800
|
|
||||||
tempstack_end:
|
|
||||||
|
|
||||||
.align 0x1000
|
|
||||||
.data
|
|
||||||
#include "boot/m68k/final.asminclude"
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
OUTPUT_FORMAT("elf32-m68k", "elf32-m68k", "elf32-m68k")
|
|
||||||
OUTPUT_ARCH(m68k)
|
|
||||||
|
|
||||||
/*
|
|
||||||
PHDRS
|
|
||||||
{
|
|
||||||
reginfo 0x70000000;
|
|
||||||
text PT_LOAD;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
ENTRY(_start)
|
|
||||||
SECTIONS
|
|
||||||
{
|
|
||||||
|
|
||||||
. = 0x4380000;
|
|
||||||
|
|
||||||
/* text/read-only data */
|
|
||||||
.text : { *(.text .gnu.linkonce.t.*) }
|
|
||||||
|
|
||||||
__ctor_list = .;
|
|
||||||
.ctors : { *(.ctors) }
|
|
||||||
__ctor_end = .;
|
|
||||||
|
|
||||||
.rodata :
|
|
||||||
{
|
|
||||||
*(.rodata)
|
|
||||||
. = ALIGN(0x1000);
|
|
||||||
} =0x9000
|
|
||||||
|
|
||||||
/* writable data */
|
|
||||||
__data_start = .;
|
|
||||||
.data : { *(.data .gnu.linkonce.d.*) }
|
|
||||||
|
|
||||||
/* unintialized data (in same segment as writable data) */
|
|
||||||
__bss_start = .;
|
|
||||||
.bss : { *(.bss) }
|
|
||||||
|
|
||||||
. = ALIGN(0x1000);
|
|
||||||
_end = . ;
|
|
||||||
|
|
||||||
/* Strip unnecessary stuff */
|
|
||||||
/DISCARD/ : { *(.reginfo .comment .note .eh_frame .dtors) }
|
|
||||||
}
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
/*
|
|
||||||
** Copyright 2002, Travis Geiselbrecht. All rights reserved.
|
|
||||||
** Distributed under the terms of the NewOS License.
|
|
||||||
*/
|
|
||||||
#include "stage2_priv.h"
|
|
||||||
#include <boot/bootdir.h>
|
|
||||||
#include <boot/stage2.h>
|
|
||||||
#include <arch/cpu.h>
|
|
||||||
|
|
||||||
static kernel_args ka = { 0 };
|
|
||||||
|
|
||||||
#define BOOTDIR_ADDR 0x4381000
|
|
||||||
static const boot_entry *bootdir = (boot_entry*)BOOTDIR_ADDR;
|
|
||||||
|
|
||||||
int _start(char *boot_args, char *monitor);
|
|
||||||
int _start(char *boot_args, char *monitor)
|
|
||||||
{
|
|
||||||
unsigned int bootdir_pages;
|
|
||||||
|
|
||||||
init_nextmon(monitor);
|
|
||||||
dprintf("\nNewOS stage2: args '%s', monitor %p\n", boot_args, monitor);
|
|
||||||
|
|
||||||
probe_memory(&ka);
|
|
||||||
|
|
||||||
dprintf("tc 0x%x\n", get_tc());
|
|
||||||
dprintf("urp 0x%x\n", get_urp());
|
|
||||||
dprintf("srp 0x%x\n", get_srp());
|
|
||||||
|
|
||||||
// calculate how big the bootdir is
|
|
||||||
{
|
|
||||||
int entry;
|
|
||||||
bootdir_pages = 0;
|
|
||||||
for (entry = 0; entry < BOOTDIR_MAX_ENTRIES; entry++) {
|
|
||||||
if (bootdir[entry].be_type == BE_TYPE_NONE)
|
|
||||||
break;
|
|
||||||
|
|
||||||
bootdir_pages += bootdir[entry].be_size;
|
|
||||||
}
|
|
||||||
ka.bootdir_addr.start = (unsigned long)bootdir;
|
|
||||||
ka.bootdir_addr.size = bootdir_pages * PAGE_SIZE;
|
|
||||||
dprintf("bootdir: start %p, size 0x%x\n", (char *)ka.bootdir_addr.start, ka.bootdir_addr.size);
|
|
||||||
}
|
|
||||||
|
|
||||||
// begin to set up the physical page allocation range data structures
|
|
||||||
ka.num_phys_alloc_ranges = 1;
|
|
||||||
ka.phys_alloc_range[0].start = ka.bootdir_addr.start;
|
|
||||||
ka.phys_alloc_range[0].size = ka.bootdir_addr.size;
|
|
||||||
|
|
||||||
// allocate a stack for the kernel when we jump into it
|
|
||||||
ka.cpu_kstack[0].start = allocate_page(&ka);
|
|
||||||
ka.cpu_kstack[0].size = PAGE_SIZE;
|
|
||||||
|
|
||||||
ka.num_cpus = 0;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long allocate_page(kernel_args *ka)
|
|
||||||
{
|
|
||||||
unsigned long page;
|
|
||||||
|
|
||||||
page = ka->phys_alloc_range[0].start + ka->phys_alloc_range[0].size;
|
|
||||||
ka->phys_alloc_range[0].size += PAGE_SIZE;
|
|
||||||
|
|
||||||
return page;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
OUTPUT_FORMAT("elf32-m68k", "elf32-m68k", "elf32-m68k")
|
|
||||||
OUTPUT_ARCH(m68k)
|
|
||||||
|
|
||||||
/*
|
|
||||||
PHDRS
|
|
||||||
{
|
|
||||||
reginfo 0x70000000;
|
|
||||||
text PT_LOAD;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
ENTRY(_start)
|
|
||||||
SECTIONS
|
|
||||||
{
|
|
||||||
. = 0x4382000 + SIZEOF_HEADERS;
|
|
||||||
|
|
||||||
/* text/read-only data */
|
|
||||||
.text : { *(.text .gnu.linkonce.t.*) }
|
|
||||||
|
|
||||||
__ctor_list = .;
|
|
||||||
.ctors : { *(.ctors) }
|
|
||||||
__ctor_end = .;
|
|
||||||
|
|
||||||
.rodata :
|
|
||||||
{
|
|
||||||
*(.rodata)
|
|
||||||
. = ALIGN(0x1000);
|
|
||||||
} =0x9000
|
|
||||||
|
|
||||||
/* writable data */
|
|
||||||
__data_start = .;
|
|
||||||
.data : { *(.data .gnu.linkonce.d.*) }
|
|
||||||
|
|
||||||
/* unintialized data (in same segment as writable data) */
|
|
||||||
__bss_start = .;
|
|
||||||
.bss : { *(.bss) }
|
|
||||||
|
|
||||||
. = ALIGN(0x1000);
|
|
||||||
_end = . ;
|
|
||||||
|
|
||||||
/* Strip unnecessary stuff */
|
|
||||||
/DISCARD/ : { *(.reginfo .comment .note .eh_frame .dtors) }
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
/*
|
|
||||||
** Copyright 2002, Travis Geiselbrecht. All rights reserved.
|
|
||||||
** Distributed under the terms of the NewOS License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
.text
|
|
||||||
|
|
||||||
.globl get_tc
|
|
||||||
get_tc:
|
|
||||||
.long 0x4e7a0003 // movec %tc,%d0
|
|
||||||
rts
|
|
||||||
|
|
||||||
.globl set_tc
|
|
||||||
set_tc:
|
|
||||||
.long 0x4e7b0003 // movec %d0,%tc
|
|
||||||
rts
|
|
||||||
|
|
||||||
.globl get_urp
|
|
||||||
get_urp:
|
|
||||||
.long 0x4e7a0806 // movec %urp,%d0
|
|
||||||
rts
|
|
||||||
|
|
||||||
.globl set_urp
|
|
||||||
set_urp:
|
|
||||||
.long 0x4e7b0806 // movec %d0,%urp
|
|
||||||
rts
|
|
||||||
|
|
||||||
.globl get_srp
|
|
||||||
get_srp:
|
|
||||||
.long 0x4e7a0807 // movec %srp,%d0
|
|
||||||
rts
|
|
||||||
|
|
||||||
.globl set_srp
|
|
||||||
set_srp:
|
|
||||||
.long 0x4e7b0807 // movec %d0,%srp
|
|
||||||
rts
|
|
||||||
|
|
||||||
@@ -1,184 +0,0 @@
|
|||||||
/*
|
|
||||||
** Copyright 2002, Travis Geiselbrecht. All rights reserved.
|
|
||||||
** Distributed under the terms of the NewOS License.
|
|
||||||
*/
|
|
||||||
#include "stage2_priv.h"
|
|
||||||
|
|
||||||
#define MG_simm 0
|
|
||||||
#define MG_flags 4
|
|
||||||
#define MG_sid 6
|
|
||||||
#define MG_pagesize 10
|
|
||||||
#define MG_mon_stack 14
|
|
||||||
#define MG_vbr 18
|
|
||||||
#define MG_nvram 22
|
|
||||||
#define MG_inetntoa 54
|
|
||||||
#define MG_inputline 72
|
|
||||||
#define MG_region 200
|
|
||||||
#define MG_alloc_base 232
|
|
||||||
#define MG_alloc_brk 236
|
|
||||||
#define MG_boot_dev 240
|
|
||||||
#define MG_boot_arg 244
|
|
||||||
#define MG_boot_info 248
|
|
||||||
#define MG_boot_file 252
|
|
||||||
#define MG_bootfile 256
|
|
||||||
#define MG_boot_how 320
|
|
||||||
#define MG_km 324
|
|
||||||
#define MG_km_flags 368
|
|
||||||
#define MG_mon_init 370
|
|
||||||
#define MG_si 374
|
|
||||||
#define MG_time 378
|
|
||||||
#define MG_sddp 382
|
|
||||||
#define MG_dgp 386
|
|
||||||
#define MG_s5cp 390
|
|
||||||
#define MG_odc 394
|
|
||||||
#define MG_odd 398
|
|
||||||
#define MG_radix 402
|
|
||||||
#define MG_dmachip 404
|
|
||||||
#define MG_diskchip 408
|
|
||||||
#define MG_intrstat 412
|
|
||||||
#define MG_intrmask 416
|
|
||||||
#define MG_nofault 420
|
|
||||||
#define MG_fmt 424
|
|
||||||
#define MG_addr 426
|
|
||||||
#define MG_na 458
|
|
||||||
#define MG_mx 462
|
|
||||||
#define MG_my 466
|
|
||||||
#define MG_cursor_save 470
|
|
||||||
#define MG_getc 726
|
|
||||||
#define MG_try_getc 730
|
|
||||||
#define MG_putc 734
|
|
||||||
#define MG_alert 738
|
|
||||||
#define MG_alert_confirm 742
|
|
||||||
#define MG_alloc 746
|
|
||||||
#define MG_boot_slider 750
|
|
||||||
#define MG_eventc 754
|
|
||||||
#define MG_event_high 758
|
|
||||||
#define MG_animate 762
|
|
||||||
#define MG_anim_time 766
|
|
||||||
#define MG_scsi_intr 770
|
|
||||||
#define MG_scsi_intrarg 774
|
|
||||||
#define MG_minor 778
|
|
||||||
#define MG_seq 780
|
|
||||||
#define MG_anim_run 782
|
|
||||||
#define MG_major 786
|
|
||||||
#define MG_con_slot 844
|
|
||||||
#define MG_con_fbnum 845
|
|
||||||
#define MG_con_map_vaddr0 860
|
|
||||||
#define MG_con_map_vaddr1 872
|
|
||||||
#define MG_con_map_vaddr2 884
|
|
||||||
#define MG_con_map_vaddr3 896
|
|
||||||
#define MG_con_map_vaddr4 908
|
|
||||||
#define MG_con_map_vaddr5 920
|
|
||||||
|
|
||||||
#define MG_clientetheraddr 788
|
|
||||||
#define MG_machine_type 936
|
|
||||||
#define MG_board_rev 937
|
|
||||||
|
|
||||||
#define N_SIMM 4 /* number of SIMMs in machine */
|
|
||||||
|
|
||||||
/* SIMM types */
|
|
||||||
#define SIMM_SIZE 0x03
|
|
||||||
#define SIMM_SIZE_EMPTY 0x00
|
|
||||||
#define SIMM_SIZE_16MB 0x01
|
|
||||||
#define SIMM_SIZE_4MB 0x02
|
|
||||||
#define SIMM_SIZE_1MB 0x03
|
|
||||||
#define SIMM_PAGE_MODE 0x04
|
|
||||||
#define SIMM_PARITY 0x08 /* ?? */
|
|
||||||
|
|
||||||
#define NEXT_RAMBASE 0x4000000
|
|
||||||
|
|
||||||
/* Machine types */
|
|
||||||
#define NeXT_CUBE 0
|
|
||||||
#define NeXT_WARP9 1
|
|
||||||
#define NeXT_X15 2
|
|
||||||
#define NeXT_WARP9C 3
|
|
||||||
#define NeXT_TURBO 4
|
|
||||||
#define NeXT_TURBO_COLOR 5
|
|
||||||
|
|
||||||
typedef int (*getcptr)(void);
|
|
||||||
typedef int (*putcptr)(int);
|
|
||||||
|
|
||||||
#define MON(type, off) (*(type *)((unsigned int) (mg) + off))
|
|
||||||
|
|
||||||
static char *mg = 0;
|
|
||||||
|
|
||||||
int init_nextmon(char *monitor)
|
|
||||||
{
|
|
||||||
mg = monitor;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int probe_memory(kernel_args *ka)
|
|
||||||
{
|
|
||||||
int i, r;
|
|
||||||
char machine_type = MON(char,MG_machine_type);
|
|
||||||
int msize1, msize4, msize16;
|
|
||||||
|
|
||||||
/* depending on the machine, the bank layout is different */
|
|
||||||
dprintf("machine type: 0x%x\n", machine_type);
|
|
||||||
switch(machine_type) {
|
|
||||||
case NeXT_WARP9:
|
|
||||||
case NeXT_X15:
|
|
||||||
msize16 = 0x10000000;
|
|
||||||
msize4 = 0x400000;
|
|
||||||
msize1 = 0x100000;
|
|
||||||
break;
|
|
||||||
case NeXT_WARP9C:
|
|
||||||
msize16 = 0x800000;
|
|
||||||
msize4 = 0x200000;
|
|
||||||
msize1 = 0x80000;
|
|
||||||
break;
|
|
||||||
case NeXT_TURBO:
|
|
||||||
case NeXT_TURBO_COLOR:
|
|
||||||
msize16 = 0x2000000;
|
|
||||||
msize4 = 0x800000;
|
|
||||||
msize1 = 0x200000;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
msize16 = 0x100000;
|
|
||||||
msize4 = 0x100000;
|
|
||||||
msize1 = 0x100000;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* start probing ram */
|
|
||||||
dprintf("memory probe:\n");
|
|
||||||
ka->num_phys_mem_ranges = 0;
|
|
||||||
for(i=0; i<N_SIMM; i++) {
|
|
||||||
char probe = MON(char,MG_simm+i);
|
|
||||||
|
|
||||||
if((probe & SIMM_SIZE) != SIMM_SIZE_EMPTY) {
|
|
||||||
ka->phys_mem_range[ka->num_phys_mem_ranges].start = NEXT_RAMBASE + (msize16 * i);
|
|
||||||
}
|
|
||||||
switch(probe & SIMM_SIZE) {
|
|
||||||
case SIMM_SIZE_16MB:
|
|
||||||
ka->phys_mem_range[ka->num_phys_mem_ranges].size = msize16;
|
|
||||||
break;
|
|
||||||
case SIMM_SIZE_4MB:
|
|
||||||
ka->phys_mem_range[ka->num_phys_mem_ranges].size = msize4;
|
|
||||||
break;
|
|
||||||
case SIMM_SIZE_1MB:
|
|
||||||
ka->phys_mem_range[ka->num_phys_mem_ranges].size = msize1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
dprintf("bank %i: start 0x%x, size 0x%x\n", i,
|
|
||||||
ka->phys_mem_range[ka->num_phys_mem_ranges].start, ka->phys_mem_range[ka->num_phys_mem_ranges].size);
|
|
||||||
ka->num_phys_mem_ranges++;
|
|
||||||
}
|
|
||||||
|
|
||||||
dprintf("alloc_base: 0x%x\n", MON(int, MG_alloc_base));
|
|
||||||
dprintf("alloc_brk: 0x%x\n", MON(int, MG_alloc_brk));
|
|
||||||
dprintf("mon_stack: 0x%x\n", MON(int, MG_mon_stack));
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void putc(int c)
|
|
||||||
{
|
|
||||||
MON(putcptr,MG_putc)(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
int getc(void)
|
|
||||||
{
|
|
||||||
return(MON(getcptr,MG_getc)());
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
/*
|
|
||||||
** Copyright 2002, Travis Geiselbrecht. All rights reserved.
|
|
||||||
** Distributed under the terms of the NewOS License.
|
|
||||||
*/
|
|
||||||
#include "stage2_priv.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
void puts(const char *str)
|
|
||||||
{
|
|
||||||
while (*str)
|
|
||||||
putc(*str++);
|
|
||||||
}
|
|
||||||
|
|
||||||
int dprintf(const char *fmt, ...)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
va_list args;
|
|
||||||
char temp[256];
|
|
||||||
|
|
||||||
va_start(args, fmt);
|
|
||||||
ret = vsprintf(temp,fmt,args);
|
|
||||||
va_end(args);
|
|
||||||
|
|
||||||
puts(temp);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
SubDir HAIKU_TOP src system boot arch mips ;
|
|
||||||
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
ifneq ($(_BOOT_MAKE),1)
|
|
||||||
_BOOT_MAKE = 1
|
|
||||||
|
|
||||||
# include targets we depend on
|
|
||||||
include lib/lib.mk
|
|
||||||
include kernel/kernel.mk
|
|
||||||
include apps/apps.mk
|
|
||||||
|
|
||||||
# mips stage2 makefile
|
|
||||||
BOOT_DIR = boot/$(ARCH)
|
|
||||||
BOOT_OBJ_DIR = $(BOOT_DIR)/$(OBJ_DIR)
|
|
||||||
|
|
||||||
STAGE2_OBJS = \
|
|
||||||
$(BOOT_OBJ_DIR)/stage2.o
|
|
||||||
|
|
||||||
DEPS += $(STAGE2_OBJS:.o=.d)
|
|
||||||
|
|
||||||
STAGE2 = $(BOOT_OBJ_DIR)/stage2
|
|
||||||
|
|
||||||
$(STAGE2): $(STAGE2_OBJS) $(KLIBS)
|
|
||||||
$(LD) -dN --script=$(BOOT_DIR)/stage2.ld -L $(LIBGCC_PATH) $(STAGE2_OBJS) $(KLIBS) $(LIBGCC) -o $@
|
|
||||||
|
|
||||||
stage2: $(STAGE2)
|
|
||||||
|
|
||||||
stage2clean:
|
|
||||||
rm -f $(STAGE2_OBJS) $(STAGE2)
|
|
||||||
|
|
||||||
CLEAN += stage2clean
|
|
||||||
|
|
||||||
SEMIFINAL = $(BOOT_DIR)/final.bootdir
|
|
||||||
|
|
||||||
$(SEMIFINAL): $(STAGE2) $(KERNEL) $(APPS) tools
|
|
||||||
$(BOOTMAKER) $(BOOT_DIR)/config.ini -o $(SEMIFINAL)
|
|
||||||
|
|
||||||
STAGE1_OBJS = \
|
|
||||||
$(BOOT_OBJ_DIR)/stage1.o
|
|
||||||
|
|
||||||
DEPS += $(STAGE1_OBJS:.o=.d)
|
|
||||||
|
|
||||||
FINAL = $(BOOT_DIR)/final
|
|
||||||
|
|
||||||
$(FINAL): $(STAGE1_OBJS)
|
|
||||||
$(LD) -dN --script=$(BOOT_DIR)/stage1.ld $(STAGE1_OBJS) -o $@
|
|
||||||
|
|
||||||
FINAL_ASMINCLUDE = $(BOOT_DIR)/final.asminclude
|
|
||||||
|
|
||||||
$(BOOT_OBJ_DIR)/stage1.o: $(BOOT_DIR)/stage1.S
|
|
||||||
@if [ ! -d $(BOOT_OBJ_DIR) ]; then mkdir -p $(BOOT_OBJ_DIR); fi
|
|
||||||
$(CC) -c $< $(GLOBAL_CFLAGS) -I. -Iinclude -o $@
|
|
||||||
|
|
||||||
$(FINAL_ASMINCLUDE): $(SEMIFINAL) tools
|
|
||||||
$(BIN2ASM) < $(SEMIFINAL) > $(FINAL_ASMINCLUDE)
|
|
||||||
|
|
||||||
finalclean:
|
|
||||||
rm -f $(STAGE1_OBJS) $(FINAL) $(SEMIFINAL) $(FINAL_ASMINCLUDE)
|
|
||||||
|
|
||||||
CLEAN += finalclean
|
|
||||||
|
|
||||||
#
|
|
||||||
$(BOOT_OBJ_DIR)/%.o: $(BOOT_DIR)/%.c
|
|
||||||
@if [ ! -d $(BOOT_OBJ_DIR) ]; then mkdir -p $(BOOT_OBJ_DIR); fi
|
|
||||||
$(CC) -c $< $(GLOBAL_CFLAGS) -Iinclude -o $@
|
|
||||||
|
|
||||||
$(BOOT_OBJ_DIR)/%.d: $(BOOT_DIR)/%.c
|
|
||||||
@if [ ! -d $(BOOT_OBJ_DIR) ]; then mkdir -p $(BOOT_OBJ_DIR); fi
|
|
||||||
@echo "making deps for $<..."
|
|
||||||
@($(ECHO) -n $(dir $@);$(CC) $(GLOBAL_CFLAGS) -Iinclude -M -MG $<) > $@
|
|
||||||
|
|
||||||
$(BOOT_OBJ_DIR)/%.d: $(BOOT_DIR)/%.S
|
|
||||||
@if [ ! -d $(BOOT_OBJ_DIR) ]; then mkdir -p $(BOOT_OBJ_DIR); fi
|
|
||||||
@echo "making deps for $<..."
|
|
||||||
@($(ECHO) -n $(dir $@);$(CC) $(GLOBAL_CFLAGS) -Iinclude -M -MG $<) > $@
|
|
||||||
|
|
||||||
$(BOOT_OBJ_DIR)/%.o: $(BOOT_DIR)/%.S
|
|
||||||
@if [ ! -d $(BOOT_OBJ_DIR) ]; then mkdir -p $(BOOT_OBJ_DIR); fi
|
|
||||||
$(CC) -c $< $(GLOBAL_CFLAGS) -Iinclude -o $@
|
|
||||||
|
|
||||||
endif
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
# ---------------------------------------------------------------
|
|
||||||
# The bootstrap code is where control starts once netboot, boot.com,
|
|
||||||
# etc loads the image. It creates a page table to map the kernel in
|
|
||||||
# at 0x80000000 and then jumps to the kernel entrypoint where things
|
|
||||||
# really start happening. This MUST be the first entry in the .ini
|
|
||||||
#
|
|
||||||
[bootstrap]
|
|
||||||
type=boot
|
|
||||||
file=boot/mips/obj.mips/stage2
|
|
||||||
ventry=128
|
|
||||||
|
|
||||||
[kernel]
|
|
||||||
type=code
|
|
||||||
file=kernel/obj.mips/system
|
|
||||||
ventry=128
|
|
||||||
|
|
||||||
[testapp]
|
|
||||||
type=code
|
|
||||||
file=apps/testapp/obj.mips/testapp
|
|
||||||
ventry=116
|
|
||||||
|
|
||||||
[testfile]
|
|
||||||
type=data
|
|
||||||
file=boot/testfile
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
/*
|
|
||||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
|
||||||
** Distributed under the terms of the NewOS License.
|
|
||||||
*/
|
|
||||||
.text
|
|
||||||
.globl _start
|
|
||||||
_start:
|
|
||||||
j 0x88004074; // start of the stage2 bootloader
|
|
||||||
nop
|
|
||||||
|
|
||||||
.data
|
|
||||||
foo:
|
|
||||||
#include "boot/mips/final.asminclude"
|
|
||||||
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
OUTPUT_FORMAT("elf32-bigmips", "elf32-bigmips", "elf32-bigmips")
|
|
||||||
OUTPUT_ARCH(mips)
|
|
||||||
|
|
||||||
/*
|
|
||||||
PHDRS
|
|
||||||
{
|
|
||||||
reginfo 0x70000000;
|
|
||||||
text PT_LOAD;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
ENTRY(_start)
|
|
||||||
SECTIONS
|
|
||||||
{
|
|
||||||
|
|
||||||
. = 0x88002000;
|
|
||||||
|
|
||||||
/* text/read-only data */
|
|
||||||
.text : { *(.text .gnu.linkonce.t.*) }
|
|
||||||
|
|
||||||
__ctor_list = .;
|
|
||||||
.ctors : { *(.ctors) }
|
|
||||||
__ctor_end = .;
|
|
||||||
|
|
||||||
.rodata :
|
|
||||||
{
|
|
||||||
*(.rodata)
|
|
||||||
. = ALIGN(0x1000);
|
|
||||||
} =0x9000
|
|
||||||
|
|
||||||
/* writable data */
|
|
||||||
__data_start = .;
|
|
||||||
.data : { *(.data .gnu.linkonce.d.*) }
|
|
||||||
|
|
||||||
/* unintialized data (in same segment as writable data) */
|
|
||||||
__bss_start = .;
|
|
||||||
.bss : { *(.bss) }
|
|
||||||
|
|
||||||
. = ALIGN(0x1000);
|
|
||||||
_end = . ;
|
|
||||||
|
|
||||||
/* Strip unnecessary stuff */
|
|
||||||
/DISCARD/ : { *(.reginfo .comment .note .eh_frame .dtors) }
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
/*
|
|
||||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
|
||||||
** Distributed under the terms of the NewOS License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int stack[1024];
|
|
||||||
|
|
||||||
asm("
|
|
||||||
.text
|
|
||||||
.globl _start
|
|
||||||
_start:
|
|
||||||
lw $sp,_stack_end_addr
|
|
||||||
j start
|
|
||||||
nop
|
|
||||||
_stack_end_addr:
|
|
||||||
.word stack+(1024*4)
|
|
||||||
|
|
||||||
");
|
|
||||||
|
|
||||||
void start()
|
|
||||||
{
|
|
||||||
int *a = stack;
|
|
||||||
int *b = 0;
|
|
||||||
*b = 4;
|
|
||||||
for(;;);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
OUTPUT_FORMAT("elf32-bigmips", "elf32-bigmips", "elf32-bigmips")
|
|
||||||
OUTPUT_ARCH(mips)
|
|
||||||
|
|
||||||
ENTRY(_start)
|
|
||||||
SECTIONS
|
|
||||||
{
|
|
||||||
|
|
||||||
/* this is the starting address the SGI Indy puts the image at
|
|
||||||
+ the size of the stage1 bootloader
|
|
||||||
+ the size of the bootdir
|
|
||||||
+ the size of the program headers */
|
|
||||||
. = 0x88002000 + 0x2000 + SIZEOF_HEADERS;
|
|
||||||
|
|
||||||
/* text/read-only data */
|
|
||||||
.text : { *(.text .gnu.linkonce.t.*) }
|
|
||||||
|
|
||||||
__ctor_list = .;
|
|
||||||
.ctors : { *(.ctors) }
|
|
||||||
__ctor_end = .;
|
|
||||||
|
|
||||||
.rodata :
|
|
||||||
{
|
|
||||||
*(.rodata)
|
|
||||||
. = ALIGN(0x1000);
|
|
||||||
} =0x9000
|
|
||||||
|
|
||||||
/* writable data */
|
|
||||||
__data_start = .;
|
|
||||||
.data : { *(.data .gnu.linkonce.d.*) }
|
|
||||||
|
|
||||||
/* unintialized data (in same segment as writable data) */
|
|
||||||
__bss_start = .;
|
|
||||||
.bss : { *(.bss) }
|
|
||||||
|
|
||||||
. = ALIGN(0x1000);
|
|
||||||
_end = . ;
|
|
||||||
|
|
||||||
/* Strip unnecessary stuff */
|
|
||||||
/DISCARD/ : { *(.reginfo .comment .note .eh_frame .dtors) }
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
SubDir HAIKU_TOP src system boot arch ppc ;
|
|
||||||
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
ifneq ($(_BOOT_MAKE),1)
|
|
||||||
_BOOT_MAKE = 1
|
|
||||||
|
|
||||||
# include targets we depend on
|
|
||||||
include lib/lib.mk
|
|
||||||
include kernel/kernel.mk
|
|
||||||
include apps/apps.mk
|
|
||||||
|
|
||||||
# sh4 stage2 makefile
|
|
||||||
BOOT_DIR = boot/$(ARCH)
|
|
||||||
BOOT_OBJ_DIR = $(BOOT_DIR)/$(OBJ_DIR)
|
|
||||||
STAGE2_OBJS = $(BOOT_OBJ_DIR)/stage2.o \
|
|
||||||
$(BOOT_OBJ_DIR)/stage2_asm.o \
|
|
||||||
$(BOOT_OBJ_DIR)/stage2_mmu.o \
|
|
||||||
$(BOOT_OBJ_DIR)/stage2_of.o \
|
|
||||||
$(BOOT_OBJ_DIR)/stage2_text.o \
|
|
||||||
$(BOOT_OBJ_DIR)/stage2_faults.o
|
|
||||||
|
|
||||||
DEPS += $(STAGE2_OBJS:.o=.d)
|
|
||||||
|
|
||||||
STAGE2 = $(BOOT_OBJ_DIR)/stage2
|
|
||||||
|
|
||||||
$(STAGE2): $(STAGE2_OBJS) $(LIBC)
|
|
||||||
$(LD) $(GLOBAL_LDFLAGS) -dN --script=$(BOOT_DIR)/stage2.ld -L $(LIBGCC_PATH) $(STAGE2_OBJS) $(LIBC) $(LIBGCC) -o $@
|
|
||||||
|
|
||||||
stage2: $(STAGE2)
|
|
||||||
|
|
||||||
stage2clean:
|
|
||||||
rm -f $(STAGE2_OBJS) $(STAGE2)
|
|
||||||
|
|
||||||
CLEAN += stage2clean
|
|
||||||
|
|
||||||
SEMIFINAL = $(BOOT_DIR)/final.bootdir
|
|
||||||
|
|
||||||
$(SEMIFINAL): $(STAGE2) $(KERNEL) $(APPS) tools
|
|
||||||
$(BOOTMAKER) --bigendian $(BOOT_DIR)/config.ini -o $(SEMIFINAL)
|
|
||||||
|
|
||||||
STAGE1_OBJS = \
|
|
||||||
$(BOOT_OBJ_DIR)/stage1.o
|
|
||||||
|
|
||||||
DEPS += $(STAGE1_OBJS:.o=.d)
|
|
||||||
|
|
||||||
FINAL = $(BOOT_DIR)/final
|
|
||||||
|
|
||||||
$(FINAL): $(STAGE1_OBJS)
|
|
||||||
$(LD) $(GLOBAL_LDFLAGS) -dN --script=$(BOOT_DIR)/stage1.ld $(STAGE1_OBJS) -o $@
|
|
||||||
|
|
||||||
FINAL_ASMINCLUDE = $(BOOT_DIR)/final.asminclude
|
|
||||||
|
|
||||||
$(FINAL_ASMINCLUDE): $(SEMIFINAL) tools
|
|
||||||
$(BIN2ASM) < $(SEMIFINAL) > $(FINAL_ASMINCLUDE)
|
|
||||||
|
|
||||||
finalclean:
|
|
||||||
rm -f $(STAGE1_OBJS) $(FINAL) $(SEMIFINAL) $(FINAL_ASMINCLUDE)
|
|
||||||
|
|
||||||
CLEAN += finalclean
|
|
||||||
|
|
||||||
#
|
|
||||||
$(BOOT_OBJ_DIR)/stage1.o: $(BOOT_DIR)/stage1.S
|
|
||||||
@mkdir -p $(BOOT_OBJ_DIR)
|
|
||||||
$(CC) $(GLOBAL_CFLAGS) -g -I. -Iinclude -I$(BOOT_DIR) -c $< -o $@
|
|
||||||
|
|
||||||
$(BOOT_OBJ_DIR)/%.o: $(BOOT_DIR)/%.c
|
|
||||||
@mkdir -p $(BOOT_OBJ_DIR)
|
|
||||||
$(CC) $(GLOBAL_CFLAGS) -g -Iinclude -I$(BOOT_DIR) -c $< -o $@
|
|
||||||
|
|
||||||
$(BOOT_OBJ_DIR)/%.d: $(BOOT_DIR)/%.c
|
|
||||||
@mkdir -p $(BOOT_OBJ_DIR)
|
|
||||||
@echo "making deps for $<..."
|
|
||||||
@($(ECHO) -n $(dir $@);$(CC) $(GLOBAL_CFLAGS) -g -Iinclude -I$(BOOT_DIR) -M -MG $<) > $@
|
|
||||||
|
|
||||||
$(BOOT_OBJ_DIR)/%.d: $(BOOT_DIR)/%.S
|
|
||||||
@mkdir -p $(BOOT_OBJ_DIR)
|
|
||||||
@echo "making deps for $<..."
|
|
||||||
@($(ECHO) -n $(dir $@);$(CC) $(GLOBAL_CFLAGS) -g -Iinclude -I$(BOOT_DIR) -M -MG $<) > $@
|
|
||||||
|
|
||||||
$(BOOT_OBJ_DIR)/%.o: $(BOOT_DIR)/%.S
|
|
||||||
@mkdir -p $(BOOT_OBJ_DIR)
|
|
||||||
$(CC) $(GLOBAL_CFLAGS) -g -Iinclude -I$(BOOT_DIR) -c $< -o $@
|
|
||||||
endif
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
/*
|
|
||||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
|
||||||
** Distributed under the terms of the NewOS License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define BASE 0x100000
|
|
||||||
#define BOOTDIR_BASE (BASE + 0x1000)
|
|
||||||
#define STAGE2_BOOTDIR_PAGE (BOOTDIR_BASE + 0x60)
|
|
||||||
#define STAGE2_OFFSET (BOOTDIR_BASE + 0x74)
|
|
||||||
|
|
||||||
.text
|
|
||||||
.globl _start
|
|
||||||
_start:
|
|
||||||
lis 1,tempstack_end@ha /* load the new stack */
|
|
||||||
ori 1,1,tempstack_end@l
|
|
||||||
|
|
||||||
/* load the base of the bootdir */
|
|
||||||
lis 8,BOOTDIR_BASE@ha
|
|
||||||
ori 8,8,BOOTDIR_BASE@l
|
|
||||||
|
|
||||||
/* load the offset the stage2 will start into the bootdir */
|
|
||||||
lis 9,STAGE2_BOOTDIR_PAGE@ha
|
|
||||||
ori 9,9,STAGE2_BOOTDIR_PAGE@l
|
|
||||||
lwz 9,0(9)
|
|
||||||
mulli 9,9,4096
|
|
||||||
|
|
||||||
/* load the offset into that page the stage2 entry point will be */
|
|
||||||
lis 10,STAGE2_OFFSET@ha
|
|
||||||
ori 10,10,STAGE2_OFFSET@l
|
|
||||||
lwz 10,0(10)
|
|
||||||
|
|
||||||
/* add them all together */
|
|
||||||
add 11,8,9
|
|
||||||
add 11,11,10
|
|
||||||
|
|
||||||
/* jump there */
|
|
||||||
mtlr 11
|
|
||||||
blr
|
|
||||||
|
|
||||||
.align 4
|
|
||||||
tempstack:
|
|
||||||
.skip 0x800
|
|
||||||
tempstack_end:
|
|
||||||
|
|
||||||
.data
|
|
||||||
#include "boot/ppc/final.asminclude"
|
|
||||||
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc")
|
|
||||||
OUTPUT_ARCH(powerpc)
|
|
||||||
|
|
||||||
ENTRY(_start)
|
|
||||||
SECTIONS
|
|
||||||
{
|
|
||||||
. = 0x100000 + SIZEOF_HEADERS;
|
|
||||||
|
|
||||||
/* text/read-only data */
|
|
||||||
.text : { *(.text .gnu.linkonce.t.*) }
|
|
||||||
|
|
||||||
__ctor_list = .;
|
|
||||||
.ctors : { *(.ctors) }
|
|
||||||
__ctor_end = .;
|
|
||||||
|
|
||||||
.rodata : { *(.rodata) }
|
|
||||||
|
|
||||||
/* writable data */
|
|
||||||
. = ALIGN(0x1000);
|
|
||||||
__data_start = .;
|
|
||||||
.data : { *(.data .gnu.linkonce.d.*) }
|
|
||||||
|
|
||||||
/* unintialized data (in same segment as writable data) */
|
|
||||||
__bss_start = .;
|
|
||||||
.bss : { *(.bss) }
|
|
||||||
|
|
||||||
. = ALIGN(0x1000);
|
|
||||||
_end = . ;
|
|
||||||
|
|
||||||
/* Strip unnecessary stuff */
|
|
||||||
/DISCARD/ : { *(.comment .note .eh_frame .dtors) }
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
|
||||||
** Distributed under the terms of the NewOS License.
|
|
||||||
*/
|
|
||||||
#include <boot/stage2.h>
|
|
||||||
#include <libc/stdarg.h>
|
|
||||||
#include <libc/printf.h>
|
|
||||||
#include <libc/string.h>
|
|
||||||
#include "stage2_priv.h"
|
|
||||||
|
|
||||||
void _start(int arg1, int arg2, void *openfirmware);
|
|
||||||
|
|
||||||
static kernel_args ka = {0};
|
|
||||||
|
|
||||||
void _start(int arg1, int arg2, void *openfirmware)
|
|
||||||
{
|
|
||||||
int handle;
|
|
||||||
|
|
||||||
memset(&ka, 0, sizeof(ka));
|
|
||||||
|
|
||||||
of_init(openfirmware);
|
|
||||||
s2_text_init(&ka);
|
|
||||||
|
|
||||||
printf("Welcome to the stage2 bootloader!\n");
|
|
||||||
|
|
||||||
printf("arg1 0x%x, arg2 0x%x, openfirmware 0x%x\n", arg1, arg2, openfirmware);
|
|
||||||
|
|
||||||
printf("msr = 0x%x\n", getmsr());
|
|
||||||
|
|
||||||
s2_mmu_init(&ka);
|
|
||||||
|
|
||||||
for(;;);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,242 +0,0 @@
|
|||||||
/*
|
|
||||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
|
||||||
** Distributed under the terms of the NewOS License.
|
|
||||||
*/
|
|
||||||
.text
|
|
||||||
// void getibats(int bats[8]);
|
|
||||||
.globl getibats
|
|
||||||
getibats:
|
|
||||||
mfibatu 0,0
|
|
||||||
stw 0,0(3)
|
|
||||||
mfibatl 0,0
|
|
||||||
stwu 0,4(3)
|
|
||||||
mfibatu 0,1
|
|
||||||
stwu 0,4(3)
|
|
||||||
mfibatl 0,1
|
|
||||||
stwu 0,4(3)
|
|
||||||
mfibatu 0,2
|
|
||||||
stwu 0,4(3)
|
|
||||||
mfibatl 0,2
|
|
||||||
stwu 0,4(3)
|
|
||||||
mfibatu 0,3
|
|
||||||
stwu 0,4(3)
|
|
||||||
mfibatl 0,3
|
|
||||||
stwu 0,4(3)
|
|
||||||
blr
|
|
||||||
|
|
||||||
// void setibats(int bats[8]);
|
|
||||||
.globl setibats
|
|
||||||
setibats:
|
|
||||||
mfmsr 8
|
|
||||||
li 0,0
|
|
||||||
mtmsr 0
|
|
||||||
|
|
||||||
lwz 0,0(3)
|
|
||||||
mtibatu 0,0
|
|
||||||
isync
|
|
||||||
lwzu 0,4(3)
|
|
||||||
mtibatl 0,0
|
|
||||||
isync
|
|
||||||
lwzu 0,4(3)
|
|
||||||
mtibatu 1,0
|
|
||||||
isync
|
|
||||||
lwzu 0,4(3)
|
|
||||||
mtibatl 1,0
|
|
||||||
isync
|
|
||||||
lwzu 0,4(3)
|
|
||||||
mtibatu 2,0
|
|
||||||
isync
|
|
||||||
lwzu 0,4(3)
|
|
||||||
mtibatl 2,0
|
|
||||||
isync
|
|
||||||
lwzu 0,4(3)
|
|
||||||
mtibatu 3,0
|
|
||||||
isync
|
|
||||||
lwzu 0,4(3)
|
|
||||||
mtibatl 3,0
|
|
||||||
|
|
||||||
isync
|
|
||||||
|
|
||||||
mtmsr 8
|
|
||||||
isync
|
|
||||||
blr
|
|
||||||
|
|
||||||
// void getdbats(int bats[8]);
|
|
||||||
.globl getdbats
|
|
||||||
getdbats:
|
|
||||||
mfdbatu 0,0
|
|
||||||
stw 0,0(3)
|
|
||||||
mfdbatl 0,0
|
|
||||||
stwu 0,4(3)
|
|
||||||
mfdbatu 0,1
|
|
||||||
stwu 0,4(3)
|
|
||||||
mfdbatl 0,1
|
|
||||||
stwu 0,4(3)
|
|
||||||
mfdbatu 0,2
|
|
||||||
stwu 0,4(3)
|
|
||||||
mfdbatl 0,2
|
|
||||||
stwu 0,4(3)
|
|
||||||
mfdbatu 0,3
|
|
||||||
stwu 0,4(3)
|
|
||||||
mfdbatl 0,3
|
|
||||||
stwu 0,4(3)
|
|
||||||
blr
|
|
||||||
|
|
||||||
// void setdbats(int bats[8]);
|
|
||||||
.globl setdbats
|
|
||||||
setdbats:
|
|
||||||
mfmsr 8
|
|
||||||
li 0,0
|
|
||||||
mtmsr 0
|
|
||||||
|
|
||||||
lwz 0,0(3)
|
|
||||||
mtdbatu 0,0
|
|
||||||
lwzu 0,4(3)
|
|
||||||
mtdbatl 0,0
|
|
||||||
lwzu 0,4(3)
|
|
||||||
mtdbatu 1,0
|
|
||||||
lwzu 0,4(3)
|
|
||||||
mtdbatl 1,0
|
|
||||||
lwzu 0,4(3)
|
|
||||||
mtdbatu 2,0
|
|
||||||
lwzu 0,4(3)
|
|
||||||
mtdbatl 2,0
|
|
||||||
lwzu 0,4(3)
|
|
||||||
mtdbatu 3,0
|
|
||||||
lwzu 0,4(3)
|
|
||||||
mtdbatl 3,0
|
|
||||||
|
|
||||||
mtmsr 8
|
|
||||||
sync
|
|
||||||
blr
|
|
||||||
|
|
||||||
// unsigned int getsdr1();
|
|
||||||
.globl getsdr1
|
|
||||||
getsdr1:
|
|
||||||
mfsdr1 3
|
|
||||||
blr
|
|
||||||
|
|
||||||
// void setsdr1(unsigned int sdr);
|
|
||||||
.globl setsdr1
|
|
||||||
setsdr1:
|
|
||||||
sync
|
|
||||||
mtsdr1 3
|
|
||||||
sync
|
|
||||||
blr
|
|
||||||
|
|
||||||
// unsigned int getsr(int sr);
|
|
||||||
.globl getsr
|
|
||||||
getsr:
|
|
||||||
mfsrin 3,3
|
|
||||||
blr
|
|
||||||
|
|
||||||
// unsigned int getmsr();
|
|
||||||
.globl getmsr
|
|
||||||
getmsr:
|
|
||||||
mfmsr 3
|
|
||||||
blr
|
|
||||||
|
|
||||||
// void setmsr(unsigned int msr);
|
|
||||||
.globl setmsr
|
|
||||||
setmsr:
|
|
||||||
mtmsr 3
|
|
||||||
blr
|
|
||||||
|
|
||||||
.globl system_reset_exception_entry
|
|
||||||
system_reset_exception_entry:
|
|
||||||
lis 3,system_reset_exception@ha
|
|
||||||
ori 3,3,system_reset_exception@l
|
|
||||||
mtlr 3
|
|
||||||
blr
|
|
||||||
.globl system_reset_exception_entry_end
|
|
||||||
system_reset_exception_entry_end:
|
|
||||||
|
|
||||||
.globl machine_check_exception_entry
|
|
||||||
machine_check_exception_entry:
|
|
||||||
lis 3,machine_check_exception@ha
|
|
||||||
ori 3,3,machine_check_exception@l
|
|
||||||
mtlr 3
|
|
||||||
blr
|
|
||||||
.globl machine_check_exception_entry_end
|
|
||||||
machine_check_exception_entry_end:
|
|
||||||
|
|
||||||
.globl dsi_exception_entry
|
|
||||||
dsi_exception_entry:
|
|
||||||
lis 3,dsi_exception@ha
|
|
||||||
ori 3,3,dsi_exception@l
|
|
||||||
mtlr 3
|
|
||||||
blr
|
|
||||||
.globl dsi_exception_entry_end
|
|
||||||
dsi_exception_entry_end:
|
|
||||||
|
|
||||||
.globl isi_exception_entry
|
|
||||||
isi_exception_entry:
|
|
||||||
lis 3,isi_exception@ha
|
|
||||||
ori 3,3,isi_exception@l
|
|
||||||
mtlr 3
|
|
||||||
blr
|
|
||||||
.globl isi_exception_entry_end
|
|
||||||
isi_exception_entry_end:
|
|
||||||
|
|
||||||
.globl external_interrupt_entry
|
|
||||||
external_interrupt_entry:
|
|
||||||
lis 3,external_interrupt@ha
|
|
||||||
ori 3,3,external_interrupt@l
|
|
||||||
mtlr 3
|
|
||||||
blr
|
|
||||||
.globl external_interrupt_entry_end
|
|
||||||
external_interrupt_entry_end:
|
|
||||||
|
|
||||||
.globl alignment_exception_entry
|
|
||||||
alignment_exception_entry:
|
|
||||||
lis 3,alignment_exception@ha
|
|
||||||
ori 3,3,alignment_exception@l
|
|
||||||
mtlr 3
|
|
||||||
blr
|
|
||||||
.globl alignment_exception_entry_end
|
|
||||||
alignment_exception_entry_end:
|
|
||||||
|
|
||||||
.globl program_exception_entry
|
|
||||||
program_exception_entry:
|
|
||||||
lis 3,program_exception@ha
|
|
||||||
ori 3,3,program_exception@l
|
|
||||||
mtlr 3
|
|
||||||
blr
|
|
||||||
.globl program_exception_entry_end
|
|
||||||
program_exception_entry_end:
|
|
||||||
|
|
||||||
.globl decrementer_exception_entry
|
|
||||||
decrementer_exception_entry:
|
|
||||||
lis 3,decrementer_exception@ha
|
|
||||||
ori 3,3,decrementer_exception@l
|
|
||||||
mtlr 3
|
|
||||||
blr
|
|
||||||
.globl decrementer_exception_entry_end
|
|
||||||
decrementer_exception_entry_end:
|
|
||||||
|
|
||||||
.globl system_call_exception_entry
|
|
||||||
system_call_exception_entry:
|
|
||||||
lis 3,system_call_exception@ha
|
|
||||||
ori 3,3,system_call_exception@l
|
|
||||||
mtlr 3
|
|
||||||
blr
|
|
||||||
.globl system_call_exception_entry_end
|
|
||||||
system_call_exception_entry_end:
|
|
||||||
|
|
||||||
.globl trace_exception_entry
|
|
||||||
trace_exception_entry:
|
|
||||||
lis 3,trace_exception@ha
|
|
||||||
ori 3,3,trace_exception@l
|
|
||||||
mtlr 3
|
|
||||||
blr
|
|
||||||
.globl trace_exception_entry_end
|
|
||||||
trace_exception_entry_end:
|
|
||||||
|
|
||||||
.globl floating_point_assist_exception_entry
|
|
||||||
floating_point_assist_exception_entry:
|
|
||||||
lis 3,floating_point_assist_exception@ha
|
|
||||||
ori 3,3,floating_point_assist_exception@l
|
|
||||||
mtlr 3
|
|
||||||
blr
|
|
||||||
.globl floating_point_assist_exception_entry_end
|
|
||||||
floating_point_assist_exception_entry_end:
|
|
||||||
@@ -1,141 +0,0 @@
|
|||||||
/*
|
|
||||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
|
||||||
** Distributed under the terms of the NewOS License.
|
|
||||||
*/
|
|
||||||
#include <boot/stage2.h>
|
|
||||||
#include "stage2_priv.h"
|
|
||||||
|
|
||||||
void system_reset_exception_entry();
|
|
||||||
extern int system_reset_exception_entry_end;
|
|
||||||
void machine_check_exception_entry();
|
|
||||||
extern int machine_check_exception_entry_end;
|
|
||||||
void dsi_exception_entry();
|
|
||||||
extern int dsi_exception_entry_end;
|
|
||||||
void isi_exception_entry();
|
|
||||||
extern int isi_exception_entry_end;
|
|
||||||
void external_interrupt_entry();
|
|
||||||
extern int external_interrupt_entry_end;
|
|
||||||
void alignment_exception_entry();
|
|
||||||
extern int alignment_exception_entry_end;
|
|
||||||
void program_exception_entry();
|
|
||||||
extern int program_exception_entry_end;
|
|
||||||
void decrementer_exception_entry();
|
|
||||||
extern int decrementer_exception_entry_end;
|
|
||||||
void system_call_exception_entry();
|
|
||||||
extern int system_call_exception_entry_end;
|
|
||||||
void trace_exception_entry();
|
|
||||||
extern int trace_exception_entry_end;
|
|
||||||
void floating_point_assist_exception_entry();
|
|
||||||
extern int floating_point_assist_exception_entry_end;
|
|
||||||
|
|
||||||
void s2_faults_init(kernel_args *ka)
|
|
||||||
{
|
|
||||||
printf("s2_faults_init: entry\n");
|
|
||||||
setmsr(getmsr() & ~0x00000040); // make it look for exceptions in the zero page
|
|
||||||
printf("s2_faults_init: foo\n");
|
|
||||||
printf("0x%x\n", *(unsigned int *)0x00000100);
|
|
||||||
printf("0x%x\n", *(unsigned int *)0x00000104);
|
|
||||||
printf("0x%x\n", *(unsigned int *)0x00000108);
|
|
||||||
printf("0x%x\n", *(unsigned int *)0x0000010c);
|
|
||||||
printf("%d\n", (int)&system_reset_exception_entry_end - (int)&system_reset_exception_entry);
|
|
||||||
memcpy((void *)0x00000100, &system_reset_exception_entry,
|
|
||||||
(int)&system_reset_exception_entry_end - (int)&system_reset_exception_entry);
|
|
||||||
printf("%d\n",
|
|
||||||
memcmp((void *)0x00000100, &system_reset_exception_entry,
|
|
||||||
(int)&system_reset_exception_entry_end - (int)&system_reset_exception_entry));
|
|
||||||
printf("0x%x\n", *(unsigned int *)0x00000100);
|
|
||||||
printf("0x%x\n", *(unsigned int *)0x00000104);
|
|
||||||
printf("0x%x\n", *(unsigned int *)0x00000108);
|
|
||||||
printf("0x%x\n", *(unsigned int *)0x0000010c);
|
|
||||||
memcpy((void *)0x00000200, &machine_check_exception_entry,
|
|
||||||
(int)&machine_check_exception_entry_end - (int)&machine_check_exception_entry);
|
|
||||||
memcpy((void *)0x00000300, &dsi_exception_entry,
|
|
||||||
(int)&dsi_exception_entry_end - (int)&dsi_exception_entry);
|
|
||||||
memcpy((void *)0x00000400, &isi_exception_entry,
|
|
||||||
(int)&isi_exception_entry_end - (int)&isi_exception_entry);
|
|
||||||
memcpy((void *)0x00000500, &external_interrupt_entry,
|
|
||||||
(int)&external_interrupt_entry_end - (int)&external_interrupt_entry);
|
|
||||||
memcpy((void *)0x00000600, &alignment_exception_entry,
|
|
||||||
(int)&alignment_exception_entry_end - (int)&alignment_exception_entry);
|
|
||||||
memcpy((void *)0x00000700, &program_exception_entry,
|
|
||||||
(int)&program_exception_entry_end - (int)&program_exception_entry);
|
|
||||||
memcpy((void *)0x00000900, &decrementer_exception_entry,
|
|
||||||
(int)&decrementer_exception_entry_end - (int)&decrementer_exception_entry);
|
|
||||||
memcpy((void *)0x00000c00, &system_call_exception_entry,
|
|
||||||
(int)&system_call_exception_entry_end - (int)&system_call_exception_entry);
|
|
||||||
memcpy((void *)0x00000d00, &trace_exception_entry,
|
|
||||||
(int)&trace_exception_entry_end - (int)&trace_exception_entry);
|
|
||||||
memcpy((void *)0x00000e00, &floating_point_assist_exception_entry,
|
|
||||||
(int)&floating_point_assist_exception_entry_end - (int)&floating_point_assist_exception_entry);
|
|
||||||
printf("s2_faults_init: exit\n");
|
|
||||||
|
|
||||||
syncicache(0, 0x1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
void system_reset_exception()
|
|
||||||
{
|
|
||||||
printf("system_reset_exception\n");
|
|
||||||
for(;;);
|
|
||||||
}
|
|
||||||
|
|
||||||
void machine_check_exception()
|
|
||||||
{
|
|
||||||
printf("machine_check_exception\n");
|
|
||||||
for(;;);
|
|
||||||
}
|
|
||||||
|
|
||||||
void dsi_exception()
|
|
||||||
{
|
|
||||||
*(int *)0x16008190 = 0xffffff;
|
|
||||||
printf("dsi_exception\n");
|
|
||||||
for(;;);
|
|
||||||
}
|
|
||||||
|
|
||||||
void isi_exception()
|
|
||||||
{
|
|
||||||
printf("isi_exception\n");
|
|
||||||
for(;;);
|
|
||||||
}
|
|
||||||
|
|
||||||
void external_interrupt()
|
|
||||||
{
|
|
||||||
printf("external_interrupt\n");
|
|
||||||
for(;;);
|
|
||||||
}
|
|
||||||
|
|
||||||
void alignment_exception()
|
|
||||||
{
|
|
||||||
printf("alignment_exception\n");
|
|
||||||
for(;;);
|
|
||||||
}
|
|
||||||
|
|
||||||
void program_exception()
|
|
||||||
{
|
|
||||||
printf("program_exception\n");
|
|
||||||
for(;;);
|
|
||||||
}
|
|
||||||
|
|
||||||
void decrementer_exception()
|
|
||||||
{
|
|
||||||
printf("decrementer_exception\n");
|
|
||||||
for(;;);
|
|
||||||
}
|
|
||||||
|
|
||||||
void system_call_exception()
|
|
||||||
{
|
|
||||||
printf("system_call_exception\n");
|
|
||||||
for(;;);
|
|
||||||
}
|
|
||||||
|
|
||||||
void trace_exception()
|
|
||||||
{
|
|
||||||
printf("trace_exception\n");
|
|
||||||
for(;;);
|
|
||||||
}
|
|
||||||
|
|
||||||
void floating_point_assist_exception()
|
|
||||||
{
|
|
||||||
printf("floating_point_assist_exception\n");
|
|
||||||
for(;;);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,554 +0,0 @@
|
|||||||
/*
|
|
||||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
|
||||||
** Distributed under the terms of the NewOS License.
|
|
||||||
*/
|
|
||||||
#include <boot/stage2.h>
|
|
||||||
#include <kernel/kernel.h>
|
|
||||||
#include <arch/cpu.h>
|
|
||||||
#include <libc/string.h>
|
|
||||||
#include "stage2_priv.h"
|
|
||||||
|
|
||||||
static unsigned int primary_hash(unsigned int vsid, unsigned int vaddr);
|
|
||||||
static unsigned int secondary_hash(unsigned int primary_hash);
|
|
||||||
|
|
||||||
static struct ppc_pteg *ptable = 0;
|
|
||||||
static int ptable_size = 0;
|
|
||||||
static unsigned int ptable_hash_mask = 0;
|
|
||||||
|
|
||||||
|
|
||||||
static unsigned long total_ram_size = 0;
|
|
||||||
|
|
||||||
static void print_pte(struct ppc_pte *e);
|
|
||||||
|
|
||||||
static bool does_intersect(unsigned long base1, unsigned long len1, unsigned long base2, unsigned long len2)
|
|
||||||
{
|
|
||||||
unsigned long end1 = base1 + len1;
|
|
||||||
unsigned long end2 = base2 + len2;
|
|
||||||
|
|
||||||
if(base2 >= base1 && base2 <= end1)
|
|
||||||
return true; // base2 is inside first range
|
|
||||||
if(end2 >= base1 && end2 <= end1)
|
|
||||||
return true; // end of second range inside first range
|
|
||||||
if(base1 >= base2 && base1 <= end2)
|
|
||||||
return true; // base1 is inside second range
|
|
||||||
if(end1 >= base2 && end1 <= end2)
|
|
||||||
return true; // end of first range inside second range
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void find_phys_memory_map(kernel_args *ka)
|
|
||||||
{
|
|
||||||
int handle;
|
|
||||||
unsigned int i;
|
|
||||||
struct mem_region {
|
|
||||||
unsigned long pa;
|
|
||||||
int len;
|
|
||||||
} mem_regions[33];
|
|
||||||
unsigned int mem_regions_len = 0;
|
|
||||||
|
|
||||||
// get the physical memory map of the system
|
|
||||||
handle = of_finddevice("/memory");
|
|
||||||
memset(mem_regions, 0, sizeof(mem_regions));
|
|
||||||
mem_regions_len = of_getprop(handle, "reg", mem_regions, sizeof(mem_regions[0]) * 32);
|
|
||||||
mem_regions_len /= sizeof(struct mem_region);
|
|
||||||
|
|
||||||
// copy these regions over to the kernel args structure
|
|
||||||
ka->num_phys_mem_ranges = 0;
|
|
||||||
for(i=0; i<mem_regions_len; i++) {
|
|
||||||
if(mem_regions[i].len > 0) {
|
|
||||||
total_ram_size += mem_regions[i].len;
|
|
||||||
if(i > 0) {
|
|
||||||
if(mem_regions[i].pa == ka->phys_mem_range[ka->num_phys_mem_ranges-1].start + ka->phys_mem_range[ka->num_phys_mem_ranges-1].size) {
|
|
||||||
// this range just extends the old one
|
|
||||||
ka->phys_mem_range[ka->num_phys_mem_ranges-1].size += mem_regions[i].len;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ka->phys_mem_range[ka->num_phys_mem_ranges].start = mem_regions[i].pa;
|
|
||||||
ka->phys_mem_range[ka->num_phys_mem_ranges].size = mem_regions[i].len;
|
|
||||||
ka->num_phys_mem_ranges++;
|
|
||||||
if(ka->num_phys_mem_ranges == MAX_PHYS_MEM_ADDR_RANGE) {
|
|
||||||
printf("too many physical memory maps, increase MAX_PHYS_MEM_ADDR_RANGE\n");
|
|
||||||
for(;;);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(i=0; i<ka->num_phys_mem_ranges; i++) {
|
|
||||||
printf("phys map %d: pa 0x%lx, len 0x%lx\n", i, ka->phys_mem_range[i].start, ka->phys_mem_range[i].size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool is_in_phys_mem(kernel_args *ka, unsigned long addr)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
for(i = 0; i < ka->num_phys_mem_ranges; i++) {
|
|
||||||
if(does_intersect(ka->phys_mem_range[i].start, ka->phys_mem_range[i].size, addr, 0))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mark_used_phys_mem_range(kernel_args *ka, unsigned long base, unsigned long len)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
unsigned long start;
|
|
||||||
|
|
||||||
base = ROUNDOWN(base, PAGE_SIZE);
|
|
||||||
len = ROUNDUP(len, PAGE_SIZE);
|
|
||||||
start = base;
|
|
||||||
|
|
||||||
while(start < base + len){
|
|
||||||
// cycle through the list of physical runs of used pages,
|
|
||||||
// seeing if start will intersect one of them
|
|
||||||
for(i = 0; i < ka->num_phys_alloc_ranges; i++) {
|
|
||||||
if(start == ka->phys_alloc_range[i].start + ka->phys_alloc_range[i].size) {
|
|
||||||
// it will extend it
|
|
||||||
ka->phys_alloc_range[i].size += PAGE_SIZE;
|
|
||||||
goto next_page;
|
|
||||||
}
|
|
||||||
if(start + PAGE_SIZE == ka->phys_alloc_range[i].start) {
|
|
||||||
// it will prepend it
|
|
||||||
ka->phys_alloc_range[i].start = start;
|
|
||||||
ka->phys_alloc_range[i].size += PAGE_SIZE;
|
|
||||||
goto next_page;
|
|
||||||
}
|
|
||||||
if(does_intersect(ka->phys_alloc_range[i].start, ka->phys_alloc_range[i].size, start, PAGE_SIZE)) {
|
|
||||||
// it's off in the middle of this range, skip it
|
|
||||||
goto next_page;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// didn't find it in one of the existing ranges, must need to start a new one
|
|
||||||
if(ka->num_phys_alloc_ranges >= MAX_PHYS_ALLOC_ADDR_RANGE) {
|
|
||||||
printf("mark_used_phys_mem_range: MAX_PHYS_ALLOC_ADDR_RANGE (%d) too small\n", MAX_PHYS_ALLOC_ADDR_RANGE);
|
|
||||||
for(;;);
|
|
||||||
}
|
|
||||||
|
|
||||||
// create a new allocated range
|
|
||||||
ka->phys_alloc_range[ka->num_phys_alloc_ranges].start = start;
|
|
||||||
ka->phys_alloc_range[ka->num_phys_alloc_ranges].size = PAGE_SIZE;
|
|
||||||
ka->num_phys_alloc_ranges++;
|
|
||||||
|
|
||||||
next_page:
|
|
||||||
start += PAGE_SIZE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void find_used_phys_memory_map(kernel_args *ka)
|
|
||||||
{
|
|
||||||
int handle;
|
|
||||||
unsigned int i;
|
|
||||||
struct translation_map {
|
|
||||||
unsigned long va;
|
|
||||||
int len;
|
|
||||||
unsigned long pa;
|
|
||||||
int mode;
|
|
||||||
} memmap[64];
|
|
||||||
unsigned int translation_map_len = 0;
|
|
||||||
|
|
||||||
ka->num_phys_alloc_ranges = 0;
|
|
||||||
|
|
||||||
// get the current translation map of the system,
|
|
||||||
// to find how much memory was mapped to load the stage1 and bootdir
|
|
||||||
handle = of_finddevice("/chosen");
|
|
||||||
of_getprop(handle, "mmu", &handle, sizeof(handle));
|
|
||||||
handle = of_instance_to_package(handle);
|
|
||||||
memset(&memmap, 0, sizeof(memmap));
|
|
||||||
translation_map_len = of_getprop(handle, "translations", memmap, sizeof(memmap));
|
|
||||||
translation_map_len /= sizeof(struct translation_map);
|
|
||||||
for(i=0; i<translation_map_len; i++) {
|
|
||||||
if(is_in_phys_mem(ka, memmap[i].va)) {
|
|
||||||
printf("package loaded at pa 0x%lx va 0x%lx, len 0x%x\n", memmap[i].pa, memmap[i].va, memmap[i].len);
|
|
||||||
// we found the translation that covers the loaded package. Save this.
|
|
||||||
mark_used_phys_mem_range(ka, memmap[i].pa, memmap[i].len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(i=0; i<ka->num_phys_alloc_ranges; i++) {
|
|
||||||
printf("phys alloc map %d: pa 0x%lx, len 0x%lx\n", i, ka->phys_alloc_range[i].start, ka->phys_alloc_range[i].size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mark_used_virt_mem_range(kernel_args *ka, unsigned long base, unsigned long len)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
unsigned long start;
|
|
||||||
|
|
||||||
base = ROUNDOWN(base, PAGE_SIZE);
|
|
||||||
len = ROUNDUP(len, PAGE_SIZE);
|
|
||||||
start = base;
|
|
||||||
|
|
||||||
while(start < base + len) {
|
|
||||||
// cycle through the list of virtual runs of used pages,
|
|
||||||
// seeing if start will intersect one of them
|
|
||||||
for(i = 0; i < ka->num_virt_alloc_ranges; i++) {
|
|
||||||
if(start == ka->virt_alloc_range[i].start + ka->virt_alloc_range[i].size) {
|
|
||||||
// it will extend it
|
|
||||||
ka->virt_alloc_range[i].size += PAGE_SIZE;
|
|
||||||
goto next_page;
|
|
||||||
}
|
|
||||||
if(start + PAGE_SIZE == ka->virt_alloc_range[i].start) {
|
|
||||||
// it will prepend it
|
|
||||||
ka->virt_alloc_range[i].start = start;
|
|
||||||
ka->virt_alloc_range[i].size += PAGE_SIZE;
|
|
||||||
goto next_page;
|
|
||||||
}
|
|
||||||
if(does_intersect(ka->virt_alloc_range[i].start, ka->virt_alloc_range[i].size, start, PAGE_SIZE)) {
|
|
||||||
// it's off in the middle of this range, skip it
|
|
||||||
goto next_page;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// didn't find it in one of the existing ranges, must need to start a new one
|
|
||||||
if(ka->num_virt_alloc_ranges >= MAX_VIRT_ALLOC_ADDR_RANGE) {
|
|
||||||
printf("mark_used_virt_mem_range: MAX_VIRT_ALLOC_ADDR_RANGE (%d) too small\n", MAX_VIRT_ALLOC_ADDR_RANGE);
|
|
||||||
for(;;);
|
|
||||||
}
|
|
||||||
|
|
||||||
// create a new allocated range
|
|
||||||
ka->virt_alloc_range[ka->num_virt_alloc_ranges].start = start;
|
|
||||||
ka->virt_alloc_range[ka->num_virt_alloc_ranges].size = PAGE_SIZE;
|
|
||||||
ka->num_virt_alloc_ranges++;
|
|
||||||
|
|
||||||
next_page:
|
|
||||||
start += PAGE_SIZE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long mmu_allocate_page(kernel_args *ka)
|
|
||||||
{
|
|
||||||
unsigned long page;
|
|
||||||
|
|
||||||
if(ka->num_phys_alloc_ranges == 0) {
|
|
||||||
// no physical allocated ranges, start one
|
|
||||||
page = ka->phys_mem_range[0].start;
|
|
||||||
mark_used_phys_mem_range(ka, page, PAGE_SIZE);
|
|
||||||
return page;
|
|
||||||
}
|
|
||||||
|
|
||||||
// allocate from the first allocated physical range
|
|
||||||
page = ka->phys_alloc_range[0].start + ka->phys_alloc_range[0].size;
|
|
||||||
ka->phys_alloc_range[0].size += PAGE_SIZE;
|
|
||||||
|
|
||||||
// XXX check for validity better
|
|
||||||
|
|
||||||
return page;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void tlbia()
|
|
||||||
{
|
|
||||||
unsigned long i;
|
|
||||||
|
|
||||||
asm volatile("sync");
|
|
||||||
for(i=0; i< 0x40000; i += 0x1000) {
|
|
||||||
asm volatile("tlbie %0" :: "r" (i));
|
|
||||||
asm volatile("eieio");
|
|
||||||
asm volatile("sync");
|
|
||||||
}
|
|
||||||
asm volatile("tlbsync");
|
|
||||||
asm volatile("sync");
|
|
||||||
}
|
|
||||||
|
|
||||||
#define CACHELINE 32
|
|
||||||
|
|
||||||
void syncicache(void *address, int len)
|
|
||||||
{
|
|
||||||
int l, off;
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
off = (unsigned int)address & (CACHELINE - 1);
|
|
||||||
len += off;
|
|
||||||
|
|
||||||
l = len;
|
|
||||||
p = (char *)address - off;
|
|
||||||
do {
|
|
||||||
asm volatile ("dcbst 0,%0" :: "r"(p));
|
|
||||||
p += CACHELINE;
|
|
||||||
} while((l -= CACHELINE) > 0);
|
|
||||||
asm volatile ("sync");
|
|
||||||
p = (char *)address - off;
|
|
||||||
do {
|
|
||||||
asm volatile ("icbi 0,%0" :: "r"(p));
|
|
||||||
p += CACHELINE;
|
|
||||||
} while((len -= CACHELINE) > 0);
|
|
||||||
asm volatile ("sync");
|
|
||||||
asm volatile ("isync");
|
|
||||||
}
|
|
||||||
|
|
||||||
int s2_mmu_init(kernel_args *ka)
|
|
||||||
{
|
|
||||||
unsigned int ibats[8];
|
|
||||||
unsigned int dbats[8];
|
|
||||||
unsigned long top_ram = 0;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
ka->num_virt_alloc_ranges = 0;
|
|
||||||
|
|
||||||
// figure out where physical memory is and what is being used
|
|
||||||
find_phys_memory_map(ka);
|
|
||||||
find_used_phys_memory_map(ka);
|
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// find the largest address of physical memory, but with a max of 256 MB,
|
|
||||||
// so it'll be within our 256 MB BAT window
|
|
||||||
for(i=0; i<ka->num_phys_mem_ranges; i++) {
|
|
||||||
if(ka->phys_mem_range[i].start + ka->phys_mem_range[i].size > top_ram) {
|
|
||||||
if(ka->phys_mem_range[i].start + ka->phys_mem_range[i].size > 256*1024*1024) {
|
|
||||||
if(ka->phys_mem_range[i].start < 256*1024*1024) {
|
|
||||||
top_ram = 256*1024*1024;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
top_ram = ka->phys_mem_range[i].start + ka->phys_mem_range[i].size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("top of ram (but under 256MB) is 0x%x\n", top_ram);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// figure the size of the new pagetable, as recommended by Motorola
|
|
||||||
if(total_ram_size <= 8*1024*1024) {
|
|
||||||
ptable_size = 64*1024;
|
|
||||||
} else if(total_ram_size <= 16*1024*1024) {
|
|
||||||
ptable_size = 128*1024;
|
|
||||||
} else if(total_ram_size <= 32*1024*1024) {
|
|
||||||
ptable_size = 256*1024;
|
|
||||||
} else if(total_ram_size <= 64*1024*1024) {
|
|
||||||
ptable_size = 512*1024;
|
|
||||||
} else if(total_ram_size <= 128*1024*1024) {
|
|
||||||
ptable_size = 1024*1024;
|
|
||||||
} else if(total_ram_size <= 256*1024*1024) {
|
|
||||||
ptable_size = 2*1024*1024;
|
|
||||||
} else if(total_ram_size <= 512*1024*1024) {
|
|
||||||
ptable_size = 4*1024*1024;
|
|
||||||
} else if(total_ram_size <= 1024*1024*1024) {
|
|
||||||
ptable_size = 8*1024*1024;
|
|
||||||
} else if(total_ram_size <= 2*1024*1024*1024UL) {
|
|
||||||
ptable_size = 16*1024*1024;
|
|
||||||
} else {
|
|
||||||
ptable_size = 32*1024*1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
// figure out where to put the page table
|
|
||||||
printf("allocating a page table using claim\n");
|
|
||||||
ptable_hash_mask = (ptable_size >> 6) - 1;
|
|
||||||
ptable = (struct ppc_pteg *)of_claim(0, ptable_size, ptable_size);
|
|
||||||
printf("ptable at pa 0x%x, size 0x%x\n", ptable, ptable_size);
|
|
||||||
printf("mask = 0x%x\n", ptable_hash_mask);
|
|
||||||
|
|
||||||
// mark it used
|
|
||||||
mark_used_phys_mem_range(ka, (unsigned long)ptable, ptable_size);
|
|
||||||
|
|
||||||
// save it's new location in the kernel args
|
|
||||||
ka->arch_args.page_table.start = (unsigned long)ptable;
|
|
||||||
ka->arch_args.page_table.size = ptable_size;
|
|
||||||
ka->arch_args.page_table_mask = ptable_hash_mask;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
{
|
|
||||||
struct ppc_pteg *old_ptable;
|
|
||||||
int j;
|
|
||||||
|
|
||||||
printf("sdr1 = 0x%x\n", getsdr1());
|
|
||||||
|
|
||||||
old_ptable = (struct ppc_pteg *)((unsigned int)getsdr1() & 0xffff0000);
|
|
||||||
printf("old_ptable %p\n", old_ptable);
|
|
||||||
for(i=0; i< (64*1024) >> 6 ; i++) {
|
|
||||||
for(j=0; j< 8; j++)
|
|
||||||
if(old_ptable[i].pte[j].v && old_ptable[i].pte[j].vsid == 0)
|
|
||||||
print_pte(&old_ptable[i].pte[j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
unsigned int sp;
|
|
||||||
asm volatile("mr %0,1" : "=r"(sp));
|
|
||||||
printf("sp = 0x%x\n", sp);
|
|
||||||
|
|
||||||
/* set up the new BATs */
|
|
||||||
getibats(ibats);
|
|
||||||
getdbats(dbats);
|
|
||||||
|
|
||||||
for(i=0; i<8; i++) {
|
|
||||||
ibats[i] = 0;
|
|
||||||
dbats[i] = 0;
|
|
||||||
}
|
|
||||||
// identity map the first 256MB of RAM
|
|
||||||
dbats[0] = ibats[0] = BATU_LEN_256M | BATU_VS;
|
|
||||||
dbats[1] = ibats[1] = BATL_MC | BATL_PP_RW;
|
|
||||||
|
|
||||||
// map the framebuffer using a BAT to 256MB
|
|
||||||
{
|
|
||||||
unsigned int framebuffer_phys = ka->fb.mapping.start & ~((16*1024*1024) - 1);
|
|
||||||
|
|
||||||
dbats[2] = ibats[2] = 0x10000000 | BATU_LEN_16M | BATU_VS;
|
|
||||||
dbats[3] = ibats[3] = framebuffer_phys | BATL_CI | BATL_PP_RW;
|
|
||||||
printf("remapping framebuffer at pa 0x%x to va 0x%x using BAT\n",
|
|
||||||
ka->fb.mapping.start, 0x10000000 + ka->fb.mapping.start - framebuffer_phys);
|
|
||||||
s2_change_framebuffer_addr(ka, 0x10000000 + ka->fb.mapping.start - framebuffer_phys);
|
|
||||||
}
|
|
||||||
setibats(ibats);
|
|
||||||
setdbats(dbats);
|
|
||||||
|
|
||||||
tlbia();
|
|
||||||
|
|
||||||
printf("unsetting the old page table\n");
|
|
||||||
setsdr1(0);
|
|
||||||
tlbia();
|
|
||||||
|
|
||||||
printf("memsetting new pagetable\n");
|
|
||||||
memset(ptable, 0, ptable_size);
|
|
||||||
|
|
||||||
printf("done\n");
|
|
||||||
|
|
||||||
printf("setting up the 16 segment registers\n");
|
|
||||||
// set up the segment registers
|
|
||||||
for(i=0; i<16; i++) {
|
|
||||||
setsr(i * 0x10000000, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("done, setting sdr1\n");
|
|
||||||
setsdr1(((unsigned int)ptable & 0xffff0000) | (ptable_hash_mask >> 10));
|
|
||||||
tlbia();
|
|
||||||
printf("sdr1 = 0x%x\n", getsdr1());
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
mmu_map_page(0x96008000, 0x96008000);
|
|
||||||
mmu_map_page(0x96009000, 0x96009000);
|
|
||||||
mmu_map_page(0x9600a000, 0x9600a000);
|
|
||||||
mmu_map_page(0x96008000, 0x30000000);
|
|
||||||
|
|
||||||
printf("testing...\n");
|
|
||||||
printf("hello\n");
|
|
||||||
printf("%d\n", *(int *)0x30000000);
|
|
||||||
printf("%d\n", *(int *)0x96008000);
|
|
||||||
|
|
||||||
*(int *)0x30000000 = 0x99;
|
|
||||||
printf("%d\n", *(int *)0x30000000);
|
|
||||||
printf("%d\n", *(int *)0x96008000);
|
|
||||||
|
|
||||||
printf("hello2\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
printf("done\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int s2_mmu_remap_pagetable(kernel_args *ka)
|
|
||||||
{
|
|
||||||
unsigned long i;
|
|
||||||
unsigned long new_ptable;
|
|
||||||
|
|
||||||
// find a new spot to allocate the page table
|
|
||||||
// XXX make better
|
|
||||||
new_ptable = ka->virt_alloc_range[0].start + ka->virt_alloc_range[0].size;
|
|
||||||
|
|
||||||
for(i = 0; i < ptable_size; i += PAGE_SIZE) {
|
|
||||||
mmu_map_page(ka, ka->arch_args.page_table.start + i, new_ptable + i, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
ka->arch_args.page_table_virt.start = new_ptable;
|
|
||||||
ka->arch_args.page_table_virt.size = ka->arch_args.page_table.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
int s2_mmu_remove_fb_bat_entries(kernel_args *ka)
|
|
||||||
{
|
|
||||||
unsigned int ibat[8];
|
|
||||||
unsigned int dbat[8];
|
|
||||||
|
|
||||||
// zero out the 2nd bat entry, used to map the framebuffer
|
|
||||||
getibats(ibat);
|
|
||||||
getdbats(dbat);
|
|
||||||
ibat[2] = ibat[3] = dbat[2] = dbat[3] = 0;
|
|
||||||
setibats(ibat);
|
|
||||||
setdbats(dbat);
|
|
||||||
|
|
||||||
return NO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void print_pte(struct ppc_pte *e)
|
|
||||||
{
|
|
||||||
printf("entry %p: ", e);
|
|
||||||
printf("v %d ", e->v);
|
|
||||||
if(e->v) {
|
|
||||||
printf("vsid 0x%x ", e->vsid);
|
|
||||||
printf("hash %d ", e->hash);
|
|
||||||
printf("api 0x%x ", e->api);
|
|
||||||
|
|
||||||
printf("ppn 0x%x ", e->ppn);
|
|
||||||
printf("r %d ", e->r);
|
|
||||||
printf("c %d ", e->c);
|
|
||||||
printf("wimg 0x%x ", e->wimg);
|
|
||||||
printf("pp 0x%x ", e->pp);
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void mmu_map_page(kernel_args *ka, unsigned long pa, unsigned long va, bool cached)
|
|
||||||
{
|
|
||||||
unsigned int hash;
|
|
||||||
struct ppc_pteg *pteg;
|
|
||||||
int i;
|
|
||||||
unsigned int vsid;
|
|
||||||
|
|
||||||
// mark it used if this is in the kernel area
|
|
||||||
if(va >= KERNEL_BASE) {
|
|
||||||
mark_used_virt_mem_range(ka, va, PAGE_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// lookup the vsid based off the va
|
|
||||||
vsid = getsr(va) & 0xffffff;
|
|
||||||
|
|
||||||
// printf("mmu_map_page: vsid %d, pa 0x%x, va 0x%x\n", vsid, pa, va);
|
|
||||||
|
|
||||||
hash = primary_hash(vsid, va);
|
|
||||||
// printf("hash = 0x%x\n", hash);
|
|
||||||
|
|
||||||
pteg = &ptable[hash];
|
|
||||||
// printf("pteg @ 0x%x\n", pteg);
|
|
||||||
|
|
||||||
// search for the first free slot for this pte
|
|
||||||
for(i=0; i<8; i++) {
|
|
||||||
// printf("trying pteg[%i]\n", i);
|
|
||||||
if(pteg->pte[i].v == 0) {
|
|
||||||
// upper word
|
|
||||||
pteg->pte[i].ppn = pa / PAGE_SIZE;
|
|
||||||
pteg->pte[i].unused = 0;
|
|
||||||
pteg->pte[i].r = 0;
|
|
||||||
pteg->pte[i].c = 0;
|
|
||||||
pteg->pte[i].wimg = cached ? 0 : (1 << 3);
|
|
||||||
pteg->pte[i].unused1 = 0;
|
|
||||||
pteg->pte[i].pp = 0x2; // RW
|
|
||||||
asm volatile("eieio");
|
|
||||||
// lower word
|
|
||||||
pteg->pte[i].vsid = vsid;
|
|
||||||
pteg->pte[i].hash = 0; // primary
|
|
||||||
pteg->pte[i].api = (va >> 22) & 0x3f;
|
|
||||||
pteg->pte[i].v = 1;
|
|
||||||
tlbia();
|
|
||||||
// printf("set pteg to ");
|
|
||||||
// print_pte(&pteg->pte[i]);
|
|
||||||
// printf("set pteg to 0x%x 0x%x\n", *((int *)&pteg->pte[i]), *(((int *)&pteg->pte[i])+1));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned int primary_hash(unsigned int vsid, unsigned int vaddr)
|
|
||||||
{
|
|
||||||
unsigned int page_index;
|
|
||||||
|
|
||||||
vsid &= 0x7ffff;
|
|
||||||
page_index = (vaddr >> 12) & 0xffff;
|
|
||||||
|
|
||||||
return (vsid ^ page_index) & ptable_hash_mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned int secondary_hash(unsigned int primary_hash)
|
|
||||||
{
|
|
||||||
return ~primary_hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,197 +0,0 @@
|
|||||||
/*
|
|
||||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
|
||||||
** Distributed under the terms of the NewOS License.
|
|
||||||
*/
|
|
||||||
#include <boot/stage2.h>
|
|
||||||
#include "stage2_priv.h"
|
|
||||||
|
|
||||||
static int (*of)(void *) = 0; // openfirmware entry
|
|
||||||
|
|
||||||
int of_init(void *of_entry)
|
|
||||||
{
|
|
||||||
of = of_entry;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int of_open(const char *node_name)
|
|
||||||
{
|
|
||||||
struct {
|
|
||||||
const char *name;
|
|
||||||
int num_args;
|
|
||||||
int num_returns;
|
|
||||||
const char *node_name;
|
|
||||||
int handle;
|
|
||||||
} args;
|
|
||||||
|
|
||||||
args.name = "open";
|
|
||||||
args.num_args = 1;
|
|
||||||
args.num_returns = 1;
|
|
||||||
args.node_name = node_name;
|
|
||||||
|
|
||||||
of(&args);
|
|
||||||
|
|
||||||
return args.handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
int of_finddevice(const char *dev)
|
|
||||||
{
|
|
||||||
struct {
|
|
||||||
const char *name;
|
|
||||||
int num_args;
|
|
||||||
int num_returns;
|
|
||||||
const char *device;
|
|
||||||
int handle;
|
|
||||||
} args;
|
|
||||||
|
|
||||||
args.name = "finddevice";
|
|
||||||
args.num_args = 1;
|
|
||||||
args.num_returns = 1;
|
|
||||||
args.device = dev;
|
|
||||||
|
|
||||||
of(&args);
|
|
||||||
|
|
||||||
return args.handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
int of_instance_to_package(int in_handle)
|
|
||||||
{
|
|
||||||
struct {
|
|
||||||
const char *name;
|
|
||||||
int num_args;
|
|
||||||
int num_returns;
|
|
||||||
int in_handle;
|
|
||||||
int handle;
|
|
||||||
} args;
|
|
||||||
|
|
||||||
args.name = "instance-to-package";
|
|
||||||
args.num_args = 1;
|
|
||||||
args.num_returns = 1;
|
|
||||||
args.in_handle = in_handle;
|
|
||||||
|
|
||||||
of(&args);
|
|
||||||
|
|
||||||
return args.handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
int of_getprop(int handle, const char *prop, void *buf, int buf_len)
|
|
||||||
{
|
|
||||||
struct {
|
|
||||||
const char *name;
|
|
||||||
int num_args;
|
|
||||||
int num_returns;
|
|
||||||
int handle;
|
|
||||||
const char *prop;
|
|
||||||
void *buf;
|
|
||||||
int buf_len;
|
|
||||||
int size;
|
|
||||||
} args;
|
|
||||||
|
|
||||||
args.name = "getprop";
|
|
||||||
args.num_args = 4;
|
|
||||||
args.num_returns = 1;
|
|
||||||
args.handle = handle;
|
|
||||||
args.prop = prop;
|
|
||||||
args.buf = buf;
|
|
||||||
args.buf_len = buf_len;
|
|
||||||
|
|
||||||
of(&args);
|
|
||||||
|
|
||||||
return args.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
int of_setprop(int handle, const char *prop, const void *buf, int buf_len)
|
|
||||||
{
|
|
||||||
struct {
|
|
||||||
const char *name;
|
|
||||||
int num_args;
|
|
||||||
int num_returns;
|
|
||||||
int handle;
|
|
||||||
const char *prop;
|
|
||||||
const void *buf;
|
|
||||||
int buf_len;
|
|
||||||
int size;
|
|
||||||
} args;
|
|
||||||
|
|
||||||
args.name = "setprop";
|
|
||||||
args.num_args = 4;
|
|
||||||
args.num_returns = 1;
|
|
||||||
args.handle = handle;
|
|
||||||
args.prop = prop;
|
|
||||||
args.buf = buf;
|
|
||||||
args.buf_len = buf_len;
|
|
||||||
|
|
||||||
of(&args);
|
|
||||||
|
|
||||||
return args.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
int of_read(int handle, void *buf, int buf_len)
|
|
||||||
{
|
|
||||||
struct {
|
|
||||||
const char *name;
|
|
||||||
int num_args;
|
|
||||||
int num_returns;
|
|
||||||
int handle;
|
|
||||||
void *buf;
|
|
||||||
int buf_len;
|
|
||||||
int size;
|
|
||||||
} args;
|
|
||||||
|
|
||||||
args.name = "read";
|
|
||||||
args.num_args = 3;
|
|
||||||
args.num_returns = 1;
|
|
||||||
args.handle = handle;
|
|
||||||
args.buf = buf;
|
|
||||||
args.buf_len = buf_len;
|
|
||||||
|
|
||||||
of(&args);
|
|
||||||
|
|
||||||
return args.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
int of_write(int handle, void *buf, int buf_len)
|
|
||||||
{
|
|
||||||
struct {
|
|
||||||
const char *name;
|
|
||||||
int num_args;
|
|
||||||
int num_returns;
|
|
||||||
int handle;
|
|
||||||
void *buf;
|
|
||||||
int buf_len;
|
|
||||||
int size;
|
|
||||||
} args;
|
|
||||||
|
|
||||||
args.name = "write";
|
|
||||||
args.num_args = 3;
|
|
||||||
args.num_returns = 1;
|
|
||||||
args.handle = handle;
|
|
||||||
args.buf = buf;
|
|
||||||
args.buf_len = buf_len;
|
|
||||||
|
|
||||||
of(&args);
|
|
||||||
|
|
||||||
return args.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
int of_seek(int handle, long long pos)
|
|
||||||
{
|
|
||||||
struct {
|
|
||||||
const char *name;
|
|
||||||
int num_args;
|
|
||||||
int num_returns;
|
|
||||||
int handle;
|
|
||||||
long long pos;
|
|
||||||
int status;
|
|
||||||
} args;
|
|
||||||
|
|
||||||
args.name= "seek";
|
|
||||||
args.num_args = 3;
|
|
||||||
args.num_returns = 1;
|
|
||||||
args.handle = handle;
|
|
||||||
args.pos = pos;
|
|
||||||
|
|
||||||
of(&args);
|
|
||||||
|
|
||||||
return args.status;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,242 +0,0 @@
|
|||||||
/*
|
|
||||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
|
||||||
** Distributed under the terms of the NewOS License.
|
|
||||||
*/
|
|
||||||
#include <libc/string.h>
|
|
||||||
#include <libc/stdarg.h>
|
|
||||||
#include <libc/printf.h>
|
|
||||||
#include <boot/stage2.h>
|
|
||||||
#include "stage2_priv.h"
|
|
||||||
|
|
||||||
unsigned char FONT[] = {
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */
|
|
||||||
0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, /* '!' */
|
|
||||||
0x00, 0x14, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* '"' */
|
|
||||||
0x00, 0x00, 0x14, 0x14, 0x3e, 0x14, 0x3e, 0x14, 0x14, 0x00, 0x00, 0x00, /* '#' */
|
|
||||||
0x00, 0x00, 0x08, 0x3c, 0x0a, 0x1c, 0x28, 0x1e, 0x08, 0x00, 0x00, 0x00, /* '$' */
|
|
||||||
0x00, 0x00, 0x06, 0x26, 0x10, 0x08, 0x04, 0x32, 0x30, 0x00, 0x00, 0x00, /* '%' */
|
|
||||||
0x00, 0x00, 0x1c, 0x02, 0x02, 0x04, 0x2a, 0x12, 0x2c, 0x00, 0x00, 0x00, /* '&' */
|
|
||||||
0x00, 0x18, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ''' */
|
|
||||||
0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x00, /* '(' */
|
|
||||||
0x02, 0x04, 0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x02, 0x00, /* ')' */
|
|
||||||
0x00, 0x00, 0x00, 0x08, 0x2a, 0x1c, 0x2a, 0x08, 0x00, 0x00, 0x00, 0x00, /* '*' */
|
|
||||||
0x00, 0x00, 0x00, 0x08, 0x08, 0x3e, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* '+' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x08, 0x04, 0x00, /* ',' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* '-' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, /* '.' */
|
|
||||||
0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x00, 0x00, /* '/' */
|
|
||||||
0x00, 0x1c, 0x22, 0x32, 0x2a, 0x26, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /* '0' */
|
|
||||||
0x00, 0x08, 0x0c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, /* '1' */
|
|
||||||
0x00, 0x1c, 0x22, 0x20, 0x10, 0x08, 0x04, 0x02, 0x3e, 0x00, 0x00, 0x00, /* '2' */
|
|
||||||
0x00, 0x1c, 0x22, 0x20, 0x18, 0x20, 0x20, 0x22, 0x1c, 0x00, 0x00, 0x00, /* '3' */
|
|
||||||
0x00, 0x10, 0x18, 0x18, 0x14, 0x14, 0x3e, 0x10, 0x38, 0x00, 0x00, 0x00, /* '4' */
|
|
||||||
0x00, 0x3e, 0x02, 0x02, 0x1e, 0x20, 0x20, 0x22, 0x1c, 0x00, 0x00, 0x00, /* '5' */
|
|
||||||
0x00, 0x18, 0x04, 0x02, 0x1e, 0x22, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /* '6' */
|
|
||||||
0x00, 0x3e, 0x22, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x00, 0x00, 0x00, /* '7' */
|
|
||||||
0x00, 0x1c, 0x22, 0x22, 0x1c, 0x22, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /* '8' */
|
|
||||||
0x00, 0x1c, 0x22, 0x22, 0x22, 0x3c, 0x20, 0x10, 0x0c, 0x00, 0x00, 0x00, /* '9' */
|
|
||||||
0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, /* ':' */
|
|
||||||
0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x08, 0x04, 0x00, /* ';' */
|
|
||||||
0x00, 0x00, 0x00, 0x30, 0x0c, 0x03, 0x0c, 0x30, 0x00, 0x00, 0x00, 0x00, /* '<' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, /* '=' */
|
|
||||||
0x00, 0x00, 0x00, 0x03, 0x0c, 0x30, 0x0c, 0x03, 0x00, 0x00, 0x00, 0x00, /* '>' */
|
|
||||||
0x00, 0x1c, 0x22, 0x20, 0x10, 0x08, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, /* '?' */
|
|
||||||
0x00, 0x00, 0x1c, 0x22, 0x3a, 0x3a, 0x1a, 0x02, 0x1c, 0x00, 0x00, 0x00, /* '@' */
|
|
||||||
0x00, 0x00, 0x08, 0x14, 0x22, 0x22, 0x3e, 0x22, 0x22, 0x00, 0x00, 0x00, /* 'A' */
|
|
||||||
0x00, 0x00, 0x1e, 0x22, 0x22, 0x1e, 0x22, 0x22, 0x1e, 0x00, 0x00, 0x00, /* 'B' */
|
|
||||||
0x00, 0x00, 0x1c, 0x22, 0x02, 0x02, 0x02, 0x22, 0x1c, 0x00, 0x00, 0x00, /* 'C' */
|
|
||||||
0x00, 0x00, 0x0e, 0x12, 0x22, 0x22, 0x22, 0x12, 0x0e, 0x00, 0x00, 0x00, /* 'D' */
|
|
||||||
0x00, 0x00, 0x3e, 0x02, 0x02, 0x1e, 0x02, 0x02, 0x3e, 0x00, 0x00, 0x00, /* 'E' */
|
|
||||||
0x00, 0x00, 0x3e, 0x02, 0x02, 0x1e, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, /* 'F' */
|
|
||||||
0x00, 0x00, 0x1c, 0x22, 0x02, 0x32, 0x22, 0x22, 0x3c, 0x00, 0x00, 0x00, /* 'G' */
|
|
||||||
0x00, 0x00, 0x22, 0x22, 0x22, 0x3e, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, /* 'H' */
|
|
||||||
0x00, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, /* 'I' */
|
|
||||||
0x00, 0x00, 0x38, 0x20, 0x20, 0x20, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /* 'J' */
|
|
||||||
0x00, 0x00, 0x22, 0x12, 0x0a, 0x06, 0x0a, 0x12, 0x22, 0x00, 0x00, 0x00, /* 'K' */
|
|
||||||
0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x3e, 0x00, 0x00, 0x00, /* 'L' */
|
|
||||||
0x00, 0x00, 0x22, 0x36, 0x2a, 0x2a, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, /* 'M' */
|
|
||||||
0x00, 0x00, 0x22, 0x26, 0x26, 0x2a, 0x32, 0x32, 0x22, 0x00, 0x00, 0x00, /* 'N' */
|
|
||||||
0x00, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /* 'O' */
|
|
||||||
0x00, 0x00, 0x1e, 0x22, 0x22, 0x1e, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, /* 'P' */
|
|
||||||
0x00, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c, 0x30, 0x00, 0x00, /* 'Q' */
|
|
||||||
0x00, 0x00, 0x1e, 0x22, 0x22, 0x1e, 0x0a, 0x12, 0x22, 0x00, 0x00, 0x00, /* 'R' */
|
|
||||||
0x00, 0x00, 0x1c, 0x22, 0x02, 0x1c, 0x20, 0x22, 0x1c, 0x00, 0x00, 0x00, /* 'S' */
|
|
||||||
0x00, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, /* 'T' */
|
|
||||||
0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /* 'U' */
|
|
||||||
0x00, 0x00, 0x22, 0x22, 0x22, 0x14, 0x14, 0x08, 0x08, 0x00, 0x00, 0x00, /* 'V' */
|
|
||||||
0x00, 0x00, 0x22, 0x22, 0x22, 0x2a, 0x2a, 0x36, 0x22, 0x00, 0x00, 0x00, /* 'W' */
|
|
||||||
0x00, 0x00, 0x22, 0x22, 0x14, 0x08, 0x14, 0x22, 0x22, 0x00, 0x00, 0x00, /* 'X' */
|
|
||||||
0x00, 0x00, 0x22, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, /* 'Y' */
|
|
||||||
0x00, 0x00, 0x3e, 0x20, 0x10, 0x08, 0x04, 0x02, 0x3e, 0x00, 0x00, 0x00, /* 'Z' */
|
|
||||||
0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, /* '[' */
|
|
||||||
0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x00, 0x00, /* '\' */
|
|
||||||
0x0e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0e, 0x00, /* ']' */
|
|
||||||
0x00, 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* '^' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, /* '_' */
|
|
||||||
0x00, 0x0c, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* '`' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x3c, 0x22, 0x22, 0x32, 0x2c, 0x00, 0x00, 0x00, /* 'a' */
|
|
||||||
0x00, 0x02, 0x02, 0x02, 0x1e, 0x22, 0x22, 0x22, 0x1e, 0x00, 0x00, 0x00, /* 'b' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x3c, 0x02, 0x02, 0x02, 0x3c, 0x00, 0x00, 0x00, /* 'c' */
|
|
||||||
0x00, 0x20, 0x20, 0x20, 0x3c, 0x22, 0x22, 0x22, 0x3c, 0x00, 0x00, 0x00, /* 'd' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x3e, 0x02, 0x1c, 0x00, 0x00, 0x00, /* 'e' */
|
|
||||||
0x00, 0x38, 0x04, 0x04, 0x1e, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, /* 'f' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x3c, 0x22, 0x22, 0x22, 0x3c, 0x20, 0x20, 0x1c, /* 'g' */
|
|
||||||
0x00, 0x02, 0x02, 0x02, 0x1e, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, /* 'h' */
|
|
||||||
0x00, 0x08, 0x08, 0x00, 0x0c, 0x08, 0x08, 0x08, 0x1c, 0x00, 0x00, 0x00, /* 'i' */
|
|
||||||
0x00, 0x10, 0x10, 0x00, 0x1c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0e, /* 'j' */
|
|
||||||
0x00, 0x02, 0x02, 0x02, 0x12, 0x0a, 0x06, 0x0a, 0x12, 0x00, 0x00, 0x00, /* 'k' */
|
|
||||||
0x00, 0x0c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1c, 0x00, 0x00, 0x00, /* 'l' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x16, 0x2a, 0x2a, 0x2a, 0x22, 0x00, 0x00, 0x00, /* 'm' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x1a, 0x26, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, /* 'n' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /* 'o' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x1e, 0x22, 0x22, 0x22, 0x1e, 0x02, 0x02, 0x02, /* 'p' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x3c, 0x22, 0x22, 0x22, 0x3c, 0x20, 0x20, 0x20, /* 'q' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x1a, 0x06, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, /* 'r' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x3c, 0x02, 0x1c, 0x20, 0x1e, 0x00, 0x00, 0x00, /* 's' */
|
|
||||||
0x00, 0x08, 0x08, 0x08, 0x3e, 0x08, 0x08, 0x08, 0x30, 0x00, 0x00, 0x00, /* 't' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x32, 0x2c, 0x00, 0x00, 0x00, /* 'u' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x36, 0x14, 0x14, 0x08, 0x08, 0x00, 0x00, 0x00, /* 'v' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x22, 0x2a, 0x2a, 0x2a, 0x14, 0x00, 0x00, 0x00, /* 'w' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x22, 0x14, 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, /* 'x' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x3c, 0x20, 0x20, 0x1c, /* 'y' */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x3e, 0x10, 0x08, 0x04, 0x3e, 0x00, 0x00, 0x00, /* 'z' */
|
|
||||||
0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x10, 0x10, 0x10, 0x10, 0x20, 0x00, /* '{' */
|
|
||||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, /* '|' */
|
|
||||||
0x02, 0x04, 0x04, 0x04, 0x04, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x00, /* '}' */
|
|
||||||
0x00, 0x04, 0x2a, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* '~' */
|
|
||||||
0x00, 0x00, 0x00, 0x08, 0x08, 0x14, 0x14, 0x22, 0x3e, 0x00, 0x00, 0x00, /* '' */
|
|
||||||
};
|
|
||||||
|
|
||||||
static unsigned char *framebuffer;
|
|
||||||
static unsigned char draw_color;
|
|
||||||
static unsigned char back_color;
|
|
||||||
static int char_x,char_y;
|
|
||||||
static int screen_size_x, screen_size_y;
|
|
||||||
static int num_cols, num_rows;
|
|
||||||
|
|
||||||
#define CHAR_WIDTH 6
|
|
||||||
#define CHAR_HEIGHT 12
|
|
||||||
|
|
||||||
static void draw_char(unsigned char c, int x, int y)
|
|
||||||
{
|
|
||||||
int i,j;
|
|
||||||
unsigned char *base = &framebuffer[y*screen_size_x + x];
|
|
||||||
unsigned char line;
|
|
||||||
|
|
||||||
for(i=0; i<CHAR_HEIGHT; i++) {
|
|
||||||
line = FONT[c*CHAR_HEIGHT + i];
|
|
||||||
for(j=0; j<CHAR_WIDTH; j++) {
|
|
||||||
base[j] = (line & 0x1) ? draw_color : back_color;
|
|
||||||
line = line >> 1;
|
|
||||||
}
|
|
||||||
base += screen_size_x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int printf(const char *fmt, ...)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
va_list args;
|
|
||||||
char temp[256];
|
|
||||||
|
|
||||||
va_start(args, fmt);
|
|
||||||
ret = vsprintf(temp,fmt,args);
|
|
||||||
va_end(args);
|
|
||||||
|
|
||||||
puts(temp);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void puts(char *str)
|
|
||||||
{
|
|
||||||
while(*str) {
|
|
||||||
putchar(*str);
|
|
||||||
str++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void putchar(char c)
|
|
||||||
{
|
|
||||||
if(c == '\n') {
|
|
||||||
char_x = 0;
|
|
||||||
char_y++;
|
|
||||||
} else {
|
|
||||||
draw_char(c, char_x * CHAR_WIDTH, char_y * CHAR_HEIGHT);
|
|
||||||
char_x++;
|
|
||||||
}
|
|
||||||
if(char_x >= num_cols) {
|
|
||||||
char_x = 0;
|
|
||||||
char_y++;
|
|
||||||
}
|
|
||||||
if(char_y >= num_rows) {
|
|
||||||
// scroll up
|
|
||||||
memcpy(framebuffer, framebuffer + screen_size_x*CHAR_HEIGHT, screen_size_x * screen_size_y - screen_size_x*CHAR_HEIGHT);
|
|
||||||
memset(framebuffer + (screen_size_y-CHAR_HEIGHT)*screen_size_x, back_color, screen_size_x*CHAR_HEIGHT);
|
|
||||||
char_y--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int s2_text_init(kernel_args *ka)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
framebuffer = (unsigned char *)0x96008000;
|
|
||||||
screen_size_x = 1024;
|
|
||||||
screen_size_y = 768;
|
|
||||||
back_color = 0x0;
|
|
||||||
draw_color = 0xff;
|
|
||||||
char_x = char_y = 0;
|
|
||||||
|
|
||||||
num_cols = screen_size_x / CHAR_WIDTH;
|
|
||||||
num_rows = screen_size_y / CHAR_HEIGHT;
|
|
||||||
|
|
||||||
for(i = 0; i<screen_size_x * screen_size_y; i++) {
|
|
||||||
framebuffer[i] = back_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
ka->arch_args.screen_x = 1024;
|
|
||||||
ka->arch_args.screen_y = 768;
|
|
||||||
ka->arch_args.screen_depth = 8;
|
|
||||||
ka->arch_args.framebuffer.start = (unsigned long)framebuffer;
|
|
||||||
ka->arch_args.framebuffer.size = ka->arch_args.screen_x * ka->arch_args.screen_y * ka->arch_args.screen_depth / 8;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void s2_change_framebuffer_addr(unsigned int address)
|
|
||||||
{
|
|
||||||
framebuffer = (unsigned char *)address;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
SubDir HAIKU_TOP src system boot arch sh4 ;
|
|
||||||
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
ifneq ($(_BOOT_MAKE),1)
|
|
||||||
_BOOT_MAKE = 1
|
|
||||||
|
|
||||||
# include targets we depend on
|
|
||||||
include lib/lib.mk
|
|
||||||
include kernel/kernel.mk
|
|
||||||
include apps/apps.mk
|
|
||||||
|
|
||||||
# sh4 stage2 makefile
|
|
||||||
BOOT_DIR = boot/$(ARCH)
|
|
||||||
BOOT_OBJ_DIR = $(BOOT_DIR)/$(OBJ_DIR)
|
|
||||||
STAGE2_OBJS = $(BOOT_OBJ_DIR)/stage2.o \
|
|
||||||
$(BOOT_OBJ_DIR)/serial.o \
|
|
||||||
$(BOOT_OBJ_DIR)/mmu.o \
|
|
||||||
$(BOOT_OBJ_DIR)/vcpu.o \
|
|
||||||
$(BOOT_OBJ_DIR)/vcpu_c.o
|
|
||||||
DEPS += $(STAGE2_OBJS:.o=.d)
|
|
||||||
|
|
||||||
STAGE2 = $(BOOT_OBJ_DIR)/stage2
|
|
||||||
|
|
||||||
$(STAGE2): $(STAGE2_OBJS) $(KLIBS)
|
|
||||||
$(LD) $(GLOBAL_LDFLAGS) -dN --script=$(BOOT_DIR)/stage2.ld -L $(LIBGCC_PATH) $(STAGE2_OBJS) $(LINK_KLIBS) $(LIBGCC) -o $@
|
|
||||||
|
|
||||||
stage2: $(STAGE2)
|
|
||||||
|
|
||||||
stage2clean:
|
|
||||||
rm -f $(STAGE2_OBJS) $(STAGE2)
|
|
||||||
|
|
||||||
CLEAN += stage2clean
|
|
||||||
|
|
||||||
SEMIFINAL = $(BOOT_DIR)/final.bootdir
|
|
||||||
|
|
||||||
$(SEMIFINAL): $(STAGE2) $(KERNEL) $(KERNEL_ADDONS) $(APPS) tools
|
|
||||||
$(BOOTMAKER) $(BOOT_DIR)/config.ini -o $(SEMIFINAL)
|
|
||||||
|
|
||||||
STAGE1_OBJS = \
|
|
||||||
$(BOOT_OBJ_DIR)/stage1.o
|
|
||||||
|
|
||||||
DEPS += $(STAGE1_OBJS:.o=.d)
|
|
||||||
|
|
||||||
STAGE1 = $(BOOT_OBJ_DIR)/stage1
|
|
||||||
|
|
||||||
$(STAGE1): $(STAGE1_OBJS)
|
|
||||||
$(LD) $(GLOBAL_LDFLAGS) -N -Ttext 0x8c000000 $(STAGE1_OBJS) -o $(STAGE1)
|
|
||||||
|
|
||||||
$(STAGE1).bin: $(STAGE1)
|
|
||||||
$(OBJCOPY) -O binary $(STAGE1) $@1
|
|
||||||
dd if=/dev/zero of=$(STAGE1).bin bs=4096 count=1 2> /dev/null
|
|
||||||
dd if=$(STAGE1).bin1 of=$(STAGE1).bin conv=notrunc 2> /dev/null
|
|
||||||
rm $(STAGE1).bin1
|
|
||||||
|
|
||||||
stage1clean:
|
|
||||||
rm -f $(STAGE1_OBJS) $(STAGE1) $(STAGE1).bin $(STAGE1).bin1
|
|
||||||
|
|
||||||
CLEAN += stage1clean
|
|
||||||
|
|
||||||
FINAL = $(BOOT_DIR)/final
|
|
||||||
|
|
||||||
$(FINAL): $(SEMIFINAL) $(STAGE1).bin
|
|
||||||
cat $(STAGE1).bin $(SEMIFINAL) > $(FINAL)
|
|
||||||
|
|
||||||
#
|
|
||||||
$(BOOT_OBJ_DIR)/%.o: $(BOOT_DIR)/%.c
|
|
||||||
@mkdir -p $(BOOT_OBJ_DIR)
|
|
||||||
$(CC) $(GLOBAL_CFLAGS) -Iinclude -Iinclude/nulibc -I$(BOOT_DIR) -c $< -o $@
|
|
||||||
|
|
||||||
$(BOOT_OBJ_DIR)/%.d: $(BOOT_DIR)/%.c
|
|
||||||
@mkdir -p $(BOOT_OBJ_DIR)
|
|
||||||
@echo "making deps for $<..."
|
|
||||||
@($(ECHO) -n $(dir $@);$(CC) $(GLOBAL_CFLAGS) -Iinclude -Iinclude/nulibc -I$(BOOT_DIR) -M -MG $<) > $@
|
|
||||||
|
|
||||||
$(BOOT_OBJ_DIR)/%.d: $(BOOT_DIR)/%.S
|
|
||||||
@mkdir -p $(BOOT_OBJ_DIR)
|
|
||||||
@echo "making deps for $<..."
|
|
||||||
@($(ECHO) -n $(dir $@);$(CC) $(GLOBAL_CFLAGS) -Iinclude -Iinclude/nulibc -I$(BOOT_DIR) -M -MG $<) > $@
|
|
||||||
|
|
||||||
$(BOOT_OBJ_DIR)/%.o: $(BOOT_DIR)/%.S
|
|
||||||
@mkdir -p $(BOOT_OBJ_DIR)
|
|
||||||
$(CC) $(GLOBAL_CFLAGS) -Iinclude -Iinclude/nulibc -I$(BOOT_DIR) -c $< -o $@
|
|
||||||
endif
|
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
# ---------------------------------------------------------------
|
|
||||||
# The bootstrap code is where control starts once netboot, boot.com,
|
|
||||||
# etc loads the image. It creates a page table to map the kernel in
|
|
||||||
# at 0x80000000 and then jumps to the kernel entrypoint where things
|
|
||||||
# really start happening. This MUST be the first entry in the .ini
|
|
||||||
#
|
|
||||||
[bootstrap]
|
|
||||||
type=elf32
|
|
||||||
file=build/sh4/boot/stage2
|
|
||||||
|
|
||||||
[kernel]
|
|
||||||
type=elf32
|
|
||||||
file=build/sh4/kernel/kernel
|
|
||||||
|
|
||||||
[addons/fs/iso9660]
|
|
||||||
type=elf32
|
|
||||||
file=build/sh4/kernel/addons/fs/iso9660/iso9660
|
|
||||||
|
|
||||||
[addons/fs/zfs]
|
|
||||||
type=elf32
|
|
||||||
file=build/sh4/kernel/addons/fs/zfs/zfs
|
|
||||||
|
|
||||||
[bin/init]
|
|
||||||
type=elf32
|
|
||||||
file=build/sh4/apps/init/init
|
|
||||||
|
|
||||||
[bin/shell]
|
|
||||||
type=elf32
|
|
||||||
file=build/sh4/apps/shell/shell
|
|
||||||
|
|
||||||
[bin/ls]
|
|
||||||
type=elf32
|
|
||||||
file=build/sh4/apps/ls/ls
|
|
||||||
|
|
||||||
[bin/mount]
|
|
||||||
type=elf32
|
|
||||||
file=build/sh4/apps/mount/mount
|
|
||||||
|
|
||||||
[bin/unmount]
|
|
||||||
type=elf32
|
|
||||||
file=build/sh4/apps/unmount/unmount
|
|
||||||
|
|
||||||
[bin/fortune]
|
|
||||||
type=elf32
|
|
||||||
file=build/sh4/apps/fortune/fortune
|
|
||||||
|
|
||||||
[etc/fortunes]
|
|
||||||
type=data
|
|
||||||
file=apps/fortune/fortunes
|
|
||||||
|
|
||||||
[bin/testapp]
|
|
||||||
type=elf32
|
|
||||||
file=build/sh4/apps/testapp/testapp
|
|
||||||
|
|
||||||
[bin/true]
|
|
||||||
type=elf32
|
|
||||||
file=build/sh4/apps/true/true
|
|
||||||
|
|
||||||
[bin/false]
|
|
||||||
type=elf32
|
|
||||||
file=build/sh4/apps/false/false
|
|
||||||
|
|
||||||
[bin/vmtest]
|
|
||||||
type=elf32
|
|
||||||
file=build/sh4/apps/vmtest/vmtest
|
|
||||||
|
|
||||||
[bin/fibo]
|
|
||||||
type=elf32
|
|
||||||
file=build/sh4/apps/fibo/fibo
|
|
||||||
|
|
||||||
[libexec/rld.so]
|
|
||||||
type=elf32
|
|
||||||
file=build/sh4/apps/rld/rld.so
|
|
||||||
|
|
||||||
[bin/rldtest]
|
|
||||||
type=elf32
|
|
||||||
file=build/sh4/apps/rldtest/rldtest
|
|
||||||
|
|
||||||
[lib/librldtest.so]
|
|
||||||
type=elf32
|
|
||||||
file=build/sh4/apps/rldtest/librldtest.so
|
|
||||||
|
|
||||||
[lib/girlfriend.so]
|
|
||||||
type=elf32
|
|
||||||
file=build/sh4/apps/rldtest/girlfriend.so
|
|
||||||
|
|
||||||
[lib/libc.so]
|
|
||||||
type=elf32
|
|
||||||
file=build/sh4/lib/libc/libc.so
|
|
||||||
|
|
||||||
[lib/libm.so]
|
|
||||||
type=elf32
|
|
||||||
file=build/sh4/lib/libm/libm.so
|
|
||||||
|
|
||||||
[testfile]
|
|
||||||
type=data
|
|
||||||
file=boot/testfile
|
|
||||||
|
|
||||||
[test.iso]
|
|
||||||
type=data
|
|
||||||
file=boot/test.iso
|
|
||||||
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
/*
|
|
||||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
|
||||||
** Distributed under the terms of the NewOS License.
|
|
||||||
*/
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <boot/stage2.h>
|
|
||||||
#include <arch/cpu.h>
|
|
||||||
#include <arch/sh4/vcpu.h>
|
|
||||||
#include <arch/sh4/sh4.h>
|
|
||||||
#include "serial.h"
|
|
||||||
#include "mmu.h"
|
|
||||||
|
|
||||||
#define KERNEL_LOAD_ADDR 0xc0000000
|
|
||||||
|
|
||||||
struct pdent *pd = 0;
|
|
||||||
|
|
||||||
void mmu_map_page(unsigned int vaddr, unsigned int paddr)
|
|
||||||
{
|
|
||||||
struct ptent *pt;
|
|
||||||
int index;
|
|
||||||
|
|
||||||
vaddr &= 0xfffff000;
|
|
||||||
paddr &= 0xfffff000;
|
|
||||||
dprintf("mmu_map_page: mapping 0x%x to 0x%x\n", paddr, vaddr);
|
|
||||||
|
|
||||||
if(vaddr < P1_AREA) {
|
|
||||||
dprintf("mmu_map_page: cannot map user space now!\n");
|
|
||||||
for(;;);
|
|
||||||
}
|
|
||||||
|
|
||||||
vaddr &= 0x7fffffff;
|
|
||||||
|
|
||||||
index = vaddr >> 22;
|
|
||||||
if(pd[index].v == 0) {
|
|
||||||
dprintf("mmu_map_page: no page dir exists for this address\n");
|
|
||||||
for(;;);
|
|
||||||
}
|
|
||||||
|
|
||||||
pt = (struct ptent *)PHYS_ADDR_TO_P1(pd[index].ppn << 12);
|
|
||||||
|
|
||||||
index = (vaddr >> 12) & 0x00000fff;
|
|
||||||
pt[index].wt = 0;
|
|
||||||
pt[index].pr = 1; // rw, supervisor only
|
|
||||||
pt[index].ppn = paddr >> 12;
|
|
||||||
pt[index].tlb_ent = 0;
|
|
||||||
pt[index].c = 1;
|
|
||||||
pt[index].sz = 1; // 4k page
|
|
||||||
pt[index].sh = 0;
|
|
||||||
pt[index].d = 0;
|
|
||||||
pt[index].v = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mmu_init(kernel_args *ka, unsigned int *next_paddr)
|
|
||||||
{
|
|
||||||
struct ptent *pt;
|
|
||||||
int index;
|
|
||||||
|
|
||||||
dprintf("mmu_init: entry\n");
|
|
||||||
|
|
||||||
// allocate a kernel pgdir
|
|
||||||
ka->arch_args.vcpu->kernel_pgdir = (unsigned int *)PHYS_ADDR_TO_P1(*next_paddr);
|
|
||||||
(*next_paddr) += PAGE_SIZE;
|
|
||||||
|
|
||||||
pd = (struct pdent *)ka->arch_args.vcpu->kernel_pgdir;
|
|
||||||
memset(pd, 0, sizeof(struct pdent) * 512);
|
|
||||||
|
|
||||||
dprintf("kernel_pgdir = 0x%x\n", ka->arch_args.vcpu->kernel_pgdir);
|
|
||||||
|
|
||||||
// allocate an initial page table
|
|
||||||
pt = (struct ptent *)PHYS_ADDR_TO_P1(*next_paddr);
|
|
||||||
memset(pt, 0, sizeof(struct ptent) * 1024);
|
|
||||||
(*next_paddr) += PAGE_SIZE;
|
|
||||||
|
|
||||||
dprintf("intial page table = 0x%x\n", pt);
|
|
||||||
|
|
||||||
index = (KERNEL_LOAD_ADDR & 0x7fffffff) >> 22;
|
|
||||||
pd[index].ppn = (unsigned int)pt >> 12;
|
|
||||||
pd[index].v = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
/*
|
|
||||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
|
||||||
** Distributed under the terms of the NewOS License.
|
|
||||||
*/
|
|
||||||
#include <boot/stage2.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "serial.h"
|
|
||||||
|
|
||||||
int dprintf(const char *fmt, ...)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
va_list args;
|
|
||||||
char temp[128];
|
|
||||||
|
|
||||||
va_start(args, fmt);
|
|
||||||
ret = vsprintf(temp, fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
|
|
||||||
serial_puts(temp);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int serial_init()
|
|
||||||
{
|
|
||||||
volatile unsigned short *scif16 = (unsigned short*)0xffe80000;
|
|
||||||
volatile unsigned char *scif8 = (unsigned char*)0xffe80000;
|
|
||||||
int x;
|
|
||||||
|
|
||||||
/* Disable interrupts, transmit/receive, and use internal clock */
|
|
||||||
scif16[8/2] = 0;
|
|
||||||
|
|
||||||
/* 8N1, use P0 clock */
|
|
||||||
scif16[0] = 0;
|
|
||||||
|
|
||||||
/* Set baudrate, N = P0/(32*B)-1 */
|
|
||||||
// scif8[4] = (50000000 / (32 * baud_rate)) - 1;
|
|
||||||
|
|
||||||
// scif8[4] = 80; // 19200
|
|
||||||
// scif8[4] = 40; // 38400
|
|
||||||
// scif8[4] = 26; // 57600
|
|
||||||
scif8[4] = 13; // 115200
|
|
||||||
|
|
||||||
/* Reset FIFOs, enable hardware flow control */
|
|
||||||
scif16[24/2] = 4; //12;
|
|
||||||
|
|
||||||
for(x = 0; x < 100000; x++);
|
|
||||||
scif16[24/2] = 0; //8;
|
|
||||||
|
|
||||||
/* Disable manual pin control */
|
|
||||||
scif16[32/2] = 0;
|
|
||||||
|
|
||||||
/* Clear status */
|
|
||||||
scif16[16/2] = 0x60;
|
|
||||||
scif16[36/2] = 0;
|
|
||||||
|
|
||||||
/* Enable transmit/receive */
|
|
||||||
scif16[8/2] = 0x30;
|
|
||||||
|
|
||||||
for(x = 0; x < 100000; x++);
|
|
||||||
|
|
||||||
serial_puts("serial initted\n");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Flush all FIFO'd bytes out of the serial port buffer */
|
|
||||||
static void serial_flush() {
|
|
||||||
volatile unsigned short *ack = (unsigned short*)0xffe80010;
|
|
||||||
|
|
||||||
*ack &= 0xbf;
|
|
||||||
while (!(*ack & 0x40))
|
|
||||||
;
|
|
||||||
*ack &= 0xbf;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _serial_putch(const char c)
|
|
||||||
{
|
|
||||||
volatile unsigned short *ack = (unsigned short*)0xffe80010;
|
|
||||||
volatile unsigned char *fifo = (unsigned char*)0xffe8000c;
|
|
||||||
|
|
||||||
/* Wait until the transmit buffer has space */
|
|
||||||
while (!(*ack & 0x20))
|
|
||||||
;
|
|
||||||
/* Send the char */
|
|
||||||
*fifo = c;
|
|
||||||
|
|
||||||
/* Clear status */
|
|
||||||
*ack &= 0x9f;
|
|
||||||
}
|
|
||||||
|
|
||||||
char serial_putch(const char c)
|
|
||||||
{
|
|
||||||
if (c == '\n') {
|
|
||||||
_serial_putch('\r');
|
|
||||||
_serial_putch('\n');
|
|
||||||
} else if (c != '\r')
|
|
||||||
_serial_putch(c);
|
|
||||||
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
void serial_puts(const char *s)
|
|
||||||
{
|
|
||||||
while(*s != '\0') {
|
|
||||||
serial_putch(*s);
|
|
||||||
s++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
|
||||||
** Distributed under the terms of the NewOS License.
|
|
||||||
*/
|
|
||||||
/* addresses of values stored in the bootdir, which starts on the next
|
|
||||||
page after this code. */
|
|
||||||
#define BASE 0x8c000000
|
|
||||||
#define BOOTDIR_BASE (BASE + 0x1000)
|
|
||||||
#define STAGE2_BOOTDIR_PAGE (BOOTDIR_BASE + 0x60)
|
|
||||||
#define STAGE2_OFFSET (BOOTDIR_BASE + 0x74)
|
|
||||||
.text
|
|
||||||
|
|
||||||
start:
|
|
||||||
mov.l bootdir_base,r0
|
|
||||||
|
|
||||||
/* load and calculate the offset of the stage2 bootloader into the bootdir */
|
|
||||||
mov.l page_addr_addr,r1
|
|
||||||
mov.l @r1,r1
|
|
||||||
shll8 r1
|
|
||||||
shll2 r1
|
|
||||||
shll2 r1 /* multiply the offset address by 4096 */
|
|
||||||
|
|
||||||
/* find the offset into the stage2 bootloader where the entry point is */
|
|
||||||
mov.l offset_addr,r2
|
|
||||||
mov.l @r2,r2
|
|
||||||
|
|
||||||
/* add all of these numbers together and jump to it */
|
|
||||||
add r1,r0
|
|
||||||
add r2,r0
|
|
||||||
jmp @r0
|
|
||||||
nop
|
|
||||||
|
|
||||||
.align 2
|
|
||||||
bootdir_base:
|
|
||||||
.long BOOTDIR_BASE
|
|
||||||
page_addr_addr:
|
|
||||||
.long STAGE2_BOOTDIR_PAGE
|
|
||||||
offset_addr:
|
|
||||||
.long STAGE2_OFFSET
|
|
||||||
@@ -1,213 +0,0 @@
|
|||||||
/*
|
|
||||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
|
||||||
** Distributed under the terms of the NewOS License.
|
|
||||||
*/
|
|
||||||
#include <boot/bootdir.h>
|
|
||||||
#include <boot/stage2.h>
|
|
||||||
#include <arch/cpu.h>
|
|
||||||
#include <arch/sh4/sh4.h>
|
|
||||||
#include <arch/sh4/vcpu.h>
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <newos/elf32.h>
|
|
||||||
#include "serial.h"
|
|
||||||
#include "mmu.h"
|
|
||||||
|
|
||||||
#define BOOTDIR 0x8c001000
|
|
||||||
#define P2_AREA 0x8c000000
|
|
||||||
#define PHYS_ADDR_START 0x0c000000
|
|
||||||
|
|
||||||
#define ROUNDUP(a, b) (((a) + ((b)-1)) & ~((b)-1))
|
|
||||||
#define ROUNDOWN(a, b) (((a) / (b)) * (b))
|
|
||||||
|
|
||||||
void test_interrupt();
|
|
||||||
void switch_stacks_and_call(unsigned int stack, unsigned int call_addr, unsigned int call_arg, unsigned int call_arg2);
|
|
||||||
|
|
||||||
void load_elf_image(void *data, unsigned int *next_paddr, addr_range *ar0, addr_range *ar1, unsigned int *start_addr, addr_range *dynamic_section);
|
|
||||||
|
|
||||||
int _start()
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
boot_entry *bootdir = (boot_entry *)BOOTDIR;
|
|
||||||
unsigned int bootdir_len;
|
|
||||||
unsigned int next_vaddr;
|
|
||||||
unsigned int next_paddr;
|
|
||||||
unsigned int kernel_entry;
|
|
||||||
kernel_args *ka;
|
|
||||||
|
|
||||||
serial_init();
|
|
||||||
|
|
||||||
serial_puts("Stage 2 loader entry\n");
|
|
||||||
|
|
||||||
// look at the bootdir
|
|
||||||
bootdir_len = 1; // account for bootdir directory
|
|
||||||
for(i=0; i<64; i++) {
|
|
||||||
if(bootdir[i].be_type == BE_TYPE_NONE)
|
|
||||||
break;
|
|
||||||
bootdir_len += bootdir[i].be_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
dprintf("bootdir is %d pages long\n", bootdir_len);
|
|
||||||
next_paddr = PHYS_ADDR_START + bootdir_len * PAGE_SIZE;
|
|
||||||
|
|
||||||
// find a location for the kernel args
|
|
||||||
ka = (kernel_args *)(P2_AREA + bootdir_len * PAGE_SIZE);
|
|
||||||
memset(ka, 0, sizeof(kernel_args));
|
|
||||||
next_paddr += PAGE_SIZE;
|
|
||||||
|
|
||||||
// initialize the vcpu
|
|
||||||
vcpu_init(ka);
|
|
||||||
mmu_init(ka, &next_paddr);
|
|
||||||
|
|
||||||
// map the kernel text & data
|
|
||||||
load_elf_image((void *)(bootdir[2].be_offset * PAGE_SIZE + BOOTDIR), &next_paddr,
|
|
||||||
&ka->kernel_seg0_addr, &ka->kernel_seg1_addr, &kernel_entry, &ka->kernel_dynamic_section_addr);
|
|
||||||
dprintf("mapped kernel from 0x%x to 0x%x\n", ka->kernel_seg0_addr.start, ka->kernel_seg1_addr.start + ka->kernel_seg1_addr.size);
|
|
||||||
dprintf("kernel entry @ 0x%x\n", kernel_entry);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
dprintf("diffing the mapped memory\n");
|
|
||||||
dprintf("memcmp = %d\n", memcmp((void *)KERNEL_LOAD_ADDR, (void *)BOOTDIR + bootdir[2].be_offset * PAGE_SIZE, PAGE_SIZE));
|
|
||||||
dprintf("done diffing the memory\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
next_vaddr = ROUNDUP(ka->kernel_seg1_addr.start + ka->kernel_seg1_addr.size, PAGE_SIZE);
|
|
||||||
|
|
||||||
// map in a kernel stack
|
|
||||||
ka->cpu_kstack[0].start = next_vaddr;
|
|
||||||
for(i=0; i<2; i++) {
|
|
||||||
mmu_map_page(next_vaddr, next_paddr);
|
|
||||||
next_vaddr += PAGE_SIZE;
|
|
||||||
next_paddr += PAGE_SIZE;
|
|
||||||
}
|
|
||||||
ka->cpu_kstack[0].size = next_vaddr - ka->cpu_kstack[0].start;
|
|
||||||
|
|
||||||
// record this first region of allocation space
|
|
||||||
ka->phys_alloc_range[0].start = PHYS_ADDR_START;
|
|
||||||
ka->phys_alloc_range[0].size = next_paddr - PHYS_ADDR_START;
|
|
||||||
ka->num_phys_alloc_ranges = 1;
|
|
||||||
ka->virt_alloc_range[0].start = ka->kernel_seg0_addr.start;
|
|
||||||
ka->virt_alloc_range[0].size = next_vaddr - ka->virt_alloc_range[0].start;
|
|
||||||
ka->virt_alloc_range[1].start = ka->kernel_seg1_addr.start;
|
|
||||||
ka->virt_alloc_range[1].size = next_vaddr - ka->virt_alloc_range[1].start;
|
|
||||||
ka->num_virt_alloc_ranges = 2;
|
|
||||||
|
|
||||||
ka->fb.enabled = 1;
|
|
||||||
ka->fb.x_size = 640;
|
|
||||||
ka->fb.y_size = 480;
|
|
||||||
ka->fb.bit_depth = 16;
|
|
||||||
ka->fb.mapping.start = 0xa5000000;
|
|
||||||
ka->fb.mapping.size = ka->fb.x_size * ka->fb.y_size * 2;
|
|
||||||
ka->fb.already_mapped = 1;
|
|
||||||
|
|
||||||
ka->cons_line = 0;
|
|
||||||
ka->str = 0;
|
|
||||||
ka->bootdir_addr.start = P1_TO_PHYS_ADDR(BOOTDIR);
|
|
||||||
ka->bootdir_addr.size = bootdir_len * PAGE_SIZE;
|
|
||||||
ka->phys_mem_range[0].start = PHYS_ADDR_START;
|
|
||||||
ka->phys_mem_range[0].size = 16*1024*1024;
|
|
||||||
ka->num_phys_mem_ranges = 1;
|
|
||||||
ka->num_cpus = 1;
|
|
||||||
|
|
||||||
for(i=0; i<ka->num_phys_alloc_ranges; i++) {
|
|
||||||
dprintf("prange %d start = 0x%x, size = 0x%x\n",
|
|
||||||
i, ka->phys_alloc_range[i].start, ka->phys_alloc_range[i].size);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i=0; i<ka->num_virt_alloc_ranges; i++) {
|
|
||||||
dprintf("vrange %d start = 0x%x, size = 0x%x\n",
|
|
||||||
i, ka->virt_alloc_range[i].start, ka->virt_alloc_range[i].size);
|
|
||||||
}
|
|
||||||
|
|
||||||
dprintf("switching stack to 0x%x and calling 0x%x\n",
|
|
||||||
ka->cpu_kstack[0].start + ka->cpu_kstack[0].size - 4, kernel_entry);
|
|
||||||
switch_stacks_and_call(ka->cpu_kstack[0].start + ka->cpu_kstack[0].size - 4,
|
|
||||||
kernel_entry,
|
|
||||||
(unsigned int)ka,
|
|
||||||
0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
asm(".text\n"
|
|
||||||
".align 2\n"
|
|
||||||
"_switch_stacks_and_call:\n"
|
|
||||||
" mov r4,r15\n"
|
|
||||||
" mov r5,r1\n"
|
|
||||||
" mov r6,r4\n"
|
|
||||||
" jsr @r1\n"
|
|
||||||
" mov r7,r5");
|
|
||||||
|
|
||||||
void load_elf_image(void *data, unsigned int *next_paddr, addr_range *ar0, addr_range *ar1, unsigned int *start_addr, addr_range *dynamic_section)
|
|
||||||
{
|
|
||||||
struct Elf32_Ehdr *imageHeader = (struct Elf32_Ehdr*) data;
|
|
||||||
struct Elf32_Phdr *segments = (struct Elf32_Phdr*)(imageHeader->e_phoff + (unsigned) imageHeader);
|
|
||||||
int segmentIndex;
|
|
||||||
int foundSegmentIndex = 0;
|
|
||||||
|
|
||||||
ar0->size = 0;
|
|
||||||
ar1->size = 0;
|
|
||||||
dynamic_section->size = 0;
|
|
||||||
|
|
||||||
for (segmentIndex = 0; segmentIndex < imageHeader->e_phnum; segmentIndex++) {
|
|
||||||
struct Elf32_Phdr *segment = &segments[segmentIndex];
|
|
||||||
unsigned segmentOffset;
|
|
||||||
|
|
||||||
switch(segment->p_type) {
|
|
||||||
case PT_LOAD:
|
|
||||||
break;
|
|
||||||
case PT_DYNAMIC:
|
|
||||||
dynamic_section->start = segment->p_vaddr;
|
|
||||||
dynamic_section->size = segment->p_memsz;
|
|
||||||
default:
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
dprintf("segment %d\n", segmentIndex);
|
|
||||||
dprintf("p_offset 0x%x p_vaddr 0x%x p_paddr 0x%x p_filesz 0x%x p_memsz 0x%x\n",
|
|
||||||
segment->p_offset, segment->p_vaddr, segment->p_paddr, segment->p_filesz, segment->p_memsz);
|
|
||||||
|
|
||||||
/* Map initialized portion */
|
|
||||||
for (segmentOffset = 0;
|
|
||||||
segmentOffset < ROUNDUP(segment->p_filesz, PAGE_SIZE);
|
|
||||||
segmentOffset += PAGE_SIZE) {
|
|
||||||
|
|
||||||
mmu_map_page(segment->p_vaddr + segmentOffset, *next_paddr);
|
|
||||||
memcpy((void *)ROUNDOWN(segment->p_vaddr + segmentOffset, PAGE_SIZE),
|
|
||||||
(void *)ROUNDOWN((unsigned)data + segment->p_offset + segmentOffset, PAGE_SIZE), PAGE_SIZE);
|
|
||||||
(*next_paddr) += PAGE_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clean out the leftover part of the last page */
|
|
||||||
if(((segment->p_vaddr + segment->p_filesz) % PAGE_SIZE) > 0) {
|
|
||||||
dprintf("memsetting 0 to va 0x%x, size %d\n", (void*)((unsigned)segment->p_vaddr + segment->p_filesz),
|
|
||||||
PAGE_SIZE - ((segment->p_vaddr + segment->p_filesz) % PAGE_SIZE));
|
|
||||||
memset((void*)((unsigned)segment->p_vaddr + segment->p_filesz), 0,
|
|
||||||
PAGE_SIZE - ((segment->p_vaddr + segment->p_filesz) % PAGE_SIZE));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Map uninitialized portion */
|
|
||||||
for (; segmentOffset < ROUNDUP(segment->p_memsz, PAGE_SIZE); segmentOffset += PAGE_SIZE) {
|
|
||||||
dprintf("mapping zero page at va 0x%x\n", segment->p_vaddr + segmentOffset);
|
|
||||||
mmu_map_page(segment->p_vaddr + segmentOffset, *next_paddr);
|
|
||||||
memset((void *)(segment->p_vaddr + segmentOffset), 0, PAGE_SIZE);
|
|
||||||
(*next_paddr) += PAGE_SIZE;
|
|
||||||
}
|
|
||||||
switch(foundSegmentIndex) {
|
|
||||||
case 0:
|
|
||||||
ar0->start = segment->p_vaddr;
|
|
||||||
ar0->size = segment->p_memsz;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
ar1->start = segment->p_vaddr;
|
|
||||||
ar1->size = segment->p_memsz;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
;
|
|
||||||
}
|
|
||||||
foundSegmentIndex++;
|
|
||||||
}
|
|
||||||
*start_addr = imageHeader->e_entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
OUTPUT_FORMAT("elf32-shl", "elf32-shl", "elf32-shl")
|
|
||||||
OUTPUT_ARCH(sh)
|
|
||||||
PHDRS
|
|
||||||
{
|
|
||||||
text PT_LOAD;
|
|
||||||
data PT_LOAD;
|
|
||||||
}
|
|
||||||
|
|
||||||
ENTRY(__start)
|
|
||||||
SECTIONS
|
|
||||||
{
|
|
||||||
/* . = 0x8c100000 + 0x1200 + SIZEOF_HEADERS; */
|
|
||||||
. = 0x8c000000 + 0x2000 + 0x80;
|
|
||||||
|
|
||||||
/* text/read-only data */
|
|
||||||
.text : { *(.text .gnu.linkonce.t.*) }
|
|
||||||
|
|
||||||
.rodata : { *(.rodata) }
|
|
||||||
|
|
||||||
/* writable data */
|
|
||||||
/* . = ALIGN(0x1000);*/
|
|
||||||
__ctor_list = .;
|
|
||||||
.ctors : { *(.ctors) }
|
|
||||||
__ctor_end = .;
|
|
||||||
|
|
||||||
__data_start = .;
|
|
||||||
.data : { *(.data .gnu.linkonce.d.*) }
|
|
||||||
|
|
||||||
/* unintialized data (in same segment as writable data) */
|
|
||||||
__bss_start = .;
|
|
||||||
.bss : { *(.bss) }
|
|
||||||
|
|
||||||
. = ALIGN(0x1000);
|
|
||||||
_end = . ;
|
|
||||||
|
|
||||||
/* Strip unnecessary stuff */
|
|
||||||
/DISCARD/ : { *(.comment .note .eh_frame .dtors) }
|
|
||||||
}
|
|
||||||
@@ -1,575 +0,0 @@
|
|||||||
/*
|
|
||||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
|
||||||
** Distributed under the terms of the NewOS License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define SAVE_CPU_STATE 0
|
|
||||||
|
|
||||||
.text
|
|
||||||
.align 2
|
|
||||||
|
|
||||||
.globl _vector_base
|
|
||||||
_vector_base:
|
|
||||||
.skip 0x100
|
|
||||||
exception_ent_1:
|
|
||||||
mov.l expevt_addr1,r0
|
|
||||||
mov.l @r0,r0
|
|
||||||
shlr2 r0
|
|
||||||
shlr r0 /* shift the exception code over 3 bits */
|
|
||||||
|
|
||||||
cmp/eq #0x10,r0 /* test if its a initial page write */
|
|
||||||
bt _tlb_ipw
|
|
||||||
nop
|
|
||||||
|
|
||||||
/* not a inital page write exception */
|
|
||||||
/* just enter the kernel and let it deal with it */
|
|
||||||
bra switch_banks_and_enter_kernel
|
|
||||||
nop
|
|
||||||
|
|
||||||
_tlb_ipw:
|
|
||||||
/* deal with inital page write exception */
|
|
||||||
/* we can stay on reg bank 1, switch to a tlb stack */
|
|
||||||
mov.l tlb_stack_addr1,r15
|
|
||||||
|
|
||||||
/* save some of the floating point registers */
|
|
||||||
/* they seem to be used by some of the libgcc stuff */
|
|
||||||
/* saving: fpscr, fpul, dr0, dr2, dr4 */
|
|
||||||
fmov.s fr0,@-r15
|
|
||||||
fmov.s fr1,@-r15
|
|
||||||
fmov.s fr2,@-r15
|
|
||||||
fmov.s fr3,@-r15
|
|
||||||
fmov.s fr4,@-r15
|
|
||||||
fmov.s fr5,@-r15
|
|
||||||
sts.l fpul,@-r15
|
|
||||||
sts.l fpscr,@-r15
|
|
||||||
|
|
||||||
mov r0,r4 /* arg 1, excode */
|
|
||||||
shlr2 r4 /* shift arg 1 over two more bits */
|
|
||||||
mov.l r4,@-r15 /* save the excode for after the call */
|
|
||||||
sts.l pr,@-r15 /* save the pr reg */
|
|
||||||
stc spc,r5 /* arg 2, spc */
|
|
||||||
mov.l initial_page_write_handler,r1
|
|
||||||
jsr @r1
|
|
||||||
nop
|
|
||||||
|
|
||||||
/* restore regs */
|
|
||||||
lds.l @r15+,pr
|
|
||||||
mov.l @r15+,r1
|
|
||||||
lds.l @r15+,fpscr
|
|
||||||
lds.l @r15+,fpul
|
|
||||||
fmov.s @r15+,fr5
|
|
||||||
fmov.s @r15+,fr4
|
|
||||||
fmov.s @r15+,fr3
|
|
||||||
fmov.s @r15+,fr2
|
|
||||||
fmov.s @r15+,fr1
|
|
||||||
fmov.s @r15+,fr0
|
|
||||||
|
|
||||||
/* see if the tlb handler returned another exception code */
|
|
||||||
/* if so, the tlb ipw just elevated to a page fault or other such */
|
|
||||||
/* 'soft' faults. */
|
|
||||||
|
|
||||||
cmp/eq r0,r1
|
|
||||||
bf _soft_fault
|
|
||||||
nop
|
|
||||||
|
|
||||||
/* return from the tlb miss */
|
|
||||||
stc sgr,r15
|
|
||||||
rte
|
|
||||||
nop
|
|
||||||
|
|
||||||
_soft_fault:
|
|
||||||
/* the tlb ipw handler returned another exception code */
|
|
||||||
/* we now need to enter the kernel with the soft fault */
|
|
||||||
shll2 r0
|
|
||||||
mov.l tea_addr1,r1
|
|
||||||
mov.l @r1,r1 /* load the faulted address */
|
|
||||||
bra switch_banks_and_enter_kernel
|
|
||||||
nop
|
|
||||||
|
|
||||||
.align 2
|
|
||||||
tea_addr1: .long 0xff00000c
|
|
||||||
expevt_addr1: .long 0xff000024
|
|
||||||
initial_page_write_handler: .long _tlb_initial_page_write
|
|
||||||
tlb_stack_addr1: .long tlb_stack_end-4
|
|
||||||
|
|
||||||
exception_ent_1_end:
|
|
||||||
.skip 0x300-(exception_ent_1_end-exception_ent_1)
|
|
||||||
TLB_miss_ent:
|
|
||||||
mov.l expevt_addr2,r4
|
|
||||||
mov.l @r4,r4
|
|
||||||
shlr2 r4
|
|
||||||
shlr2 r4
|
|
||||||
shlr r4 /* shift the exception code over 5 bits */
|
|
||||||
|
|
||||||
#if SAVE_CPU_STATE
|
|
||||||
/* dump the entire cpu state */
|
|
||||||
mov.l cpu_state_addr,r0
|
|
||||||
|
|
||||||
stc r0_bank,r1
|
|
||||||
mov.l r1,@(0,r0)
|
|
||||||
stc r1_bank,r1
|
|
||||||
mov.l r1,@(4,r0)
|
|
||||||
stc r2_bank,r1
|
|
||||||
mov.l r1,@(8,r0)
|
|
||||||
stc r3_bank,r1
|
|
||||||
mov.l r1,@(12,r0)
|
|
||||||
stc r4_bank,r1
|
|
||||||
mov.l r1,@(16,r0)
|
|
||||||
stc r5_bank,r1
|
|
||||||
mov.l r1,@(20,r0)
|
|
||||||
stc r6_bank,r1
|
|
||||||
mov.l r1,@(24,r0)
|
|
||||||
stc r7_bank,r1
|
|
||||||
mov.l r1,@(28,r0)
|
|
||||||
|
|
||||||
mov.l r8,@(32,r0)
|
|
||||||
mov.l r9,@(36,r0)
|
|
||||||
mov.l r10,@(40,r0)
|
|
||||||
mov.l r11,@(44,r0)
|
|
||||||
mov.l r12,@(48,r0)
|
|
||||||
mov.l r13,@(52,r0)
|
|
||||||
mov.l r14,@(56,r0)
|
|
||||||
|
|
||||||
mov.l r15,@(60,r0)
|
|
||||||
|
|
||||||
add #64,r0
|
|
||||||
|
|
||||||
stc gbr,r1
|
|
||||||
mov.l r1,@(0,r0)
|
|
||||||
sts mach,r1
|
|
||||||
mov.l r1,@(4,r0)
|
|
||||||
sts macl,r1
|
|
||||||
mov.l r1,@(8,r0)
|
|
||||||
sts pr,r1
|
|
||||||
mov.l r1,@(12,r0)
|
|
||||||
|
|
||||||
stc spc,r1
|
|
||||||
mov.l r1,@(16,r0)
|
|
||||||
stc sgr,r1
|
|
||||||
mov.l r1,@(20,r0)
|
|
||||||
stc ssr,r1
|
|
||||||
mov.l r1,@(24,r0)
|
|
||||||
|
|
||||||
sts fpul,r1
|
|
||||||
mov.l r1,@(28,r0)
|
|
||||||
sts fpscr,r1
|
|
||||||
mov.l r1,@(32,r0)
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* we can stay on reg bank 1, switch to a tlb stack */
|
|
||||||
mov.l tlb_stack_addr2,r15
|
|
||||||
|
|
||||||
/* save some of the floating point registers */
|
|
||||||
/* they seem to be used by some of the libgcc stuff */
|
|
||||||
/* saving: fpscr, fpul, dr0, dr2, dr4 */
|
|
||||||
fmov.s fr0,@-r15
|
|
||||||
fmov.s fr1,@-r15
|
|
||||||
fmov.s fr2,@-r15
|
|
||||||
fmov.s fr3,@-r15
|
|
||||||
fmov.s fr4,@-r15
|
|
||||||
fmov.s fr5,@-r15
|
|
||||||
sts.l fpul,@-r15
|
|
||||||
sts.l fpscr,@-r15
|
|
||||||
|
|
||||||
mov.l r4,@-r15 /* save the exception code */
|
|
||||||
sts.l pr,@-r15 /* save the pr reg */
|
|
||||||
|
|
||||||
/* arg 1 is exception code already in r4 */
|
|
||||||
stc spc,r5 /* arg 2, spc */
|
|
||||||
mov.l tlb_miss_handler,r1
|
|
||||||
jsr @r1
|
|
||||||
nop
|
|
||||||
|
|
||||||
/* see if the tlb miss handler returned another exception code */
|
|
||||||
/* if so, the tlb miss just elevated to a page fault or other such */
|
|
||||||
/* 'soft' faults. */
|
|
||||||
lds.l @r15+,pr /* restore pr */
|
|
||||||
mov.l @r15+,r1 /* restore the original exception code */
|
|
||||||
|
|
||||||
/* restore the saved floating point registers */
|
|
||||||
lds.l @r15+,fpscr
|
|
||||||
lds.l @r15+,fpul
|
|
||||||
fmov.s @r15+,fr5
|
|
||||||
fmov.s @r15+,fr4
|
|
||||||
fmov.s @r15+,fr3
|
|
||||||
fmov.s @r15+,fr2
|
|
||||||
fmov.s @r15+,fr1
|
|
||||||
fmov.s @r15+,fr0
|
|
||||||
|
|
||||||
cmp/eq r0,r1 /* check against the stored original exception code */
|
|
||||||
bf _soft_fault1
|
|
||||||
nop
|
|
||||||
|
|
||||||
/* return from the tlb miss */
|
|
||||||
stc sgr,r15
|
|
||||||
rte
|
|
||||||
nop
|
|
||||||
|
|
||||||
_soft_fault1:
|
|
||||||
/* the tlb miss handler returned another exception code */
|
|
||||||
/* we now need to enter the kernel with the soft fault */
|
|
||||||
|
|
||||||
shll2 r0
|
|
||||||
mov.l tea_addr2,r1
|
|
||||||
mov.l @r1,r1 /* load the faulted address */
|
|
||||||
bra switch_banks_and_enter_kernel
|
|
||||||
nop
|
|
||||||
|
|
||||||
.align 2
|
|
||||||
tea_addr2: .long 0xff00000c
|
|
||||||
expevt_addr2: .long 0xff000024
|
|
||||||
tlb_miss_handler: .long _tlb_miss
|
|
||||||
tlb_stack_addr2: .long tlb_stack_end-4
|
|
||||||
#if SAVE_CPU_STATE
|
|
||||||
cpu_state_addr: .long _last_ex_cpu_state
|
|
||||||
#endif
|
|
||||||
|
|
||||||
TLB_miss_ent_end:
|
|
||||||
.skip 0x200-(TLB_miss_ent_end-TLB_miss_ent)
|
|
||||||
interrupt_ent:
|
|
||||||
mov.l intevt_addr,r0
|
|
||||||
mov.l @r0,r0
|
|
||||||
shlr2 r0
|
|
||||||
shlr r0 /* shift the exception code over 3 bits */
|
|
||||||
|
|
||||||
/*
|
|
||||||
** args to here are
|
|
||||||
** r0: exception number (shifted left 3 bits from the cpus version
|
|
||||||
** r1: page fault address (if applicable, it still gets saved)
|
|
||||||
*/
|
|
||||||
switch_banks_and_enter_kernel:
|
|
||||||
/* disable interrupts */
|
|
||||||
mov.l imask,r3
|
|
||||||
stc sr,r2
|
|
||||||
or r3,r2
|
|
||||||
ldc r2,sr
|
|
||||||
|
|
||||||
/* check to see if we are not already using the saved_* locations */
|
|
||||||
mov.l is_pushing_registers,r2
|
|
||||||
mov #1,r3
|
|
||||||
and r2,r3
|
|
||||||
bf _save_regs
|
|
||||||
|
|
||||||
/* okay, we are in a bad state right now.
|
|
||||||
** apparently we were already in the process of moving saved registers
|
|
||||||
** from the saved_* locations. This will happen if we take a page fault
|
|
||||||
** while pushing registers to the kernel stack, for example. We are toast.
|
|
||||||
*/
|
|
||||||
mov.l tlb_stack_addr3,r15
|
|
||||||
mov.l reentrant_fault_handler,r2
|
|
||||||
jsr @r2
|
|
||||||
nop
|
|
||||||
|
|
||||||
_save_regs:
|
|
||||||
/* save the saved registers into memory */
|
|
||||||
/* this ends up with the important registers in saved_spc and friends */
|
|
||||||
mov.l is_pushing_registers_addr,r2
|
|
||||||
mov #1,r3
|
|
||||||
mov.l r3,@r2
|
|
||||||
|
|
||||||
mov.l save_stack,r2
|
|
||||||
stc.l spc,@-r2
|
|
||||||
stc.l ssr,@-r2
|
|
||||||
stc.l sgr,@-r2
|
|
||||||
mov.l r0,@-r2 /* put the modified exception code there too */
|
|
||||||
mov.l r1,@-r2 /* put the saved page fault address */
|
|
||||||
|
|
||||||
/* see if we need to load the kernel stack or stay on the current one */
|
|
||||||
stc ssr,r0
|
|
||||||
mov.l md_bit_mask,r1
|
|
||||||
and r1,r0
|
|
||||||
cmp/eq r1,r0
|
|
||||||
bt _keep_current_stack
|
|
||||||
nop
|
|
||||||
|
|
||||||
/* we need to set the stack because we came from user space */
|
|
||||||
mov.l kstack,r15
|
|
||||||
bra _have_set_stack
|
|
||||||
nop
|
|
||||||
|
|
||||||
_keep_current_stack:
|
|
||||||
stc sgr,r15
|
|
||||||
|
|
||||||
_have_set_stack:
|
|
||||||
/* enable exceptions & swap banks back to 0 */
|
|
||||||
mov.l bl_rb_bit_mask,r0
|
|
||||||
stc sr,r1
|
|
||||||
and r0,r1
|
|
||||||
ldc r1,sr
|
|
||||||
|
|
||||||
/*
|
|
||||||
** From now on we can take exceptions, though taking any between now
|
|
||||||
** and the time at which we move saved stuff out of saved_sgr and other
|
|
||||||
** fixed save points would be fatal. We are only pushing it on the kernel
|
|
||||||
** stack, which has to be present always anyway, so its not a problem, since
|
|
||||||
** a page fault is the only one we can realistically take right now anyway.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* start pushing registers */
|
|
||||||
mov.l r8,@-r15
|
|
||||||
mov.l r9,@-r15
|
|
||||||
mov.l r10,@-r15
|
|
||||||
mov.l r11,@-r15
|
|
||||||
mov.l r12,@-r15
|
|
||||||
mov.l r13,@-r15
|
|
||||||
mov.l r14,@-r15
|
|
||||||
|
|
||||||
/* push r0-r7 */
|
|
||||||
mov.l r0,@-r15
|
|
||||||
mov.l r1,@-r15
|
|
||||||
mov.l r2,@-r15
|
|
||||||
mov.l r3,@-r15
|
|
||||||
mov.l r4,@-r15
|
|
||||||
mov.l r5,@-r15
|
|
||||||
mov.l r6,@-r15
|
|
||||||
mov.l r7,@-r15
|
|
||||||
|
|
||||||
_after_r0r7_save:
|
|
||||||
/* save the floating point registers */
|
|
||||||
/* XXX see about optimizing this later */
|
|
||||||
fmov.s fr0,@-r15
|
|
||||||
fmov.s fr1,@-r15
|
|
||||||
fmov.s fr2,@-r15
|
|
||||||
fmov.s fr3,@-r15
|
|
||||||
fmov.s fr4,@-r15
|
|
||||||
fmov.s fr5,@-r15
|
|
||||||
fmov.s fr6,@-r15
|
|
||||||
fmov.s fr7,@-r15
|
|
||||||
fmov.s fr8,@-r15
|
|
||||||
fmov.s fr9,@-r15
|
|
||||||
fmov.s fr10,@-r15
|
|
||||||
fmov.s fr11,@-r15
|
|
||||||
fmov.s fr12,@-r15
|
|
||||||
fmov.s fr13,@-r15
|
|
||||||
fmov.s fr14,@-r15
|
|
||||||
fmov.s fr15,@-r15
|
|
||||||
frchg
|
|
||||||
fmov.s fr0,@-r15
|
|
||||||
fmov.s fr1,@-r15
|
|
||||||
fmov.s fr2,@-r15
|
|
||||||
fmov.s fr3,@-r15
|
|
||||||
fmov.s fr4,@-r15
|
|
||||||
fmov.s fr5,@-r15
|
|
||||||
fmov.s fr6,@-r15
|
|
||||||
fmov.s fr7,@-r15
|
|
||||||
fmov.s fr8,@-r15
|
|
||||||
fmov.s fr9,@-r15
|
|
||||||
fmov.s fr10,@-r15
|
|
||||||
fmov.s fr11,@-r15
|
|
||||||
fmov.s fr12,@-r15
|
|
||||||
fmov.s fr13,@-r15
|
|
||||||
fmov.s fr14,@-r15
|
|
||||||
fmov.s fr15,@-r15
|
|
||||||
frchg
|
|
||||||
sts.l fpul,@-r15
|
|
||||||
sts.l fpscr,@-r15
|
|
||||||
|
|
||||||
/* can save most of the special registers we need in r8-r14 */
|
|
||||||
/* the abi we are working with saves r8-14 on function calls */
|
|
||||||
stc.l gbr,@-r15
|
|
||||||
sts.l mach,@-r15
|
|
||||||
sts.l macl,@-r15
|
|
||||||
sts.l pr,@-r15
|
|
||||||
mov.l saved_sgr,r12
|
|
||||||
mov.l r12,@-r15
|
|
||||||
mov.l saved_ssr,r12
|
|
||||||
mov.l r12,@-r15
|
|
||||||
mov.l saved_spc,r12
|
|
||||||
mov.l r12,@-r15
|
|
||||||
mov.l saved_excode,r12
|
|
||||||
shlr2 r12
|
|
||||||
mov.l r12,@-r15
|
|
||||||
mov.l saved_pfault,r12
|
|
||||||
mov.l r12,@-r15
|
|
||||||
|
|
||||||
/* record that we are not in a critical section now where we cant */
|
|
||||||
/* take an exception */
|
|
||||||
mov.l is_pushing_registers_addr,r2
|
|
||||||
mov #0,r3
|
|
||||||
mov.l r3,@r2
|
|
||||||
|
|
||||||
/* arg1: address of the iframe */
|
|
||||||
mov r15,r4
|
|
||||||
|
|
||||||
/* jump through the vector table into the kernel */
|
|
||||||
mov.l vector_table_addr,r0
|
|
||||||
mov.l saved_excode,r2
|
|
||||||
mov.l @(r0,r2),r1
|
|
||||||
jsr @r1
|
|
||||||
nop
|
|
||||||
|
|
||||||
/* entering a critical section now where we cant */
|
|
||||||
/* take an exception */
|
|
||||||
mov.l is_pushing_registers_addr,r2
|
|
||||||
mov #1,r3
|
|
||||||
mov.l r3,@r2
|
|
||||||
|
|
||||||
/* restore everything and get outta here */
|
|
||||||
add #0x8,r15 /* pop the pfault and excode data from the stack */
|
|
||||||
mov.l saved_spc_addr,r1
|
|
||||||
mov.l @r15+,r2
|
|
||||||
mov.l r2,@r1
|
|
||||||
mov.l saved_ssr_addr,r1
|
|
||||||
mov.l @r15+,r2
|
|
||||||
mov.l r2,@r1
|
|
||||||
mov.l saved_sgr_addr,r1
|
|
||||||
mov.l @r15+,r2
|
|
||||||
mov.l r2,@r1
|
|
||||||
lds.l @r15+,pr
|
|
||||||
lds.l @r15+,macl
|
|
||||||
lds.l @r15+,mach
|
|
||||||
ldc.l @r15+,gbr
|
|
||||||
|
|
||||||
/* restore the floating point registers */
|
|
||||||
lds.l @r15+,fpscr
|
|
||||||
lds.l @r15+,fpul
|
|
||||||
frchg
|
|
||||||
fmov.s @r15+,fr15
|
|
||||||
fmov.s @r15+,fr14
|
|
||||||
fmov.s @r15+,fr13
|
|
||||||
fmov.s @r15+,fr12
|
|
||||||
fmov.s @r15+,fr11
|
|
||||||
fmov.s @r15+,fr10
|
|
||||||
fmov.s @r15+,fr9
|
|
||||||
fmov.s @r15+,fr8
|
|
||||||
fmov.s @r15+,fr7
|
|
||||||
fmov.s @r15+,fr6
|
|
||||||
fmov.s @r15+,fr5
|
|
||||||
fmov.s @r15+,fr4
|
|
||||||
fmov.s @r15+,fr3
|
|
||||||
fmov.s @r15+,fr2
|
|
||||||
fmov.s @r15+,fr1
|
|
||||||
fmov.s @r15+,fr0
|
|
||||||
frchg
|
|
||||||
fmov.s @r15+,fr15
|
|
||||||
fmov.s @r15+,fr14
|
|
||||||
fmov.s @r15+,fr13
|
|
||||||
fmov.s @r15+,fr12
|
|
||||||
fmov.s @r15+,fr11
|
|
||||||
fmov.s @r15+,fr10
|
|
||||||
fmov.s @r15+,fr9
|
|
||||||
fmov.s @r15+,fr8
|
|
||||||
fmov.s @r15+,fr7
|
|
||||||
fmov.s @r15+,fr6
|
|
||||||
fmov.s @r15+,fr5
|
|
||||||
fmov.s @r15+,fr4
|
|
||||||
fmov.s @r15+,fr3
|
|
||||||
fmov.s @r15+,fr2
|
|
||||||
fmov.s @r15+,fr1
|
|
||||||
fmov.s @r15+,fr0
|
|
||||||
|
|
||||||
mov.l @r15+,r7
|
|
||||||
mov.l @r15+,r6
|
|
||||||
mov.l @r15+,r5
|
|
||||||
mov.l @r15+,r4
|
|
||||||
mov.l @r15+,r3
|
|
||||||
mov.l @r15+,r2
|
|
||||||
mov.l @r15+,r1
|
|
||||||
mov.l @r15+,r0
|
|
||||||
|
|
||||||
_after_r0r7_restore:
|
|
||||||
/* We need to calculate a new sr with exceptions off & register bank 1*/
|
|
||||||
mov.l bl_rb_bit_mask,r8
|
|
||||||
not r8,r8
|
|
||||||
stc sr,r9
|
|
||||||
or r9,r8
|
|
||||||
mov.l modified_sr_addr,r9
|
|
||||||
mov.l r8,@r9
|
|
||||||
|
|
||||||
/* pop the last few registers */
|
|
||||||
mov.l @r15+,r14
|
|
||||||
mov.l @r15+,r13
|
|
||||||
mov.l @r15+,r12
|
|
||||||
mov.l @r15+,r11
|
|
||||||
mov.l @r15+,r10
|
|
||||||
mov.l @r15+,r9
|
|
||||||
mov.l @r15+,r8
|
|
||||||
|
|
||||||
/* now we only have r15 to use */
|
|
||||||
mov.l modified_sr,r15
|
|
||||||
ldc r15,sr
|
|
||||||
|
|
||||||
/* restore the ssr & spc registers */
|
|
||||||
mov.l saved_spc,r15
|
|
||||||
ldc r15,spc
|
|
||||||
mov.l saved_ssr,r15
|
|
||||||
ldc r15,ssr
|
|
||||||
mov.l saved_sgr,r15
|
|
||||||
|
|
||||||
/* record that we are not in a critical section now where we cant */
|
|
||||||
/* take an exception */
|
|
||||||
mov.l is_pushing_registers_addr,r2
|
|
||||||
mov #0,r3
|
|
||||||
mov.l r3,@r2
|
|
||||||
|
|
||||||
/* get out of here */
|
|
||||||
rte
|
|
||||||
nop
|
|
||||||
|
|
||||||
.align 2
|
|
||||||
reentrant_fault_handler: .long _reentrant_fault
|
|
||||||
modified_sr_addr: .long modified_sr
|
|
||||||
vector_table_addr: .long vector_table
|
|
||||||
trap_exception: .long 0x2c
|
|
||||||
vector_base_addr: .long _vector_base
|
|
||||||
md_bit_mask: .long 0x40000000
|
|
||||||
bl_rb_bit_mask: .long 0xcfffffff
|
|
||||||
saved_page_fault_addr: .long saved_pfault
|
|
||||||
saved_excode_addr: .long saved_excode
|
|
||||||
saved_spc_addr: .long saved_spc
|
|
||||||
saved_ssr_addr: .long saved_ssr
|
|
||||||
saved_sgr_addr: .long saved_sgr
|
|
||||||
tlb_stack_addr3: .long tlb_stack_end-4
|
|
||||||
intevt_addr: .long 0xff000028
|
|
||||||
tra_addr: .long 0xff000020
|
|
||||||
imask: .long 0x000000f0
|
|
||||||
|
|
||||||
/* the next memory addresses are used for temporary storage or
|
|
||||||
data structures for the kernel to write in. They are in the
|
|
||||||
text segment, I know, but its much faster if we can reference
|
|
||||||
them pcrel. */
|
|
||||||
saved_pfault: .long 0
|
|
||||||
saved_excode: .long 0
|
|
||||||
saved_sgr: .long 0
|
|
||||||
saved_ssr: .long 0
|
|
||||||
saved_spc: .long 0 /* these four addresses are used to
|
|
||||||
save the saved registers while we switch to another
|
|
||||||
stack and register set */
|
|
||||||
save_stack: .long saved_spc+4
|
|
||||||
modified_sr: .long 0
|
|
||||||
|
|
||||||
/* stores whether or not we are in a state at which we cannot take a fault */
|
|
||||||
is_pushing_registers: .long 0
|
|
||||||
is_pushing_registers_addr: .long is_pushing_registers
|
|
||||||
|
|
||||||
/* These memory locations are written to by the kernel */
|
|
||||||
.globl _kernel_struct
|
|
||||||
_kernel_struct:
|
|
||||||
kernel_pgdir: .long 0
|
|
||||||
user_pgdir: .long 0
|
|
||||||
kernel_asid: .long 0
|
|
||||||
user_asid: .long 0
|
|
||||||
kstack: .long 0
|
|
||||||
vector_table:
|
|
||||||
.rep 0x100
|
|
||||||
.long 0
|
|
||||||
.endr
|
|
||||||
|
|
||||||
.data
|
|
||||||
.align 4
|
|
||||||
tlb_stack:
|
|
||||||
.rep 0x1000
|
|
||||||
.long 0
|
|
||||||
.endr
|
|
||||||
tlb_stack_end:
|
|
||||||
|
|
||||||
#if SAVE_CPU_STATE
|
|
||||||
.align 4
|
|
||||||
.global _last_ex_cpu_state
|
|
||||||
_last_ex_cpu_state:
|
|
||||||
.rep 0x1000
|
|
||||||
.long 99
|
|
||||||
.endr
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,448 +0,0 @@
|
|||||||
/*
|
|
||||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
|
||||||
** Distributed under the terms of the NewOS License.
|
|
||||||
*/
|
|
||||||
#include <arch/sh4/vcpu.h>
|
|
||||||
#include <arch/sh4/vcpu_struct.h>
|
|
||||||
#include <boot/stage2.h>
|
|
||||||
#include "serial.h"
|
|
||||||
#include <string.h>
|
|
||||||
#include <arch/cpu.h>
|
|
||||||
#include <arch/sh4/sh4.h>
|
|
||||||
|
|
||||||
#define SAVE_CPU_STATE 0
|
|
||||||
|
|
||||||
#define ROUNDUP(a, b) (((a) + ((b)-1)) & ~((b)-1))
|
|
||||||
|
|
||||||
#define CHATTY_TLB 0
|
|
||||||
|
|
||||||
extern vcpu_struct kernel_struct;
|
|
||||||
#if SAVE_CPU_STATE
|
|
||||||
extern unsigned int last_ex_cpu_state[];
|
|
||||||
#endif
|
|
||||||
unsigned int next_utlb_ent = 0;
|
|
||||||
|
|
||||||
unsigned int vector_base();
|
|
||||||
unsigned int boot_stack[256] = { 0, };
|
|
||||||
|
|
||||||
void vcpu_clear_all_itlb_entries();
|
|
||||||
void vcpu_clear_all_utlb_entries();
|
|
||||||
void vcpu_dump_utlb_entry(int ent);
|
|
||||||
void vcpu_dump_all_itlb_entries();
|
|
||||||
void vcpu_dump_all_utlb_entries();
|
|
||||||
|
|
||||||
unsigned int get_sr();
|
|
||||||
void set_sr(unsigned int sr);
|
|
||||||
unsigned int get_vbr();
|
|
||||||
void set_vbr(unsigned int vbr);
|
|
||||||
unsigned int get_sgr();
|
|
||||||
unsigned int get_ssr();
|
|
||||||
unsigned int get_spc();
|
|
||||||
asm(
|
|
||||||
".globl _get_sr,_set_sr\n"
|
|
||||||
".globl _get_vbr,_set_vbr\n"
|
|
||||||
".globl _get_sgr\n"
|
|
||||||
|
|
||||||
"_get_sr:\n"
|
|
||||||
" stc sr,r0\n"
|
|
||||||
" rts\n"
|
|
||||||
" nop\n"
|
|
||||||
|
|
||||||
"_set_sr:\n"
|
|
||||||
" ldc r4,sr\n"
|
|
||||||
" rts\n"
|
|
||||||
" nop\n"
|
|
||||||
|
|
||||||
"_get_vbr:\n"
|
|
||||||
" stc vbr,r0\n"
|
|
||||||
" rts\n"
|
|
||||||
" nop\n"
|
|
||||||
|
|
||||||
"_set_vbr:\n"
|
|
||||||
" ldc r4,vbr\n"
|
|
||||||
" rts\n"
|
|
||||||
" nop\n"
|
|
||||||
|
|
||||||
"_get_sgr:\n"
|
|
||||||
" stc sgr,r0\n"
|
|
||||||
" rts\n"
|
|
||||||
" nop\n"
|
|
||||||
|
|
||||||
"_get_ssr:\n"
|
|
||||||
" stc ssr,r0\n"
|
|
||||||
" rts\n"
|
|
||||||
" nop\n"
|
|
||||||
|
|
||||||
"_get_spc:\n"
|
|
||||||
" stc spc,r0\n"
|
|
||||||
" rts\n"
|
|
||||||
" nop\n"
|
|
||||||
);
|
|
||||||
|
|
||||||
#if SAVE_CPU_STATE
|
|
||||||
static void dump_cpu_state()
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
unsigned int *stack;
|
|
||||||
unsigned int *stack_top;
|
|
||||||
|
|
||||||
dprintf("dump_cpu_state entry\n");
|
|
||||||
|
|
||||||
dprintf("registers:\n");
|
|
||||||
for(i=0; i<16; i++) {
|
|
||||||
dprintf("r%d 0x%x\n", i, last_ex_cpu_state[i]);
|
|
||||||
}
|
|
||||||
dprintf("gbr 0x%x\n", last_ex_cpu_state[16]);
|
|
||||||
dprintf("mach 0x%x\n", last_ex_cpu_state[17]);
|
|
||||||
dprintf("macl 0x%x\n", last_ex_cpu_state[18]);
|
|
||||||
dprintf("pr 0x%x\n", last_ex_cpu_state[19]);
|
|
||||||
dprintf("spc 0x%x\n", last_ex_cpu_state[20]);
|
|
||||||
dprintf("sgr 0x%x\n", last_ex_cpu_state[21]);
|
|
||||||
dprintf("ssr 0x%x\n", last_ex_cpu_state[22]);
|
|
||||||
dprintf("fpul 0x%x\n", last_ex_cpu_state[23]);
|
|
||||||
dprintf("fpscr 0x%x\n", last_ex_cpu_state[24]);
|
|
||||||
|
|
||||||
stack = (unsigned int *)(get_sgr() - 0x200);
|
|
||||||
stack_top = (unsigned int *)ROUNDUP((unsigned int)stack, PAGE_SIZE);
|
|
||||||
dprintf("stack at 0x%x to 0x%x\n", stack, stack_top);
|
|
||||||
// dump the stack
|
|
||||||
for(;stack < stack_top; stack++)
|
|
||||||
dprintf("0x%x\n", *stack);
|
|
||||||
|
|
||||||
dprintf("utlb entries:\n");
|
|
||||||
vcpu_dump_all_utlb_entries();
|
|
||||||
dprintf("itlb entries:\n");
|
|
||||||
vcpu_dump_all_itlb_entries();
|
|
||||||
|
|
||||||
|
|
||||||
for(;;);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
int reentrant_fault()
|
|
||||||
{
|
|
||||||
dprintf("bad reentrancy fault\n");
|
|
||||||
dprintf("spinning forever\n");
|
|
||||||
for(;;);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int default_vector(void *_frame)
|
|
||||||
{
|
|
||||||
struct iframe *frame = (struct iframe *)_frame;
|
|
||||||
|
|
||||||
dprintf("default_vector: ex_code 0x%x, pc 0x%x\n", frame->excode, frame->spc);
|
|
||||||
dprintf("sgr = 0x%x\n", frame->sgr);
|
|
||||||
dprintf("spinning forever\n");
|
|
||||||
for(;;);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int vcpu_init(kernel_args *ka)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
unsigned int sr;
|
|
||||||
unsigned int vbr;
|
|
||||||
|
|
||||||
dprintf("vcpu_init: entry\n");
|
|
||||||
|
|
||||||
memset(&kernel_struct, 0, sizeof(kernel_struct));
|
|
||||||
for(i=0; i<256; i++) {
|
|
||||||
kernel_struct.vt[i].func = &default_vector;
|
|
||||||
}
|
|
||||||
kernel_struct.kstack = (unsigned int *)((int)boot_stack + sizeof(boot_stack) - 4);
|
|
||||||
|
|
||||||
// set the vbr
|
|
||||||
vbr = (unsigned int)&vector_base;
|
|
||||||
set_vbr(vbr);
|
|
||||||
dprintf("vbr = 0x%x\n", get_vbr());
|
|
||||||
|
|
||||||
// disable exceptions
|
|
||||||
sr = get_sr();
|
|
||||||
sr |= 0x10000000;
|
|
||||||
set_sr(sr);
|
|
||||||
|
|
||||||
if((sr & 0x20000000) != 0) {
|
|
||||||
// we're using register bank 1 now
|
|
||||||
dprintf("using bank 1, switching register banks\n");
|
|
||||||
// this switches in the bottom 8 registers.
|
|
||||||
// dont have to do anything more, since the bottom 8 are
|
|
||||||
// not saved in the call.
|
|
||||||
set_sr(sr & 0xdfffffff);
|
|
||||||
}
|
|
||||||
|
|
||||||
// enable exceptions
|
|
||||||
sr = get_sr();
|
|
||||||
sr &= 0xefffffff;
|
|
||||||
set_sr(sr);
|
|
||||||
|
|
||||||
ka->arch_args.vcpu = &kernel_struct;
|
|
||||||
|
|
||||||
// enable the mmu
|
|
||||||
vcpu_clear_all_itlb_entries();
|
|
||||||
vcpu_clear_all_utlb_entries();
|
|
||||||
*(int *)PTEH = 0;
|
|
||||||
*(int *)MMUCR = 0x00000105;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct ptent *get_ptent(struct pdent *pd, unsigned int fault_address)
|
|
||||||
{
|
|
||||||
struct ptent *pt;
|
|
||||||
|
|
||||||
#if CHATTY_TLB
|
|
||||||
dprintf("get_ptent: fault_address 0x%x\n", fault_address);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if((unsigned int)pd < P1_PHYS_MEM_START || (unsigned int)pd >= P1_PHYS_MEM_END) {
|
|
||||||
#if CHATTY_TLB
|
|
||||||
dprintf("get_ptent: bad pdent 0x%x\n", pd);
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(pd[fault_address >> 22].v == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
pt = (struct ptent *)PHYS_ADDR_TO_P1(pd[fault_address >> 22].ppn << 12);
|
|
||||||
#if CHATTY_TLB
|
|
||||||
dprintf("get_ptent: found ptent 0x%x\n", pt);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return &pt[(fault_address >> 12) & 0x000003ff];
|
|
||||||
}
|
|
||||||
|
|
||||||
static void tlb_map(unsigned int vpn, struct ptent *ptent, unsigned int tlb_ent, unsigned int asid)
|
|
||||||
{
|
|
||||||
union {
|
|
||||||
struct utlb_data data;
|
|
||||||
unsigned int n[3];
|
|
||||||
} u;
|
|
||||||
|
|
||||||
ptent->tlb_ent = tlb_ent;
|
|
||||||
|
|
||||||
u.n[0] = 0;
|
|
||||||
u.data.a.asid = asid;
|
|
||||||
u.data.a.vpn = vpn << 2;
|
|
||||||
u.data.a.dirty = ptent->d;
|
|
||||||
u.data.a.valid = 1;
|
|
||||||
|
|
||||||
u.n[1] = 0;
|
|
||||||
u.data.da1.ppn = ptent->ppn << 2;
|
|
||||||
u.data.da1.valid = 1;
|
|
||||||
u.data.da1.psize1 = (ptent->sz & 0x2) ? 1 : 0;
|
|
||||||
u.data.da1.prot_key = ptent->pr;
|
|
||||||
u.data.da1.psize0 = ptent->sz & 0x1;
|
|
||||||
u.data.da1.cacheability = ptent->c;
|
|
||||||
u.data.da1.dirty = ptent->d;
|
|
||||||
u.data.da1.sh = ptent->sh;
|
|
||||||
u.data.da1.wt = ptent->wt;
|
|
||||||
|
|
||||||
u.n[2] = 0;
|
|
||||||
|
|
||||||
*((unsigned int *)(UTLB | (next_utlb_ent << UTLB_ADDR_SHIFT))) = u.n[0];
|
|
||||||
*((unsigned int *)(UTLB1 | (next_utlb_ent << UTLB_ADDR_SHIFT))) = u.n[1];
|
|
||||||
*((unsigned int *)(UTLB2 | (next_utlb_ent << UTLB_ADDR_SHIFT))) = u.n[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int tlb_miss(unsigned int excode, unsigned int pc)
|
|
||||||
{
|
|
||||||
struct pdent *pd;
|
|
||||||
struct ptent *ent;
|
|
||||||
unsigned int fault_addr = *(unsigned int *)TEA;
|
|
||||||
unsigned int shifted_fault_addr;
|
|
||||||
unsigned int asid;
|
|
||||||
|
|
||||||
#if CHATTY_TLB
|
|
||||||
dprintf("tlb_miss: excode 0x%x, pc 0x%x, sgr 0x%x, fault_address 0x%x\n", excode, pc, get_sgr(), fault_addr);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// if(fault_addr == 0 || pc == 0 || get_sgr() == 0)
|
|
||||||
// dump_cpu_state();
|
|
||||||
|
|
||||||
if(fault_addr >= P1_AREA) {
|
|
||||||
pd = (struct pdent *)kernel_struct.kernel_pgdir;
|
|
||||||
asid = kernel_struct.kernel_asid;
|
|
||||||
shifted_fault_addr = fault_addr & 0x7fffffff;
|
|
||||||
} else {
|
|
||||||
pd = (struct pdent *)kernel_struct.user_pgdir;
|
|
||||||
asid = kernel_struct.user_asid;
|
|
||||||
shifted_fault_addr = fault_addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
ent = get_ptent(pd, shifted_fault_addr);
|
|
||||||
if(ent == NULL || ent->v == 0) {
|
|
||||||
if(excode == 0x2)
|
|
||||||
return EXCEPTION_PAGE_FAULT_READ;
|
|
||||||
else
|
|
||||||
return EXCEPTION_PAGE_FAULT_WRITE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if CHATTY_TLB
|
|
||||||
dprintf("found entry. vaddr 0x%x maps to paddr 0x%x\n",
|
|
||||||
fault_addr, ent->ppn << 12);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
if(excode == 0x3) {
|
|
||||||
// this is a tlb miss because of a write, so
|
|
||||||
// go ahead and mark it dirty
|
|
||||||
ent->d = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// XXX hack!
|
|
||||||
if(fault_addr == 0x7ffffff8) {
|
|
||||||
dprintf("sr = 0x%x\n", get_sr());
|
|
||||||
dprintf("ssr = 0x%x sgr = 0x%x spc = 0x%x\n", get_ssr(), get_sgr(), get_spc());
|
|
||||||
dprintf("kernel_struct: kpgdir 0x%x upgdir 0x%x kasid 0x%x uasid 0x%x kstack 0x%x\n",
|
|
||||||
kernel_struct.kernel_pgdir, kernel_struct.user_pgdir, kernel_struct.kernel_asid,
|
|
||||||
kernel_struct.user_asid, kernel_struct.kstack);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#if 0
|
|
||||||
{
|
|
||||||
static int clear_all = 0;
|
|
||||||
if(fault_addr == 0x7ffffff8)
|
|
||||||
clear_all = 1;
|
|
||||||
if(clear_all)
|
|
||||||
vcpu_clear_all_utlb_entries();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
tlb_map(fault_addr >> 12, ent, next_utlb_ent, asid);
|
|
||||||
#if CHATTY_TLB
|
|
||||||
vcpu_dump_utlb_entry(next_utlb_ent);
|
|
||||||
#endif
|
|
||||||
next_utlb_ent++;
|
|
||||||
if(next_utlb_ent >= UTLB_COUNT)
|
|
||||||
next_utlb_ent = 0;
|
|
||||||
|
|
||||||
#if CHATTY_TLB
|
|
||||||
dprintf("tlb_miss exit\n");
|
|
||||||
#endif
|
|
||||||
return excode;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int tlb_initial_page_write(unsigned int excode, unsigned int pc)
|
|
||||||
{
|
|
||||||
struct pdent *pd;
|
|
||||||
struct ptent *ent;
|
|
||||||
unsigned int fault_addr = *(unsigned int *)TEA;
|
|
||||||
unsigned int shifted_fault_addr;
|
|
||||||
unsigned int asid;
|
|
||||||
|
|
||||||
#if CHATTY_TLB
|
|
||||||
dprintf("tlb_initial_page_write: excode 0x%x, pc 0x%x, fault_address 0x%x\n",
|
|
||||||
excode, pc, fault_addr);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(fault_addr >= P1_AREA) {
|
|
||||||
pd = (struct pdent *)kernel_struct.kernel_pgdir;
|
|
||||||
asid = kernel_struct.kernel_asid;
|
|
||||||
shifted_fault_addr = fault_addr & 0x7fffffff;
|
|
||||||
} else {
|
|
||||||
pd = (struct pdent *)kernel_struct.user_pgdir;
|
|
||||||
asid = kernel_struct.user_asid;
|
|
||||||
shifted_fault_addr = fault_addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
ent = get_ptent(pd, shifted_fault_addr);
|
|
||||||
if(ent == NULL || ent->v == 0) {
|
|
||||||
// if we're here, the page table is
|
|
||||||
// out of sync with the tlb cache.
|
|
||||||
// time to die.
|
|
||||||
dprintf("tlb_ipw exception called but no page table ent exists!\n");
|
|
||||||
for(;;);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
struct utlb_addr_array *a;
|
|
||||||
struct utlb_data_array_1 *da1;
|
|
||||||
|
|
||||||
a = (struct utlb_addr_array *)(UTLB | (ent->tlb_ent << UTLB_ADDR_SHIFT));
|
|
||||||
da1 = (struct utlb_data_array_1 *)(UTLB1 | (ent->tlb_ent << UTLB_ADDR_SHIFT));
|
|
||||||
|
|
||||||
// inspect this tlb entry to make sure it's the right one
|
|
||||||
if(asid != a->asid || (ent->ppn << 2) != da1->ppn || ((fault_addr >> 12) << 2) != a->vpn) {
|
|
||||||
dprintf("tlb_ipw exception found that the page table out of sync with tlb\n");
|
|
||||||
dprintf("page_table entry: 0x%x\n", *(unsigned int *)ent);
|
|
||||||
vcpu_dump_utlb_entry(ent->tlb_ent);
|
|
||||||
for(;;);
|
|
||||||
}
|
|
||||||
a->dirty = 1;
|
|
||||||
ent->d = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return excode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void vcpu_dump_itlb_entry(int ent)
|
|
||||||
{
|
|
||||||
struct itlb_data data;
|
|
||||||
|
|
||||||
*(int *)&data.a = *((int *)(ITLB | (ent << ITLB_ADDR_SHIFT)));
|
|
||||||
*(int *)&data.da1 = *((int *)(ITLB1 | (ent << ITLB_ADDR_SHIFT)));
|
|
||||||
*(int *)&data.da2 = *((int *)(ITLB2 | (ent << ITLB_ADDR_SHIFT)));
|
|
||||||
|
|
||||||
dprintf("itlb[%d] = \n", ent);
|
|
||||||
dprintf(" asid = %d\n", data.a.asid);
|
|
||||||
dprintf(" valid = %d\n", data.a.valid);
|
|
||||||
dprintf(" vpn = 0x%x\n", data.a.vpn << 10);
|
|
||||||
dprintf(" ppn = 0x%x\n", data.da1.ppn << 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
void vcpu_clear_all_itlb_entries()
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for(i=0; i<4; i++) {
|
|
||||||
*((int *)(ITLB | (i << ITLB_ADDR_SHIFT))) = 0;
|
|
||||||
*((int *)(ITLB1 | (i << ITLB_ADDR_SHIFT))) = 0;
|
|
||||||
*((int *)(ITLB2 | (i << ITLB_ADDR_SHIFT))) = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void vcpu_dump_all_itlb_entries()
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for(i=0; i<4; i++) {
|
|
||||||
vcpu_dump_itlb_entry(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void vcpu_dump_utlb_entry(int ent)
|
|
||||||
{
|
|
||||||
struct utlb_data data;
|
|
||||||
|
|
||||||
*(int *)&data.a = *((int *)(UTLB | (ent << UTLB_ADDR_SHIFT)));
|
|
||||||
*(int *)&data.da1 = *((int *)(UTLB1 | (ent << UTLB_ADDR_SHIFT)));
|
|
||||||
*(int *)&data.da2 = *((int *)(UTLB2 | (ent << UTLB_ADDR_SHIFT)));
|
|
||||||
|
|
||||||
dprintf("utlb[%d] = \n", ent);
|
|
||||||
dprintf(" asid = %d\n", data.a.asid);
|
|
||||||
dprintf(" valid = %d\n", data.a.valid);
|
|
||||||
dprintf(" dirty = %d\n", data.a.dirty);
|
|
||||||
dprintf(" vpn = 0x%x\n", data.a.vpn << 10);
|
|
||||||
dprintf(" ppn = 0x%x\n", data.da1.ppn << 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
void vcpu_clear_all_utlb_entries()
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for(i=0; i<64; i++) {
|
|
||||||
*((int *)(UTLB | (i << UTLB_ADDR_SHIFT))) = 0;
|
|
||||||
*((int *)(UTLB1 | (i << UTLB_ADDR_SHIFT))) = 0;
|
|
||||||
*((int *)(UTLB2 | (i << UTLB_ADDR_SHIFT))) = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void vcpu_dump_all_utlb_entries()
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for(i=0; i<64; i++) {
|
|
||||||
vcpu_dump_utlb_entry(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
SubDir HAIKU_TOP src system boot arch sparc ;
|
|
||||||
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
/* $OpenBSD: closeall.c,v 1.1 1997/09/17 10:46:16 downsj Exp $ */
|
|
||||||
|
|
||||||
void
|
|
||||||
closeall()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,122 +0,0 @@
|
|||||||
/* $OpenBSD: dvma.c,v 1.1 1997/09/17 10:46:18 downsj Exp $ */
|
|
||||||
/* $NetBSD: dvma.c,v 1.2 1995/09/17 00:50:56 pk Exp $ */
|
|
||||||
/*
|
|
||||||
* Copyright (c) 1995 Gordon W. Ross
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
* 4. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by Gordon Ross
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
||||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
||||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
||||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The easiest way to deal with the need for DVMA mappings is
|
|
||||||
* to just map the entire third megabyte of RAM into DVMA space.
|
|
||||||
* That way, dvma_mapin can just compute the DVMA alias address,
|
|
||||||
* and dvma_mapout does nothing. Note that this assumes all
|
|
||||||
* standalone programs stay in the range SA_MIN_VA .. SA_MAX_VA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <machine/pte.h>
|
|
||||||
#include <machine/ctlreg.h>
|
|
||||||
|
|
||||||
#include <promdev.h>
|
|
||||||
|
|
||||||
#define DVMA_BASE 0xFFF00000
|
|
||||||
#define DVMA_MAPLEN 0xE0000 /* 1 MB - 128K (save MONSHORTSEG) */
|
|
||||||
|
|
||||||
#define SA_MIN_VA (RELOC - 0x40000) /* XXX - magic constant */
|
|
||||||
#define SA_MAX_VA (SA_MIN_VA + DVMA_MAPLEN)
|
|
||||||
|
|
||||||
void
|
|
||||||
dvma_init()
|
|
||||||
{
|
|
||||||
register int segva, dmava;
|
|
||||||
|
|
||||||
dmava = DVMA_BASE;
|
|
||||||
for (segva = SA_MIN_VA; segva < SA_MAX_VA; segva += NBPSG) {
|
|
||||||
setsegmap(dmava, getsegmap(segva));
|
|
||||||
dmava += NBPSG;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Convert a local address to a DVMA address.
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
dvma_mapin(char *addr, size_t len)
|
|
||||||
{
|
|
||||||
register int va = (int)addr;
|
|
||||||
|
|
||||||
/* Make sure the address is in the DVMA map. */
|
|
||||||
if ((va < SA_MIN_VA) || (va >= SA_MAX_VA))
|
|
||||||
panic("dvma_mapin");
|
|
||||||
|
|
||||||
va += DVMA_BASE - SA_MIN_VA;
|
|
||||||
|
|
||||||
return ((char *)va);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Convert a DVMA address to a local address.
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
dvma_mapout(char *addr, size_t len)
|
|
||||||
{
|
|
||||||
int va = (int)addr;
|
|
||||||
|
|
||||||
/* Make sure the address is in the DVMA map. */
|
|
||||||
if ((va < DVMA_BASE) || (va >= (DVMA_BASE + DVMA_MAPLEN)))
|
|
||||||
panic("dvma_mapout");
|
|
||||||
|
|
||||||
va -= DVMA_BASE - SA_MIN_VA;
|
|
||||||
|
|
||||||
return ((char *)va);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern char *alloc __P((int));
|
|
||||||
|
|
||||||
char *
|
|
||||||
dvma_alloc(int len)
|
|
||||||
{
|
|
||||||
char *mem;
|
|
||||||
|
|
||||||
mem = alloc(len);
|
|
||||||
if (!mem)
|
|
||||||
return (mem);
|
|
||||||
return (dvma_mapin(mem, len));
|
|
||||||
}
|
|
||||||
|
|
||||||
extern void free(void *ptr, int len);
|
|
||||||
void
|
|
||||||
dvma_free(char *dvma, int len)
|
|
||||||
{
|
|
||||||
char *mem;
|
|
||||||
|
|
||||||
mem = dvma_mapout(dvma, len);
|
|
||||||
if (mem)
|
|
||||||
free(mem, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
/* $OpenBSD: __main.c,v 1.2 1996/04/19 16:09:17 niklas Exp $ */
|
|
||||||
/* $NetBSD: __main.c,v 1.4 1996/03/14 18:52:03 christos Exp $ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 1993 Christopher G. Demetriou
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by Christopher G. Demetriou.
|
|
||||||
* 4. The name of the author may not be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
||||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
||||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
||||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
void __main __P((void));
|
|
||||||
|
|
||||||
void
|
|
||||||
__main()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
/* $OpenBSD: bzero.c,v 1.3 1997/11/07 15:56:38 niklas Exp $ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 1987 Regents of the University of California.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(LIBC_SCCS) && !defined(lint)
|
|
||||||
/*static char *sccsid = "from: @(#)bzero.c 5.7 (Berkeley) 2/24/91";*/
|
|
||||||
static char *rcsid = "$OpenBSD: bzero.c,v 1.3 1997/11/07 15:56:38 niklas Exp $";
|
|
||||||
#endif /* LIBC_SCCS and not lint */
|
|
||||||
|
|
||||||
#ifndef _KERNEL
|
|
||||||
#include <string.h>
|
|
||||||
#else
|
|
||||||
#include <libkern/libkern.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* bzero -- vax movc5 instruction
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
bzero(b, length)
|
|
||||||
void *b;
|
|
||||||
register size_t length;
|
|
||||||
{
|
|
||||||
register char *p;
|
|
||||||
|
|
||||||
for (p = b; length--;)
|
|
||||||
*p++ = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,428 +0,0 @@
|
|||||||
|
|
||||||
/* $OpenBSD: divrem.m4,v 1.4 2000/03/03 11:17:03 art Exp $ */
|
|
||||||
/* $NetBSD: divrem.m4,v 1.3 1995/04/22 09:37:39 pk Exp $ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 1992, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This software was developed by the Computer Systems Engineering group
|
|
||||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
|
||||||
* contributed to Berkeley.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS `AS IS' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* Header: divrem.m4,v 1.4 92/06/25 13:23:57 torek Exp
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Division and remainder, from Appendix E of the Sparc Version 8
|
|
||||||
* Architecture Manual, with fixes from Gordon Irlam.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(LIBC_SCCS) && !defined(lint)
|
|
||||||
#ifdef notdef
|
|
||||||
.asciz "@(#)divrem.m4 8.1 (Berkeley) 6/4/93"
|
|
||||||
#endif
|
|
||||||
.asciz "$OpenBSD: divrem.m4,v 1.4 2000/03/03 11:17:03 art Exp $"
|
|
||||||
#endif /* LIBC_SCCS and not lint */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Input: dividend and divisor in %o0 and %o1 respectively.
|
|
||||||
*
|
|
||||||
* m4 parameters:
|
|
||||||
* .udiv name of function to generate
|
|
||||||
* __udiv secondary name of function to generate
|
|
||||||
* div div=div => %o0 / %o1; div=rem => %o0 % %o1
|
|
||||||
* false false=true => signed; false=false => unsigned
|
|
||||||
*
|
|
||||||
* Algorithm parameters:
|
|
||||||
* N how many bits per iteration we try to get (4)
|
|
||||||
* WORDSIZE total number of bits (32)
|
|
||||||
*
|
|
||||||
* Derived constants:
|
|
||||||
* TWOSUPN 2^N, for label generation (m4 exponentiation currently broken)
|
|
||||||
* TOPBITS number of bits in the top decade of a number
|
|
||||||
*
|
|
||||||
* Important variables:
|
|
||||||
* Q the partial quotient under development (initially 0)
|
|
||||||
* R the remainder so far, initially the dividend
|
|
||||||
* ITER number of main division loop iterations required;
|
|
||||||
* equal to ceil(log2(quotient) / N). Note that this
|
|
||||||
* is the log base (2^N) of the quotient.
|
|
||||||
* V the current comparand, initially divisor*2^(ITER*N-1)
|
|
||||||
*
|
|
||||||
* Cost:
|
|
||||||
* Current estimate for non-large dividend is
|
|
||||||
* ceil(log2(quotient) / N) * (10 + 7N/2) + C
|
|
||||||
* A large dividend is one greater than 2^(31-TOPBITS) and takes a
|
|
||||||
* different path, as the upper bits of the quotient must be developed
|
|
||||||
* one bit at a time.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* m4 reminder: d => if a is b, then c, else d */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is the recursive definition for developing quotient digits.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* $1 the current depth, 1 <= $1 <= 4
|
|
||||||
* $2 the current accumulation of quotient bits
|
|
||||||
* 4 max depth
|
|
||||||
*
|
|
||||||
* We add a new bit to $2 and either recurse or insert the bits in
|
|
||||||
* the quotient. %o3, %o2, and %o5 are inputs and outputs as defined above;
|
|
||||||
* the condition codes are expected to reflect the input %o3, and are
|
|
||||||
* modified to reflect the output %o3.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "DEFS.h"
|
|
||||||
#include <machine/trap.h>
|
|
||||||
|
|
||||||
.globl __udiv
|
|
||||||
__udiv:
|
|
||||||
FUNC(.udiv)
|
|
||||||
|
|
||||||
! Ready to divide. Compute size of quotient; scale comparand.
|
|
||||||
orcc %o1, %g0, %o5
|
|
||||||
bnz 1f
|
|
||||||
mov %o0, %o3
|
|
||||||
|
|
||||||
! Divide by zero trap. If it returns, return 0 (about as
|
|
||||||
! wrong as possible, but that is what SunOS does...).
|
|
||||||
t ST_DIV0
|
|
||||||
retl
|
|
||||||
clr %o0
|
|
||||||
|
|
||||||
1:
|
|
||||||
cmp %o3, %o5 ! if %o1 exceeds %o0, done
|
|
||||||
blu Lgot_result ! (and algorithm fails otherwise)
|
|
||||||
clr %o2
|
|
||||||
sethi %hi(1 << (32 - 4 - 1)), %g1
|
|
||||||
cmp %o3, %g1
|
|
||||||
blu Lnot_really_big
|
|
||||||
clr %o4
|
|
||||||
|
|
||||||
! Here the dividend is >= 2^(31-N) or so. We must be careful here,
|
|
||||||
! as our usual N-at-a-shot divide step will cause overflow and havoc.
|
|
||||||
! The number of bits in the result here is N*ITER+SC, where SC <= N.
|
|
||||||
! Compute ITER in an unorthodox manner: know we need to shift V into
|
|
||||||
! the top decade: so do not even bother to compare to R.
|
|
||||||
1:
|
|
||||||
cmp %o5, %g1
|
|
||||||
bgeu 3f
|
|
||||||
mov 1, %g7
|
|
||||||
sll %o5, 4, %o5
|
|
||||||
b 1b
|
|
||||||
inc %o4
|
|
||||||
|
|
||||||
! Now compute %g7.
|
|
||||||
2: addcc %o5, %o5, %o5
|
|
||||||
bcc Lnot_too_big
|
|
||||||
inc %g7
|
|
||||||
|
|
||||||
! We get here if the %o1 overflowed while shifting.
|
|
||||||
! This means that %o3 has the high-order bit set.
|
|
||||||
! Restore %o5 and subtract from %o3.
|
|
||||||
sll %g1, 4, %g1 ! high order bit
|
|
||||||
srl %o5, 1, %o5 ! rest of %o5
|
|
||||||
add %o5, %g1, %o5
|
|
||||||
b Ldo_single_div
|
|
||||||
dec %g7
|
|
||||||
|
|
||||||
Lnot_too_big:
|
|
||||||
3: cmp %o5, %o3
|
|
||||||
blu 2b
|
|
||||||
nop
|
|
||||||
be Ldo_single_div
|
|
||||||
nop
|
|
||||||
/* NB: these are commented out in the V8-Sparc manual as well */
|
|
||||||
/* (I do not understand this) */
|
|
||||||
! %o5 > %o3: went too far: back up 1 step
|
|
||||||
! srl %o5, 1, %o5
|
|
||||||
! dec %g7
|
|
||||||
! do single-bit divide steps
|
|
||||||
!
|
|
||||||
! We have to be careful here. We know that %o3 >= %o5, so we can do the
|
|
||||||
! first divide step without thinking. BUT, the others are conditional,
|
|
||||||
! and are only done if %o3 >= 0. Because both %o3 and %o5 may have the high-
|
|
||||||
! order bit set in the first step, just falling into the regular
|
|
||||||
! division loop will mess up the first time around.
|
|
||||||
! So we unroll slightly...
|
|
||||||
Ldo_single_div:
|
|
||||||
deccc %g7
|
|
||||||
bl Lend_regular_divide
|
|
||||||
nop
|
|
||||||
sub %o3, %o5, %o3
|
|
||||||
mov 1, %o2
|
|
||||||
b Lend_single_divloop
|
|
||||||
nop
|
|
||||||
Lsingle_divloop:
|
|
||||||
sll %o2, 1, %o2
|
|
||||||
bl 1f
|
|
||||||
srl %o5, 1, %o5
|
|
||||||
! %o3 >= 0
|
|
||||||
sub %o3, %o5, %o3
|
|
||||||
b 2f
|
|
||||||
inc %o2
|
|
||||||
1: ! %o3 < 0
|
|
||||||
add %o3, %o5, %o3
|
|
||||||
dec %o2
|
|
||||||
2:
|
|
||||||
Lend_single_divloop:
|
|
||||||
deccc %g7
|
|
||||||
bge Lsingle_divloop
|
|
||||||
tst %o3
|
|
||||||
b,a Lend_regular_divide
|
|
||||||
|
|
||||||
Lnot_really_big:
|
|
||||||
1:
|
|
||||||
sll %o5, 4, %o5
|
|
||||||
cmp %o5, %o3
|
|
||||||
bleu 1b
|
|
||||||
inccc %o4
|
|
||||||
be Lgot_result
|
|
||||||
dec %o4
|
|
||||||
|
|
||||||
tst %o3 ! set up for initial iteration
|
|
||||||
Ldivloop:
|
|
||||||
sll %o2, 4, %o2
|
|
||||||
! depth 1, accumulated bits 0
|
|
||||||
bl L.1.16
|
|
||||||
srl %o5,1,%o5
|
|
||||||
! remainder is positive
|
|
||||||
subcc %o3,%o5,%o3
|
|
||||||
! depth 2, accumulated bits 1
|
|
||||||
bl L.2.17
|
|
||||||
srl %o5,1,%o5
|
|
||||||
! remainder is positive
|
|
||||||
subcc %o3,%o5,%o3
|
|
||||||
! depth 3, accumulated bits 3
|
|
||||||
bl L.3.19
|
|
||||||
srl %o5,1,%o5
|
|
||||||
! remainder is positive
|
|
||||||
subcc %o3,%o5,%o3
|
|
||||||
! depth 4, accumulated bits 7
|
|
||||||
bl L.4.23
|
|
||||||
srl %o5,1,%o5
|
|
||||||
! remainder is positive
|
|
||||||
subcc %o3,%o5,%o3
|
|
||||||
b 9f
|
|
||||||
add %o2, (7*2+1), %o2
|
|
||||||
|
|
||||||
L.4.23:
|
|
||||||
! remainder is negative
|
|
||||||
addcc %o3,%o5,%o3
|
|
||||||
b 9f
|
|
||||||
add %o2, (7*2-1), %o2
|
|
||||||
|
|
||||||
|
|
||||||
L.3.19:
|
|
||||||
! remainder is negative
|
|
||||||
addcc %o3,%o5,%o3
|
|
||||||
! depth 4, accumulated bits 5
|
|
||||||
bl L.4.21
|
|
||||||
srl %o5,1,%o5
|
|
||||||
! remainder is positive
|
|
||||||
subcc %o3,%o5,%o3
|
|
||||||
b 9f
|
|
||||||
add %o2, (5*2+1), %o2
|
|
||||||
|
|
||||||
L.4.21:
|
|
||||||
! remainder is negative
|
|
||||||
addcc %o3,%o5,%o3
|
|
||||||
b 9f
|
|
||||||
add %o2, (5*2-1), %o2
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
L.2.17:
|
|
||||||
! remainder is negative
|
|
||||||
addcc %o3,%o5,%o3
|
|
||||||
! depth 3, accumulated bits 1
|
|
||||||
bl L.3.17
|
|
||||||
srl %o5,1,%o5
|
|
||||||
! remainder is positive
|
|
||||||
subcc %o3,%o5,%o3
|
|
||||||
! depth 4, accumulated bits 3
|
|
||||||
bl L.4.19
|
|
||||||
srl %o5,1,%o5
|
|
||||||
! remainder is positive
|
|
||||||
subcc %o3,%o5,%o3
|
|
||||||
b 9f
|
|
||||||
add %o2, (3*2+1), %o2
|
|
||||||
|
|
||||||
L.4.19:
|
|
||||||
! remainder is negative
|
|
||||||
addcc %o3,%o5,%o3
|
|
||||||
b 9f
|
|
||||||
add %o2, (3*2-1), %o2
|
|
||||||
|
|
||||||
|
|
||||||
L.3.17:
|
|
||||||
! remainder is negative
|
|
||||||
addcc %o3,%o5,%o3
|
|
||||||
! depth 4, accumulated bits 1
|
|
||||||
bl L.4.17
|
|
||||||
srl %o5,1,%o5
|
|
||||||
! remainder is positive
|
|
||||||
subcc %o3,%o5,%o3
|
|
||||||
b 9f
|
|
||||||
add %o2, (1*2+1), %o2
|
|
||||||
|
|
||||||
L.4.17:
|
|
||||||
! remainder is negative
|
|
||||||
addcc %o3,%o5,%o3
|
|
||||||
b 9f
|
|
||||||
add %o2, (1*2-1), %o2
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
L.1.16:
|
|
||||||
! remainder is negative
|
|
||||||
addcc %o3,%o5,%o3
|
|
||||||
! depth 2, accumulated bits -1
|
|
||||||
bl L.2.15
|
|
||||||
srl %o5,1,%o5
|
|
||||||
! remainder is positive
|
|
||||||
subcc %o3,%o5,%o3
|
|
||||||
! depth 3, accumulated bits -1
|
|
||||||
bl L.3.15
|
|
||||||
srl %o5,1,%o5
|
|
||||||
! remainder is positive
|
|
||||||
subcc %o3,%o5,%o3
|
|
||||||
! depth 4, accumulated bits -1
|
|
||||||
bl L.4.15
|
|
||||||
srl %o5,1,%o5
|
|
||||||
! remainder is positive
|
|
||||||
subcc %o3,%o5,%o3
|
|
||||||
b 9f
|
|
||||||
add %o2, (-1*2+1), %o2
|
|
||||||
|
|
||||||
L.4.15:
|
|
||||||
! remainder is negative
|
|
||||||
addcc %o3,%o5,%o3
|
|
||||||
b 9f
|
|
||||||
add %o2, (-1*2-1), %o2
|
|
||||||
|
|
||||||
|
|
||||||
L.3.15:
|
|
||||||
! remainder is negative
|
|
||||||
addcc %o3,%o5,%o3
|
|
||||||
! depth 4, accumulated bits -3
|
|
||||||
bl L.4.13
|
|
||||||
srl %o5,1,%o5
|
|
||||||
! remainder is positive
|
|
||||||
subcc %o3,%o5,%o3
|
|
||||||
b 9f
|
|
||||||
add %o2, (-3*2+1), %o2
|
|
||||||
|
|
||||||
L.4.13:
|
|
||||||
! remainder is negative
|
|
||||||
addcc %o3,%o5,%o3
|
|
||||||
b 9f
|
|
||||||
add %o2, (-3*2-1), %o2
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
L.2.15:
|
|
||||||
! remainder is negative
|
|
||||||
addcc %o3,%o5,%o3
|
|
||||||
! depth 3, accumulated bits -3
|
|
||||||
bl L.3.13
|
|
||||||
srl %o5,1,%o5
|
|
||||||
! remainder is positive
|
|
||||||
subcc %o3,%o5,%o3
|
|
||||||
! depth 4, accumulated bits -5
|
|
||||||
bl L.4.11
|
|
||||||
srl %o5,1,%o5
|
|
||||||
! remainder is positive
|
|
||||||
subcc %o3,%o5,%o3
|
|
||||||
b 9f
|
|
||||||
add %o2, (-5*2+1), %o2
|
|
||||||
|
|
||||||
L.4.11:
|
|
||||||
! remainder is negative
|
|
||||||
addcc %o3,%o5,%o3
|
|
||||||
b 9f
|
|
||||||
add %o2, (-5*2-1), %o2
|
|
||||||
|
|
||||||
|
|
||||||
L.3.13:
|
|
||||||
! remainder is negative
|
|
||||||
addcc %o3,%o5,%o3
|
|
||||||
! depth 4, accumulated bits -7
|
|
||||||
bl L.4.9
|
|
||||||
srl %o5,1,%o5
|
|
||||||
! remainder is positive
|
|
||||||
subcc %o3,%o5,%o3
|
|
||||||
b 9f
|
|
||||||
add %o2, (-7*2+1), %o2
|
|
||||||
|
|
||||||
L.4.9:
|
|
||||||
! remainder is negative
|
|
||||||
addcc %o3,%o5,%o3
|
|
||||||
b 9f
|
|
||||||
add %o2, (-7*2-1), %o2
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
9:
|
|
||||||
Lend_regular_divide:
|
|
||||||
deccc %o4
|
|
||||||
bge Ldivloop
|
|
||||||
tst %o3
|
|
||||||
bl,a Lgot_result
|
|
||||||
! non-restoring fixup here (one instruction only!)
|
|
||||||
dec %o2
|
|
||||||
|
|
||||||
|
|
||||||
Lgot_result:
|
|
||||||
|
|
||||||
retl
|
|
||||||
mov %o2, %o0
|
|
||||||
|
|
||||||
@@ -1,428 +0,0 @@
|
|||||||
|
|
||||||
/* $OpenBSD: divrem.m4,v 1.4 2000/03/03 11:17:03 art Exp $ */
|
|
||||||
/* $NetBSD: divrem.m4,v 1.3 1995/04/22 09:37:39 pk Exp $ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 1992, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This software was developed by the Computer Systems Engineering group
|
|
||||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
|
||||||
* contributed to Berkeley.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS `AS IS' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* Header: divrem.m4,v 1.4 92/06/25 13:23:57 torek Exp
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Division and remainder, from Appendix E of the Sparc Version 8
|
|
||||||
* Architecture Manual, with fixes from Gordon Irlam.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(LIBC_SCCS) && !defined(lint)
|
|
||||||
#ifdef notdef
|
|
||||||
.asciz "@(#)divrem.m4 8.1 (Berkeley) 6/4/93"
|
|
||||||
#endif
|
|
||||||
.asciz "$OpenBSD: divrem.m4,v 1.4 2000/03/03 11:17:03 art Exp $"
|
|
||||||
#endif /* LIBC_SCCS and not lint */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Input: dividend and divisor in %o0 and %o1 respectively.
|
|
||||||
*
|
|
||||||
* m4 parameters:
|
|
||||||
* .urem name of function to generate
|
|
||||||
* __urem secondary name of function to generate
|
|
||||||
* rem rem=div => %o0 / %o1; rem=rem => %o0 % %o1
|
|
||||||
* false false=true => signed; false=false => unsigned
|
|
||||||
*
|
|
||||||
* Algorithm parameters:
|
|
||||||
* N how many bits per iteration we try to get (4)
|
|
||||||
* WORDSIZE total number of bits (32)
|
|
||||||
*
|
|
||||||
* Derived constants:
|
|
||||||
* TWOSUPN 2^N, for label generation (m4 exponentiation currently broken)
|
|
||||||
* TOPBITS number of bits in the top decade of a number
|
|
||||||
*
|
|
||||||
* Important variables:
|
|
||||||
* Q the partial quotient under development (initially 0)
|
|
||||||
* R the remainder so far, initially the dividend
|
|
||||||
* ITER number of main division loop iterations required;
|
|
||||||
* equal to ceil(log2(quotient) / N). Note that this
|
|
||||||
* is the log base (2^N) of the quotient.
|
|
||||||
* V the current comparand, initially divisor*2^(ITER*N-1)
|
|
||||||
*
|
|
||||||
* Cost:
|
|
||||||
* Current estimate for non-large dividend is
|
|
||||||
* ceil(log2(quotient) / N) * (10 + 7N/2) + C
|
|
||||||
* A large dividend is one greater than 2^(31-TOPBITS) and takes a
|
|
||||||
* different path, as the upper bits of the quotient must be developed
|
|
||||||
* one bit at a time.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* m4 reminder: d => if a is b, then c, else d */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is the recursive definition for developing quotient digits.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* $1 the current depth, 1 <= $1 <= 4
|
|
||||||
* $2 the current accumulation of quotient bits
|
|
||||||
* 4 max depth
|
|
||||||
*
|
|
||||||
* We add a new bit to $2 and either recurse or insert the bits in
|
|
||||||
* the quotient. %o3, %o2, and %o5 are inputs and outputs as defined above;
|
|
||||||
* the condition codes are expected to reflect the input %o3, and are
|
|
||||||
* modified to reflect the output %o3.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "DEFS.h"
|
|
||||||
#include <machine/trap.h>
|
|
||||||
|
|
||||||
.globl __urem
|
|
||||||
__urem:
|
|
||||||
FUNC(.urem)
|
|
||||||
|
|
||||||
! Ready to divide. Compute size of quotient; scale comparand.
|
|
||||||
orcc %o1, %g0, %o5
|
|
||||||
bnz 1f
|
|
||||||
mov %o0, %o3
|
|
||||||
|
|
||||||
! Divide by zero trap. If it returns, return 0 (about as
|
|
||||||
! wrong as possible, but that is what SunOS does...).
|
|
||||||
t ST_DIV0
|
|
||||||
retl
|
|
||||||
clr %o0
|
|
||||||
|
|
||||||
1:
|
|
||||||
cmp %o3, %o5 ! if %o1 exceeds %o0, done
|
|
||||||
blu Lgot_result ! (and algorithm fails otherwise)
|
|
||||||
clr %o2
|
|
||||||
sethi %hi(1 << (32 - 4 - 1)), %g1
|
|
||||||
cmp %o3, %g1
|
|
||||||
blu Lnot_really_big
|
|
||||||
clr %o4
|
|
||||||
|
|
||||||
! Here the dividend is >= 2^(31-N) or so. We must be careful here,
|
|
||||||
! as our usual N-at-a-shot divide step will cause overflow and havoc.
|
|
||||||
! The number of bits in the result here is N*ITER+SC, where SC <= N.
|
|
||||||
! Compute ITER in an unorthodox manner: know we need to shift V into
|
|
||||||
! the top decade: so do not even bother to compare to R.
|
|
||||||
1:
|
|
||||||
cmp %o5, %g1
|
|
||||||
bgeu 3f
|
|
||||||
mov 1, %g7
|
|
||||||
sll %o5, 4, %o5
|
|
||||||
b 1b
|
|
||||||
inc %o4
|
|
||||||
|
|
||||||
! Now compute %g7.
|
|
||||||
2: addcc %o5, %o5, %o5
|
|
||||||
bcc Lnot_too_big
|
|
||||||
inc %g7
|
|
||||||
|
|
||||||
! We get here if the %o1 overflowed while shifting.
|
|
||||||
! This means that %o3 has the high-order bit set.
|
|
||||||
! Restore %o5 and subtract from %o3.
|
|
||||||
sll %g1, 4, %g1 ! high order bit
|
|
||||||
srl %o5, 1, %o5 ! rest of %o5
|
|
||||||
add %o5, %g1, %o5
|
|
||||||
b Ldo_single_div
|
|
||||||
dec %g7
|
|
||||||
|
|
||||||
Lnot_too_big:
|
|
||||||
3: cmp %o5, %o3
|
|
||||||
blu 2b
|
|
||||||
nop
|
|
||||||
be Ldo_single_div
|
|
||||||
nop
|
|
||||||
/* NB: these are commented out in the V8-Sparc manual as well */
|
|
||||||
/* (I do not understand this) */
|
|
||||||
! %o5 > %o3: went too far: back up 1 step
|
|
||||||
! srl %o5, 1, %o5
|
|
||||||
! dec %g7
|
|
||||||
! do single-bit divide steps
|
|
||||||
!
|
|
||||||
! We have to be careful here. We know that %o3 >= %o5, so we can do the
|
|
||||||
! first divide step without thinking. BUT, the others are conditional,
|
|
||||||
! and are only done if %o3 >= 0. Because both %o3 and %o5 may have the high-
|
|
||||||
! order bit set in the first step, just falling into the regular
|
|
||||||
! division loop will mess up the first time around.
|
|
||||||
! So we unroll slightly...
|
|
||||||
Ldo_single_div:
|
|
||||||
deccc %g7
|
|
||||||
bl Lend_regular_divide
|
|
||||||
nop
|
|
||||||
sub %o3, %o5, %o3
|
|
||||||
mov 1, %o2
|
|
||||||
b Lend_single_divloop
|
|
||||||
nop
|
|
||||||
Lsingle_divloop:
|
|
||||||
sll %o2, 1, %o2
|
|
||||||
bl 1f
|
|
||||||
srl %o5, 1, %o5
|
|
||||||
! %o3 >= 0
|
|
||||||
sub %o3, %o5, %o3
|
|
||||||
b 2f
|
|
||||||
inc %o2
|
|
||||||
1: ! %o3 < 0
|
|
||||||
add %o3, %o5, %o3
|
|
||||||
dec %o2
|
|
||||||
2:
|
|
||||||
Lend_single_divloop:
|
|
||||||
deccc %g7
|
|
||||||
bge Lsingle_divloop
|
|
||||||
tst %o3
|
|
||||||
b,a Lend_regular_divide
|
|
||||||
|
|
||||||
Lnot_really_big:
|
|
||||||
1:
|
|
||||||
sll %o5, 4, %o5
|
|
||||||
cmp %o5, %o3
|
|
||||||
bleu 1b
|
|
||||||
inccc %o4
|
|
||||||
be Lgot_result
|
|
||||||
dec %o4
|
|
||||||
|
|
||||||
tst %o3 ! set up for initial iteration
|
|
||||||
Ldivloop:
|
|
||||||
sll %o2, 4, %o2
|
|
||||||
! depth 1, accumulated bits 0
|
|
||||||
bl L.1.16
|
|
||||||
srl %o5,1,%o5
|
|
||||||
! remainder is positive
|
|
||||||
subcc %o3,%o5,%o3
|
|
||||||
! depth 2, accumulated bits 1
|
|
||||||
bl L.2.17
|
|
||||||
srl %o5,1,%o5
|
|
||||||
! remainder is positive
|
|
||||||
subcc %o3,%o5,%o3
|
|
||||||
! depth 3, accumulated bits 3
|
|
||||||
bl L.3.19
|
|
||||||
srl %o5,1,%o5
|
|
||||||
! remainder is positive
|
|
||||||
subcc %o3,%o5,%o3
|
|
||||||
! depth 4, accumulated bits 7
|
|
||||||
bl L.4.23
|
|
||||||
srl %o5,1,%o5
|
|
||||||
! remainder is positive
|
|
||||||
subcc %o3,%o5,%o3
|
|
||||||
b 9f
|
|
||||||
add %o2, (7*2+1), %o2
|
|
||||||
|
|
||||||
L.4.23:
|
|
||||||
! remainder is negative
|
|
||||||
addcc %o3,%o5,%o3
|
|
||||||
b 9f
|
|
||||||
add %o2, (7*2-1), %o2
|
|
||||||
|
|
||||||
|
|
||||||
L.3.19:
|
|
||||||
! remainder is negative
|
|
||||||
addcc %o3,%o5,%o3
|
|
||||||
! depth 4, accumulated bits 5
|
|
||||||
bl L.4.21
|
|
||||||
srl %o5,1,%o5
|
|
||||||
! remainder is positive
|
|
||||||
subcc %o3,%o5,%o3
|
|
||||||
b 9f
|
|
||||||
add %o2, (5*2+1), %o2
|
|
||||||
|
|
||||||
L.4.21:
|
|
||||||
! remainder is negative
|
|
||||||
addcc %o3,%o5,%o3
|
|
||||||
b 9f
|
|
||||||
add %o2, (5*2-1), %o2
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
L.2.17:
|
|
||||||
! remainder is negative
|
|
||||||
addcc %o3,%o5,%o3
|
|
||||||
! depth 3, accumulated bits 1
|
|
||||||
bl L.3.17
|
|
||||||
srl %o5,1,%o5
|
|
||||||
! remainder is positive
|
|
||||||
subcc %o3,%o5,%o3
|
|
||||||
! depth 4, accumulated bits 3
|
|
||||||
bl L.4.19
|
|
||||||
srl %o5,1,%o5
|
|
||||||
! remainder is positive
|
|
||||||
subcc %o3,%o5,%o3
|
|
||||||
b 9f
|
|
||||||
add %o2, (3*2+1), %o2
|
|
||||||
|
|
||||||
L.4.19:
|
|
||||||
! remainder is negative
|
|
||||||
addcc %o3,%o5,%o3
|
|
||||||
b 9f
|
|
||||||
add %o2, (3*2-1), %o2
|
|
||||||
|
|
||||||
|
|
||||||
L.3.17:
|
|
||||||
! remainder is negative
|
|
||||||
addcc %o3,%o5,%o3
|
|
||||||
! depth 4, accumulated bits 1
|
|
||||||
bl L.4.17
|
|
||||||
srl %o5,1,%o5
|
|
||||||
! remainder is positive
|
|
||||||
subcc %o3,%o5,%o3
|
|
||||||
b 9f
|
|
||||||
add %o2, (1*2+1), %o2
|
|
||||||
|
|
||||||
L.4.17:
|
|
||||||
! remainder is negative
|
|
||||||
addcc %o3,%o5,%o3
|
|
||||||
b 9f
|
|
||||||
add %o2, (1*2-1), %o2
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
L.1.16:
|
|
||||||
! remainder is negative
|
|
||||||
addcc %o3,%o5,%o3
|
|
||||||
! depth 2, accumulated bits -1
|
|
||||||
bl L.2.15
|
|
||||||
srl %o5,1,%o5
|
|
||||||
! remainder is positive
|
|
||||||
subcc %o3,%o5,%o3
|
|
||||||
! depth 3, accumulated bits -1
|
|
||||||
bl L.3.15
|
|
||||||
srl %o5,1,%o5
|
|
||||||
! remainder is positive
|
|
||||||
subcc %o3,%o5,%o3
|
|
||||||
! depth 4, accumulated bits -1
|
|
||||||
bl L.4.15
|
|
||||||
srl %o5,1,%o5
|
|
||||||
! remainder is positive
|
|
||||||
subcc %o3,%o5,%o3
|
|
||||||
b 9f
|
|
||||||
add %o2, (-1*2+1), %o2
|
|
||||||
|
|
||||||
L.4.15:
|
|
||||||
! remainder is negative
|
|
||||||
addcc %o3,%o5,%o3
|
|
||||||
b 9f
|
|
||||||
add %o2, (-1*2-1), %o2
|
|
||||||
|
|
||||||
|
|
||||||
L.3.15:
|
|
||||||
! remainder is negative
|
|
||||||
addcc %o3,%o5,%o3
|
|
||||||
! depth 4, accumulated bits -3
|
|
||||||
bl L.4.13
|
|
||||||
srl %o5,1,%o5
|
|
||||||
! remainder is positive
|
|
||||||
subcc %o3,%o5,%o3
|
|
||||||
b 9f
|
|
||||||
add %o2, (-3*2+1), %o2
|
|
||||||
|
|
||||||
L.4.13:
|
|
||||||
! remainder is negative
|
|
||||||
addcc %o3,%o5,%o3
|
|
||||||
b 9f
|
|
||||||
add %o2, (-3*2-1), %o2
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
L.2.15:
|
|
||||||
! remainder is negative
|
|
||||||
addcc %o3,%o5,%o3
|
|
||||||
! depth 3, accumulated bits -3
|
|
||||||
bl L.3.13
|
|
||||||
srl %o5,1,%o5
|
|
||||||
! remainder is positive
|
|
||||||
subcc %o3,%o5,%o3
|
|
||||||
! depth 4, accumulated bits -5
|
|
||||||
bl L.4.11
|
|
||||||
srl %o5,1,%o5
|
|
||||||
! remainder is positive
|
|
||||||
subcc %o3,%o5,%o3
|
|
||||||
b 9f
|
|
||||||
add %o2, (-5*2+1), %o2
|
|
||||||
|
|
||||||
L.4.11:
|
|
||||||
! remainder is negative
|
|
||||||
addcc %o3,%o5,%o3
|
|
||||||
b 9f
|
|
||||||
add %o2, (-5*2-1), %o2
|
|
||||||
|
|
||||||
|
|
||||||
L.3.13:
|
|
||||||
! remainder is negative
|
|
||||||
addcc %o3,%o5,%o3
|
|
||||||
! depth 4, accumulated bits -7
|
|
||||||
bl L.4.9
|
|
||||||
srl %o5,1,%o5
|
|
||||||
! remainder is positive
|
|
||||||
subcc %o3,%o5,%o3
|
|
||||||
b 9f
|
|
||||||
add %o2, (-7*2+1), %o2
|
|
||||||
|
|
||||||
L.4.9:
|
|
||||||
! remainder is negative
|
|
||||||
addcc %o3,%o5,%o3
|
|
||||||
b 9f
|
|
||||||
add %o2, (-7*2-1), %o2
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
9:
|
|
||||||
Lend_regular_divide:
|
|
||||||
deccc %o4
|
|
||||||
bge Ldivloop
|
|
||||||
tst %o3
|
|
||||||
bl,a Lgot_result
|
|
||||||
! non-restoring fixup here (one instruction only!)
|
|
||||||
add %o3, %o1, %o3
|
|
||||||
|
|
||||||
|
|
||||||
Lgot_result:
|
|
||||||
|
|
||||||
retl
|
|
||||||
mov %o3, %o0
|
|
||||||
|
|
||||||
@@ -1,233 +0,0 @@
|
|||||||
/* $OpenBSD: alloc.c,v 1.5 1997/08/01 21:57:09 pefo Exp $ */
|
|
||||||
/* $NetBSD: alloc.c,v 1.6 1997/02/04 18:36:33 thorpej Exp $ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 1997 Christopher G. Demetriou. All rights reserved.
|
|
||||||
* Copyright (c) 1996
|
|
||||||
* Matthias Drochner. All rights reserved.
|
|
||||||
* Copyright (c) 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* The Mach Operating System project at Carnegie-Mellon University.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @(#)alloc.c 8.1 (Berkeley) 6/11/93
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Copyright (c) 1989, 1990, 1991 Carnegie Mellon University
|
|
||||||
* All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Author: Alessandro Forin
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify and distribute this software and its
|
|
||||||
* documentation is hereby granted, provided that both the copyright
|
|
||||||
* notice and this permission notice appear in all copies of the
|
|
||||||
* software, derivative works or modified versions, and any portions
|
|
||||||
* thereof, and that both notices appear in supporting documentation.
|
|
||||||
*
|
|
||||||
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
|
|
||||||
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
|
|
||||||
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
|
|
||||||
*
|
|
||||||
* Carnegie Mellon requests users of this software to return to
|
|
||||||
*
|
|
||||||
* Software Distribution Coordinator or [email protected]
|
|
||||||
* School of Computer Science
|
|
||||||
* Carnegie Mellon University
|
|
||||||
* Pittsburgh PA 15213-3890
|
|
||||||
*
|
|
||||||
* any improvements or extensions that they make and grant Carnegie the
|
|
||||||
* rights to redistribute these changes.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Dynamic memory allocator.
|
|
||||||
*
|
|
||||||
* Compile options:
|
|
||||||
*
|
|
||||||
* ALLOC_TRACE enable tracing of allocations/deallocations
|
|
||||||
*
|
|
||||||
* ALLOC_FIRST_FIT use a first-fit allocation algorithm, rather than
|
|
||||||
* the default best-fit algorithm.
|
|
||||||
*
|
|
||||||
* HEAP_LIMIT heap limit address (defaults to "no limit").
|
|
||||||
*
|
|
||||||
* HEAP_START start address of heap (defaults to '&end').
|
|
||||||
*
|
|
||||||
* DEBUG enable debugging sanity checks.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/param.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Each block actually has ALIGN(unsigned) + ALIGN(size) bytes allocated
|
|
||||||
* to it, as follows:
|
|
||||||
*
|
|
||||||
* 0 ... (sizeof(unsigned) - 1)
|
|
||||||
* allocated or unallocated: holds size of user-data part of block.
|
|
||||||
*
|
|
||||||
* sizeof(unsigned) ... (ALIGN(sizeof(unsigned)) - 1)
|
|
||||||
* allocated: unused
|
|
||||||
* unallocated: depends on packing of struct fl
|
|
||||||
*
|
|
||||||
* ALIGN(sizeof(unsigned)) ... (ALIGN(sizeof(unsigned)) + ALIGN(data size) - 1)
|
|
||||||
* allocated: user data
|
|
||||||
* unallocated: depends on packing of struct fl
|
|
||||||
*
|
|
||||||
* 'next' is only used when the block is unallocated (i.e. on the free list).
|
|
||||||
* However, note that ALIGN(sizeof(unsigned)) + ALIGN(data size) must
|
|
||||||
* be at least 'sizeof(struct fl)', so that blocks can be used as structures
|
|
||||||
* when on the free list.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "stand.h"
|
|
||||||
|
|
||||||
struct fl {
|
|
||||||
unsigned size;
|
|
||||||
struct fl *next;
|
|
||||||
} *freelist = (struct fl *)0;
|
|
||||||
|
|
||||||
#ifdef HEAP_START
|
|
||||||
static char *top = (char*)HEAP_START;
|
|
||||||
#else
|
|
||||||
extern char end[];
|
|
||||||
static char *top = end;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void *
|
|
||||||
alloc(size)
|
|
||||||
unsigned size;
|
|
||||||
{
|
|
||||||
register struct fl **f = &freelist, **bestf = NULL;
|
|
||||||
#ifndef ALLOC_FIRST_FIT
|
|
||||||
unsigned bestsize = 0xffffffff; /* greater than any real size */
|
|
||||||
#endif
|
|
||||||
char *help;
|
|
||||||
int failed;
|
|
||||||
|
|
||||||
#ifdef ALLOC_TRACE
|
|
||||||
printf("alloc(%u)", size);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ALLOC_FIRST_FIT
|
|
||||||
while (*f != (struct fl *)0 && (*f)->size < size)
|
|
||||||
f = &((*f)->next);
|
|
||||||
bestf = f;
|
|
||||||
failed = (*bestf == (struct fl *)0);
|
|
||||||
#else
|
|
||||||
/* scan freelist */
|
|
||||||
while (*f) {
|
|
||||||
if ((*f)->size >= size) {
|
|
||||||
if ((*f)->size == size) /* exact match */
|
|
||||||
goto found;
|
|
||||||
|
|
||||||
if ((*f)->size < bestsize) {
|
|
||||||
/* keep best fit */
|
|
||||||
bestf = f;
|
|
||||||
bestsize = (*f)->size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
f = &((*f)->next);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* no match in freelist if bestsize unchanged */
|
|
||||||
failed = (bestsize == 0xffffffff);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (failed) { /* nothing found */
|
|
||||||
/*
|
|
||||||
* allocate from heap, keep chunk len in
|
|
||||||
* first word
|
|
||||||
*/
|
|
||||||
help = top;
|
|
||||||
|
|
||||||
/* make _sure_ the region can hold a struct fl. */
|
|
||||||
if (size < ALIGN(sizeof (struct fl *)))
|
|
||||||
size = ALIGN(sizeof (struct fl *));
|
|
||||||
top += ALIGN(sizeof(unsigned)) + ALIGN(size);
|
|
||||||
#ifdef HEAP_LIMIT
|
|
||||||
if (top > (char*)HEAP_LIMIT)
|
|
||||||
panic("heap full (0x%lx+%u)", help, size);
|
|
||||||
#endif
|
|
||||||
*(unsigned *)help = ALIGN(size);
|
|
||||||
#ifdef ALLOC_TRACE
|
|
||||||
printf("=%p\n", help + ALIGN(sizeof(unsigned)));
|
|
||||||
#endif
|
|
||||||
return(help + ALIGN(sizeof(unsigned)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we take the best fit */
|
|
||||||
f = bestf;
|
|
||||||
|
|
||||||
#ifndef ALLOC_FIRST_FIT
|
|
||||||
found:
|
|
||||||
#endif
|
|
||||||
/* remove from freelist */
|
|
||||||
help = (char*)*f;
|
|
||||||
*f = (*f)->next;
|
|
||||||
#ifdef ALLOC_TRACE
|
|
||||||
printf("=%p (origsize %u)\n", help + ALIGN(sizeof(unsigned)),
|
|
||||||
*(unsigned *)help);
|
|
||||||
#endif
|
|
||||||
return(help + ALIGN(sizeof(unsigned)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
free(ptr, size)
|
|
||||||
void *ptr;
|
|
||||||
unsigned size; /* only for consistence check */
|
|
||||||
{
|
|
||||||
register struct fl *f =
|
|
||||||
(struct fl *)((char*)ptr - ALIGN(sizeof(unsigned)));
|
|
||||||
#ifdef ALLOC_TRACE
|
|
||||||
printf("free(%p, %u) (origsize %u)\n", ptr, size, f->size);
|
|
||||||
#endif
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (size > f->size)
|
|
||||||
printf("free %u bytes @%p, should be <=%u\n",
|
|
||||||
size, ptr, f->size);
|
|
||||||
#ifdef HEAP_START
|
|
||||||
if (ptr < (void *)HEAP_START)
|
|
||||||
#else
|
|
||||||
if (ptr < (void *)end)
|
|
||||||
#endif
|
|
||||||
printf("free: %lx before start of heap.\n", (u_long)ptr);
|
|
||||||
|
|
||||||
#ifdef HEAP_LIMIT
|
|
||||||
if (ptr > (void *)HEAP_LIMIT)
|
|
||||||
printf("free: %lx beyond end of heap.\n", (u_long)ptr);
|
|
||||||
#endif
|
|
||||||
#endif /* DEBUG */
|
|
||||||
/* put into freelist */
|
|
||||||
f->next = freelist;
|
|
||||||
freelist = f;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
/* $OpenBSD: exit.c,v 1.4 1997/07/25 18:21:56 mickey Exp $ */
|
|
||||||
/* $NetBSD: exit.c,v 1.11 1996/12/01 20:22:19 pk Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1993 John Brezak
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
|
|
||||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
|
||||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
||||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
#ifdef __STDC__
|
|
||||||
#include <machine/stdarg.h>
|
|
||||||
#else
|
|
||||||
#include <machine/varargs.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "stand.h"
|
|
||||||
|
|
||||||
__dead void
|
|
||||||
#ifdef __STDC__
|
|
||||||
panic(const char *fmt, ...)
|
|
||||||
#else
|
|
||||||
panic(fmt /*, va_alist */)
|
|
||||||
char *fmt;
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
extern void closeall __P((void));
|
|
||||||
va_list ap;
|
|
||||||
static int paniced;
|
|
||||||
|
|
||||||
if (!paniced) {
|
|
||||||
paniced = 1;
|
|
||||||
closeall();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __STDC__
|
|
||||||
va_start(ap, fmt);
|
|
||||||
#else
|
|
||||||
va_start(ap);
|
|
||||||
#endif
|
|
||||||
vprintf(fmt, ap);
|
|
||||||
printf("\n");
|
|
||||||
va_end(ap);
|
|
||||||
_rtt();
|
|
||||||
/*NOTREACHED*/
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
exit()
|
|
||||||
{
|
|
||||||
panic("exit");
|
|
||||||
/*NOTREACHED*/
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
/*-
|
|
||||||
* Copyright (c) 1990 The Regents of the University of California.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Chris Torek.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(LIBC_SCCS) && !defined(lint)
|
|
||||||
static char *rcsid = "$OpenBSD: memcmp.c,v 1.4 1997/04/07 05:59:30 millert Exp $";
|
|
||||||
#endif /* LIBC_SCCS and not lint */
|
|
||||||
|
|
||||||
#include "stand.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Compare memory regions.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
memcmp(s1, s2, n)
|
|
||||||
const void *s1, *s2;
|
|
||||||
size_t n;
|
|
||||||
{
|
|
||||||
if (n != 0) {
|
|
||||||
register const unsigned char *p1 = s1, *p2 = s2;
|
|
||||||
|
|
||||||
do {
|
|
||||||
if (*p1++ != *p2++)
|
|
||||||
return (*--p1 - *--p2);
|
|
||||||
} while (--n != 0);
|
|
||||||
}
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
/* $OpenBSD: memcpy.c,v 1.3 1996/10/16 11:32:07 mickey Exp $ */
|
|
||||||
/* $NetBSD: bcopy.c,v 1.5 1995/04/22 13:46:50 cgd Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @(#)bcopy.c 8.1 (Berkeley) 6/11/93
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include "stand.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is designed to be small, not fast.
|
|
||||||
*/
|
|
||||||
void *
|
|
||||||
memcpy(s1, s2, n)
|
|
||||||
void *s1;
|
|
||||||
const void *s2;
|
|
||||||
size_t n;
|
|
||||||
{
|
|
||||||
register const char *f = s2;
|
|
||||||
register char *t = s1;
|
|
||||||
|
|
||||||
if (f < t) {
|
|
||||||
f += n;
|
|
||||||
t += n;
|
|
||||||
while (n-- > 0)
|
|
||||||
*--t = *--f;
|
|
||||||
} else
|
|
||||||
while (n-- > 0)
|
|
||||||
*t++ = *f++;
|
|
||||||
return s1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
/* $OpenBSD: memset.c,v 1.1 1996/10/15 09:41:55 mickey Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* from: @(#)bcopy.c 8.1 (Berkeley) 6/11/93
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include "stand.h"
|
|
||||||
|
|
||||||
void *
|
|
||||||
memset(s1, c, n)
|
|
||||||
void *s1;
|
|
||||||
int c;
|
|
||||||
size_t n;
|
|
||||||
{
|
|
||||||
register char *p = s1;
|
|
||||||
while (n--)
|
|
||||||
*p++ = c;
|
|
||||||
return s1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,257 +0,0 @@
|
|||||||
/* $OpenBSD: printf.c,v 1.14 1999/08/16 09:21:38 downsj Exp $ */
|
|
||||||
/* $NetBSD: printf.c,v 1.10 1996/11/30 04:19:21 gwr Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @(#)printf.c 8.1 (Berkeley) 6/11/93
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Scaled down version of printf(3).
|
|
||||||
*
|
|
||||||
* One additional format:
|
|
||||||
*
|
|
||||||
* The format %b is supported to decode error registers.
|
|
||||||
* Its usage is:
|
|
||||||
*
|
|
||||||
* printf("reg=%b\n", regval, "<base><arg>*");
|
|
||||||
*
|
|
||||||
* where <base> is the output base expressed as a control character, e.g.
|
|
||||||
* \10 gives octal; \20 gives hex. Each arg is a sequence of characters,
|
|
||||||
* the first of which gives the bit number to be inspected (origin 1), and
|
|
||||||
* the next characters (up to a control character, i.e. a character <= 32),
|
|
||||||
* give the name of the register. Thus:
|
|
||||||
*
|
|
||||||
* printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
|
|
||||||
*
|
|
||||||
* would produce output:
|
|
||||||
*
|
|
||||||
* reg=3<BITTWO,BITONE>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#ifdef __STDC__
|
|
||||||
#include <machine/stdarg.h>
|
|
||||||
#else
|
|
||||||
#include <machine/varargs.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "stand.h"
|
|
||||||
|
|
||||||
static void kprintn __P((void (*)(int), u_long, int));
|
|
||||||
static void kdoprnt __P((void (*)(int), const char *, va_list));
|
|
||||||
|
|
||||||
#ifndef STRIPPED
|
|
||||||
static void sputchar __P((int));
|
|
||||||
static char *sbuf;
|
|
||||||
|
|
||||||
static void
|
|
||||||
sputchar(c)
|
|
||||||
int c;
|
|
||||||
{
|
|
||||||
*sbuf++ = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
#ifdef __STDC__
|
|
||||||
sprintf(char *buf, const char *fmt, ...)
|
|
||||||
#else
|
|
||||||
sprintf(buf, fmt, va_alist)
|
|
||||||
char *buf, *fmt;
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
sbuf = buf;
|
|
||||||
#ifdef __STDC__
|
|
||||||
va_start(ap, fmt);
|
|
||||||
#else
|
|
||||||
va_start(ap);
|
|
||||||
#endif
|
|
||||||
kdoprnt(sputchar, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
*sbuf = '\0';
|
|
||||||
}
|
|
||||||
#endif /* NO_SPRINTF */
|
|
||||||
|
|
||||||
void
|
|
||||||
#ifdef __STDC__
|
|
||||||
printf(const char *fmt, ...)
|
|
||||||
#else
|
|
||||||
printf(fmt, va_alist)
|
|
||||||
char *fmt;
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
#ifdef __STDC__
|
|
||||||
va_start(ap, fmt);
|
|
||||||
#else
|
|
||||||
va_start(ap);
|
|
||||||
#endif
|
|
||||||
kdoprnt(putchar, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
vprintf(const char *fmt, va_list ap)
|
|
||||||
{
|
|
||||||
kdoprnt(putchar, fmt, ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
kdoprnt(put, fmt, ap)
|
|
||||||
void (*put)__P((int));
|
|
||||||
const char *fmt;
|
|
||||||
va_list ap;
|
|
||||||
{
|
|
||||||
register char *p;
|
|
||||||
register int ch;
|
|
||||||
unsigned long ul;
|
|
||||||
int lflag;
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
while ((ch = *fmt++) != '%') {
|
|
||||||
if (ch == '\0')
|
|
||||||
return;
|
|
||||||
put(ch);
|
|
||||||
}
|
|
||||||
lflag = 0;
|
|
||||||
reswitch: switch (ch = *fmt++) {
|
|
||||||
case 'l':
|
|
||||||
lflag = 1;
|
|
||||||
goto reswitch;
|
|
||||||
#ifndef STRIPPED
|
|
||||||
case 'b':
|
|
||||||
{
|
|
||||||
register int set, n;
|
|
||||||
ul = va_arg(ap, int);
|
|
||||||
p = va_arg(ap, char *);
|
|
||||||
kprintn(put, ul, *p++);
|
|
||||||
|
|
||||||
if (!ul)
|
|
||||||
break;
|
|
||||||
|
|
||||||
for (set = 0; (n = *p++);) {
|
|
||||||
if (ul & (1 << (n - 1))) {
|
|
||||||
put(set ? ',' : '<');
|
|
||||||
for (; (n = *p) > ' '; ++p)
|
|
||||||
put(n);
|
|
||||||
set = 1;
|
|
||||||
} else
|
|
||||||
for (; *p > ' '; ++p);
|
|
||||||
}
|
|
||||||
if (set)
|
|
||||||
put('>');
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
case 'c':
|
|
||||||
ch = va_arg(ap, int);
|
|
||||||
put(ch & 0x7f);
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
p = va_arg(ap, char *);
|
|
||||||
while ((ch = *p++))
|
|
||||||
put(ch);
|
|
||||||
break;
|
|
||||||
case 'd':
|
|
||||||
ul = lflag ?
|
|
||||||
va_arg(ap, long) : va_arg(ap, int);
|
|
||||||
if ((long)ul < 0) {
|
|
||||||
put('-');
|
|
||||||
ul = -(long)ul;
|
|
||||||
}
|
|
||||||
kprintn(put, ul, 10);
|
|
||||||
break;
|
|
||||||
case 'o':
|
|
||||||
ul = lflag ?
|
|
||||||
va_arg(ap, u_long) : va_arg(ap, u_int);
|
|
||||||
kprintn(put, ul, 8);
|
|
||||||
break;
|
|
||||||
case 'u':
|
|
||||||
ul = lflag ?
|
|
||||||
va_arg(ap, u_long) : va_arg(ap, u_int);
|
|
||||||
kprintn(put, ul, 10);
|
|
||||||
break;
|
|
||||||
case 'p':
|
|
||||||
put('0');
|
|
||||||
put('x');
|
|
||||||
lflag += sizeof(void *)==sizeof(u_long)? 1 : 0;
|
|
||||||
case 'x':
|
|
||||||
ul = lflag ?
|
|
||||||
va_arg(ap, u_long) : va_arg(ap, u_int);
|
|
||||||
kprintn(put, ul, 16);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
put('%');
|
|
||||||
if (lflag)
|
|
||||||
put('l');
|
|
||||||
put(ch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
kprintn(put, ul, base)
|
|
||||||
void (*put)__P((int));
|
|
||||||
unsigned long ul;
|
|
||||||
int base;
|
|
||||||
{
|
|
||||||
/* hold a long in base 8 */
|
|
||||||
char *p, buf[(sizeof(long) * NBBY / 3) + 1];
|
|
||||||
|
|
||||||
p = buf;
|
|
||||||
do {
|
|
||||||
*p++ = "0123456789abcdef"[ul % base];
|
|
||||||
} while (ul /= base);
|
|
||||||
do {
|
|
||||||
put(*--p);
|
|
||||||
} while (p > buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
int donottwiddle = 0;
|
|
||||||
|
|
||||||
void
|
|
||||||
twiddle()
|
|
||||||
{
|
|
||||||
static int pos;
|
|
||||||
|
|
||||||
if (!donottwiddle) {
|
|
||||||
putchar("|/-\\"[pos++ & 3]);
|
|
||||||
putchar('\b');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
/* $OpenBSD: strcmp.c,v 1.2 1996/10/16 11:32:07 mickey Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1996 Michael Shalayeff
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by Michael Shalayeff.
|
|
||||||
* 4. The name of the author may not be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
||||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include "stand.h"
|
|
||||||
|
|
||||||
int
|
|
||||||
strcmp(s1, s2)
|
|
||||||
register const char *s1;
|
|
||||||
register const char *s2;
|
|
||||||
{
|
|
||||||
while(*s1 && *s2 && *s1 == *s2)
|
|
||||||
s1++, s2++;
|
|
||||||
return *s1 - *s2;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,806 +0,0 @@
|
|||||||
/* $OpenBSD: promdev.c,v 1.2 1999/01/11 05:12:00 millert Exp $ */
|
|
||||||
/* $NetBSD: promdev.c,v 1.16 1995/11/14 15:04:01 pk Exp $ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 1993 Paul Kranenburg
|
|
||||||
* Copyright (c) 1995 Gordon W. Ross
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by Paul Kranenburg.
|
|
||||||
* 4. The name of the author may not be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
||||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
||||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
||||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Note: the `#ifndef BOOTXX' in here serve to queeze the code size
|
|
||||||
* of the 1st-stage boot program.
|
|
||||||
*/
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <sys/reboot.h>
|
|
||||||
#include <machine/idprom.h>
|
|
||||||
#include <machine/oldmon.h>
|
|
||||||
#include <machine/ctlreg.h>
|
|
||||||
|
|
||||||
#include <stand.h>
|
|
||||||
|
|
||||||
#include <promdev.h>
|
|
||||||
|
|
||||||
/* u_long _randseed = 1; */
|
|
||||||
|
|
||||||
|
|
||||||
int obp_close __P((struct open_file *));
|
|
||||||
int obp_strategy __P((void *, int, daddr_t, size_t, void *, size_t *));
|
|
||||||
ssize_t obp_xmit __P((struct promdata *, void *, size_t));
|
|
||||||
ssize_t obp_recv __P((struct promdata *, void *, size_t));
|
|
||||||
int prom0_close __P((struct open_file *));
|
|
||||||
int prom0_strategy __P((void *, int, daddr_t, size_t, void *, size_t *));
|
|
||||||
void prom0_iclose __P((struct saioreq *));
|
|
||||||
int prom0_iopen __P((struct promdata *));
|
|
||||||
ssize_t prom0_xmit __P((struct promdata *, void *, size_t));
|
|
||||||
ssize_t prom0_recv __P((struct promdata *, void *, size_t));
|
|
||||||
|
|
||||||
static char *prom_mapin __P((u_long, int, int));
|
|
||||||
|
|
||||||
int getdevtype __P((int, char *));
|
|
||||||
int getprop __P((int, char *, void *, int));
|
|
||||||
char *getpropstring __P((int, char *));
|
|
||||||
|
|
||||||
static void prom0_fake __P((void));
|
|
||||||
|
|
||||||
extern struct filesystem file_system_nfs[];
|
|
||||||
extern struct filesystem file_system_cd9660[];
|
|
||||||
extern struct filesystem file_system_ufs[];
|
|
||||||
|
|
||||||
int prom_open __P((struct open_file *f, ...)) { return 0; }
|
|
||||||
int prom_ioctl __P((struct open_file *f, u_long c, void *d)) { return EIO; }
|
|
||||||
|
|
||||||
struct devsw devsw[] = {
|
|
||||||
{ "prom0", prom0_strategy, prom_open, prom0_close, prom_ioctl },
|
|
||||||
{ "prom", obp_strategy, prom_open, obp_close, prom_ioctl }
|
|
||||||
};
|
|
||||||
|
|
||||||
int ndevs = (sizeof(devsw)/sizeof(devsw[0]));
|
|
||||||
|
|
||||||
char *prom_bootdevice;
|
|
||||||
char *prom_bootfile;
|
|
||||||
int prom_boothow;
|
|
||||||
|
|
||||||
struct promvec *promvec;
|
|
||||||
static int saveecho;
|
|
||||||
|
|
||||||
void
|
|
||||||
prom_init()
|
|
||||||
{
|
|
||||||
register char *ap, *cp, *dp;
|
|
||||||
|
|
||||||
if (cputyp == CPU_SUN4)
|
|
||||||
prom0_fake();
|
|
||||||
|
|
||||||
if (promvec->pv_romvec_vers >= 2) {
|
|
||||||
static char filestore[16];
|
|
||||||
|
|
||||||
prom_bootdevice = *promvec->pv_v2bootargs.v2_bootpath;
|
|
||||||
|
|
||||||
#ifndef BOOTXX
|
|
||||||
cp = *promvec->pv_v2bootargs.v2_bootargs;
|
|
||||||
dp = prom_bootfile = filestore;
|
|
||||||
while (*cp && *cp != '-')
|
|
||||||
*dp++ = *cp++;
|
|
||||||
while (dp > prom_bootfile && *--dp == ' ');
|
|
||||||
*++dp = '\0';
|
|
||||||
ap = cp;
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
static char bootstore[16];
|
|
||||||
dp = prom_bootdevice = bootstore;
|
|
||||||
cp = (*promvec->pv_v0bootargs)->ba_argv[0];
|
|
||||||
while (*cp) {
|
|
||||||
*dp++ = *cp;
|
|
||||||
if (*cp++ == ')')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*dp = '\0';
|
|
||||||
#ifndef BOOTXX
|
|
||||||
prom_bootfile = (*promvec->pv_v0bootargs)->ba_kernel;
|
|
||||||
ap = (*promvec->pv_v0bootargs)->ba_argv[1];
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef BOOTXX
|
|
||||||
if (ap == NULL || *ap != '-')
|
|
||||||
return;
|
|
||||||
|
|
||||||
while (*ap) {
|
|
||||||
switch (*ap++) {
|
|
||||||
case 'a':
|
|
||||||
prom_boothow |= RB_ASKNAME;
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
prom_boothow |= RB_SINGLE;
|
|
||||||
break;
|
|
||||||
case 'd':
|
|
||||||
prom_boothow |= RB_KDB;
|
|
||||||
debug = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
devopen(f, fname, file)
|
|
||||||
struct open_file *f;
|
|
||||||
const char *fname;
|
|
||||||
char **file;
|
|
||||||
{
|
|
||||||
int error = 0, fd;
|
|
||||||
struct promdata *pd;
|
|
||||||
|
|
||||||
pd = (struct promdata *)alloc(sizeof *pd);
|
|
||||||
|
|
||||||
if (cputyp == CPU_SUN4) {
|
|
||||||
error = prom0_iopen(pd);
|
|
||||||
#ifndef BOOTXX
|
|
||||||
pd->xmit = prom0_xmit;
|
|
||||||
pd->recv = prom0_recv;
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
fd = (promvec->pv_romvec_vers >= 2)
|
|
||||||
? (*promvec->pv_v2devops.v2_open)(prom_bootdevice)
|
|
||||||
: (*promvec->pv_v0devops.v0_open)(prom_bootdevice);
|
|
||||||
if (fd == 0) {
|
|
||||||
error = ENXIO;
|
|
||||||
} else {
|
|
||||||
pd->fd = fd;
|
|
||||||
#ifndef BOOTXX
|
|
||||||
pd->xmit = obp_xmit;
|
|
||||||
pd->recv = obp_recv;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
printf("Can't open device `%s'\n", prom_bootdevice);
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef BOOTXX
|
|
||||||
pd->devtype = DT_BLOCK;
|
|
||||||
#else /* BOOTXX */
|
|
||||||
pd->devtype = getdevtype(fd, prom_bootdevice);
|
|
||||||
/* Assume type BYTE is a raw device */
|
|
||||||
if (pd->devtype != DT_BYTE)
|
|
||||||
*file = (char *)fname;
|
|
||||||
|
|
||||||
if (pd->devtype == DT_NET) {
|
|
||||||
bcopy(file_system_nfs, file_system, sizeof(struct fs_ops));
|
|
||||||
if ((error = net_open(pd)) != 0) {
|
|
||||||
printf("Can't open network device `%s'\n",
|
|
||||||
prom_bootdevice);
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
bcopy(file_system_ufs, file_system, sizeof(struct fs_ops));
|
|
||||||
bcopy(&file_system_cd9660, file_system + 1, sizeof file_system[0]);
|
|
||||||
nfsys = 2;
|
|
||||||
}
|
|
||||||
#endif /* BOOTXX */
|
|
||||||
|
|
||||||
f->f_dev = &devsw[cputyp == CPU_SUN4 ? 0 : 1];
|
|
||||||
f->f_devdata = (void *)pd;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
obp_strategy(devdata, flag, dblk, size, buf, rsize)
|
|
||||||
void *devdata;
|
|
||||||
int flag;
|
|
||||||
daddr_t dblk;
|
|
||||||
size_t size;
|
|
||||||
void *buf;
|
|
||||||
size_t *rsize;
|
|
||||||
{
|
|
||||||
int error = 0;
|
|
||||||
struct promdata *pd = (struct promdata *)devdata;
|
|
||||||
int fd = pd->fd;
|
|
||||||
|
|
||||||
#ifdef DEBUG_PROM
|
|
||||||
printf("promstrategy: size=%d dblk=%d\n", size, dblk);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (promvec->pv_romvec_vers >= 2) {
|
|
||||||
if (pd->devtype == DT_BLOCK)
|
|
||||||
(*promvec->pv_v2devops.v2_seek)(fd, 0, dbtob(dblk));
|
|
||||||
|
|
||||||
*rsize = (*((flag == F_READ)
|
|
||||||
? (u_int (*)())promvec->pv_v2devops.v2_read
|
|
||||||
: (u_int (*)())promvec->pv_v2devops.v2_write
|
|
||||||
))(fd, buf, size);
|
|
||||||
} else {
|
|
||||||
int n = (*((flag == F_READ)
|
|
||||||
? (u_int (*)())promvec->pv_v0devops.v0_rbdev
|
|
||||||
: (u_int (*)())promvec->pv_v0devops.v0_wbdev
|
|
||||||
))(fd, btodb(size), dblk, buf);
|
|
||||||
*rsize = dbtob(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG_PROM
|
|
||||||
printf("rsize = %x\n", *rsize);
|
|
||||||
#endif
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* On old-monitor machines, things work differently.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
prom0_strategy(devdata, flag, dblk, size, buf, rsize)
|
|
||||||
void *devdata;
|
|
||||||
int flag;
|
|
||||||
daddr_t dblk;
|
|
||||||
size_t size;
|
|
||||||
void *buf;
|
|
||||||
size_t *rsize;
|
|
||||||
{
|
|
||||||
struct promdata *pd = devdata;
|
|
||||||
struct saioreq *si;
|
|
||||||
struct om_boottable *ops;
|
|
||||||
char *dmabuf;
|
|
||||||
int si_flag;
|
|
||||||
size_t xcnt;
|
|
||||||
|
|
||||||
si = pd->si;
|
|
||||||
ops = si->si_boottab;
|
|
||||||
|
|
||||||
#ifdef DEBUG_PROM
|
|
||||||
printf("prom_strategy: size=%d dblk=%d\n", size, dblk);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
dmabuf = dvma_mapin(buf, size);
|
|
||||||
|
|
||||||
si->si_bn = dblk;
|
|
||||||
si->si_ma = dmabuf;
|
|
||||||
si->si_cc = size;
|
|
||||||
|
|
||||||
si_flag = (flag == F_READ) ? SAIO_F_READ : SAIO_F_WRITE;
|
|
||||||
xcnt = (*ops->b_strategy)(si, si_flag);
|
|
||||||
dvma_mapout(dmabuf, size);
|
|
||||||
|
|
||||||
#ifdef DEBUG_PROM
|
|
||||||
printf("disk_strategy: xcnt = %x\n", xcnt);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (xcnt <= 0)
|
|
||||||
return (EIO);
|
|
||||||
|
|
||||||
*rsize = xcnt;
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
obp_close(f)
|
|
||||||
struct open_file *f;
|
|
||||||
{
|
|
||||||
struct promdata *pd = f->f_devdata;
|
|
||||||
register int fd = pd->fd;
|
|
||||||
|
|
||||||
#ifndef BOOTXX
|
|
||||||
if (pd->devtype == DT_NET)
|
|
||||||
net_close(pd);
|
|
||||||
#endif
|
|
||||||
if (promvec->pv_romvec_vers >= 2)
|
|
||||||
(void)(*promvec->pv_v2devops.v2_close)(fd);
|
|
||||||
else
|
|
||||||
(void)(*promvec->pv_v0devops.v0_close)(fd);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
prom0_close(f)
|
|
||||||
struct open_file *f;
|
|
||||||
{
|
|
||||||
struct promdata *pd = f->f_devdata;
|
|
||||||
|
|
||||||
#ifndef BOOTXX
|
|
||||||
if (pd->devtype == DT_NET)
|
|
||||||
net_close(pd);
|
|
||||||
#endif
|
|
||||||
prom0_iclose(pd->si);
|
|
||||||
pd->si = NULL;
|
|
||||||
*romp->echo = saveecho; /* Hmm, probably must go somewhere else */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef BOOTXX
|
|
||||||
ssize_t
|
|
||||||
obp_xmit(pd, buf, len)
|
|
||||||
struct promdata *pd;
|
|
||||||
void *buf;
|
|
||||||
size_t len;
|
|
||||||
{
|
|
||||||
return (promvec->pv_romvec_vers >= 2
|
|
||||||
? (*promvec->pv_v2devops.v2_write)(pd->fd, buf, len)
|
|
||||||
: (*promvec->pv_v0devops.v0_wnet)(pd->fd, len, buf));
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t
|
|
||||||
obp_recv(pd, buf, len)
|
|
||||||
struct promdata *pd;
|
|
||||||
void *buf;
|
|
||||||
size_t len;
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
|
|
||||||
n = (promvec->pv_romvec_vers >= 2
|
|
||||||
? (*promvec->pv_v2devops.v2_read)(pd->fd, buf, len)
|
|
||||||
: (*promvec->pv_v0devops.v0_rnet)(pd->fd, len, buf));
|
|
||||||
return (n == -2 ? 0 : n);
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t
|
|
||||||
prom0_xmit(pd, buf, len)
|
|
||||||
struct promdata *pd;
|
|
||||||
void *buf;
|
|
||||||
size_t len;
|
|
||||||
{
|
|
||||||
struct saioreq *si;
|
|
||||||
struct saif *sif;
|
|
||||||
char *dmabuf;
|
|
||||||
int rv;
|
|
||||||
|
|
||||||
si = pd->si;
|
|
||||||
sif = si->si_sif;
|
|
||||||
if (sif == NULL) {
|
|
||||||
printf("xmit: not a network device\n");
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
dmabuf = dvma_mapin(buf, len);
|
|
||||||
rv = sif->sif_xmit(si->si_devdata, dmabuf, len);
|
|
||||||
dvma_mapout(dmabuf, len);
|
|
||||||
|
|
||||||
return (ssize_t)(rv ? -1 : len);
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t
|
|
||||||
prom0_recv(pd, buf, len)
|
|
||||||
struct promdata *pd;
|
|
||||||
void *buf;
|
|
||||||
size_t len;
|
|
||||||
{
|
|
||||||
struct saioreq *si;
|
|
||||||
struct saif *sif;
|
|
||||||
char *dmabuf;
|
|
||||||
int rv;
|
|
||||||
|
|
||||||
si = pd->si;
|
|
||||||
sif = si->si_sif;
|
|
||||||
dmabuf = dvma_mapin(buf, len);
|
|
||||||
rv = sif->sif_poll(si->si_devdata, dmabuf);
|
|
||||||
dvma_mapout(dmabuf, len);
|
|
||||||
|
|
||||||
return (ssize_t)rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
getchar()
|
|
||||||
{
|
|
||||||
char c;
|
|
||||||
register int n;
|
|
||||||
|
|
||||||
if (promvec->pv_romvec_vers > 2)
|
|
||||||
while ((n = (*promvec->pv_v2devops.v2_read)
|
|
||||||
(*promvec->pv_v2bootargs.v2_fd0, (caddr_t)&c, 1)) != 1);
|
|
||||||
else
|
|
||||||
c = (*promvec->pv_getchar)();
|
|
||||||
|
|
||||||
if (c == '\r')
|
|
||||||
c = '\n';
|
|
||||||
return (c);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
cngetc()
|
|
||||||
{
|
|
||||||
return getchar();
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
peekchar()
|
|
||||||
{
|
|
||||||
char c;
|
|
||||||
register int n;
|
|
||||||
|
|
||||||
if (promvec->pv_romvec_vers > 2) {
|
|
||||||
n = (*promvec->pv_v2devops.v2_read)
|
|
||||||
(*promvec->pv_v2bootargs.v2_fd0, (caddr_t)&c, 1);
|
|
||||||
if (n < 0)
|
|
||||||
return -1;
|
|
||||||
} else
|
|
||||||
c = (*promvec->pv_nbgetchar)();
|
|
||||||
|
|
||||||
if (c == '\r')
|
|
||||||
c = '\n';
|
|
||||||
return (c);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void
|
|
||||||
pv_putchar(c)
|
|
||||||
int c;
|
|
||||||
{
|
|
||||||
char c0 = c;
|
|
||||||
|
|
||||||
if (promvec->pv_romvec_vers > 2)
|
|
||||||
(*promvec->pv_v2devops.v2_write)
|
|
||||||
(*promvec->pv_v2bootargs.v2_fd1, &c0, 1);
|
|
||||||
else
|
|
||||||
(*promvec->pv_putchar)(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
putchar(c)
|
|
||||||
int c;
|
|
||||||
{
|
|
||||||
|
|
||||||
if (c == '\n')
|
|
||||||
pv_putchar('\r');
|
|
||||||
pv_putchar(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
_rtt()
|
|
||||||
{
|
|
||||||
promvec->pv_halt();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef BOOTXX
|
|
||||||
int hz = 1000;
|
|
||||||
|
|
||||||
time_t
|
|
||||||
getsecs()
|
|
||||||
{
|
|
||||||
register int ticks = getticks();
|
|
||||||
return ((time_t)(ticks / hz));
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
getticks()
|
|
||||||
{
|
|
||||||
if (promvec->pv_romvec_vers >= 2) {
|
|
||||||
char c;
|
|
||||||
(void)(*promvec->pv_v2devops.v2_read)
|
|
||||||
(*promvec->pv_v2bootargs.v2_fd0, (caddr_t)&c, 0);
|
|
||||||
} else {
|
|
||||||
(void)(*promvec->pv_nbgetchar)();
|
|
||||||
}
|
|
||||||
return *(promvec->pv_ticks);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
prom_getether(fd, ea)
|
|
||||||
u_char *ea;
|
|
||||||
{
|
|
||||||
if (cputyp == CPU_SUN4) {
|
|
||||||
static struct idprom sun4_idprom;
|
|
||||||
u_char *src, *dst;
|
|
||||||
int len, x;
|
|
||||||
|
|
||||||
if (sun4_idprom.id_format == 0) {
|
|
||||||
dst = (char*)&sun4_idprom;
|
|
||||||
src = (char*)AC_IDPROM;
|
|
||||||
len = sizeof(struct idprom);
|
|
||||||
do {
|
|
||||||
x = lduba(src++, ASI_CONTROL);
|
|
||||||
*dst++ = x;
|
|
||||||
} while (--len > 0);
|
|
||||||
}
|
|
||||||
bcopy(sun4_idprom.id_ether, ea, 6);
|
|
||||||
} else if (promvec->pv_romvec_vers <= 2) {
|
|
||||||
(void)(*promvec->pv_enaddr)(fd, (char *)ea);
|
|
||||||
} else {
|
|
||||||
char buf[64];
|
|
||||||
sprintf(buf, "%x mac-address drop swap 6 cmove", ea);
|
|
||||||
promvec->pv_fortheval.v2_eval(buf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A number of well-known devices on sun4s.
|
|
||||||
*/
|
|
||||||
static struct dtab {
|
|
||||||
char *name;
|
|
||||||
int type;
|
|
||||||
} dtab[] = {
|
|
||||||
{ "sd", DT_BLOCK },
|
|
||||||
{ "st", DT_BLOCK },
|
|
||||||
{ "xd", DT_BLOCK },
|
|
||||||
{ "xy", DT_BLOCK },
|
|
||||||
{ "fd", DT_BLOCK },
|
|
||||||
{ "le", DT_NET },
|
|
||||||
{ "ie", DT_NET },
|
|
||||||
{ NULL, 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
int
|
|
||||||
getdevtype(fd, name)
|
|
||||||
int fd;
|
|
||||||
char *name;
|
|
||||||
{
|
|
||||||
if (promvec->pv_romvec_vers >= 2) {
|
|
||||||
int node = (*promvec->pv_v2devops.v2_fd_phandle)(fd);
|
|
||||||
char *cp = getpropstring(node, "device_type");
|
|
||||||
if (strcmp(cp, "block") == 0)
|
|
||||||
return DT_BLOCK;
|
|
||||||
else if (strcmp(cp, "network") == 0)
|
|
||||||
return DT_NET;
|
|
||||||
else if (strcmp(cp, "byte") == 0)
|
|
||||||
return DT_BYTE;
|
|
||||||
} else {
|
|
||||||
struct dtab *dp;
|
|
||||||
for (dp = dtab; dp->name; dp++) {
|
|
||||||
if (name[0] == dp->name[0] &&
|
|
||||||
name[1] == dp->name[1])
|
|
||||||
return dp->type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* OpenPROM nodes & property routines (from <sparc/autoconf.c>).
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
getprop(node, name, buf, bufsiz)
|
|
||||||
int node;
|
|
||||||
char *name;
|
|
||||||
void *buf;
|
|
||||||
register int bufsiz;
|
|
||||||
{
|
|
||||||
register struct nodeops *no;
|
|
||||||
register int len;
|
|
||||||
|
|
||||||
no = promvec->pv_nodeops;
|
|
||||||
len = no->no_proplen(node, name);
|
|
||||||
if (len > bufsiz) {
|
|
||||||
printf("node %x property %s length %d > %d\n",
|
|
||||||
node, name, len, bufsiz);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
no->no_getprop(node, name, buf);
|
|
||||||
return (len);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return a string property. There is a (small) limit on the length;
|
|
||||||
* the string is fetched into a static buffer which is overwritten on
|
|
||||||
* subsequent calls.
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
getpropstring(node, name)
|
|
||||||
int node;
|
|
||||||
char *name;
|
|
||||||
{
|
|
||||||
register int len;
|
|
||||||
static char stringbuf[64];
|
|
||||||
|
|
||||||
len = getprop(node, name, (void *)stringbuf, sizeof stringbuf - 1);
|
|
||||||
if (len == -1)
|
|
||||||
len = 0;
|
|
||||||
stringbuf[len] = '\0'; /* usually unnecessary */
|
|
||||||
return (stringbuf);
|
|
||||||
}
|
|
||||||
#endif /* BOOTXX */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Old monitor routines
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <machine/pte.h>
|
|
||||||
|
|
||||||
struct saioreq prom_si;
|
|
||||||
static int promdev_inuse;
|
|
||||||
|
|
||||||
int
|
|
||||||
prom0_iopen(pd)
|
|
||||||
struct promdata *pd;
|
|
||||||
{
|
|
||||||
struct om_bootparam *bp;
|
|
||||||
struct om_boottable *ops;
|
|
||||||
struct devinfo *dip;
|
|
||||||
struct saioreq *si;
|
|
||||||
int error;
|
|
||||||
|
|
||||||
if (promdev_inuse)
|
|
||||||
return(EMFILE);
|
|
||||||
|
|
||||||
bp = *romp->bootParam;
|
|
||||||
ops = bp->bootTable;
|
|
||||||
dip = ops->b_devinfo;
|
|
||||||
|
|
||||||
#ifdef DEBUG_PROM
|
|
||||||
printf("Boot device type: %s\n", ops->b_desc);
|
|
||||||
printf("d_devbytes=%d\n", dip->d_devbytes);
|
|
||||||
printf("d_dmabytes=%d\n", dip->d_dmabytes);
|
|
||||||
printf("d_localbytes=%d\n", dip->d_localbytes);
|
|
||||||
printf("d_stdcount=%d\n", dip->d_stdcount);
|
|
||||||
printf("d_stdaddrs[%d]=%x\n", bp->ctlrNum, dip->d_stdaddrs[bp->ctlrNum]);
|
|
||||||
printf("d_devtype=%d\n", dip->d_devtype);
|
|
||||||
printf("d_maxiobytes=%d\n", dip->d_maxiobytes);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
dvma_init();
|
|
||||||
|
|
||||||
si = &prom_si;
|
|
||||||
bzero((caddr_t)si, sizeof(*si));
|
|
||||||
si->si_boottab = ops;
|
|
||||||
si->si_ctlr = bp->ctlrNum;
|
|
||||||
si->si_unit = bp->unitNum;
|
|
||||||
si->si_boff = bp->partNum;
|
|
||||||
|
|
||||||
if (si->si_ctlr > dip->d_stdcount) {
|
|
||||||
printf("Invalid controller number\n");
|
|
||||||
return(ENXIO);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dip->d_devbytes) {
|
|
||||||
si->si_devaddr = prom_mapin(dip->d_stdaddrs[si->si_ctlr],
|
|
||||||
dip->d_devbytes, dip->d_devtype);
|
|
||||||
#ifdef DEBUG_PROM
|
|
||||||
printf("prom_iopen: devaddr=0x%x pte=0x%x\n",
|
|
||||||
si->si_devaddr,
|
|
||||||
getpte((u_long)si->si_devaddr & ~PGOFSET));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dip->d_dmabytes) {
|
|
||||||
si->si_dmaaddr = dvma_alloc(dip->d_dmabytes);
|
|
||||||
#ifdef DEBUG_PROM
|
|
||||||
printf("prom_iopen: dmaaddr=0x%x\n", si->si_dmaaddr);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dip->d_localbytes) {
|
|
||||||
si->si_devdata = alloc(dip->d_localbytes);
|
|
||||||
#ifdef DEBUG_PROM
|
|
||||||
printf("prom_iopen: devdata=0x%x\n", si->si_devdata);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* OK, call the PROM device open routine. */
|
|
||||||
error = (*ops->b_open)(si);
|
|
||||||
if (error != 0) {
|
|
||||||
printf("prom_iopen: \"%s\" error=%d\n",
|
|
||||||
ops->b_desc, error);
|
|
||||||
return (ENXIO);
|
|
||||||
}
|
|
||||||
#ifdef DEBUG_PROM
|
|
||||||
printf("prom_iopen: succeeded, error=%d\n", error);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
pd->si = si;
|
|
||||||
promdev_inuse++;
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
prom0_iclose(si)
|
|
||||||
struct saioreq *si;
|
|
||||||
{
|
|
||||||
struct om_boottable *ops;
|
|
||||||
struct devinfo *dip;
|
|
||||||
|
|
||||||
if (promdev_inuse == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ops = si->si_boottab;
|
|
||||||
dip = ops->b_devinfo;
|
|
||||||
|
|
||||||
(*ops->b_close)(si);
|
|
||||||
|
|
||||||
if (si->si_dmaaddr) {
|
|
||||||
dvma_free(si->si_dmaaddr, dip->d_dmabytes);
|
|
||||||
si->si_dmaaddr = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
promdev_inuse = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct mapinfo {
|
|
||||||
int maptype;
|
|
||||||
int pgtype;
|
|
||||||
int base;
|
|
||||||
} prom_mapinfo[] = {
|
|
||||||
{ MAP_MAINMEM, PG_OBMEM, 0 },
|
|
||||||
{ MAP_OBIO, PG_OBIO, 0 },
|
|
||||||
{ MAP_MBMEM, PG_VME16, 0xFF000000 },
|
|
||||||
{ MAP_MBIO, PG_VME16, 0xFFFF0000 },
|
|
||||||
{ MAP_VME16A16D, PG_VME16, 0xFFFF0000 },
|
|
||||||
{ MAP_VME16A32D, PG_VME32, 0xFFFF0000 },
|
|
||||||
{ MAP_VME24A16D, PG_VME16, 0xFF000000 },
|
|
||||||
{ MAP_VME24A32D, PG_VME32, 0xFF000000 },
|
|
||||||
{ MAP_VME32A16D, PG_VME16, 0 },
|
|
||||||
{ MAP_VME32A32D, PG_VME32, 0 },
|
|
||||||
};
|
|
||||||
static prom_mapinfo_cnt = sizeof(prom_mapinfo) / sizeof(prom_mapinfo[0]);
|
|
||||||
|
|
||||||
/* The virtual address we will use for PROM device mappings. */
|
|
||||||
static u_long prom_devmap = MONSHORTSEG;
|
|
||||||
|
|
||||||
static char *
|
|
||||||
prom_mapin(physaddr, length, maptype)
|
|
||||||
u_long physaddr;
|
|
||||||
int length, maptype;
|
|
||||||
{
|
|
||||||
int i, pa, pte, va;
|
|
||||||
|
|
||||||
if (length > (4*NBPG))
|
|
||||||
panic("prom_mapin: length=%d", length);
|
|
||||||
|
|
||||||
for (i = 0; i < prom_mapinfo_cnt; i++)
|
|
||||||
if (prom_mapinfo[i].maptype == maptype)
|
|
||||||
goto found;
|
|
||||||
panic("prom_mapin: invalid maptype %d", maptype);
|
|
||||||
found:
|
|
||||||
|
|
||||||
pte = prom_mapinfo[i].pgtype;
|
|
||||||
pte |= (PG_V|PG_W|PG_S|PG_NC);
|
|
||||||
pa = prom_mapinfo[i].base;
|
|
||||||
pa += physaddr;
|
|
||||||
pte |= ((pa >> PGSHIFT) & PG_PFNUM);
|
|
||||||
|
|
||||||
va = prom_devmap;
|
|
||||||
do {
|
|
||||||
setpte(va, pte);
|
|
||||||
va += NBPG;
|
|
||||||
pte += 1;
|
|
||||||
length -= NBPG;
|
|
||||||
} while (length > 0);
|
|
||||||
return ((char*)(prom_devmap | (pa & PGOFSET)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
prom0_fake()
|
|
||||||
{
|
|
||||||
static struct promvec promvecstore;
|
|
||||||
|
|
||||||
promvec = &promvecstore;
|
|
||||||
|
|
||||||
promvec->pv_stdin = romp->inSource;
|
|
||||||
promvec->pv_stdout = romp->outSink;
|
|
||||||
promvec->pv_putchar = romp->putChar;
|
|
||||||
promvec->pv_putstr = romp->fbWriteStr;
|
|
||||||
promvec->pv_nbgetchar = romp->mayGet;
|
|
||||||
promvec->pv_getchar = romp->getChar;
|
|
||||||
promvec->pv_romvec_vers = 0; /* eek! */
|
|
||||||
promvec->pv_reboot = romp->reBoot;
|
|
||||||
promvec->pv_abort = romp->abortEntry;
|
|
||||||
promvec->pv_setctxt = romp->setcxsegmap;
|
|
||||||
promvec->pv_v0bootargs = (struct v0bootargs **)(romp->bootParam);
|
|
||||||
promvec->pv_halt = romp->exitToMon;
|
|
||||||
promvec->pv_ticks = romp->nmiClock;
|
|
||||||
saveecho = *romp->echo;
|
|
||||||
*romp->echo = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,180 +0,0 @@
|
|||||||
/* $OpenBSD: srt0.S,v 1.1 1997/09/17 10:46:20 downsj Exp $ */
|
|
||||||
/* $NetBSD: srt0.S,v 1.5.4.2 1996/07/17 01:51:46 jtc Exp $ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 1994 Paul Kranenburg
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by Paul Kranenburg.
|
|
||||||
* 4. The name of the author may not be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
||||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
||||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
||||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <machine/param.h>
|
|
||||||
#include <machine/psl.h>
|
|
||||||
|
|
||||||
.file "str0.s"
|
|
||||||
|
|
||||||
.data
|
|
||||||
.global cputyp, nbpg, pgofset, pgshift
|
|
||||||
cputyp:
|
|
||||||
.word 1
|
|
||||||
nbpg:
|
|
||||||
.word 1
|
|
||||||
pgofset:
|
|
||||||
.word 1
|
|
||||||
pgshift:
|
|
||||||
.word 1
|
|
||||||
#define STACK_SIZE 2048
|
|
||||||
tstack:
|
|
||||||
.fill STACK_SIZE
|
|
||||||
|
|
||||||
.text
|
|
||||||
.globl start
|
|
||||||
|
|
||||||
start:
|
|
||||||
/*
|
|
||||||
* Set up a stack.
|
|
||||||
*/
|
|
||||||
set tstack, %o1
|
|
||||||
save %o1, STACK_SIZE-4, %sp
|
|
||||||
|
|
||||||
4:
|
|
||||||
#ifdef notyet
|
|
||||||
/*
|
|
||||||
* Enable traps
|
|
||||||
*/
|
|
||||||
wr %g0, 0, %wim ! make sure we can set psr
|
|
||||||
nop; nop; nop
|
|
||||||
wr %g0, PSR_S|PSR_PS|PSR_PIL, %psr ! set initial psr
|
|
||||||
nop; nop; nop
|
|
||||||
wr %g0, 2, %wim ! set initial %wim (w1 invalid)
|
|
||||||
|
|
||||||
rd %psr, %l0
|
|
||||||
wr %l0, PSR_ET, %psr
|
|
||||||
nop; nop; nop
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Clear BSS
|
|
||||||
*/
|
|
||||||
set _edata, %o0 ! bzero(edata, end - edata)
|
|
||||||
set _end, %o1
|
|
||||||
call bzero
|
|
||||||
sub %o1, %o0, %o1
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Enable interrupts, but only above level 11. This enables "L1-A",
|
|
||||||
* but avoids spurious interrupt bites from most other devices.
|
|
||||||
*/
|
|
||||||
rd %psr, %o0
|
|
||||||
andn %o0, PSR_PIL, %o0
|
|
||||||
wr %o0, 0xb00, %psr ! (11 << 8)
|
|
||||||
nop; nop; nop
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set CPU type that we are running on.
|
|
||||||
*/
|
|
||||||
sethi %hi(cputyp), %o0
|
|
||||||
set 0x4000, %g7
|
|
||||||
cmp %i0, %g7
|
|
||||||
beq 5f
|
|
||||||
nop
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Save address of PROM vector (passed in %i0).
|
|
||||||
*/
|
|
||||||
sethi %hi(promvec), %o1
|
|
||||||
st %i0, [%o1 + %lo(promvec)]
|
|
||||||
|
|
||||||
mov CPU_SUN4C, %g4
|
|
||||||
mov SUN4CM_PGSHIFT, %g5
|
|
||||||
b,a 6f
|
|
||||||
|
|
||||||
5:
|
|
||||||
mov CPU_SUN4, %g4
|
|
||||||
mov SUN4_PGSHIFT, %g5
|
|
||||||
|
|
||||||
6:
|
|
||||||
st %g4, [%o0 + %lo(cputyp)]
|
|
||||||
sethi %hi(pgshift), %o0 ! pgshift = log2(nbpg)
|
|
||||||
st %g5, [%o0 + %lo(pgshift)]
|
|
||||||
|
|
||||||
mov 1, %o0 ! nbpg = 1 << pgshift
|
|
||||||
sll %o0, %g5, %g5
|
|
||||||
sethi %hi(nbpg), %o0 ! nbpg = bytes in a page
|
|
||||||
st %g5, [%o0 + %lo(nbpg)]
|
|
||||||
|
|
||||||
sub %g5, 1, %g5
|
|
||||||
sethi %hi(pgofset), %o0 ! page offset = bytes in a page - 1
|
|
||||||
st %g5, [%o0 + %lo(pgofset)]
|
|
||||||
|
|
||||||
call main
|
|
||||||
mov %i0, %o0
|
|
||||||
|
|
||||||
ret
|
|
||||||
restore
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef TIGHT
|
|
||||||
|
|
||||||
/*
|
|
||||||
* XXX - Space saving .div & .rem routines (small & non-negative numbres only)
|
|
||||||
*/
|
|
||||||
.align 4
|
|
||||||
.global .div, .udiv
|
|
||||||
! int n = 0; while (a >= b) { a -= b; n++; }; return n;
|
|
||||||
.div:
|
|
||||||
.udiv:
|
|
||||||
cmp %o0, %o1
|
|
||||||
bl 2f
|
|
||||||
mov 0, %o5
|
|
||||||
1:
|
|
||||||
sub %o0, %o1, %o0
|
|
||||||
cmp %o0, %o1
|
|
||||||
bge 1b
|
|
||||||
add %o5, 1, %o5
|
|
||||||
2:
|
|
||||||
retl
|
|
||||||
mov %o5, %o0
|
|
||||||
|
|
||||||
.align 4
|
|
||||||
.global .rem, .urem
|
|
||||||
! while (a>=b) a -= b; return a;
|
|
||||||
.rem:
|
|
||||||
.urem:
|
|
||||||
cmp %o0, %o1
|
|
||||||
bl 2f
|
|
||||||
nop
|
|
||||||
sub %o0, %o1, %o0
|
|
||||||
1:
|
|
||||||
cmp %o0, %o1
|
|
||||||
bge,a 1b
|
|
||||||
sub %o0, %o1, %o0
|
|
||||||
2:
|
|
||||||
retl
|
|
||||||
nop
|
|
||||||
|
|
||||||
#endif /* TIGHT */
|
|
||||||
|
|
||||||
@@ -1,263 +0,0 @@
|
|||||||
/* $OpenBSD: bootxx.c,v 1.1 1997/09/17 10:46:16 downsj Exp $ */
|
|
||||||
/* $NetBSD: bootxx.c,v 1.2 1997/09/14 19:28:17 pk Exp $ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 1994 Paul Kranenburg
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by Paul Kranenburg.
|
|
||||||
* 4. The name of the author may not be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
||||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
||||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
||||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
|
|
||||||
#include <stand.h>
|
|
||||||
|
|
||||||
#include <promdev.h>
|
|
||||||
|
|
||||||
int debug;
|
|
||||||
int netif_debug;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Boot device is derived from ROM provided information.
|
|
||||||
*/
|
|
||||||
const char progname[] = "bootxx";
|
|
||||||
struct open_file io;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The contents of the block_* variables below is set by installboot(8)
|
|
||||||
* to hold the the filesystem data of the second-stage boot program
|
|
||||||
* (typically `/boot'): filesystem block size, # of filesystem blocks and
|
|
||||||
* the block numbers themselves.
|
|
||||||
*/
|
|
||||||
#define MAXBLOCKNUM 256 /* enough for a 2MB boot program (bs 8K) */
|
|
||||||
int32_t block_size = 0;
|
|
||||||
int32_t block_count = MAXBLOCKNUM;
|
|
||||||
daddr_t block_table[MAXBLOCKNUM] = { 0 };
|
|
||||||
|
|
||||||
int memory_node = 0;
|
|
||||||
|
|
||||||
void loadboot __P((struct open_file *, caddr_t));
|
|
||||||
|
|
||||||
void scan_node(int node, char *buf, int recurse, int level)
|
|
||||||
{
|
|
||||||
char *ptr;
|
|
||||||
int node1;
|
|
||||||
|
|
||||||
do {
|
|
||||||
// printf("%dnode 0x%x\n", level, node);
|
|
||||||
ptr = NULL;
|
|
||||||
for(ptr = promvec->pv_nodeops->no_nextprop(node, NULL);
|
|
||||||
ptr != NULL && ptr[0] != '\0';
|
|
||||||
ptr = promvec->pv_nodeops->no_nextprop(node, ptr)) {
|
|
||||||
|
|
||||||
// printf("%d\tproperty '%s'\n", level, ptr);
|
|
||||||
|
|
||||||
if(!strcmp(ptr, "name")) {
|
|
||||||
promvec->pv_nodeops->no_getprop(node, ptr, buf);
|
|
||||||
// printf("%d\t\tname = '%s'\n", level, buf);
|
|
||||||
if(!strcmp(buf, "memory")) {
|
|
||||||
memory_node = node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
node1 = promvec->pv_nodeops->no_child(node);
|
|
||||||
// printf("%d\tchild = 0x%x\n", level, node1);
|
|
||||||
if(node1 != 0 && recurse != 0) {
|
|
||||||
scan_node(node1, buf, recurse, level+1);
|
|
||||||
}
|
|
||||||
node = promvec->pv_nodeops->no_nextnode(node);
|
|
||||||
} while(node != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void scan_nodes()
|
|
||||||
{
|
|
||||||
char buf[64];
|
|
||||||
|
|
||||||
// Walk through the nodes
|
|
||||||
{
|
|
||||||
int node = 0;
|
|
||||||
|
|
||||||
node = promvec->pv_nodeops->no_nextnode(node);
|
|
||||||
scan_node(node, buf, 1, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Internal form of getprop(). Returns the actual length.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
getprop(node, name, buf, bufsiz)
|
|
||||||
int node;
|
|
||||||
char *name;
|
|
||||||
void *buf;
|
|
||||||
register int bufsiz;
|
|
||||||
{
|
|
||||||
#if defined(SUN4C) || defined(SUN4M)
|
|
||||||
register struct nodeops *no;
|
|
||||||
register int len;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(SUN4)
|
|
||||||
if (CPU_ISSUN4) {
|
|
||||||
printf("WARNING: getprop not valid on sun4! %s\n", name);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(SUN4C) || defined(SUN4M)
|
|
||||||
no = promvec->pv_nodeops;
|
|
||||||
len = no->no_proplen(node, name);
|
|
||||||
if (len > bufsiz) {
|
|
||||||
printf("node 0x%x property %s length %d > %d\n",
|
|
||||||
node, name, len, bufsiz);
|
|
||||||
#ifdef DEBUG
|
|
||||||
panic("getprop");
|
|
||||||
#else
|
|
||||||
return (0);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
no->no_getprop(node, name, buf);
|
|
||||||
return (len);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main()
|
|
||||||
{
|
|
||||||
char *dummy;
|
|
||||||
size_t n;
|
|
||||||
register void (*entry)__P((caddr_t)) = (void (*)__P((caddr_t)))LOADADDR;
|
|
||||||
|
|
||||||
prom_init();
|
|
||||||
|
|
||||||
printf("Welcome to second stage bootloader!\n");
|
|
||||||
|
|
||||||
printf("cputyp = %d\n", cputyp);
|
|
||||||
printf("nbpg = %d\n", nbpg);
|
|
||||||
printf("pgofset = %d\n", pgofset);
|
|
||||||
printf("pgshift = %d\n", pgshift);
|
|
||||||
printf("promvec = 0x%x\n", (unsigned int)promvec);
|
|
||||||
|
|
||||||
printf("Scanning nodes...");
|
|
||||||
scan_nodes();
|
|
||||||
printf("done\n");
|
|
||||||
printf("memory_node = 0x%x\n", memory_node);
|
|
||||||
|
|
||||||
// Look at how memory is laid out
|
|
||||||
{
|
|
||||||
struct openprom_addr addr[64];
|
|
||||||
int len;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
len = getprop(memory_node, "reg", &addr, sizeof(addr)) /
|
|
||||||
sizeof(struct openprom_addr);
|
|
||||||
printf("retrieved physical memory layout struct. size %d:\n", len);
|
|
||||||
|
|
||||||
for(i=0; i<len; i++) {
|
|
||||||
printf("\tstart addr 0x%x, len 0x%x\n",
|
|
||||||
addr[i].oa_base, addr[i].oa_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
len = getprop(memory_node, "available", &addr, sizeof(addr)) /
|
|
||||||
sizeof(struct openprom_addr);
|
|
||||||
printf("retrieved available physical memory layout struct. size %d:\n", len);
|
|
||||||
|
|
||||||
for(i=0; i<len; i++) {
|
|
||||||
printf("\tstart addr 0x%x, len 0x%x\n",
|
|
||||||
addr[i].oa_base, addr[i].oa_size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
io.f_flags = F_RAW;
|
|
||||||
if (devopen(&io, 0, &dummy)) {
|
|
||||||
panic("%s: can't open device", progname);
|
|
||||||
}
|
|
||||||
(void)loadboot(&io, LOADADDR);
|
|
||||||
(io.f_dev->dv_close)(&io);
|
|
||||||
(*entry)(cputyp == CPU_SUN4 ? LOADADDR : (caddr_t)promvec);
|
|
||||||
*/
|
|
||||||
_rtt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
loadboot(f, addr)
|
|
||||||
register struct open_file *f;
|
|
||||||
register char *addr;
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
void
|
|
||||||
loadboot(f, addr)
|
|
||||||
register struct open_file *f;
|
|
||||||
register char *addr;
|
|
||||||
{
|
|
||||||
register int i;
|
|
||||||
register char *buf;
|
|
||||||
size_t n;
|
|
||||||
daddr_t blk;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Allocate a buffer that we can map into DVMA space; only
|
|
||||||
* needed for sun4 architecture, but use it for all machines
|
|
||||||
* to keep code size down as much as possible.
|
|
||||||
*/
|
|
||||||
buf = alloc(block_size);
|
|
||||||
if (buf == NULL)
|
|
||||||
panic("%s: alloc failed", progname);
|
|
||||||
|
|
||||||
for (i = 0; i < block_count; i++) {
|
|
||||||
if ((blk = block_table[i]) == 0)
|
|
||||||
panic("%s: block table corrupt", progname);
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
printf("%s: block # %d = %d\n", progname, i, blk);
|
|
||||||
#endif
|
|
||||||
if ((f->f_dev->dv_strategy)(f->f_devdata, F_READ,
|
|
||||||
blk, block_size, buf, &n)) {
|
|
||||||
panic("%s: read failure", progname);
|
|
||||||
}
|
|
||||||
bcopy(buf, addr, block_size);
|
|
||||||
if (n != block_size)
|
|
||||||
panic("%s: short read", progname);
|
|
||||||
if (i == 0) {
|
|
||||||
register int m = N_GETMAGIC(*(struct exec *)addr);
|
|
||||||
if (m == ZMAGIC || m == NMAGIC || m == OMAGIC) {
|
|
||||||
/* Move exec header out of the way */
|
|
||||||
bcopy(addr, addr - sizeof(struct exec), n);
|
|
||||||
addr -= sizeof(struct exec);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
addr += n;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
CFLAGS = -O3 -DBOOTXX -D_STANDALONE -DSTANDALONE -DRELOC=0x380000 -DSUN4M -DSUN_BOOTPARAMS -DDEBUG -DDEBUG_PROM -Iboot/$(ARCH)/include
|
|
||||||
LIBSACFLAGS = -O3 -D_STANDALONE -D__INTERNAL_LIBSA_CREAD -Iboot/$(ARCH)/include
|
|
||||||
LIBKERNCFLAGS = -O3 -D_KERNEL -Iboot/$(ARCH)/include
|
|
||||||
|
|
||||||
STAGE2_OBJS = boot/$(ARCH)/srt0.o \
|
|
||||||
boot/$(ARCH)/promdev.o \
|
|
||||||
boot/$(ARCH)/closeall.o \
|
|
||||||
boot/$(ARCH)/dvma.o \
|
|
||||||
boot/$(ARCH)/stage2.o \
|
|
||||||
boot/$(ARCH)/libsa/alloc.o \
|
|
||||||
boot/$(ARCH)/libsa/exit.o \
|
|
||||||
boot/$(ARCH)/libsa/printf.o \
|
|
||||||
boot/$(ARCH)/libsa/memset.o \
|
|
||||||
boot/$(ARCH)/libsa/memcpy.o \
|
|
||||||
boot/$(ARCH)/libsa/memcmp.o \
|
|
||||||
boot/$(ARCH)/libsa/strcmp.o \
|
|
||||||
boot/$(ARCH)/libkern/bzero.o \
|
|
||||||
boot/$(ARCH)/libkern/udiv.o \
|
|
||||||
boot/$(ARCH)/libkern/urem.o \
|
|
||||||
boot/$(ARCH)/libkern/__main.o
|
|
||||||
|
|
||||||
DEPS += $(STAGE2_OBJS:.o=.d)
|
|
||||||
|
|
||||||
boot/$(ARCH)/stage2: $(STAGE2_OBJS)
|
|
||||||
ld -dN -Ttext 0x381278 -e start $(STAGE2_OBJS) -o $@
|
|
||||||
|
|
||||||
boot/$(ARCH)/libsa/%.o: boot/$(ARCH)/libsa/%.c
|
|
||||||
$(CC) $(LIBSACFLAGS) -c $< -o $@
|
|
||||||
|
|
||||||
boot/$(ARCH)/libsa/%.d: boot/$(ARCH)/libsa/%.c
|
|
||||||
@($(ECHO) -n $(dir $@);$(CC) $(LIBSACFLAGS) -M -MG $<) > $@
|
|
||||||
|
|
||||||
boot/$(ARCH)/libkern/%.o: boot/$(ARCH)/libkern/%.c
|
|
||||||
$(CC) $(LIBKERNCFLAGS) -c $< -o $@
|
|
||||||
|
|
||||||
boot/$(ARCH)/libkern/%.d: boot/$(ARCH)/libkern/%.c
|
|
||||||
@($(ECHO) -n $(dir $@);$(CC) $(LIBKERNCFLAGS) -M -MG $<) > $@
|
|
||||||
|
|
||||||
boot/$(ARCH)/libkern/%.o: boot/$(ARCH)/libkern/%.S
|
|
||||||
$(CC) $(LIBKERNCFLAGS) -c $< -o $@
|
|
||||||
|
|
||||||
boot/$(ARCH)/libkern/%.d: boot/$(ARCH)/libkern/%.S
|
|
||||||
@($(ECHO) -n $(dir $@);$(CC) $(LIBKERNCFLAGS) -M -MG $<) > $@
|
|
||||||
|
|
||||||
boot/$(ARCH)/%.o: boot/$(ARCH)/%.S
|
|
||||||
$(CC) $(CFLAGS) -D_LOCORE -c $< -o $@
|
|
||||||
|
|
||||||
boot/$(ARCH)/%.d: boot/$(ARCH)/%.S
|
|
||||||
@($(ECHO) -n $(dir $@);$(CC) $(CFLAGS) -D_LOCORE -M -MG $<) > $@
|
|
||||||
|
|
||||||
boot/$(ARCH)/%.o: boot/$(ARCH)/%.c
|
|
||||||
$(CC) $(CFLAGS) -c $< -o $@
|
|
||||||
|
|
||||||
boot/$(ARCH)/%.d: boot/$(ARCH)/%.c
|
|
||||||
@($(ECHO) -n $(dir $@);$(CC) $(CFLAGS) -M -MG $<) > $@
|
|
||||||
|
|
||||||
stage2clean:
|
|
||||||
rm -f $(STAGE2_OBJS) boot/$(ARCH)/stage2 boot/$(ARCH)/a.out
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
SubDir HAIKU_TOP src system boot arch sparc64 ;
|
|
||||||
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
# i386 stage2 makefile
|
|
||||||
STAGE2_DIR = boot/$(ARCH)
|
|
||||||
STAGE2_OBJ_DIR = $(STAGE2_DIR)/$(OBJ_DIR)
|
|
||||||
STAGE2_OBJS = \
|
|
||||||
|
|
||||||
DEPS += $(STAGE2_OBJS:.o=.d)
|
|
||||||
|
|
||||||
STAGE2 = $(STAGE2_OBJ_DIR)/stage2
|
|
||||||
|
|
||||||
$(STAGE2): $(STAGE2_OBJS) $(KLIBS)
|
|
||||||
$(LD) -dN --script=$(STAGE2_DIR)/stage2.ld -L $(LIBGCC_PATH) $(STAGE2_OBJS) $(KLIBS) $(LIBGCC) -o $@
|
|
||||||
|
|
||||||
stage2clean:
|
|
||||||
rm -f $(STAGE2_OBJS) $(STAGE2)
|
|
||||||
|
|
||||||
#
|
|
||||||
$(STAGE2_OBJ_DIR)/%.o: $(STAGE2_DIR)/%.c
|
|
||||||
@mkdir -p $(STAGE2_OBJ_DIR)
|
|
||||||
$(CC) -c $< $(GLOBAL_CFLAGS) -Iinclude -I$(STAGE2_DIR) -o $@
|
|
||||||
|
|
||||||
$(STAGE2_OBJ_DIR)/%.d: $(STAGE2_DIR)/%.c
|
|
||||||
@mkdir -p $(STAGE2_OBJ_DIR)
|
|
||||||
@echo "making deps for $<..."
|
|
||||||
@($(ECHO) -n $(dir $@);$(CC) $(GLOBAL_CFLAGS) -Iinclude -I$(STAGE2_DIR) -M -MG $<) > $@
|
|
||||||
|
|
||||||
$(STAGE2_OBJ_DIR)/%.d: $(STAGE2_DIR)/%.S
|
|
||||||
@mkdir -p $(STAGE2_OBJ_DIR)
|
|
||||||
@echo "making deps for $<..."
|
|
||||||
@($(ECHO) -n $(dir $@);$(CC) $(GLOBAL_CFLAGS) -Iinclude -I$(STAGE2_DIR) -M -MG $<) > $@
|
|
||||||
|
|
||||||
$(STAGE2_OBJ_DIR)/%.o: $(STAGE2_DIR)/%.S
|
|
||||||
@mkdir -p $(STAGE2_OBJ_DIR)
|
|
||||||
$(CC) -c $< $(GLOBAL_CFLAGS) -Iinclude -I$(STAGE2_DIR) -o $@
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
SubDir HAIKU_TOP src system boot arch x86 ;
|
|
||||||
|
|
||||||
KernelMergeObject boot_arch_stage2.o :
|
|
||||||
<$(SOURCE_GRIST)>stage2.c
|
|
||||||
<$(SOURCE_GRIST)>stage2_asm.S
|
|
||||||
<$(SOURCE_GRIST)>smp_boot.c
|
|
||||||
<$(SOURCE_GRIST)>smp_trampoline.S
|
|
||||||
:
|
|
||||||
-fno-pic
|
|
||||||
;
|
|
||||||
@@ -1,416 +0,0 @@
|
|||||||
; **
|
|
||||||
; ** Copyright 1998 Brian J. Swetland
|
|
||||||
; ** All rights reserved.
|
|
||||||
; **
|
|
||||||
; ** Redistribution and use in source and binary forms, with or without
|
|
||||||
; ** modification, are permitted provided that the following conditions
|
|
||||||
; ** are met:
|
|
||||||
; ** 1. Redistributions of source code must retain the above copyright
|
|
||||||
; ** notice, this list of conditions, and the following disclaimer.
|
|
||||||
; ** 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
; ** notice, this list of conditions, and the following disclaimer in the
|
|
||||||
; ** documentation and/or other materials provided with the distribution.
|
|
||||||
; ** 3. The name of the author may not be used to endorse or promote products
|
|
||||||
; ** derived from this software without specific prior written permission.
|
|
||||||
; **
|
|
||||||
; ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
||||||
; ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
||||||
; ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
||||||
; ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
; ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
; ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
; ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
; ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
; ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
; ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
; /*
|
|
||||||
; ** Copyright 2004, The OpenBeOS Team. All rights reserved.
|
|
||||||
; ** Distributed under the terms of the OpenBeOS License.
|
|
||||||
; **
|
|
||||||
; ** Copyright 2001-2004, Travis Geiselbrecht. All rights reserved.
|
|
||||||
; ** Distributed under the terms of the NewOS License.
|
|
||||||
; **
|
|
||||||
; ** Reviewed, documented and some minor modifications and bug-fixes
|
|
||||||
; ** applied by Michael Noisternig on 2001-09-02.
|
|
||||||
; */
|
|
||||||
|
|
||||||
%define VESA_X_TARGET 800
|
|
||||||
%define VESA_Y_TARGET 600
|
|
||||||
%define VESA_BIT_DEPTH_TARGET 32
|
|
||||||
|
|
||||||
SECTION
|
|
||||||
CODE16
|
|
||||||
ORG 0x7c00 ; start code at 0x7c00
|
|
||||||
jmp short start
|
|
||||||
sectors dw 800 ; this is interpreted as data (bytes 3 and 4)
|
|
||||||
; and patched from outside to the size of the bootcode (in sectors)
|
|
||||||
start:
|
|
||||||
cli ; no interrupts please
|
|
||||||
cld
|
|
||||||
xor ax,ax
|
|
||||||
mov ss,ax ; setup stack from 0 - 0x7c00
|
|
||||||
mov sp,0x7c00 ; stack pointer to top of stack
|
|
||||||
call enable_a20 ; enable a20 gate
|
|
||||||
lgdt [ss:gdt] ; load global descriptor table
|
|
||||||
mov eax,cr0 ; switch to protected mode
|
|
||||||
or al,0x1 ; by setting 'protected mode enable' bit
|
|
||||||
mov cr0,eax ; and writing back
|
|
||||||
jmp dword 0x8:unreal32 ; do the actual switch into protected mode
|
|
||||||
; The switch into protected mode and back is to get the processor into 'unreal' mode
|
|
||||||
; where it is in 16-bit mode but with segments that are larger than 64k.
|
|
||||||
; this way, the floppy code can load the image directly into memory >1Mb.
|
|
||||||
unreal32:
|
|
||||||
mov bx,0x10 ; load all of the data segments with large 32-bit segment
|
|
||||||
mov ds,bx
|
|
||||||
mov es,bx
|
|
||||||
mov ss,bx
|
|
||||||
and al,0xfe ; switch back to real mode
|
|
||||||
mov cr0,eax
|
|
||||||
jmp 0x7c0:unreal-0x7c00 ; actually go back to 16-bit
|
|
||||||
unreal:
|
|
||||||
xor ax,ax ; load NULL-descriptor (base 0) into ds, es, ss
|
|
||||||
mov es,ax ; the processor doesn't clear the internal high size bits on these descriptors
|
|
||||||
mov ds,ax ; so the descriptors can now reference 4Gb of memory, with size extensions
|
|
||||||
mov ss,ax
|
|
||||||
|
|
||||||
; read in the second half of this stage of the bootloader
|
|
||||||
xor dx,dx ; start at head 0
|
|
||||||
mov bx,0x2 ; start at sector 2 for the second half of this loader
|
|
||||||
mov cx,1 ; one sector
|
|
||||||
mov edi,0x7e00 ; right after this one
|
|
||||||
sti
|
|
||||||
call load_floppy
|
|
||||||
|
|
||||||
; read in the rest of the disk
|
|
||||||
mov edi,0x100000 ; destination buffer (at 1 MB) for sector reading in load_floppy
|
|
||||||
mov bx,0x3 ; start at sector 3 (and cylinder 0)
|
|
||||||
mov cx,[sectors] ; read that much sectors
|
|
||||||
xor dx,dx ; start at head 0
|
|
||||||
sti
|
|
||||||
mov si,loadmsg
|
|
||||||
call print
|
|
||||||
call load_floppy ; read remaining sectors at address edi
|
|
||||||
call disable_floppy_motor
|
|
||||||
mov si,okmsg
|
|
||||||
call print
|
|
||||||
|
|
||||||
; uncomment the next two lines to enable the VESA mode switch
|
|
||||||
; call enable_vesa
|
|
||||||
; mov [in_vesa],al
|
|
||||||
|
|
||||||
call find_mem_size_real
|
|
||||||
cli
|
|
||||||
|
|
||||||
mov ebx,[dword 0x100074] ; load dword at rel. address 0x74 from read-destination-buffer
|
|
||||||
add ebx,0x101000 ; for stage2 entry
|
|
||||||
mov al,0xcf
|
|
||||||
mov [ds:gdt+14],al ; set desc. 1 and 2
|
|
||||||
mov [ds:gdt+22],al ; to 32-bit segment
|
|
||||||
lgdt [ds:gdt] ; load global descriptor table
|
|
||||||
|
|
||||||
mov eax,1
|
|
||||||
mov cr0,eax ; enter protected mode
|
|
||||||
jmp dword 0x8:code32 ; flush prefetch queue
|
|
||||||
code32:
|
|
||||||
BITS 32
|
|
||||||
mov ax,0x10 ; load descriptor 2 in all segment selectors (except cs)
|
|
||||||
mov ds,ax
|
|
||||||
mov es,ax
|
|
||||||
mov fs,ax
|
|
||||||
mov gs,ax
|
|
||||||
mov ss,ax
|
|
||||||
mov ebp,0x10000
|
|
||||||
mov esp,ebp
|
|
||||||
|
|
||||||
mov eax,[vesa_info] ; set up arguments for _start()
|
|
||||||
push eax
|
|
||||||
|
|
||||||
xor eax,eax
|
|
||||||
mov al,[in_vesa]
|
|
||||||
push eax
|
|
||||||
|
|
||||||
xor eax,eax
|
|
||||||
mov al,[ext_mem_count]
|
|
||||||
push eax
|
|
||||||
|
|
||||||
cmp al, 0x0
|
|
||||||
je probe_mem
|
|
||||||
|
|
||||||
mov eax,[ext_mem_info]
|
|
||||||
push eax
|
|
||||||
|
|
||||||
xor eax,eax ; argument mem_size is loaded
|
|
||||||
push eax ; with zero
|
|
||||||
|
|
||||||
jmp call_stage2
|
|
||||||
|
|
||||||
probe_mem:
|
|
||||||
xor eax,eax ; argument ext_mem_info is
|
|
||||||
push eax ; loaded with zero
|
|
||||||
|
|
||||||
call find_mem_size_probe
|
|
||||||
push eax
|
|
||||||
; falls through
|
|
||||||
|
|
||||||
call_stage2:
|
|
||||||
call ebx ; jump to stage2 entry
|
|
||||||
inf:jmp short inf
|
|
||||||
|
|
||||||
BITS 16
|
|
||||||
; read sectors into memory
|
|
||||||
; IN: bx = sector # to start with: should be 2 as sector 1 (bootsector) was read by BIOS
|
|
||||||
; cx = # of sectors to read
|
|
||||||
; edi = buffer
|
|
||||||
load_floppy:
|
|
||||||
push bx
|
|
||||||
push cx
|
|
||||||
tryagain:
|
|
||||||
mov al,0x13 ; read a maximum of 18 sectors
|
|
||||||
sub al,bl ; substract first sector (to prevent wrap-around ???)
|
|
||||||
|
|
||||||
xor ah,ah ; TK: don't read more then required, VMWare doesn't like that
|
|
||||||
cmp ax,cx
|
|
||||||
jl shorten
|
|
||||||
mov ax,cx
|
|
||||||
shorten:
|
|
||||||
|
|
||||||
mov cx,bx ; -> sector/cylinder # to read from
|
|
||||||
mov bx,0x8000 ; buffer address
|
|
||||||
mov ah,0x2 ; command 'read sectors'
|
|
||||||
push ax
|
|
||||||
int 0x13 ; call BIOS
|
|
||||||
pop ax ; TK: should return number of transferred sectors in al
|
|
||||||
; but VMWare 3 clobbers it, so we (re-)load al manually
|
|
||||||
jnc okok ; no error -> proceed as usual
|
|
||||||
dec byte [retrycnt]
|
|
||||||
jz fail
|
|
||||||
xor ah,ah ; reset disk controller
|
|
||||||
int 0x13
|
|
||||||
jmp tryagain ; retry
|
|
||||||
okok:
|
|
||||||
mov byte [retrycnt], 3 ; reload retrycnt
|
|
||||||
mov si,dot
|
|
||||||
call print
|
|
||||||
mov esi,0x8000 ; source
|
|
||||||
xor ecx,ecx
|
|
||||||
mov cl,al ; copy # of read sectors (al)
|
|
||||||
shl cx,0x7 ; of size 128*4 bytes
|
|
||||||
rep a32 movsd ; to destination (edi) setup before func3 was called
|
|
||||||
pop cx
|
|
||||||
pop bx
|
|
||||||
xor dh,0x1 ; read: next head
|
|
||||||
jnz bar6
|
|
||||||
inc bh ; read: next cylinder
|
|
||||||
bar6:
|
|
||||||
mov bl,0x1 ; read: sector 1
|
|
||||||
xor ah,ah
|
|
||||||
sub cx,ax ; substract # of read sectors
|
|
||||||
jg load_floppy ; sectors left to read ?
|
|
||||||
ret
|
|
||||||
|
|
||||||
disable_floppy_motor:
|
|
||||||
xor al,al
|
|
||||||
mov dx,0x3f2 ; disable floppy motor
|
|
||||||
out dx,al
|
|
||||||
ret
|
|
||||||
|
|
||||||
; prints message in reg. si
|
|
||||||
print:
|
|
||||||
pusha
|
|
||||||
_n:
|
|
||||||
lodsb
|
|
||||||
or al,al
|
|
||||||
jz short _e
|
|
||||||
mov ah,0x0E
|
|
||||||
mov bx,7
|
|
||||||
int 0x10
|
|
||||||
jmp _n
|
|
||||||
_e:
|
|
||||||
popa
|
|
||||||
ret
|
|
||||||
|
|
||||||
; print errormsg, wait for keypress and reboot
|
|
||||||
fail:
|
|
||||||
mov si,errormsg
|
|
||||||
call print
|
|
||||||
xor ax, ax
|
|
||||||
int 0x16
|
|
||||||
int 0x19
|
|
||||||
|
|
||||||
; enables the a20 gate
|
|
||||||
; the usual keyboard-enable-a20-gate-stuff
|
|
||||||
enable_a20:
|
|
||||||
call _a20_loop
|
|
||||||
jnz _enable_a20_done
|
|
||||||
mov al,0xd1
|
|
||||||
out 0x64,al
|
|
||||||
call _a20_loop
|
|
||||||
jnz _enable_a20_done
|
|
||||||
mov al,0xdf
|
|
||||||
out 0x60,al
|
|
||||||
_a20_loop:
|
|
||||||
mov ecx,0x20000
|
|
||||||
_loop2:
|
|
||||||
jmp short _c
|
|
||||||
_c:
|
|
||||||
in al,0x64
|
|
||||||
test al,0x2
|
|
||||||
loopne _loop2
|
|
||||||
_enable_a20_done:
|
|
||||||
ret
|
|
||||||
|
|
||||||
loadmsg db "Loading",0
|
|
||||||
errormsg db 0x0a,0x0d,"Error reading disk.",0x0a,0x0d,0
|
|
||||||
okmsg db "OK",0x0a,0x0d,0
|
|
||||||
dot db ".",0
|
|
||||||
gdt:
|
|
||||||
; the first entry serves 2 purposes: as the GDT header and as the first descriptor
|
|
||||||
; note that the first descriptor (descriptor 0) is always a NULL-descriptor
|
|
||||||
db 0xFF ; full size of GDT used
|
|
||||||
db 0xff ; which means 8192 descriptors * 8 bytes = 2^16 bytes
|
|
||||||
dw gdt ; address of GDT (dword)
|
|
||||||
dd 0
|
|
||||||
; descriptor 1:
|
|
||||||
dd 0x0000ffff ; base - limit: 0 - 0xfffff * 4K
|
|
||||||
dd 0x008f9a00 ; type: 16 bit, exec-only conforming, <present>, privilege 0
|
|
||||||
; descriptor 2:
|
|
||||||
dd 0x0000ffff ; base - limit: 0 - 0xfffff * 4K
|
|
||||||
dd 0x008f9200 ; type: 16 bit, data read/write, <present>, privilege 0
|
|
||||||
|
|
||||||
retrycnt db 3
|
|
||||||
in_vesa db 0
|
|
||||||
vesa_info dd 0
|
|
||||||
ext_mem_info dd 0
|
|
||||||
ext_mem_count db 0
|
|
||||||
|
|
||||||
times 510-($-$$) db 0 ; filler for boot sector
|
|
||||||
dw 0xaa55 ; magic number for boot sector
|
|
||||||
|
|
||||||
; Starting here is the second sector of the boot code
|
|
||||||
|
|
||||||
BITS 32
|
|
||||||
; find memory size by testing
|
|
||||||
; OUT: eax = memory size
|
|
||||||
find_mem_size_probe:
|
|
||||||
mov eax,0x31323738 ; test value
|
|
||||||
mov esi,0x100ff0 ; start above conventional mem + HMA = 1 MB + 1024 Byte
|
|
||||||
_fms_loop:
|
|
||||||
mov edx,[esi] ; read value
|
|
||||||
mov [esi],eax ; write test value
|
|
||||||
mov ecx,[esi] ; read it again
|
|
||||||
mov [esi],edx ; write back old value
|
|
||||||
cmp ecx,eax
|
|
||||||
jnz _fms_loop_out ; read value != test value -> above mem limit
|
|
||||||
add esi,0x1000 ; test next page (4 K)
|
|
||||||
jmp short _fms_loop
|
|
||||||
_fms_loop_out:
|
|
||||||
mov eax,esi
|
|
||||||
sub eax,0x1000
|
|
||||||
add eax,byte +0x10
|
|
||||||
ret
|
|
||||||
|
|
||||||
BITS 16
|
|
||||||
find_mem_size_real:
|
|
||||||
; use int 0x15, EAX=0xe820 to test for memory
|
|
||||||
; assumes es is null
|
|
||||||
|
|
||||||
mov ebx,0
|
|
||||||
mov edi,0x7000 ; the extended memory structures will go at 0x7000
|
|
||||||
mov [ext_mem_info],edi
|
|
||||||
|
|
||||||
find_mem_next:
|
|
||||||
mov eax,0xe820
|
|
||||||
mov edx,'PAMS' ; 'SMAP' in the correct order
|
|
||||||
mov ecx,0x20
|
|
||||||
|
|
||||||
int 0x15
|
|
||||||
jc done_mem_real ; if carry is set, it wasn't supported
|
|
||||||
|
|
||||||
inc byte [ext_mem_count] ; increment the count of the number
|
|
||||||
|
|
||||||
cmp ebx,0x0 ; test if we're done
|
|
||||||
je done_mem_real
|
|
||||||
|
|
||||||
add edi,0x20 ; increment the buffer by 0x20
|
|
||||||
jmp find_mem_next
|
|
||||||
|
|
||||||
done_mem_real:
|
|
||||||
ret
|
|
||||||
|
|
||||||
; fool around with vesa mode
|
|
||||||
enable_vesa:
|
|
||||||
; put the VBEInfo struct at 0x30000
|
|
||||||
mov eax,0x30000
|
|
||||||
mov [vesa_info],eax
|
|
||||||
mov dx,0x3000
|
|
||||||
mov es,dx
|
|
||||||
mov ax,0x4f00
|
|
||||||
mov di,0
|
|
||||||
int 0x10
|
|
||||||
|
|
||||||
; check the return code
|
|
||||||
cmp al,0x4f
|
|
||||||
jne done_vesa_bad
|
|
||||||
cmp ah,0x00
|
|
||||||
jne done_vesa_bad
|
|
||||||
|
|
||||||
; check the signature on the data structure
|
|
||||||
mov eax,[es:00]
|
|
||||||
cmp eax,0x41534556 ; 'VESA'
|
|
||||||
je vesa_sig_ok
|
|
||||||
cmp eax,0x32454256 ; 'VBE2'
|
|
||||||
jne done_vesa_bad
|
|
||||||
|
|
||||||
vesa_sig_ok:
|
|
||||||
; scan through each mode and grab the info on them
|
|
||||||
les bx,[es:14] ; calculate the pointer to the mode list
|
|
||||||
mov di,0x200 ; push the buffer up a little to be past the VBEInfo struct
|
|
||||||
|
|
||||||
mode_loop:
|
|
||||||
mov cx,[es:bx] ; grab the next mode in the list
|
|
||||||
cmp cx,0xffff
|
|
||||||
je done_vesa_bad
|
|
||||||
and cx,0x01ff
|
|
||||||
mov ax,0x4f01
|
|
||||||
int 0x10
|
|
||||||
|
|
||||||
; if it's 1024x768x32, go for it
|
|
||||||
mov ax,[es:di]
|
|
||||||
test ax,0x1 ; test the supported bit
|
|
||||||
jz next_mode
|
|
||||||
test ax,0x08 ; test the linear frame mode bit
|
|
||||||
jz next_mode
|
|
||||||
mov ax,[es:di+18]
|
|
||||||
cmp ax,VESA_X_TARGET ; x
|
|
||||||
jne next_mode
|
|
||||||
mov ax,[es:di+20]
|
|
||||||
cmp ax,VESA_Y_TARGET ; y
|
|
||||||
jne next_mode
|
|
||||||
mov al,[es:di+25]
|
|
||||||
cmp al,VESA_BIT_DEPTH_TARGET ; bit_depth
|
|
||||||
jne next_mode
|
|
||||||
|
|
||||||
; looks good, switch into it
|
|
||||||
mov ax,0x4f02
|
|
||||||
mov bx,cx
|
|
||||||
or bx,0x4000 ; add the linear mode bit
|
|
||||||
int 0x10
|
|
||||||
jmp done_vesa_good
|
|
||||||
|
|
||||||
next_mode:
|
|
||||||
; get ready to try the next mode
|
|
||||||
inc bx
|
|
||||||
inc bx
|
|
||||||
jmp mode_loop
|
|
||||||
|
|
||||||
done_vesa_good:
|
|
||||||
mov ax,0x1
|
|
||||||
ret
|
|
||||||
|
|
||||||
done_vesa_bad:
|
|
||||||
xor ax,ax
|
|
||||||
ret
|
|
||||||
|
|
||||||
times 1024-($-$$) db 0 ; filler for second sector of the loader
|
|
||||||
|
|
||||||
Binary file not shown.
@@ -1,509 +0,0 @@
|
|||||||
/*
|
|
||||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
|
||||||
** Distributed under the terms of the NewOS License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <boot/stage2.h>
|
|
||||||
#include <arch/x86/stage2_priv.h>
|
|
||||||
#include <arch/x86/smp_apic.h>
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#define NO_SMP 0
|
|
||||||
|
|
||||||
#define TRACE_SMP 1
|
|
||||||
#if TRACE_SMP
|
|
||||||
# define TRACE(x) dprintf x
|
|
||||||
#else
|
|
||||||
# define TRACE(x) ;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
static uint32 mp_mem_phys = 0;
|
|
||||||
static uint32 mp_mem_virt = 0;
|
|
||||||
static struct mp_flt_struct *mp_flt_ptr = NULL;
|
|
||||||
static kernel_args *saved_ka = NULL;
|
|
||||||
static uint32 kernel_entry_point = 0;
|
|
||||||
|
|
||||||
static int smp_get_current_cpu(kernel_args *ka);
|
|
||||||
|
|
||||||
|
|
||||||
static uint32
|
|
||||||
map_page(kernel_args *ka, uint32 paddr, uint32 vaddr)
|
|
||||||
{
|
|
||||||
uint32 *pentry;
|
|
||||||
uint32 *pgdir = (uint32 *)(ka->arch_args.page_hole + (4*1024*1024-PAGE_SIZE));
|
|
||||||
|
|
||||||
// check to see if a page table exists for this range
|
|
||||||
if (pgdir[vaddr / PAGE_SIZE / 1024] == 0) {
|
|
||||||
unsigned int pgtable;
|
|
||||||
// we need to allocate a pgtable
|
|
||||||
pgtable = ka->physical_allocated_range[0].start + ka->physical_allocated_range[0].size;
|
|
||||||
ka->physical_allocated_range[0].size += PAGE_SIZE;
|
|
||||||
ka->arch_args.pgtables[ka->arch_args.num_pgtables++] = pgtable;
|
|
||||||
|
|
||||||
// put it in the pgdir
|
|
||||||
pgdir[vaddr / PAGE_SIZE / 1024] = (pgtable & ADDR_MASK) | DEFAULT_PAGE_FLAGS;
|
|
||||||
|
|
||||||
// zero it out in it's new mapping
|
|
||||||
memset((uint32 *)((uint32 *)ka->arch_args.page_hole + (vaddr / PAGE_SIZE / 1024) * PAGE_SIZE), 0, PAGE_SIZE);
|
|
||||||
}
|
|
||||||
// now, fill in the pentry
|
|
||||||
pentry = (uint32 *)((uint32 *)ka->arch_args.page_hole + vaddr / PAGE_SIZE);
|
|
||||||
|
|
||||||
*pentry = (paddr & ADDR_MASK) | DEFAULT_PAGE_FLAGS;
|
|
||||||
|
|
||||||
asm volatile("invlpg (%0)" : : "r" (vaddr));
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static uint32
|
|
||||||
apic_read(uint32 offset)
|
|
||||||
{
|
|
||||||
return *(uint32 *)((uint32)saved_ka->arch_args.apic + offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
apic_write(uint32 offset, uint32 data)
|
|
||||||
{
|
|
||||||
uint32 *addr = (uint32 *)((uint32)saved_ka->arch_args.apic + offset);
|
|
||||||
*addr = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
static void *
|
|
||||||
mp_virt_to_phys(void *ptr)
|
|
||||||
{
|
|
||||||
return ((void *)(((unsigned int)ptr - mp_mem_virt) + mp_mem_phys));
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void *
|
|
||||||
mp_phys_to_virt(void *ptr)
|
|
||||||
{
|
|
||||||
return ((void *)(((uint32)ptr - mp_mem_phys) + mp_mem_virt));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static uint32 *
|
|
||||||
smp_probe(uint32 base, uint32 limit)
|
|
||||||
{
|
|
||||||
uint32 *ptr;
|
|
||||||
|
|
||||||
TRACE(("smp_probe: entry base 0x%x, limit 0x%x\n", base, limit));
|
|
||||||
|
|
||||||
for (ptr = (uint32 *) base; (uint32)ptr < limit; ptr++) {
|
|
||||||
if (*ptr == MP_FLT_SIGNATURE) {
|
|
||||||
TRACE(("smp_probe: found floating pointer structure at 0x%x\n", ptr));
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
smp_do_config(kernel_args *ka)
|
|
||||||
{
|
|
||||||
char *ptr;
|
|
||||||
int i;
|
|
||||||
struct mp_config_table *mpc;
|
|
||||||
struct mp_ext_pe *pe;
|
|
||||||
struct mp_ext_ioapic *io;
|
|
||||||
struct mp_ext_bus *bus;
|
|
||||||
#if TRACE_SMP
|
|
||||||
const char *cpu_family[] = { "", "", "", "", "Intel 486",
|
|
||||||
"Intel Pentium", "Intel Pentium Pro", "Intel Pentium II" };
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* we are not running in standard configuration, so we have to look through
|
|
||||||
* all of the mp configuration table crap to figure out how many processors
|
|
||||||
* we have, where our apics are, etc.
|
|
||||||
*/
|
|
||||||
ka->num_cpus = 0;
|
|
||||||
|
|
||||||
mpc = mp_phys_to_virt(mp_flt_ptr->mpc);
|
|
||||||
|
|
||||||
/* print out our new found configuration. */
|
|
||||||
ptr = (char *) &(mpc->oem[0]);
|
|
||||||
|
|
||||||
TRACE(("smp: oem id: %c%c%c%c%c%c%c%c product id: "
|
|
||||||
"%c%c%c%c%c%c%c%c%c%c%c%c\n", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4],
|
|
||||||
ptr[5], ptr[6], ptr[7], ptr[8], ptr[9], ptr[10], ptr[11], ptr[12],
|
|
||||||
ptr[13], ptr[14], ptr[15], ptr[16], ptr[17], ptr[18], ptr[19],
|
|
||||||
ptr[20]));
|
|
||||||
TRACE(("smp: base table has %d entries, extended section %d bytes\n",
|
|
||||||
mpc->num_entries, mpc->ext_len));
|
|
||||||
|
|
||||||
ka->arch_args.apic_phys = (uint32)mpc->apic;
|
|
||||||
|
|
||||||
ptr = (char *)((uint32)mpc + sizeof(struct mp_config_table));
|
|
||||||
for (i = 0; i < mpc->num_entries; i++) {
|
|
||||||
switch (*ptr) {
|
|
||||||
case MP_EXT_PE:
|
|
||||||
pe = (struct mp_ext_pe *) ptr;
|
|
||||||
ka->arch_args.cpu_apic_id[ka->num_cpus] = pe->apic_id;
|
|
||||||
ka->arch_args.cpu_os_id[pe->apic_id] = ka->num_cpus;
|
|
||||||
ka->arch_args.cpu_apic_version[ka->num_cpus] = pe->apic_version;
|
|
||||||
|
|
||||||
TRACE(("smp: cpu#%d: %s, apic id %d, version %d%s\n",
|
|
||||||
ka->num_cpus, cpu_family[(pe->signature & 0xf00) >> 8],
|
|
||||||
pe->apic_id, pe->apic_version, (pe->cpu_flags & 0x2) ?
|
|
||||||
", BSP" : ""));
|
|
||||||
|
|
||||||
ptr += 20;
|
|
||||||
ka->num_cpus++;
|
|
||||||
break;
|
|
||||||
case MP_EXT_BUS:
|
|
||||||
bus = (struct mp_ext_bus *)ptr;
|
|
||||||
|
|
||||||
TRACE(("smp: bus%d: %c%c%c%c%c%c\n", bus->bus_id,
|
|
||||||
bus->name[0], bus->name[1], bus->name[2], bus->name[3],
|
|
||||||
bus->name[4], bus->name[5]));
|
|
||||||
|
|
||||||
ptr += 8;
|
|
||||||
break;
|
|
||||||
case MP_EXT_IO_APIC:
|
|
||||||
io = (struct mp_ext_ioapic *) ptr;
|
|
||||||
ka->arch_args.ioapic_phys = (uint32)io->addr;
|
|
||||||
|
|
||||||
TRACE(("smp: found io apic with apic id %d, version %d\n",
|
|
||||||
io->ioapic_id, io->ioapic_version));
|
|
||||||
|
|
||||||
ptr += 8;
|
|
||||||
break;
|
|
||||||
case MP_EXT_IO_INT:
|
|
||||||
ptr += 8;
|
|
||||||
break;
|
|
||||||
case MP_EXT_LOCAL_INT:
|
|
||||||
ptr += 8;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dprintf("smp: apic @ %p, i/o apic @ %p, total %d processors detected\n",
|
|
||||||
(void *)ka->arch_args.apic_phys, (void *)ka->arch_args.ioapic_phys, ka->num_cpus);
|
|
||||||
|
|
||||||
// this BIOS looks broken, because it didn't report any cpus (VMWare)
|
|
||||||
if (ka->num_cpus == 0)
|
|
||||||
ka->num_cpus = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
struct smp_scan_spots_struct {
|
|
||||||
uint32 start;
|
|
||||||
uint32 stop;
|
|
||||||
uint32 len;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct smp_scan_spots_struct smp_scan_spots[] = {
|
|
||||||
{ 0x9fc00, 0xa0000, 0xa0000 - 0x9fc00 },
|
|
||||||
{ 0xf0000, 0x100000, 0x100000 - 0xf0000 },
|
|
||||||
{ 0, 0, 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
smp_find_mp_config(kernel_args *ka)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
// XXX for now, assume the memory is identity mapped by the 1st stage
|
|
||||||
for (i = 0; smp_scan_spots[i].len > 0; i++) {
|
|
||||||
mp_flt_ptr = (struct mp_flt_struct *)smp_probe(smp_scan_spots[i].start,
|
|
||||||
smp_scan_spots[i].stop);
|
|
||||||
if (mp_flt_ptr != NULL)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#if NO_SMP
|
|
||||||
if (0) {
|
|
||||||
#else
|
|
||||||
if (mp_flt_ptr != NULL) {
|
|
||||||
#endif
|
|
||||||
mp_mem_phys = smp_scan_spots[i].start;
|
|
||||||
mp_mem_virt = smp_scan_spots[i].start;
|
|
||||||
|
|
||||||
TRACE(("smp_boot: intel mp version %s, %s", (mp_flt_ptr->mp_rev == 1) ? "1.1" :
|
|
||||||
"1.4", (mp_flt_ptr->mp_feature_2 & 0x80) ?
|
|
||||||
"imcr and pic compatibility mode.\n" : "virtual wire compatibility mode.\n"));
|
|
||||||
|
|
||||||
if (mp_flt_ptr->mpc == 0) {
|
|
||||||
// XXX need to implement
|
|
||||||
#if 1
|
|
||||||
ka->num_cpus = 1;
|
|
||||||
return 1;
|
|
||||||
#else
|
|
||||||
/* this system conforms to one of the default configurations */
|
|
||||||
// mp_num_def_config = mp_flt_ptr->mp_feature_1;
|
|
||||||
TRACE(("smp: standard configuration %d\n", mp_flt_ptr->mp_feature_1));
|
|
||||||
/* num_cpus = 2;
|
|
||||||
ka->cpu_apic_id[0] = 0;
|
|
||||||
ka->cpu_apic_id[1] = 1;
|
|
||||||
apic_phys = (unsigned int *) 0xfee00000;
|
|
||||||
ioapic_phys = (unsigned int *) 0xfec00000;
|
|
||||||
kprintf ("smp: WARNING: standard configuration code is untested");
|
|
||||||
*/
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
smp_do_config(ka);
|
|
||||||
}
|
|
||||||
return ka->num_cpus;
|
|
||||||
} else {
|
|
||||||
ka->num_cpus = 1;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Target function of the trampoline code.
|
|
||||||
* The trampoline code should have the pgdir and a gdt set up for us,
|
|
||||||
* along with us being on the final stack for this processor. We need
|
|
||||||
* to set up the local APIC and load the global idt and gdt. When we're
|
|
||||||
* done, we'll jump into the kernel with the cpu number as an argument.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int
|
|
||||||
smp_cpu_ready(void)
|
|
||||||
{
|
|
||||||
kernel_args *ka = saved_ka;
|
|
||||||
uint32 curr_cpu = smp_get_current_cpu(ka);
|
|
||||||
struct gdt_idt_descr idt_descr;
|
|
||||||
struct gdt_idt_descr gdt_descr;
|
|
||||||
|
|
||||||
TRACE(("smp_cpu_ready: entry cpu %d\n", curr_cpu));
|
|
||||||
|
|
||||||
// Important. Make sure supervisor threads can fault on read only pages...
|
|
||||||
asm("movl %%eax, %%cr0" : : "a" ((1 << 31) | (1 << 16) | (1 << 5) | 1));
|
|
||||||
asm("cld");
|
|
||||||
asm("fninit");
|
|
||||||
|
|
||||||
// Set up the final idt
|
|
||||||
idt_descr.a = IDT_LIMIT - 1;
|
|
||||||
idt_descr.b = (uint32 *)ka->arch_args.vir_idt;
|
|
||||||
|
|
||||||
asm("lidt %0;"
|
|
||||||
: : "m" (idt_descr));
|
|
||||||
|
|
||||||
// Set up the final gdt
|
|
||||||
gdt_descr.a = GDT_LIMIT - 1;
|
|
||||||
gdt_descr.b = (uint32 *)ka->arch_args.vir_gdt;
|
|
||||||
|
|
||||||
asm("lgdt %0;"
|
|
||||||
: : "m" (gdt_descr));
|
|
||||||
|
|
||||||
asm("pushl %0; " // push the cpu number
|
|
||||||
"pushl %1; " // kernel args
|
|
||||||
"pushl $0x0;" // dummy retval for call to main
|
|
||||||
"pushl %2; " // this is the start address
|
|
||||||
"ret; " // jump.
|
|
||||||
: : "r" (curr_cpu), "m" (ka), "g" (kernel_entry_point));
|
|
||||||
|
|
||||||
// no where to return to
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
smp_boot_all_cpus(kernel_args *ka)
|
|
||||||
{
|
|
||||||
uint32 trampoline_code;
|
|
||||||
uint32 trampoline_stack;
|
|
||||||
uint32 i;
|
|
||||||
|
|
||||||
// XXX assume low 1 meg is identity mapped by the 1st stage bootloader
|
|
||||||
// and nothing important is in 0x9e000 & 0x9f000
|
|
||||||
|
|
||||||
// allocate a stack and a code area for the smp trampoline
|
|
||||||
// (these have to be < 1M physical)
|
|
||||||
trampoline_code = 0x9f000; // 640kB - 4096 == 0x9f000
|
|
||||||
trampoline_stack = 0x9e000; // 640kB - 8192 == 0x9e000
|
|
||||||
map_page(ka, 0x9f000, 0x9f000);
|
|
||||||
map_page(ka, 0x9e000, 0x9e000);
|
|
||||||
|
|
||||||
// copy the trampoline code over
|
|
||||||
memcpy((char *)trampoline_code, &smp_trampoline,
|
|
||||||
(uint32)&smp_trampoline_end - (uint32)&smp_trampoline);
|
|
||||||
|
|
||||||
// boot the cpus
|
|
||||||
for (i = 1; i < ka->num_cpus; i++) {
|
|
||||||
uint32 *final_stack;
|
|
||||||
uint32 *final_stack_ptr;
|
|
||||||
uint32 *tramp_stack_ptr;
|
|
||||||
uint32 config;
|
|
||||||
uint32 num_startups;
|
|
||||||
uint32 j;
|
|
||||||
|
|
||||||
// create a final stack the trampoline code will put the ap processor on
|
|
||||||
ka->cpu_kstack[i].start = ka->virtual_allocated_range[0].start + ka->virtual_allocated_range[0].size;
|
|
||||||
ka->cpu_kstack[i].size = STACK_SIZE * PAGE_SIZE;
|
|
||||||
for (j = 0; j < ka->cpu_kstack[i].size / PAGE_SIZE; j++) {
|
|
||||||
// map the pages in
|
|
||||||
map_page(ka, ka->physical_allocated_range[0].start + ka->physical_allocated_range[0].size,
|
|
||||||
ka->virtual_allocated_range[0].start + ka->virtual_allocated_range[0].size);
|
|
||||||
ka->physical_allocated_range[0].size += PAGE_SIZE;
|
|
||||||
ka->virtual_allocated_range[0].size += PAGE_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set this stack up
|
|
||||||
final_stack = (uint32 *)ka->cpu_kstack[i].start;
|
|
||||||
memset(final_stack, 0, STACK_SIZE * PAGE_SIZE);
|
|
||||||
final_stack_ptr = (final_stack + (STACK_SIZE * PAGE_SIZE) / sizeof(uint32)) - 1;
|
|
||||||
*final_stack_ptr = (uint32)&smp_cpu_ready;
|
|
||||||
final_stack_ptr--;
|
|
||||||
|
|
||||||
// set the trampoline stack up
|
|
||||||
tramp_stack_ptr = (uint32 *)(trampoline_stack + PAGE_SIZE - 4);
|
|
||||||
// final location of the stack
|
|
||||||
*tramp_stack_ptr = ((uint32)final_stack) + STACK_SIZE * PAGE_SIZE - sizeof(uint32);
|
|
||||||
tramp_stack_ptr--;
|
|
||||||
// page dir
|
|
||||||
*tramp_stack_ptr = ka->arch_args.phys_pgdir;
|
|
||||||
tramp_stack_ptr--;
|
|
||||||
|
|
||||||
// put a gdt descriptor at the bottom of the stack
|
|
||||||
*((uint16 *)trampoline_stack) = 0x18 - 1; // LIMIT
|
|
||||||
*((uint32 *)(trampoline_stack + 2)) = trampoline_stack + 8;
|
|
||||||
|
|
||||||
// put the gdt at the bottom
|
|
||||||
memcpy(&((uint32 *)trampoline_stack)[2], (void *)ka->arch_args.vir_gdt, 6*4);
|
|
||||||
|
|
||||||
/* clear apic errors */
|
|
||||||
if (ka->arch_args.cpu_apic_version[i] & 0xf0) {
|
|
||||||
apic_write(APIC_ESR, 0);
|
|
||||||
apic_read(APIC_ESR);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* send (aka assert) INIT IPI */
|
|
||||||
config = (apic_read(APIC_ICR2) & 0x00ffffff) | (ka->arch_args.cpu_apic_id[i] << 24);
|
|
||||||
apic_write(APIC_ICR2, config); /* set target pe */
|
|
||||||
config = (apic_read(APIC_ICR1) & 0xfff00000) | 0x0000c500;
|
|
||||||
apic_write(APIC_ICR1, config);
|
|
||||||
|
|
||||||
// wait for pending to end
|
|
||||||
while ((apic_read(APIC_ICR1) & 0x00001000) == 0x00001000)
|
|
||||||
;
|
|
||||||
|
|
||||||
/* deassert INIT */
|
|
||||||
config = (apic_read(APIC_ICR2) & 0x00ffffff) | (ka->arch_args.cpu_apic_id[i] << 24);
|
|
||||||
apic_write(APIC_ICR2, config);
|
|
||||||
config = (apic_read(APIC_ICR1) & 0xfff00000) | 0x00008500;
|
|
||||||
apic_write(APIC_ICR1, config);
|
|
||||||
|
|
||||||
// wait for pending to end
|
|
||||||
while ((apic_read(APIC_ICR1) & 0x00001000) == 0x00001000)
|
|
||||||
;
|
|
||||||
|
|
||||||
/* wait 10ms */
|
|
||||||
spin(10000);
|
|
||||||
|
|
||||||
/* is this a local apic or an 82489dx ? */
|
|
||||||
num_startups = (ka->arch_args.cpu_apic_version[i] & 0xf0) ? 2 : 0;
|
|
||||||
for (j = 0; j < num_startups; j++) {
|
|
||||||
/* it's a local apic, so send STARTUP IPIs */
|
|
||||||
apic_write(APIC_ESR, 0);
|
|
||||||
|
|
||||||
/* set target pe */
|
|
||||||
config = (apic_read(APIC_ICR2) & 0xf0ffffff) | (ka->arch_args.cpu_apic_id[i] << 24);
|
|
||||||
apic_write(APIC_ICR2, config);
|
|
||||||
|
|
||||||
/* send the IPI */
|
|
||||||
config = (apic_read(APIC_ICR1) & 0xfff0f800) | APIC_DM_STARTUP |
|
|
||||||
(0x9f000 >> 12);
|
|
||||||
apic_write(APIC_ICR1, config);
|
|
||||||
|
|
||||||
/* wait */
|
|
||||||
spin(200);
|
|
||||||
|
|
||||||
while ((apic_read(APIC_ICR1)& 0x00001000) == 0x00001000)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
calculate_apic_timer_conversion_factor(kernel_args *ka)
|
|
||||||
{
|
|
||||||
int64 t1, t2;
|
|
||||||
uint32 config;
|
|
||||||
uint32 count;
|
|
||||||
|
|
||||||
// setup the timer
|
|
||||||
config = apic_read(APIC_LVTT);
|
|
||||||
config = (config & ~APIC_LVTT_MASK) + APIC_LVTT_M; // timer masked, vector 0
|
|
||||||
apic_write(APIC_LVTT, config);
|
|
||||||
|
|
||||||
config = (apic_read(APIC_TDCR) & ~0x0000000f) + 0xb; // divide clock by one
|
|
||||||
apic_write(APIC_TDCR, config);
|
|
||||||
|
|
||||||
t1 = system_time();
|
|
||||||
apic_write(APIC_ICRT, 0xffffffff); // start the counter
|
|
||||||
|
|
||||||
execute_n_instructions(128*20000);
|
|
||||||
|
|
||||||
count = apic_read(APIC_CCRT);
|
|
||||||
t2 = system_time();
|
|
||||||
|
|
||||||
count = 0xffffffff - count;
|
|
||||||
|
|
||||||
ka->arch_args.apic_time_cv_factor = (uint32)((1000000.0/(t2 - t1)) * count);
|
|
||||||
|
|
||||||
TRACE(("APIC ticks/sec = %d\n", ka->arch_args.apic_time_cv_factor));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
smp_boot(kernel_args *ka, uint32 kernel_entry)
|
|
||||||
{
|
|
||||||
// dprintf("smp_boot: entry\n");
|
|
||||||
|
|
||||||
kernel_entry_point = kernel_entry;
|
|
||||||
saved_ka = ka;
|
|
||||||
|
|
||||||
if (smp_find_mp_config(ka) > 1) {
|
|
||||||
TRACE(("smp_boot: had found > 1 cpus\n"));
|
|
||||||
TRACE(("post config:\n"));
|
|
||||||
TRACE(("num_cpus = %ld\n", ka->num_cpus));
|
|
||||||
TRACE(("apic_phys = %p\n", ka->arch_args.apic_phys));
|
|
||||||
TRACE(("ioapic_phys = %p\n", ka->arch_args.ioapic_phys));
|
|
||||||
|
|
||||||
// map in the apic & ioapic
|
|
||||||
map_page(ka, ka->arch_args.apic_phys, ka->virtual_allocated_range[0].start + ka->virtual_allocated_range[0].size);
|
|
||||||
ka->arch_args.apic = (uint32 *)(ka->virtual_allocated_range[0].start + ka->virtual_allocated_range[0].size);
|
|
||||||
ka->virtual_allocated_range[0].size += PAGE_SIZE;
|
|
||||||
|
|
||||||
map_page(ka, ka->arch_args.ioapic_phys, ka->virtual_allocated_range[0].start + ka->virtual_allocated_range[0].size);
|
|
||||||
ka->arch_args.ioapic = (uint32 *)(ka->virtual_allocated_range[0].start + ka->virtual_allocated_range[0].size);
|
|
||||||
ka->virtual_allocated_range[0].size += PAGE_SIZE;
|
|
||||||
|
|
||||||
TRACE(("apic = %p\n", ka->arch_args.apic));
|
|
||||||
TRACE(("ioapic = %p\n", ka->arch_args.ioapic));
|
|
||||||
|
|
||||||
// calculate how fast the apic timer is
|
|
||||||
calculate_apic_timer_conversion_factor(ka);
|
|
||||||
|
|
||||||
TRACE(("trampolining other cpus\n"));
|
|
||||||
smp_boot_all_cpus(ka);
|
|
||||||
TRACE(("done trampolining\n"));
|
|
||||||
}
|
|
||||||
|
|
||||||
TRACE(("smp_boot: exit\n"));
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
smp_get_current_cpu(kernel_args *ka)
|
|
||||||
{
|
|
||||||
if (ka->arch_args.apic == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return ka->arch_args.cpu_os_id[(apic_read(APIC_ID) & 0xffffffff) >> 24];
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
/*
|
|
||||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
|
||||||
** Distributed under the terms of the NewOS License.
|
|
||||||
*/
|
|
||||||
// expects a stack page like this:
|
|
||||||
// (stack has to be at (0x9e000)
|
|
||||||
// 0x9effc : final esp
|
|
||||||
// 0x9eff8 : page dir
|
|
||||||
//
|
|
||||||
// 0x9e000 - 0x9e006 : gdt descriptor
|
|
||||||
// 0x9e008 - 0x9e020 : gdt
|
|
||||||
//
|
|
||||||
// smp_trampoline must be located at 0x9f000
|
|
||||||
.globl smp_trampoline
|
|
||||||
.globl smp_trampoline_end
|
|
||||||
.globl foo
|
|
||||||
|
|
||||||
.code16
|
|
||||||
smp_trampoline:
|
|
||||||
cli
|
|
||||||
|
|
||||||
mov $0x9e00,%ax
|
|
||||||
mov %ax,%ds
|
|
||||||
|
|
||||||
// lgdt 0x9e000 # load the gdt
|
|
||||||
.byte 0x66, 0x0f, 0x01, 0x15, 0x00, 0xe0, 0x09, 0x00
|
|
||||||
|
|
||||||
movl %cr0,%eax
|
|
||||||
orl $0x01,%eax
|
|
||||||
movl %eax,%cr0 # switch into protected mode
|
|
||||||
|
|
||||||
.code32
|
|
||||||
_trampoline_32:
|
|
||||||
.byte 0x66
|
|
||||||
ljmp $0x08,$(trampoline_32 - smp_trampoline + 0x9f000)
|
|
||||||
trampoline_32:
|
|
||||||
mov $0x10, %ax
|
|
||||||
mov %ax, %ds
|
|
||||||
mov %ax, %es
|
|
||||||
mov %ax, %fs
|
|
||||||
mov %ax, %gs
|
|
||||||
mov %ax, %ss
|
|
||||||
|
|
||||||
movl $0x9eff8,%esp # set up the stack pointer
|
|
||||||
|
|
||||||
popl %eax # get the page dir
|
|
||||||
movl %eax,%cr3 # set the page dir
|
|
||||||
|
|
||||||
popl %eax # get the final stack location
|
|
||||||
movl %eax,%esp
|
|
||||||
|
|
||||||
// load an address for an indirect jump
|
|
||||||
movl $trampoline_after_paging,%ecx
|
|
||||||
|
|
||||||
movl %cr0,%eax
|
|
||||||
orl $0x80000000,%eax
|
|
||||||
movl %eax,%cr0 # enable paging
|
|
||||||
|
|
||||||
// jump to the address previously loaded. NOTE:
|
|
||||||
// this address is the address at which the code is originally linked,
|
|
||||||
// which is > 1MB. We will be out of the low memory at this point.
|
|
||||||
jmp *%ecx
|
|
||||||
trampoline_after_paging:
|
|
||||||
// just return, the bsp would have set the return address to the
|
|
||||||
// target function at the top of the passed stack
|
|
||||||
ret
|
|
||||||
|
|
||||||
smp_trampoline_end:
|
|
||||||
|
|
||||||
@@ -1,869 +0,0 @@
|
|||||||
/*
|
|
||||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
|
||||||
** Distributed under the terms of the NewOS License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <boot/bootdir.h>
|
|
||||||
#include <boot/stage2.h>
|
|
||||||
#include "arch/x86/stage2_priv.h"
|
|
||||||
#include "arch/x86/descriptors.h"
|
|
||||||
#include "vesa.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <elf32.h>
|
|
||||||
|
|
||||||
const unsigned kBSSSize = 0x9000;
|
|
||||||
|
|
||||||
#define STAGE2_TRACE 0
|
|
||||||
#if STAGE2_TRACE
|
|
||||||
# define PRINT(x) dprintf x
|
|
||||||
# define MESSAGE(x) dprintf x
|
|
||||||
#else
|
|
||||||
# define PRINT(x)
|
|
||||||
# define MESSAGE(x)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// memory structure returned by int 0x15, ax 0xe820
|
|
||||||
typedef struct ext_memory {
|
|
||||||
uint64 base_addr;
|
|
||||||
uint64 length;
|
|
||||||
uint64 type;
|
|
||||||
uint64 filler;
|
|
||||||
} ext_memory;
|
|
||||||
|
|
||||||
// we're running out of the first 'file' contained in the bootdir, which is
|
|
||||||
// a set of binaries and data packed back to back, described by an array
|
|
||||||
// of boot_entry structures at the beginning. The load address is fixed.
|
|
||||||
#define BOOTDIR_ADDR 0x100000
|
|
||||||
static const boot_entry *bootdir = (boot_entry *)BOOTDIR_ADDR;
|
|
||||||
|
|
||||||
// stick the kernel arguments in a pseudo-random page that will be mapped
|
|
||||||
// at least during the call into the kernel. The kernel should copy the
|
|
||||||
// data out and unmap the page.
|
|
||||||
static kernel_args *ka = (kernel_args *)0x20000;
|
|
||||||
|
|
||||||
// needed for message
|
|
||||||
static uint16 *kScreenBase = (uint16 *)0xb8000;
|
|
||||||
static uint32 screenOffset = 0;
|
|
||||||
|
|
||||||
unsigned int cv_factor = 0;
|
|
||||||
|
|
||||||
// size of bootdir in pages
|
|
||||||
static uint32 bootdir_pages = 0;
|
|
||||||
|
|
||||||
// working pagedir and pagetable
|
|
||||||
static uint32 *pgdir = 0;
|
|
||||||
static uint32 *pgtable = 0;
|
|
||||||
|
|
||||||
// function decls for this module
|
|
||||||
static void sort_addr_range(addr_range *range, int count);
|
|
||||||
static void calculate_cpu_conversion_factor(void);
|
|
||||||
static void load_elf_image(void *data, uint32 *next_paddr, struct preloaded_image *image,
|
|
||||||
uint32 *start_addr);
|
|
||||||
static int mmu_init(kernel_args *ka, uint32 *next_paddr);
|
|
||||||
static void mmu_map_page(uint32 vaddr, uint32 paddr);
|
|
||||||
static int check_cpu(void);
|
|
||||||
|
|
||||||
|
|
||||||
extern void _start(uint32 memSize, ext_memory *extMemoryBlock, uint32 extMemoryCount,
|
|
||||||
int in_vesa, uint32 vesa_ptr);
|
|
||||||
|
|
||||||
/* called by the stage1 bootloader.
|
|
||||||
* State:
|
|
||||||
* 32-bit
|
|
||||||
* mmu disabled
|
|
||||||
* stack somewhere below 1 MB
|
|
||||||
* supervisor mode
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
_start(uint32 memSize, ext_memory *extMemoryBlock, uint32 extMemoryCount,
|
|
||||||
int in_vesa, uint32 vesa_ptr)
|
|
||||||
{
|
|
||||||
uint32 *idt;
|
|
||||||
segment_descriptor *gdt;
|
|
||||||
uint32 next_vaddr;
|
|
||||||
uint32 next_paddr;
|
|
||||||
uint32 i;
|
|
||||||
uint32 kernel_entry;
|
|
||||||
|
|
||||||
asm("cld"); // Ain't nothing but a GCC thang.
|
|
||||||
asm("fninit"); // initialize floating point unit
|
|
||||||
|
|
||||||
clearscreen();
|
|
||||||
|
|
||||||
dprintf("stage2 bootloader entry.\n");
|
|
||||||
dprintf("args: memsize 0x%x, emem_block %p, emem_count %d, in_vesa %d, vesa = %p\n",
|
|
||||||
memSize, extMemoryBlock, extMemoryCount, in_vesa, vesa_ptr);
|
|
||||||
|
|
||||||
// verify we can run on this cpu
|
|
||||||
if (check_cpu() < 0) {
|
|
||||||
dprintf("\nSorry, this computer appears to be lacking some of the features\n");
|
|
||||||
dprintf("needed by OpenBeOS. It is currently only able to run on\n");
|
|
||||||
dprintf("Pentium class cpus and above, with a few exceptions to\n");
|
|
||||||
dprintf("that rule.\n");
|
|
||||||
dprintf("\nPlease reset your computer to continue.");
|
|
||||||
|
|
||||||
for (;;);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (extMemoryCount > 0) {
|
|
||||||
uint32 i;
|
|
||||||
|
|
||||||
dprintf("extended memory info (from 0xe820):\n");
|
|
||||||
for (i = 0; i < extMemoryCount; i++) {
|
|
||||||
dprintf(" base 0x%Lx, len 0x%Lx, type %Ld\n",
|
|
||||||
extMemoryBlock[i].base_addr, extMemoryBlock[i].length, extMemoryBlock[i].type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// calculate the conversion factor that translates rdtsc time to real microseconds
|
|
||||||
calculate_cpu_conversion_factor();
|
|
||||||
|
|
||||||
// calculate how big the bootdir is so we know where we can start grabbing pages
|
|
||||||
{
|
|
||||||
int entry;
|
|
||||||
for (entry = 0; entry < BOOTDIR_MAX_ENTRIES; entry++) {
|
|
||||||
if (bootdir[entry].be_type == BE_TYPE_NONE)
|
|
||||||
break;
|
|
||||||
|
|
||||||
bootdir_pages += bootdir[entry].be_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
MESSAGE(("bootdir is ", bootdir_pages, " pages long\n"));
|
|
||||||
}
|
|
||||||
|
|
||||||
ka->bootdir_addr.start = (uint32)bootdir;
|
|
||||||
ka->bootdir_addr.size = bootdir_pages * PAGE_SIZE;
|
|
||||||
|
|
||||||
next_paddr = BOOTDIR_ADDR + bootdir_pages * PAGE_SIZE;
|
|
||||||
|
|
||||||
if (in_vesa) {
|
|
||||||
struct VBEModeInfoBlock *mode_info = (struct VBEModeInfoBlock *)(vesa_ptr + 0x200);
|
|
||||||
|
|
||||||
ka->frame_buffer.enabled = 1;
|
|
||||||
ka->frame_buffer.width = mode_info->x_resolution;
|
|
||||||
ka->frame_buffer.height = mode_info->y_resolution;
|
|
||||||
ka->frame_buffer.depth = mode_info->bits_per_pixel;
|
|
||||||
ka->frame_buffer.physical_buffer.start = mode_info->phys_base_ptr;
|
|
||||||
ka->frame_buffer.physical_buffer.size = ka->frame_buffer.width
|
|
||||||
* ka->frame_buffer.height * (ka->frame_buffer.depth / 8);
|
|
||||||
} else
|
|
||||||
ka->frame_buffer.enabled = 0;
|
|
||||||
|
|
||||||
mmu_init(ka, &next_paddr);
|
|
||||||
|
|
||||||
// load the kernel (3rd entry in the bootdir)
|
|
||||||
load_elf_image((void *)(bootdir[2].be_offset * PAGE_SIZE + BOOTDIR_ADDR), &next_paddr,
|
|
||||||
&ka->kernel_image, &kernel_entry);
|
|
||||||
|
|
||||||
if (ka->kernel_image.data_region.size > 0) {
|
|
||||||
next_vaddr = ROUNDUP(ka->kernel_image.data_region.start
|
|
||||||
+ ka->kernel_image.data_region.size, PAGE_SIZE);
|
|
||||||
} else {
|
|
||||||
next_vaddr = ROUNDUP(ka->kernel_image.text_region.start
|
|
||||||
+ ka->kernel_image.text_region.size, PAGE_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// map in a kernel stack
|
|
||||||
ka->cpu_kstack[0].start = next_vaddr;
|
|
||||||
for (i = 0; i < STACK_SIZE; i++) {
|
|
||||||
mmu_map_page(next_vaddr, next_paddr);
|
|
||||||
next_vaddr += PAGE_SIZE;
|
|
||||||
next_paddr += PAGE_SIZE;
|
|
||||||
}
|
|
||||||
ka->cpu_kstack[0].size = next_vaddr - ka->cpu_kstack[0].start;
|
|
||||||
|
|
||||||
PRINT(("new stack at 0x%x to 0x%x\n", ka->cpu_kstack[0].start, ka->cpu_kstack[0].start + ka->cpu_kstack[0].size));
|
|
||||||
|
|
||||||
// set up a new idt
|
|
||||||
{
|
|
||||||
struct gdt_idt_descr idt_descr;
|
|
||||||
|
|
||||||
// find a new idt
|
|
||||||
idt = (uint32 *)next_paddr;
|
|
||||||
ka->arch_args.phys_idt = (uint32)idt;
|
|
||||||
next_paddr += PAGE_SIZE;
|
|
||||||
|
|
||||||
MESSAGE(("idt at ", (uint32)idt, "\n"));
|
|
||||||
|
|
||||||
// clear it out
|
|
||||||
for (i = 0; i < IDT_LIMIT / 4; i++) {
|
|
||||||
idt[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// map the idt into virtual space
|
|
||||||
mmu_map_page(next_vaddr, (uint32)idt);
|
|
||||||
ka->arch_args.vir_idt = (uint32)next_vaddr;
|
|
||||||
next_vaddr += PAGE_SIZE;
|
|
||||||
|
|
||||||
// load the idt
|
|
||||||
idt_descr.a = IDT_LIMIT - 1;
|
|
||||||
idt_descr.b = (uint32 *)ka->arch_args.vir_idt;
|
|
||||||
|
|
||||||
asm("lidt %0;"
|
|
||||||
: : "m" (idt_descr));
|
|
||||||
|
|
||||||
MESSAGE(("idt at virtual address ", next_vpage, "\n"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// set up a new gdt
|
|
||||||
{
|
|
||||||
struct gdt_idt_descr gdt_descr;
|
|
||||||
|
|
||||||
// find a new gdt
|
|
||||||
gdt = (segment_descriptor *)next_paddr;
|
|
||||||
ka->arch_args.phys_gdt = (uint32)gdt;
|
|
||||||
next_paddr += PAGE_SIZE;
|
|
||||||
|
|
||||||
MESSAGE(("gdt at ", (uint32)gdt, "\n"));
|
|
||||||
|
|
||||||
// put standard segment descriptors in it
|
|
||||||
clear_segment_descriptor(&gdt[0]);
|
|
||||||
set_segment_descriptor(&gdt[1], 0, 0xfffff, DT_CODE_READABLE, DPL_KERNEL);
|
|
||||||
// seg 0x08 - kernel 4GB code
|
|
||||||
set_segment_descriptor(&gdt[2], 0, 0xfffff, DT_DATA_WRITEABLE, DPL_KERNEL);
|
|
||||||
// seg 0x10 - kernel 4GB data
|
|
||||||
|
|
||||||
set_segment_descriptor(&gdt[3], 0, 0xfffff, DT_CODE_READABLE, DPL_USER);
|
|
||||||
// seg 0x1b - ring 3 user 4GB code
|
|
||||||
set_segment_descriptor(&gdt[4], 0, 0xfffff, DT_DATA_WRITEABLE, DPL_USER);
|
|
||||||
// seg 0x23 - ring 3 user 4GB data
|
|
||||||
|
|
||||||
// gdt[5] and above will be filled later by the kernel
|
|
||||||
// to contain the TSS descriptors, and for TLS (one for every CPU)
|
|
||||||
|
|
||||||
// map the gdt into virtual space
|
|
||||||
mmu_map_page(next_vaddr, (uint32)gdt);
|
|
||||||
ka->arch_args.vir_gdt = (uint32)next_vaddr;
|
|
||||||
next_vaddr += PAGE_SIZE;
|
|
||||||
|
|
||||||
// load the GDT
|
|
||||||
gdt_descr.a = GDT_LIMIT - 1;
|
|
||||||
gdt_descr.b = (uint32 *)ka->arch_args.vir_gdt;
|
|
||||||
|
|
||||||
asm("lgdt %0;"
|
|
||||||
: : "m" (gdt_descr));
|
|
||||||
|
|
||||||
MESSAGE(("gdt at virtual address ", next_vpage, "\n"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map the pg_dir into kernel space at 0xffc00000-0xffffffff
|
|
||||||
// this enables a mmu trick where the 4 MB region that this pgdir entry
|
|
||||||
// represents now maps the 4MB of potential pagetables that the pgdir
|
|
||||||
// points to. Thrown away later in VM bringup, but useful for now.
|
|
||||||
pgdir[1023] = (uint32)pgdir | DEFAULT_PAGE_FLAGS;
|
|
||||||
|
|
||||||
// also map it on the next vpage
|
|
||||||
mmu_map_page(next_vaddr, (uint32)pgdir);
|
|
||||||
ka->arch_args.vir_pgdir = next_vaddr;
|
|
||||||
next_vaddr += PAGE_SIZE;
|
|
||||||
|
|
||||||
// mark memory that we know is used
|
|
||||||
ka->physical_allocated_range[0].start = BOOTDIR_ADDR;
|
|
||||||
ka->physical_allocated_range[0].size = next_paddr - BOOTDIR_ADDR;
|
|
||||||
ka->num_physical_allocated_ranges = 1;
|
|
||||||
|
|
||||||
// figure out the memory map
|
|
||||||
if (extMemoryCount > 0) {
|
|
||||||
uint32 i;
|
|
||||||
|
|
||||||
ka->num_physical_memory_ranges = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < extMemoryCount; i++) {
|
|
||||||
if (extMemoryBlock[i].type == 1) {
|
|
||||||
// round everything up to page boundaries, exclusive of pages it partially occupies
|
|
||||||
extMemoryBlock[i].length -= (extMemoryBlock[i].base_addr % PAGE_SIZE)
|
|
||||||
? (PAGE_SIZE - (extMemoryBlock[i].base_addr % PAGE_SIZE)) : 0;
|
|
||||||
extMemoryBlock[i].base_addr = ROUNDUP(extMemoryBlock[i].base_addr, PAGE_SIZE);
|
|
||||||
extMemoryBlock[i].length = ROUNDOWN(extMemoryBlock[i].length, PAGE_SIZE);
|
|
||||||
|
|
||||||
// this is mem we can use
|
|
||||||
if (ka->num_physical_memory_ranges == 0) {
|
|
||||||
ka->physical_memory_range[0].start = (addr_t)extMemoryBlock[i].base_addr;
|
|
||||||
ka->physical_memory_range[0].size = (addr_t)extMemoryBlock[i].length;
|
|
||||||
ka->num_physical_memory_ranges++;
|
|
||||||
} else {
|
|
||||||
// we might have to extend the previous hole
|
|
||||||
addr_t previous_end = ka->physical_memory_range[ka->num_physical_memory_ranges - 1].start
|
|
||||||
+ ka->physical_memory_range[ka->num_physical_memory_ranges - 1].size;
|
|
||||||
|
|
||||||
if (previous_end <= extMemoryBlock[i].base_addr
|
|
||||||
&& ((extMemoryBlock[i].base_addr - previous_end) < 0x100000)) {
|
|
||||||
// extend the previous buffer
|
|
||||||
ka->physical_memory_range[ka->num_physical_memory_ranges - 1].size +=
|
|
||||||
(extMemoryBlock[i].base_addr - previous_end) +
|
|
||||||
extMemoryBlock[i].length;
|
|
||||||
|
|
||||||
// mark the gap between the two allocated ranges in use
|
|
||||||
ka->physical_allocated_range[ka->num_physical_allocated_ranges].start = previous_end;
|
|
||||||
ka->physical_allocated_range[ka->num_physical_allocated_ranges].size = extMemoryBlock[i].base_addr - previous_end;
|
|
||||||
ka->num_physical_allocated_ranges++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// we dont have an extended map, assume memory is contiguously mapped at 0x0
|
|
||||||
ka->physical_memory_range[0].start = 0;
|
|
||||||
ka->physical_memory_range[0].size = memSize;
|
|
||||||
ka->num_physical_memory_ranges = 1;
|
|
||||||
|
|
||||||
// mark the bios area allocated
|
|
||||||
ka->physical_allocated_range[ka->num_physical_allocated_ranges].start = 0x9f000; // 640k - 1 page
|
|
||||||
ka->physical_allocated_range[ka->num_physical_allocated_ranges].size = 0x61000;
|
|
||||||
ka->num_physical_allocated_ranges++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// save the memory we've virtually allocated (for the kernel and other stuff)
|
|
||||||
ka->virtual_allocated_range[0].start = KERNEL_BASE;
|
|
||||||
ka->virtual_allocated_range[0].size = next_vaddr - KERNEL_BASE;
|
|
||||||
ka->num_virtual_allocated_ranges = 1;
|
|
||||||
|
|
||||||
// sort the address ranges
|
|
||||||
sort_addr_range(ka->physical_memory_range, ka->num_physical_memory_ranges);
|
|
||||||
sort_addr_range(ka->physical_allocated_range, ka->num_physical_allocated_ranges);
|
|
||||||
sort_addr_range(ka->virtual_allocated_range, ka->num_virtual_allocated_ranges);
|
|
||||||
|
|
||||||
#if 1
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
dprintf("phys memory ranges:\n");
|
|
||||||
for (i = 0; i < ka->num_physical_memory_ranges; i++) {
|
|
||||||
dprintf(" base 0x%08lx, length 0x%08lx\n", ka->physical_memory_range[i].start, ka->physical_memory_range[i].size);
|
|
||||||
}
|
|
||||||
|
|
||||||
dprintf("allocated phys memory ranges:\n");
|
|
||||||
for (i = 0; i < ka->num_physical_allocated_ranges; i++) {
|
|
||||||
dprintf(" base 0x%08lx, length 0x%08lx\n", ka->physical_allocated_range[i].start, ka->physical_allocated_range[i].size);
|
|
||||||
}
|
|
||||||
|
|
||||||
dprintf("allocated virt memory ranges:\n");
|
|
||||||
for (i = 0; i < ka->num_virtual_allocated_ranges; i++) {
|
|
||||||
dprintf(" base 0x%08lx, length 0x%08lx\n", ka->virtual_allocated_range[i].start, ka->virtual_allocated_range[i].size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// save the kernel args
|
|
||||||
ka->kernel_args_size = sizeof(kernel_args);
|
|
||||||
ka->version = CURRENT_KERNEL_ARGS_VERSION;
|
|
||||||
ka->arch_args.system_time_cv_factor = cv_factor;
|
|
||||||
ka->arch_args.page_hole = 0xffc00000;
|
|
||||||
ka->num_kernel_args_ranges = 0;
|
|
||||||
ka->num_cpus = 1;
|
|
||||||
ka->driver_settings = NULL;
|
|
||||||
#if 0
|
|
||||||
dprintf("kernel args at 0x%x\n", ka);
|
|
||||||
dprintf("pgdir = 0x%x\n", ka->pgdir);
|
|
||||||
dprintf("pgtables[0] = 0x%x\n", ka->pgtables[0]);
|
|
||||||
dprintf("phys_idt = 0x%x\n", ka->phys_idt);
|
|
||||||
dprintf("vir_idt = 0x%x\n", ka->vir_idt);
|
|
||||||
dprintf("phys_gdt = 0x%x\n", ka->phys_gdt);
|
|
||||||
dprintf("vir_gdt = 0x%x\n", ka->vir_gdt);
|
|
||||||
dprintf("mem_size = 0x%x\n", ka->mem_size);
|
|
||||||
dprintf("str = 0x%x\n", ka->str);
|
|
||||||
dprintf("bootdir = 0x%x\n", ka->bootdir);
|
|
||||||
dprintf("bootdir_size = 0x%x\n", ka->bootdir_size);
|
|
||||||
dprintf("phys_alloc_range_low = 0x%x\n", ka->phys_alloc_range_low);
|
|
||||||
dprintf("phys_alloc_range_high = 0x%x\n", ka->phys_alloc_range_high);
|
|
||||||
dprintf("virt_alloc_range_low = 0x%x\n", ka->virt_alloc_range_low);
|
|
||||||
dprintf("virt_alloc_range_high = 0x%x\n", ka->virt_alloc_range_high);
|
|
||||||
dprintf("page_hole = 0x%x\n", ka->page_hole);
|
|
||||||
#endif
|
|
||||||
PRINT(("finding and booting other cpus...\n"));
|
|
||||||
smp_boot(ka, kernel_entry);
|
|
||||||
|
|
||||||
dprintf("jumping into kernel at 0x%x\n", kernel_entry);
|
|
||||||
|
|
||||||
ka->cons_line = screenOffset / SCREEN_WIDTH;
|
|
||||||
|
|
||||||
asm("movl %0, %%eax; " // move stack out of way
|
|
||||||
"movl %%eax, %%esp; "
|
|
||||||
: : "m" (ka->cpu_kstack[0].start + ka->cpu_kstack[0].size));
|
|
||||||
asm("pushl $0x0; " // we're the BSP cpu (0)
|
|
||||||
"pushl %0; " // kernel args
|
|
||||||
"pushl $0x0;" // dummy retval for call to main
|
|
||||||
"pushl %1; " // this is the start address
|
|
||||||
"ret; " // jump.
|
|
||||||
: : "g" (ka), "g" (kernel_entry));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
load_elf_image(void *data, uint32 *next_paddr, struct preloaded_image *image,
|
|
||||||
uint32 *start_addr)
|
|
||||||
{
|
|
||||||
struct Elf32_Ehdr *imageHeader = (struct Elf32_Ehdr *)data;
|
|
||||||
struct Elf32_Phdr *segments = (struct Elf32_Phdr *)(imageHeader->e_phoff + (unsigned) imageHeader);
|
|
||||||
int segmentIndex;
|
|
||||||
int foundSegmentIndex = 0;
|
|
||||||
|
|
||||||
memset(image, 0, sizeof(struct preloaded_image));
|
|
||||||
memcpy(&image->elf_header, imageHeader, sizeof(struct Elf32_Ehdr));
|
|
||||||
|
|
||||||
for (segmentIndex = 0; segmentIndex < imageHeader->e_phnum; segmentIndex++) {
|
|
||||||
struct Elf32_Phdr *segment = &segments[segmentIndex];
|
|
||||||
struct elf_region *region;
|
|
||||||
uint32 size, virtualAddress;
|
|
||||||
uint32 segmentOffset;
|
|
||||||
|
|
||||||
switch (segment->p_type) {
|
|
||||||
case PT_LOAD:
|
|
||||||
break;
|
|
||||||
case PT_DYNAMIC:
|
|
||||||
image->dynamic_section.start = segment->p_vaddr;
|
|
||||||
image->dynamic_section.size = segment->p_memsz;
|
|
||||||
default:
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
PRINT(("segment %d\n", segmentIndex));
|
|
||||||
PRINT(("p_vaddr 0x%x p_paddr 0x%x p_filesz 0x%x p_memsz 0x%x\n",
|
|
||||||
segment->p_vaddr, segment->p_paddr, segment->p_filesz, segment->p_memsz));
|
|
||||||
|
|
||||||
size = ROUNDUP(segment->p_filesz, PAGE_SIZE);
|
|
||||||
virtualAddress = ROUNDOWN(segment->p_vaddr, PAGE_SIZE);
|
|
||||||
|
|
||||||
/* Map initialized portion */
|
|
||||||
for (segmentOffset = 0; segmentOffset < size; segmentOffset += PAGE_SIZE) {
|
|
||||||
mmu_map_page(virtualAddress + segmentOffset, *next_paddr);
|
|
||||||
memcpy((void *)(virtualAddress + segmentOffset),
|
|
||||||
(void *)ROUNDOWN((uint32)data + segment->p_offset + segmentOffset, PAGE_SIZE),
|
|
||||||
PAGE_SIZE);
|
|
||||||
(*next_paddr) += PAGE_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clean out the leftover part of the last page */
|
|
||||||
if (segment->p_filesz % PAGE_SIZE > 0) {
|
|
||||||
PRINT(("memsetting 0 to va 0x%x, size %d\n", (void *)((unsigned)segment->p_vaddr + segment->p_filesz), PAGE_SIZE - (segment->p_filesz % PAGE_SIZE)));
|
|
||||||
memset((void *)((unsigned)segment->p_vaddr + segment->p_filesz), 0, PAGE_SIZE
|
|
||||||
- (segment->p_filesz % PAGE_SIZE));
|
|
||||||
}
|
|
||||||
|
|
||||||
size = ROUNDUP(segment->p_memsz, PAGE_SIZE);
|
|
||||||
|
|
||||||
/* Map uninitialized portion */
|
|
||||||
for (; segmentOffset < size; segmentOffset += PAGE_SIZE) {
|
|
||||||
PRINT(("mapping zero page at va 0x%x\n", segment->p_vaddr + segmentOffset));
|
|
||||||
mmu_map_page(virtualAddress + segmentOffset, *next_paddr);
|
|
||||||
memset((void *)(virtualAddress + segmentOffset), 0, PAGE_SIZE);
|
|
||||||
(*next_paddr) += PAGE_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (foundSegmentIndex == 0)
|
|
||||||
region = &image->text_region;
|
|
||||||
else
|
|
||||||
region = &image->data_region;
|
|
||||||
|
|
||||||
region->start = segment->p_vaddr;
|
|
||||||
region->size = size;
|
|
||||||
region->delta = -region->start;
|
|
||||||
|
|
||||||
foundSegmentIndex++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// initialize the region pointers to the allocated region
|
|
||||||
// (text region comes first)
|
|
||||||
image->data_region.start = image->text_region.start + image->text_region.size;
|
|
||||||
|
|
||||||
image->data_region.delta += image->data_region.start;
|
|
||||||
image->text_region.delta += image->text_region.start;
|
|
||||||
|
|
||||||
*start_addr = imageHeader->e_entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* allocate a page directory and page table to facilitate mapping
|
|
||||||
* pages to the 0x80000000 - 0x80400000 region.
|
|
||||||
* also identity maps the first 8MB of memory
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int
|
|
||||||
mmu_init(kernel_args *ka, uint32 *next_paddr)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
// allocate a new pgdir
|
|
||||||
pgdir = (uint32 *)*next_paddr;
|
|
||||||
(*next_paddr) += PAGE_SIZE;
|
|
||||||
ka->arch_args.phys_pgdir = (uint32)pgdir;
|
|
||||||
|
|
||||||
// clear out the pgdir
|
|
||||||
for (i = 0; i < 1024; i++)
|
|
||||||
pgdir[i] = 0;
|
|
||||||
|
|
||||||
// make a pagetable at this random spot
|
|
||||||
pgtable = (uint32 *)0x11000;
|
|
||||||
|
|
||||||
for (i = 0; i < 1024; i++) {
|
|
||||||
pgtable[i] = (i * 0x1000) | DEFAULT_PAGE_FLAGS;
|
|
||||||
}
|
|
||||||
|
|
||||||
pgdir[0] = (uint32)pgtable | DEFAULT_PAGE_FLAGS;
|
|
||||||
|
|
||||||
// make another pagetable at this random spot
|
|
||||||
pgtable = (uint32 *)0x12000;
|
|
||||||
|
|
||||||
for (i = 0; i < 1024; i++) {
|
|
||||||
pgtable[i] = (i * 0x1000 + 0x400000) | DEFAULT_PAGE_FLAGS;
|
|
||||||
}
|
|
||||||
|
|
||||||
pgdir[1] = (uint32)pgtable | DEFAULT_PAGE_FLAGS;
|
|
||||||
|
|
||||||
// Get new page table and clear it out
|
|
||||||
pgtable = (uint32 *)*next_paddr;
|
|
||||||
ka->arch_args.pgtables[0] = (uint32)pgtable;
|
|
||||||
ka->arch_args.num_pgtables = 1;
|
|
||||||
|
|
||||||
(*next_paddr) += PAGE_SIZE;
|
|
||||||
for (i = 0; i < 1024; i++)
|
|
||||||
pgtable[i] = 0;
|
|
||||||
|
|
||||||
// put the new page table into the page directory
|
|
||||||
// this maps the kernel at KERNEL_BASE
|
|
||||||
pgdir[KERNEL_BASE/(4*1024*1024)] = (uint32)pgtable | DEFAULT_PAGE_FLAGS;
|
|
||||||
|
|
||||||
// switch to the new pgdir
|
|
||||||
asm("movl %0, %%eax;"
|
|
||||||
"movl %%eax, %%cr3;" :: "m" (pgdir) : "eax");
|
|
||||||
// Important. Make sure supervisor threads can fault on read only pages...
|
|
||||||
asm("movl %%eax, %%cr0" : : "a" ((1 << 31) | (1 << 16) | (1 << 5) | 1));
|
|
||||||
// pkx: moved the paging turn-on to here.
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* can only map the 4 meg region right after KERNEL_BASE, may fix this later
|
|
||||||
* if need arises.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void
|
|
||||||
mmu_map_page(uint32 vaddr, uint32 paddr)
|
|
||||||
{
|
|
||||||
PRINT(("mmu_map_page: vaddr 0x%x, paddr 0x%x\n", vaddr, paddr));
|
|
||||||
|
|
||||||
if (vaddr < KERNEL_BASE || vaddr >= (KERNEL_BASE + 4096*1024)) {
|
|
||||||
dprintf("mmu_map_page: asked to map invalid page!\n");
|
|
||||||
for(;;);
|
|
||||||
}
|
|
||||||
paddr &= ~(PAGE_SIZE-1);
|
|
||||||
|
|
||||||
PRINT(("paddr 0x%x @ index %d\n", paddr, (vaddr % (PAGE_SIZE * 1024)) / PAGE_SIZE));
|
|
||||||
pgtable[(vaddr % (PAGE_SIZE * 1024)) / PAGE_SIZE] = paddr | DEFAULT_PAGE_FLAGS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
check_cpu(void)
|
|
||||||
{
|
|
||||||
uint32 data[4];
|
|
||||||
char str[17];
|
|
||||||
|
|
||||||
// check the eflags register to see if the cpuid instruction exists
|
|
||||||
if ((get_eflags() & (1 << 21)) == 0) {
|
|
||||||
set_eflags(get_eflags() | (1 << 21));
|
|
||||||
if ((get_eflags() & (1 << 21)) == 0) {
|
|
||||||
// we couldn't set the ID bit of the eflags register, this cpu is old
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// we can safely call cpuid
|
|
||||||
|
|
||||||
// print some fun data
|
|
||||||
cpuid(0, data);
|
|
||||||
|
|
||||||
// build the vendor string
|
|
||||||
memset(str, 0, sizeof(str));
|
|
||||||
*(uint32 *)&str[0] = data[1];
|
|
||||||
*(uint32 *)&str[4] = data[3];
|
|
||||||
*(uint32 *)&str[8] = data[2];
|
|
||||||
|
|
||||||
// get the family, model, stepping
|
|
||||||
cpuid(1, data);
|
|
||||||
dprintf("CPU: family %d model %d stepping %d, string '%s'\n",
|
|
||||||
(data[0] >> 8) & 0xf, (data[0] >> 4) & 0xf, data[0] & 0xf, str);
|
|
||||||
|
|
||||||
// check for bits we need
|
|
||||||
cpuid(1, data);
|
|
||||||
if (!(data[3] & (1 << 4)))
|
|
||||||
return -1; // check for rdtsc
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
spin(uint64 microseconds)
|
|
||||||
{
|
|
||||||
uint64 start = system_time();
|
|
||||||
|
|
||||||
while (system_time() - start <= microseconds)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
sort_addr_range(addr_range *range, int count)
|
|
||||||
{
|
|
||||||
addr_range tempRange;
|
|
||||||
bool done;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
do {
|
|
||||||
done = true;
|
|
||||||
for (i = 1; i < count; i++) {
|
|
||||||
if (range[i].start < range[i - 1].start) {
|
|
||||||
done = false;
|
|
||||||
memcpy(&tempRange, &range[i], sizeof(addr_range));
|
|
||||||
memcpy(&range[i], &range[i - 1], sizeof(addr_range));
|
|
||||||
memcpy(&range[i - 1], &tempRange, sizeof(addr_range));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (!done);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define outb(value,port) \
|
|
||||||
asm("outb %%al,%%dx"::"a" (value),"d" (port))
|
|
||||||
|
|
||||||
|
|
||||||
#define inb(port) ({ \
|
|
||||||
unsigned char _v; \
|
|
||||||
asm volatile("inb %%dx,%%al":"=a" (_v):"d" (port)); \
|
|
||||||
_v; \
|
|
||||||
})
|
|
||||||
|
|
||||||
#define TIMER_CLKNUM_HZ (14318180/12)
|
|
||||||
|
|
||||||
static void
|
|
||||||
calculate_cpu_conversion_factor(void)
|
|
||||||
{
|
|
||||||
unsigned s_low, s_high;
|
|
||||||
unsigned low, high;
|
|
||||||
unsigned long expired;
|
|
||||||
uint64 t1, t2;
|
|
||||||
uint64 p1, p2, p3;
|
|
||||||
double r1, r2, r3;
|
|
||||||
|
|
||||||
outb(0x34, 0x43); /* program the timer to count down mode */
|
|
||||||
outb(0xff, 0x40); /* low and then high */
|
|
||||||
outb(0xff, 0x40);
|
|
||||||
|
|
||||||
/* quick sample */
|
|
||||||
quick_sample:
|
|
||||||
do {
|
|
||||||
outb(0x00, 0x43); /* latch counter value */
|
|
||||||
s_low = inb(0x40);
|
|
||||||
s_high = inb(0x40);
|
|
||||||
} while(s_high != 255);
|
|
||||||
t1 = rdtsc();
|
|
||||||
do {
|
|
||||||
outb(0x00, 0x43); /* latch counter value */
|
|
||||||
low = inb(0x40);
|
|
||||||
high = inb(0x40);
|
|
||||||
} while (high > 224);
|
|
||||||
t2 = rdtsc();
|
|
||||||
|
|
||||||
p1 = t2-t1;
|
|
||||||
r1 = (double)(p1) / (double)(((s_high << 8) | s_low) - ((high << 8) | low));
|
|
||||||
|
|
||||||
/* not so quick sample */
|
|
||||||
not_so_quick_sample:
|
|
||||||
do {
|
|
||||||
outb(0x00, 0x43); /* latch counter value */
|
|
||||||
s_low = inb(0x40);
|
|
||||||
s_high = inb(0x40);
|
|
||||||
} while (s_high!= 255);
|
|
||||||
t1 = rdtsc();
|
|
||||||
do {
|
|
||||||
outb(0x00, 0x43); /* latch counter value */
|
|
||||||
low = inb(0x40);
|
|
||||||
high = inb(0x40);
|
|
||||||
} while (high> 192);
|
|
||||||
t2 = rdtsc();
|
|
||||||
p2 = t2-t1;
|
|
||||||
r2 = (double)(p2) / (double)(((s_high << 8) | s_low) - ((high << 8) | low));
|
|
||||||
if ((r1/r2) > 1.01) {
|
|
||||||
dprintf("Tuning loop(1)\n");
|
|
||||||
goto quick_sample;
|
|
||||||
}
|
|
||||||
if ((r1/r2) < 0.99) {
|
|
||||||
dprintf("Tuning loop(1)\n");
|
|
||||||
goto quick_sample;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* slow sample */
|
|
||||||
do {
|
|
||||||
outb(0x00, 0x43); /* latch counter value */
|
|
||||||
s_low = inb(0x40);
|
|
||||||
s_high = inb(0x40);
|
|
||||||
} while (s_high!= 255);
|
|
||||||
t1 = rdtsc();
|
|
||||||
do {
|
|
||||||
outb(0x00, 0x43); /* latch counter value */
|
|
||||||
low = inb(0x40);
|
|
||||||
high = inb(0x40);
|
|
||||||
} while (high > 128);
|
|
||||||
t2 = rdtsc();
|
|
||||||
|
|
||||||
p3 = t2-t1;
|
|
||||||
r3 = (double)(p3) / (double)(((s_high << 8) | s_low) - ((high << 8) | low));
|
|
||||||
if ((r2/r3) > 1.01) {
|
|
||||||
dprintf("Tuning loop(2)\n");
|
|
||||||
goto not_so_quick_sample;
|
|
||||||
}
|
|
||||||
if ((r2/r3) < 0.99) {
|
|
||||||
dprintf("Tuning loop(2)\n");
|
|
||||||
goto not_so_quick_sample;
|
|
||||||
}
|
|
||||||
|
|
||||||
expired = ((s_high << 8) | s_low) - ((high << 8) | low);
|
|
||||||
p3 *= TIMER_CLKNUM_HZ;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* cv_factor contains time in usecs per CPU cycle * 2^32
|
|
||||||
*
|
|
||||||
* The code below is a bit fancy. Originally Michael Noistering
|
|
||||||
* had it like:
|
|
||||||
*
|
|
||||||
* cv_factor = ((uint64)1000000<<32) * expired / p3;
|
|
||||||
*
|
|
||||||
* whic is perfect, but unfortunately 1000000ULL<<32*expired
|
|
||||||
* may overflow in fast cpus with the long sampling period
|
|
||||||
* i put there for being as accurate as possible under
|
|
||||||
* vmware.
|
|
||||||
*
|
|
||||||
* The below calculation is based in that we are trying
|
|
||||||
* to calculate:
|
|
||||||
*
|
|
||||||
* (C*expired)/p3 -> (C*(x0<<k + x1))/p3 ->
|
|
||||||
* (C*(x0<<k))/p3 + (C*x1)/p3
|
|
||||||
*
|
|
||||||
* Now the term (C*(x0<<k))/p3 is rewritten as:
|
|
||||||
*
|
|
||||||
* (C*(x0<<k))/p3 -> ((C*x0)/p3)<<k + reminder
|
|
||||||
*
|
|
||||||
* where reminder is:
|
|
||||||
*
|
|
||||||
* floor((1<<k)*decimalPart((C*x0)/p3))
|
|
||||||
*
|
|
||||||
* which is approximated as:
|
|
||||||
*
|
|
||||||
* floor((1<<k)*decimalPart(((C*x0)%p3)/p3)) ->
|
|
||||||
* (((C*x0)%p3)<<k)/p3
|
|
||||||
*
|
|
||||||
* So the final expression is:
|
|
||||||
*
|
|
||||||
* ((C*x0)/p3)<<k + (((C*x0)%p3)<<k)/p3 + (C*x1)/p3
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* To get the highest accuracy with this method
|
|
||||||
* x0 should have the 12 most significant bits of expired
|
|
||||||
* to minimize the error upon <<k.
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* Of course, you are not expected to understand any of this.
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
unsigned i;
|
|
||||||
unsigned k;
|
|
||||||
uint64 C;
|
|
||||||
uint64 x0;
|
|
||||||
uint64 x1;
|
|
||||||
uint64 a, b, c;
|
|
||||||
|
|
||||||
/* first calculate k*/
|
|
||||||
k = 0;
|
|
||||||
for (i = 12; i < 16; i++) {
|
|
||||||
if (expired & (1<<i))
|
|
||||||
k = i - 11;
|
|
||||||
}
|
|
||||||
|
|
||||||
C = 1000000ULL << 32;
|
|
||||||
x0 = expired >> k;
|
|
||||||
x1 = expired & ((1 << k) - 1);
|
|
||||||
|
|
||||||
a = ((C * x0) / p3) << k;
|
|
||||||
b = (((C * x0) % p3) << k) / p3;
|
|
||||||
c = (C * x1) / p3;
|
|
||||||
#if 0
|
|
||||||
dprintf("a=%Ld\n", a);
|
|
||||||
dprintf("b=%Ld\n", b);
|
|
||||||
dprintf("c=%Ld\n", c);
|
|
||||||
dprintf("%d %Ld\n", expired, p3);
|
|
||||||
#endif
|
|
||||||
cv_factor = a + b + c;
|
|
||||||
#if 0
|
|
||||||
dprintf("cvf=%Ld\n", cv_factor);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p3 / expired / 1000000000LL)
|
|
||||||
dprintf("CPU at %Ld.%03Ld GHz\n", p3/expired/1000000000LL, ((p3/expired)%1000000000LL)/1000000LL);
|
|
||||||
else
|
|
||||||
dprintf("CPU at %Ld.%03Ld MHz\n", p3/expired/1000000LL, ((p3/expired)%1000000LL)/1000LL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
clearscreen()
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < SCREEN_WIDTH * SCREEN_HEIGHT; i++)
|
|
||||||
kScreenBase[i] = 0xf20;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
scrup()
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
memcpy(kScreenBase, kScreenBase + SCREEN_WIDTH,
|
|
||||||
SCREEN_WIDTH * SCREEN_HEIGHT * 2 - SCREEN_WIDTH * 2);
|
|
||||||
screenOffset = (SCREEN_HEIGHT - 1) * SCREEN_WIDTH;
|
|
||||||
|
|
||||||
for (i = 0; i < SCREEN_WIDTH; i++)
|
|
||||||
kScreenBase[screenOffset + i] = 0x0720;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
kputs(const char *str)
|
|
||||||
{
|
|
||||||
while (*str) {
|
|
||||||
if (*str == '\n')
|
|
||||||
screenOffset += SCREEN_WIDTH - (screenOffset % 80);
|
|
||||||
else
|
|
||||||
kScreenBase[screenOffset++] = 0xf00 | *str;
|
|
||||||
|
|
||||||
if (screenOffset >= SCREEN_WIDTH * SCREEN_HEIGHT)
|
|
||||||
scrup();
|
|
||||||
|
|
||||||
str++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
dprintf(const char *fmt, ...)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
va_list args;
|
|
||||||
char temp[256];
|
|
||||||
|
|
||||||
va_start(args, fmt);
|
|
||||||
ret = vsprintf(temp, fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
|
|
||||||
kputs(temp);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
/*
|
|
||||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
|
||||||
** Distributed under the terms of the NewOS License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* uint64 rdtsc() */
|
|
||||||
.global rdtsc
|
|
||||||
rdtsc:
|
|
||||||
rdtsc
|
|
||||||
ret
|
|
||||||
|
|
||||||
.global execute_n_instructions
|
|
||||||
execute_n_instructions:
|
|
||||||
movl 4(%esp), %ecx
|
|
||||||
shrl $4, %ecx
|
|
||||||
.again:
|
|
||||||
xorl %eax, %eax
|
|
||||||
xorl %eax, %eax
|
|
||||||
xorl %eax, %eax
|
|
||||||
xorl %eax, %eax
|
|
||||||
xorl %eax, %eax
|
|
||||||
xorl %eax, %eax
|
|
||||||
xorl %eax, %eax
|
|
||||||
xorl %eax, %eax
|
|
||||||
xorl %eax, %eax
|
|
||||||
xorl %eax, %eax
|
|
||||||
xorl %eax, %eax
|
|
||||||
xorl %eax, %eax
|
|
||||||
xorl %eax, %eax
|
|
||||||
xorl %eax, %eax
|
|
||||||
xorl %eax, %eax
|
|
||||||
xorl %eax, %eax
|
|
||||||
loop .again
|
|
||||||
ret
|
|
||||||
|
|
||||||
.global system_time
|
|
||||||
system_time:
|
|
||||||
/* load 64-bit factor into %eax (low), %edx (high) */
|
|
||||||
/* hand-assemble rdtsc -- read time stamp counter */
|
|
||||||
rdtsc /* time in %edx,%eax */
|
|
||||||
|
|
||||||
pushl %ebx
|
|
||||||
movl cv_factor, %ebx
|
|
||||||
movl %edx, %ecx /* save high half */
|
|
||||||
mull %ebx /* truncate %eax, but keep %edx */
|
|
||||||
movl %ecx, %eax
|
|
||||||
movl %edx, %ecx /* save high half of low */
|
|
||||||
mull %ebx /*, %eax*/
|
|
||||||
/* now compute [%edx, %eax] + [%ecx], propagating carry */
|
|
||||||
subl %ebx, %ebx /* need zero to propagate carry */
|
|
||||||
addl %ecx, %eax
|
|
||||||
adc %ebx, %edx
|
|
||||||
popl %ebx
|
|
||||||
ret
|
|
||||||
|
|
||||||
.global cpuid
|
|
||||||
cpuid:
|
|
||||||
pushl %ebx
|
|
||||||
pushl %edi
|
|
||||||
movl 12(%esp),%eax
|
|
||||||
movl 16(%esp),%edi
|
|
||||||
cpuid
|
|
||||||
movl %eax,0(%edi)
|
|
||||||
movl %ebx,4(%edi)
|
|
||||||
movl %ecx,8(%edi)
|
|
||||||
movl %edx,12(%edi)
|
|
||||||
popl %edi
|
|
||||||
popl %ebx
|
|
||||||
ret
|
|
||||||
|
|
||||||
.global get_eflags
|
|
||||||
get_eflags:
|
|
||||||
pushfl
|
|
||||||
popl %eax
|
|
||||||
ret
|
|
||||||
|
|
||||||
.global set_eflags
|
|
||||||
set_eflags:
|
|
||||||
pushl 4(%esp)
|
|
||||||
popfl
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,606 +0,0 @@
|
|||||||
/*
|
|
||||||
** Some Portions Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
|
||||||
** Distributed under the terms of the NewOS License.
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
** Copyright 1998 Brian J. Swetland
|
|
||||||
** All rights reserved.
|
|
||||||
**
|
|
||||||
** Redistribution and use in source and binary forms, with or without
|
|
||||||
** modification, are permitted provided that the following conditions
|
|
||||||
** are met:
|
|
||||||
** 1. Redistributions of source code must retain the above copyright
|
|
||||||
** notice, this list of conditions, and the following disclaimer.
|
|
||||||
** 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
** notice, this list of conditions, and the following disclaimer in the
|
|
||||||
** documentation and/or other materials provided with the distribution.
|
|
||||||
** 3. The name of the author may not be used to endorse or promote products
|
|
||||||
** derived from this software without specific prior written permission.
|
|
||||||
**
|
|
||||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
||||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
||||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
||||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
#include "../../../headers/private/kernel/boot/bootdir.h"
|
|
||||||
|
|
||||||
//#include "sparcbootblock.h"
|
|
||||||
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#ifdef sparc
|
|
||||||
# define xBIG_ENDIAN 1
|
|
||||||
#endif
|
|
||||||
#ifdef i386
|
|
||||||
# define xLITTLE_ENDIAN 1
|
|
||||||
#endif
|
|
||||||
#if defined(__ppc__) || defined(__PPC__) || defined(__POWERPC__)
|
|
||||||
# define xBIG_ENDIAN 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define SWAP32(x) \
|
|
||||||
((((x) & 0xff) << 24) | (((x) & 0xff00) << 8) | (((x) & 0xff0000) >> 8) | (((x) & 0xff000000) >> 24))
|
|
||||||
|
|
||||||
#if xBIG_ENDIAN
|
|
||||||
# define HOST_TO_BENDIAN32(x) (x)
|
|
||||||
# define BENDIAN_TO_HOST32(x) (x)
|
|
||||||
# define HOST_TO_LENDIAN32(x) SWAP32(x)
|
|
||||||
# define LENDIAN_TO_HOST32(x) SWAP32(x)
|
|
||||||
#endif
|
|
||||||
#if xLITTLE_ENDIAN
|
|
||||||
# define HOST_TO_BENDIAN32(x) SWAP32(x)
|
|
||||||
# define BENDIAN_TO_HOST32(x) SWAP32(x)
|
|
||||||
# define HOST_TO_LENDIAN32(x) (x)
|
|
||||||
# define LENDIAN_TO_HOST32(x) (x)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !xBIG_ENDIAN && !xLITTLE_ENDIAN
|
|
||||||
# error not sure which endian the host processor is, please edit bootmaker.c
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// ELF stuff
|
|
||||||
#define ELF_MAGIC "\x7f""ELF"
|
|
||||||
#define EI_MAG0 0
|
|
||||||
#define EI_MAG1 1
|
|
||||||
#define EI_MAG2 2
|
|
||||||
#define EI_MAG3 3
|
|
||||||
#define EI_CLASS 4
|
|
||||||
#define EI_DATA 5
|
|
||||||
#define EI_VERSION 6
|
|
||||||
#define EI_PAD 7
|
|
||||||
#define EI_NIDENT 16
|
|
||||||
|
|
||||||
#define ELFCLASS32 1
|
|
||||||
#define ELFCLASS64 2
|
|
||||||
#define ELFDATA2LSB 1
|
|
||||||
#define ELFDATA2MSB 2
|
|
||||||
|
|
||||||
// XXX not safe across all build architectures
|
|
||||||
typedef unsigned int Elf32_Addr;
|
|
||||||
typedef unsigned short Elf32_Half;
|
|
||||||
typedef unsigned int Elf32_Off;
|
|
||||||
typedef int Elf32_Sword;
|
|
||||||
typedef unsigned int Elf32_Word;
|
|
||||||
|
|
||||||
struct Elf32_Ehdr {
|
|
||||||
unsigned char e_ident[EI_NIDENT];
|
|
||||||
Elf32_Half e_type;
|
|
||||||
Elf32_Half e_machine;
|
|
||||||
Elf32_Word e_version;
|
|
||||||
Elf32_Addr e_entry;
|
|
||||||
Elf32_Off e_phoff;
|
|
||||||
Elf32_Off e_shoff;
|
|
||||||
Elf32_Word e_flags;
|
|
||||||
Elf32_Half e_ehsize;
|
|
||||||
Elf32_Half e_phentsize;
|
|
||||||
Elf32_Half e_phnum;
|
|
||||||
Elf32_Half e_shentsize;
|
|
||||||
Elf32_Half e_shnum;
|
|
||||||
Elf32_Half e_shstrndx;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Elf32_Phdr {
|
|
||||||
Elf32_Word p_type;
|
|
||||||
Elf32_Off p_offset;
|
|
||||||
Elf32_Addr p_vaddr;
|
|
||||||
Elf32_Addr p_paddr;
|
|
||||||
Elf32_Word p_filesz;
|
|
||||||
Elf32_Word p_memsz;
|
|
||||||
Elf32_Word p_flags;
|
|
||||||
Elf32_Word p_align;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifndef O_BINARY
|
|
||||||
# define O_BINARY 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define LE 0
|
|
||||||
#define BE 1
|
|
||||||
|
|
||||||
// define host endian as default for the target environment
|
|
||||||
#if xBIG_ENDIAN
|
|
||||||
static int target_endian = BE;
|
|
||||||
#else
|
|
||||||
static int target_endian = LE;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define fix(x) ((target_endian == BE) ? HOST_TO_BENDIAN32(x) : HOST_TO_LENDIAN32(x))
|
|
||||||
|
|
||||||
static int make_sparcboot = 0;
|
|
||||||
static int strip_debug = 0;
|
|
||||||
static char *strip_binary = "strip";
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
die(char *s, char *a)
|
|
||||||
{
|
|
||||||
fprintf(stderr,"error: ");
|
|
||||||
fprintf(stderr,s,a);
|
|
||||||
fprintf(stderr,"\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void *
|
|
||||||
loadfile(char *file, int *size)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
char *data;
|
|
||||||
struct stat info;
|
|
||||||
|
|
||||||
if ((fd = open(file, O_BINARY|O_RDONLY)) != -1) {
|
|
||||||
if (fstat(fd, &info)) {
|
|
||||||
close(fd);
|
|
||||||
*size = 0;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
data = (char *)malloc(info.st_size);
|
|
||||||
if (read(fd, data, info.st_size) != info.st_size) {
|
|
||||||
close(fd);
|
|
||||||
*size = 0;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
close(fd);
|
|
||||||
*size = info.st_size;
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
*size = 0;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void *
|
|
||||||
loadstripfile(char *file, int *size)
|
|
||||||
{
|
|
||||||
char temp[256];
|
|
||||||
char cmd[4096];
|
|
||||||
void *retval;
|
|
||||||
|
|
||||||
if (strip_debug) {
|
|
||||||
strcpy(temp, "/tmp/mkboot.XXXXXXXX");
|
|
||||||
mktemp(temp);
|
|
||||||
sprintf(cmd, "cp %s %s; %s %s", file, temp, strip_binary, temp);
|
|
||||||
system(cmd);
|
|
||||||
|
|
||||||
retval = loadfile(temp, size);
|
|
||||||
|
|
||||||
unlink(temp);
|
|
||||||
} else {
|
|
||||||
retval = loadfile(file, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// write a boot block to the head of the dir.
|
|
||||||
// note: the first 0x20 bytes are removed by the sparc prom
|
|
||||||
// which makes the whole file off by 0x20 bytes
|
|
||||||
/*
|
|
||||||
int
|
|
||||||
writesparcbootblock(int fd, unsigned int blocks)
|
|
||||||
{
|
|
||||||
unsigned char bb[0x200+0x20];
|
|
||||||
|
|
||||||
memset(bb, 0, sizeof(bb));
|
|
||||||
memcpy(bb, sparcbootblock, sizeof(sparcbootblock));
|
|
||||||
|
|
||||||
return write(fd, bb, sizeof(bb));
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct _nvpair
|
|
||||||
{
|
|
||||||
struct _nvpair *next;
|
|
||||||
char *name;
|
|
||||||
char *value;
|
|
||||||
} nvpair;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct _section
|
|
||||||
{
|
|
||||||
struct _section *next;
|
|
||||||
char *name;
|
|
||||||
struct _nvpair *firstnv;
|
|
||||||
} section;
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
print_sections(section *first)
|
|
||||||
{
|
|
||||||
nvpair *p;
|
|
||||||
|
|
||||||
while (first) {
|
|
||||||
printf("\n[%s]\n", first->name);
|
|
||||||
|
|
||||||
for (p = first->firstnv; p; p = p->next) {
|
|
||||||
printf("%s=%s\n", p->name, p->value);
|
|
||||||
}
|
|
||||||
first = first->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define stNEWLINE 0
|
|
||||||
#define stSKIPLINE 1
|
|
||||||
#define stHEADER 2
|
|
||||||
#define stLHS 3
|
|
||||||
#define stRHS 4
|
|
||||||
|
|
||||||
section *first = NULL;
|
|
||||||
section *last = NULL;
|
|
||||||
|
|
||||||
section *
|
|
||||||
load_ini(char *file)
|
|
||||||
{
|
|
||||||
char *data, *end;
|
|
||||||
int size;
|
|
||||||
int state = stNEWLINE;
|
|
||||||
section *cur;
|
|
||||||
char *lhs, *rhs;
|
|
||||||
|
|
||||||
if (!(data = loadfile(file, &size)))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
end = data+size;
|
|
||||||
|
|
||||||
while (data < end) {
|
|
||||||
switch (state) {
|
|
||||||
case stSKIPLINE:
|
|
||||||
if (*data == '\n' || *data == '\r')
|
|
||||||
state = stNEWLINE;
|
|
||||||
|
|
||||||
data++;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case stNEWLINE:
|
|
||||||
if (*data == '\n' || *data == '\r') {
|
|
||||||
data++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*data == '[') {
|
|
||||||
lhs = data+1;
|
|
||||||
state = stHEADER;
|
|
||||||
data++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*data == '#' || *data <= ' ') {
|
|
||||||
state = stSKIPLINE;
|
|
||||||
data++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
lhs = data;
|
|
||||||
data++;
|
|
||||||
state = stLHS;
|
|
||||||
break;
|
|
||||||
case stHEADER:
|
|
||||||
if (*data == ']') {
|
|
||||||
cur = (section *) malloc(sizeof(section));
|
|
||||||
cur->name = lhs;
|
|
||||||
cur->firstnv = NULL;
|
|
||||||
cur->next = NULL;
|
|
||||||
if (last) {
|
|
||||||
last->next = cur;
|
|
||||||
last = cur;
|
|
||||||
} else {
|
|
||||||
last = first = cur;
|
|
||||||
}
|
|
||||||
*data = 0;
|
|
||||||
state = stSKIPLINE;
|
|
||||||
}
|
|
||||||
data++;
|
|
||||||
break;
|
|
||||||
case stLHS:
|
|
||||||
if (*data == '\n' || *data == '\r')
|
|
||||||
state = stNEWLINE;
|
|
||||||
|
|
||||||
if (*data == '=') {
|
|
||||||
*data = 0;
|
|
||||||
rhs = data+1;
|
|
||||||
state = stRHS;
|
|
||||||
}
|
|
||||||
data++;
|
|
||||||
continue;
|
|
||||||
case stRHS:
|
|
||||||
if (*data == '\n' || *data == '\r') {
|
|
||||||
nvpair *p = (nvpair *)malloc(sizeof(nvpair));
|
|
||||||
p->name = lhs;
|
|
||||||
p->value = rhs;
|
|
||||||
*data = 0;
|
|
||||||
p->next = cur->firstnv;
|
|
||||||
cur->firstnv = p;
|
|
||||||
state = stNEWLINE;
|
|
||||||
}
|
|
||||||
data++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return first;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
char *
|
|
||||||
getval(section *s, char *name)
|
|
||||||
{
|
|
||||||
nvpair *p;
|
|
||||||
for (p = s->firstnv; p; p = p->next) {
|
|
||||||
if (!strcmp(p->name, name))
|
|
||||||
return p->value;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
char *
|
|
||||||
getvaldef(section *s, char *name, char *def)
|
|
||||||
{
|
|
||||||
nvpair *p;
|
|
||||||
for (p = s->firstnv; p; p = p->next) {
|
|
||||||
if (!strcmp(p->name, name))
|
|
||||||
return p->value;
|
|
||||||
}
|
|
||||||
return def;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Elf32_Addr
|
|
||||||
elf_find_entry(void *buf, int size)
|
|
||||||
{
|
|
||||||
struct Elf32_Ehdr *header;
|
|
||||||
struct Elf32_Phdr *pheader;
|
|
||||||
char *cbuf = buf;
|
|
||||||
int byte_swap;
|
|
||||||
int index;
|
|
||||||
|
|
||||||
#define SWAPIT(x) ((byte_swap) ? SWAP32(x) : (x))
|
|
||||||
|
|
||||||
if (memcmp(cbuf, ELF_MAGIC, sizeof(ELF_MAGIC)-1) != 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (cbuf[EI_CLASS] != ELFCLASS32)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
byte_swap = 0;
|
|
||||||
#if xBIG_ENDIAN
|
|
||||||
if (cbuf[EI_DATA] == ELFDATA2LSB) {
|
|
||||||
byte_swap = 1;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (cbuf[EI_DATA] == ELFDATA2MSB) {
|
|
||||||
byte_swap = 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
header = (struct Elf32_Ehdr *)cbuf;
|
|
||||||
pheader = (struct Elf32_Phdr *)&cbuf[SWAPIT(header->e_phoff)];
|
|
||||||
|
|
||||||
// XXX only looking at the first program header. Should be ok
|
|
||||||
return SWAPIT(pheader->p_offset);
|
|
||||||
}
|
|
||||||
#undef SWAPIT
|
|
||||||
|
|
||||||
#define centry bdir.bd_entry[c]
|
|
||||||
void
|
|
||||||
makeboot(section *s, char *outfile)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
void *rawdata[64];
|
|
||||||
int rawsize[64];
|
|
||||||
char fill[4096];
|
|
||||||
boot_dir bdir;
|
|
||||||
int i,c;
|
|
||||||
int nextpage = 1; /* page rel offset of next loaded object */
|
|
||||||
|
|
||||||
memset(fill, 0, 4096);
|
|
||||||
memset(&bdir, 0, 4096);
|
|
||||||
|
|
||||||
for (i = 0; i < 64; i++) {
|
|
||||||
rawdata[i] = NULL;
|
|
||||||
rawsize[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
c = 1;
|
|
||||||
|
|
||||||
bdir.bd_entry[0].be_type = fix(BE_TYPE_DIRECTORY);
|
|
||||||
bdir.bd_entry[0].be_size = fix(1);
|
|
||||||
bdir.bd_entry[0].be_vsize = fix(1);
|
|
||||||
rawdata[0] = (void *) &bdir;
|
|
||||||
rawsize[0] = 4096;
|
|
||||||
|
|
||||||
strcpy(bdir.bd_entry[0].be_name,"SBBB/Directory");
|
|
||||||
|
|
||||||
while (s) {
|
|
||||||
char *type = getvaldef(s, "type", "NONE");
|
|
||||||
char *file = getval(s, "file");
|
|
||||||
int vsize;
|
|
||||||
int size;
|
|
||||||
struct stat statbuf;
|
|
||||||
|
|
||||||
if (!type)
|
|
||||||
die("section %s has no type", s->name);
|
|
||||||
|
|
||||||
strncpy(centry.be_name,s->name, BOOTDIR_NAMELEN);
|
|
||||||
centry.be_name[BOOTDIR_NAMELEN - 1] = 0;
|
|
||||||
|
|
||||||
if (!file)
|
|
||||||
die("section %s has no file", s->name);
|
|
||||||
|
|
||||||
rawdata[c] = ((strcmp(type, "elf32")==0) ? loadstripfile : loadfile)(file,&rawsize[c]);
|
|
||||||
if (!rawdata[c])
|
|
||||||
die("cannot load \"%s\"",file);
|
|
||||||
|
|
||||||
if (stat(file,&statbuf))
|
|
||||||
die("cannot stat \"%s\"",file);
|
|
||||||
vsize = statbuf.st_size;
|
|
||||||
|
|
||||||
centry.be_size = rawsize[c] / 4096 + (rawsize[c] % 4096 ? 1 : 0);
|
|
||||||
centry.be_vsize = (vsize < centry.be_size) ? centry.be_size : vsize;
|
|
||||||
|
|
||||||
centry.be_offset = nextpage;
|
|
||||||
nextpage += centry.be_size;
|
|
||||||
|
|
||||||
centry.be_size = fix(centry.be_size);
|
|
||||||
centry.be_vsize = fix(centry.be_vsize);
|
|
||||||
centry.be_offset = fix(centry.be_offset);
|
|
||||||
|
|
||||||
if (!strcmp(type,"boot")) {
|
|
||||||
centry.be_type = fix(BE_TYPE_BOOTSTRAP);
|
|
||||||
centry.be_code_vaddr = fix(atoi(getvaldef(s, "vaddr", "0")));
|
|
||||||
centry.be_code_ventr = fix(atoi(getvaldef(s, "ventry", "0")));
|
|
||||||
}
|
|
||||||
if(!strcmp(type,"code")){
|
|
||||||
centry.be_type = fix(BE_TYPE_CODE);
|
|
||||||
centry.be_code_vaddr = fix(atoi(getvaldef(s, "vaddr", "0")));
|
|
||||||
centry.be_code_ventr = fix(atoi(getvaldef(s, "ventry", "0")));
|
|
||||||
}
|
|
||||||
if (!strcmp(type, "data"))
|
|
||||||
centry.be_type = fix(BE_TYPE_DATA);
|
|
||||||
|
|
||||||
if (!strcmp(type, "elf32")) {
|
|
||||||
centry.be_type = fix(BE_TYPE_ELF32);
|
|
||||||
centry.be_code_vaddr = 0;
|
|
||||||
centry.be_code_ventr = fix(elf_find_entry(rawdata[c], rawsize[c]));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (centry.be_type == BE_TYPE_NONE)
|
|
||||||
die("unrecognized section type \"%s\"", type);
|
|
||||||
|
|
||||||
c++;
|
|
||||||
s = s->next;
|
|
||||||
|
|
||||||
if (c == BOOTDIR_MAX_ENTRIES)
|
|
||||||
die("too many sections (>63)",NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((fd = open(outfile, O_BINARY|O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
|
|
||||||
die("cannot write to \"%s\"",outfile);
|
|
||||||
|
|
||||||
/* XXX - Hope this isn't needed :(
|
|
||||||
if (make_sparcboot)
|
|
||||||
writesparcbootblock(fd, nextpage + 1);
|
|
||||||
*/
|
|
||||||
for (i = 0; i < c; i++) {
|
|
||||||
write(fd, rawdata[i], rawsize[i]);
|
|
||||||
if (rawsize[i] % 4096)
|
|
||||||
write(fd, fill, 4096 - (rawsize[i]%4096));
|
|
||||||
}
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
usage(char *name)
|
|
||||||
{
|
|
||||||
char *programName = strrchr(name, '/');
|
|
||||||
if (programName == NULL)
|
|
||||||
programName = name;
|
|
||||||
else
|
|
||||||
programName++;
|
|
||||||
|
|
||||||
fprintf(stderr,
|
|
||||||
"usage: %s [--littleendian] [--bigendian ] [ --strip-binary <binary ] [ --strip-debug] [ --sparc | -s ] [ <inifile> ... ] -o <bootfile>\n"
|
|
||||||
"\tdefaults to "
|
|
||||||
#if xBIG_ENDIAN
|
|
||||||
"\"big-endian\""
|
|
||||||
#else
|
|
||||||
"\"little-endian\""
|
|
||||||
#endif
|
|
||||||
" on this platform\n", programName);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
char *file = NULL;
|
|
||||||
char *programName = argv[0];
|
|
||||||
section *s;
|
|
||||||
|
|
||||||
if (argc < 2)
|
|
||||||
usage(programName);
|
|
||||||
|
|
||||||
argc--;
|
|
||||||
argv++;
|
|
||||||
|
|
||||||
while (argc){
|
|
||||||
if (!strcmp(*argv,"--sparc")) {
|
|
||||||
make_sparcboot = 1;
|
|
||||||
} else if (!strcmp(*argv, "--bigendian")) {
|
|
||||||
target_endian = BE;
|
|
||||||
} else if (!strcmp(*argv,"-o")) {
|
|
||||||
argc--;
|
|
||||||
argv++;
|
|
||||||
if (argc)
|
|
||||||
file = *argv;
|
|
||||||
else
|
|
||||||
usage(programName);
|
|
||||||
} else if (!strcmp(*argv, "--strip-binary")) {
|
|
||||||
argc--;
|
|
||||||
argv++;
|
|
||||||
if (argc)
|
|
||||||
strip_binary = *argv;
|
|
||||||
else
|
|
||||||
usage(programName);
|
|
||||||
} else if (!strcmp(*argv, "--strip-debug")) {
|
|
||||||
strip_debug = 1;
|
|
||||||
} else {
|
|
||||||
if (load_ini(*argv) == NULL)
|
|
||||||
fprintf(stderr, "warning: cannot load '%s'\n", *argv);
|
|
||||||
}
|
|
||||||
argc--;
|
|
||||||
argv++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((argc > 3) && !strcmp(argv[3], "-sparc"))
|
|
||||||
make_sparcboot = 1;
|
|
||||||
|
|
||||||
if (!file){
|
|
||||||
fprintf(stderr,"error: no output specified\n");
|
|
||||||
usage(programName);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!first){
|
|
||||||
fprintf(stderr, "error: no data to write?!\n");
|
|
||||||
usage(programName);
|
|
||||||
}
|
|
||||||
|
|
||||||
makeboot(first, file);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,132 +0,0 @@
|
|||||||
/*
|
|
||||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
|
||||||
** Distributed under the terms of the NewOS License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
#ifndef O_BINARY
|
|
||||||
# define O_BINARY 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
usage(char *progName)
|
|
||||||
{
|
|
||||||
printf("usage: %s [-p #padding] bootblock payload outfile\n", progName);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
struct stat st;
|
|
||||||
unsigned int blocks;
|
|
||||||
unsigned char bootsector[1024];
|
|
||||||
unsigned char buf[512];
|
|
||||||
size_t read_size;
|
|
||||||
size_t written_bytes;
|
|
||||||
int padding = 0;
|
|
||||||
int infd;
|
|
||||||
int outfd;
|
|
||||||
signed char opt;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
char *progName = argv[0];
|
|
||||||
if (strrchr(progName,'/'))
|
|
||||||
progName = strrchr(progName,'/') + 1;
|
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "p:")) != -1) {
|
|
||||||
switch (opt) {
|
|
||||||
case 'p':
|
|
||||||
padding = atoi(optarg);
|
|
||||||
if (padding < 0) {
|
|
||||||
usage(progName);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
usage(progName);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
argc -= optind - 1;
|
|
||||||
argv += optind - 1;
|
|
||||||
|
|
||||||
if (argc < 4) {
|
|
||||||
printf("insufficient args\n");
|
|
||||||
usage(progName);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = stat(argv[2], &st);
|
|
||||||
if (err < 0) {
|
|
||||||
printf("error stating file '%s'\n", argv[2]);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
outfd = open(argv[3], O_BINARY|O_WRONLY|O_CREAT|O_TRUNC, 0666);
|
|
||||||
if (outfd < 0) {
|
|
||||||
printf("error: cannot open output file '%s'\n", argv[3]);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// first read the bootblock
|
|
||||||
infd = open(argv[1], O_BINARY|O_RDONLY);
|
|
||||||
if (infd < 0) {
|
|
||||||
printf("error: cannot open bootblock file '%s'\n", argv[1]);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (read(infd, bootsector, sizeof(bootsector)) < sizeof(bootsector)
|
|
||||||
|| lseek(infd, 0, SEEK_END) != sizeof(bootsector)) {
|
|
||||||
printf ("error: size of bootblock file '%s' must match %d bytes.\n", argv[1], sizeof(bootsector));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
close(infd);
|
|
||||||
|
|
||||||
// patch the size of the output into bytes 3 & 4 of the bootblock
|
|
||||||
blocks = st.st_size / 512;
|
|
||||||
if ((st.st_size % 512) != 0)
|
|
||||||
blocks++;
|
|
||||||
printf("size %d, blocks %d (size %d)\n", (unsigned long)st.st_size, blocks, blocks * 512);
|
|
||||||
bootsector[2] = (blocks & 0x00ff);
|
|
||||||
bootsector[3] = (blocks & 0xff00) >> 8;
|
|
||||||
|
|
||||||
write(outfd, bootsector, sizeof(bootsector));
|
|
||||||
written_bytes = sizeof(bootsector);
|
|
||||||
|
|
||||||
infd = open(argv[2], O_BINARY|O_RDONLY);
|
|
||||||
if (infd < 0) {
|
|
||||||
printf("error: cannot open input file '%s'\n", argv[1]);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((read_size = read(infd, buf, sizeof(buf))) > 0) {
|
|
||||||
write(outfd, buf, read_size);
|
|
||||||
written_bytes += read_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (padding) {
|
|
||||||
if (written_bytes % padding) {
|
|
||||||
size_t towrite = padding - written_bytes % padding;
|
|
||||||
unsigned char *buf = malloc(towrite);
|
|
||||||
|
|
||||||
memset(buf, 0, towrite);
|
|
||||||
write(outfd, buf, towrite);
|
|
||||||
written_bytes += towrite;
|
|
||||||
|
|
||||||
printf("output file padded to %ld\n", (unsigned long)written_bytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
close(outfd);
|
|
||||||
close(infd);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user