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:
Axel Dörfler
2005-10-31 00:03:41 +00:00
parent 0df3cc9c86
commit cc38261bf4
72 changed files with 0 additions and 10062 deletions
-17
View File
@@ -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 ;
-3
View File
@@ -1,3 +0,0 @@
SubDir HAIKU_TOP src system boot arch ;
SubInclude HAIKU_TOP src system boot arch $(TARGET_ARCH) ;
-2
View File
@@ -1,2 +0,0 @@
SubDir HAIKU_TOP src system boot arch alpha ;
-11
View File
@@ -1,11 +0,0 @@
/*
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
** Distributed under the terms of the NewOS License.
*/
int _start()
{
return 0;
}
-32
View File
@@ -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) }
}
-31
View File
@@ -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 $@
-2
View File
@@ -1,2 +0,0 @@
SubDir HAIKU_TOP src system boot arch m68k ;
-93
View File
@@ -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
-14
View File
@@ -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
-51
View File
@@ -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"
-44
View File
@@ -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) }
}
-67
View File
@@ -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;
}
-43
View File
@@ -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) }
}
-37
View File
@@ -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
-184
View File
@@ -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)());
}
-30
View File
@@ -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;
}
-2
View File
@@ -1,2 +0,0 @@
SubDir HAIKU_TOP src system boot arch mips ;
-78
View File
@@ -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
-24
View File
@@ -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
-14
View File
@@ -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"
-44
View File
@@ -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) }
}
-28
View File
@@ -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(;;);
}
-40
View File
@@ -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) }
}
-2
View File
@@ -1,2 +0,0 @@
SubDir HAIKU_TOP src system boot arch ppc ;
-80
View File
@@ -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
-47
View File
@@ -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"
-32
View File
@@ -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) }
}
-34
View File
@@ -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(;;);
}
-242
View File
@@ -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:
-141
View File
@@ -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(;;);
}
-554
View File
@@ -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;
}
-197
View File
@@ -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;
}
-242
View File
@@ -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;
}
-2
View File
@@ -1,2 +0,0 @@
SubDir HAIKU_TOP src system boot arch sh4 ;
-80
View File
@@ -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
-102
View File
@@ -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
-81
View File
@@ -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;
}
-109
View File
@@ -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++;
}
}
-39
View File
@@ -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
-213
View File
@@ -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;
}
-38
View File
@@ -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) }
}
-575
View File
@@ -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
-448
View File
@@ -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);
}
}
-2
View File
@@ -1,2 +0,0 @@
SubDir HAIKU_TOP src system boot arch sparc ;
-7
View File
@@ -1,7 +0,0 @@
/* $OpenBSD: closeall.c,v 1.1 1997/09/17 10:46:16 downsj Exp $ */
void
closeall()
{
}
-122
View File
@@ -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';
}
-428
View File
@@ -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
-428
View File
@@ -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
-233
View File
@@ -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;
}
-74
View File
@@ -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*/
}
-61
View File
@@ -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);
}
-64
View File
@@ -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;
}
-52
View File
@@ -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;
}
-257
View File
@@ -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');
}
}
-47
View File
@@ -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;
}
-806
View File
@@ -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;
}
-180
View File
@@ -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 */
-263
View File
@@ -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
-58
View File
@@ -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
-2
View File
@@ -1,2 +0,0 @@
SubDir HAIKU_TOP src system boot arch sparc64 ;
-33
View File
@@ -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 $@
-10
View File
@@ -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
;
-416
View File
@@ -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.
-509
View File
@@ -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];
}
-69
View File
@@ -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:
-869
View File
@@ -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;
}
-83
View File
@@ -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
-606
View File
@@ -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;
}
-132
View File
@@ -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;
}