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 ;
|
||||
|
||||
#SetupIncludes ;
|
||||
#oldccflags = $(CCFLAGS) ;
|
||||
#{
|
||||
# CCFLAGS = ;
|
||||
# local x ;
|
||||
# for x in $(CCFLAGS) {
|
||||
# if $(x) != --nostdinc {
|
||||
# CCFLAGS += $(x) ;
|
||||
# }
|
||||
# }
|
||||
#}
|
||||
|
||||
BuildPlatformMain bootmaker : bootmaker.c ;
|
||||
BuildPlatformMain bin2h : bin2h.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 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