[Etherboot-developers] [PATCH] linuxbios reorg...
Brought to you by:
marty_connor,
stefanhajnoczi
|
From: <ebi...@ln...> - 2002-01-08 07:27:19
|
I have just done a major reorganization of linuxBIOS that for booting it was passing all of the BIOS information instead of putting it in a table. Now LinuxBIOS just creates a table and you can scan for it. This is now much more robust. Now I don't need to use etherboot's multi-boot elf loader, and I can use the default one. My new version of mkelfImage (that works with this) is at ftp://download.lnxi.com/pub/src/mkelfImage/mkelfImage-1.9.tar.gz The big difference between mkelfImage and mknbi in this application is that mkelfImage strips out and replaces all of the linux kernels hardware probe code. This is great for prototyping but probably wrong for long term maintenance. For that I need to update the linux kernel. Eric diff -uNr --exclude=Config --exclude=Roms etherboot-5.0.5/src/Makefile etherboot-5.0.5.eb1/src/Makefile --- etherboot-5.0.5/src/Makefile Thu Dec 20 20:54:24 2001 +++ etherboot-5.0.5.eb1/src/Makefile Fri Jan 4 12:19:37 2002 @@ -92,7 +92,7 @@ VERSION_MAJOR= 5 VERSION_MINOR= 0 VERSION_PATCH= 5 -EXTRAVERSION= +EXTRAVERSION= eb1 VERSION= $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH)$(EXTRAVERSION) CFLAGS32+= -DVERSION_MAJOR=$(VERSION_MAJOR) \ -DVERSION_MINOR=$(VERSION_MINOR) \ @@ -160,7 +160,7 @@ LILOPREFIX= bin/liloprefix.bin START32= bin32/start32.o bin32/memsizes.o -UBE_START32= bin32/ube_start32.o bin32/ube.o +ELF_START32= bin32/elf_start32.o bin32/linuxbios.o BOBJS32= bin32/main.o bin32/osloader.o bin32/nfs.o bin32/misc.o BOBJS32+= bin32/ansiesc.o bin32/bootmenu.o bin32/md5.o bin32/floppy.o @@ -169,7 +169,7 @@ LIBS32= $(BLIB32) $(LIBC32) UTILS+= bin/makerom bin/lzhuf STDDEPS32= $(START32) $(BLIB32) $(UTILS) -UBE_DEPS32= $(UBE_START32) $(BLIB32) +ELF_DEPS32= $(ELF_START32) $(BLIB32) # MAKEDEPS is the one target that is depended by all ROMs, so we check gcc here # If you are confident that gcc 2.96 works for you, you can delete gcccheck # from the next line diff -uNr --exclude=Config --exclude=Roms etherboot-5.0.5/src/elf_start32.S etherboot-5.0.5.eb1/src/elf_start32.S --- etherboot-5.0.5/src/elf_start32.S Wed Dec 31 17:00:00 1969 +++ etherboot-5.0.5.eb1/src/elf_start32.S Fri Jan 4 11:23:28 2002 @@ -0,0 +1,165 @@ +/* #defines because ljmp wants a number, probably gas bug */ +/* .equ KERN_CODE_SEG,_pmcs-_gdt */ +#define KERN_CODE_SEG 0x08 + .equ KERN_DATA_SEG,_pmds-_gdt +/* .equ REAL_CODE_SEG,_rmcs-_gdt */ +#define REAL_CODE_SEG 0x18 + .equ REAL_DATA_SEG,_rmds-_gdt + .equ CR0_PE,1 + +#ifdef GAS291 +#define DATA32 data32; +#define ADDR32 addr32; +#define LJMPI(x) ljmp x +#else +#define DATA32 data32 +#define ADDR32 addr32 +/* newer GAS295 require #define LJMPI(x) ljmp *x */ +#define LJMPI(x) ljmp x +#endif + +/* + * NOTE: if you write a subroutine that is called from C code (gcc/egcs), + * then you only have to take care of %ebx, %esi, %edi and %ebp. These + * registers must not be altered under any circumstance. All other registers + * may be clobbered without any negative side effects. If you don't follow + * this rule then you'll run into strange effects that only occur on some + * gcc versions (because the register allocator may use different registers). + * + * All the data32 prefixes for the ljmp instructions are necessary, because + * the assembler emits code with a relocation address of 0. This means that + * all destinations are initially negative, which the assembler doesn't grok, + * because for some reason negative numbers don't fit into 16 bits. The addr32 + * prefixes are there for the same reasons, because otherwise the memory + * references are only 16 bit wide. Theoretically they are all superfluous. + * One last note about prefixes: the data32 prefixes on all call _real_to_prot + * instructions could be removed if the _real_to_prot function is changed to + * deal correctly with 16 bit return addresses. I tried it, but failed. + */ + + + +/************************************************************************** +START - Where all the fun begins.... +**************************************************************************/ +/* this must be the first thing in the file because we enter from the top */ + .global _start + .code32 +#ifdef IMAGE_MULTIBOOT +/************************************************************************** +XEND - Restart Etherboot from the beginning (from protected mode) +**************************************************************************/ + .globl xend +xend: +#endif +_start: + cli + + cs;lgdt gdtarg + ljmp $KERN_CODE_SEG, $1f +1: + /* reload other segment registers */ + movl $KERN_DATA_SEG, %ebp + movl %ebp,%ds + movl %ebp,%es + movl %ebp,%ss + movl %ebp,%fs + movl %ebp,%gs + + movl %esp, initesp + movl %eax, initeax + movl %ebx, initebx + + movl $_estack, %esp + + call main + /* fall through */ + + .globl exit +exit: + movl initesp, %esp + ret + + +/************************************************************************** +SETJMP - Save stack context for non-local goto +**************************************************************************/ + .globl setjmp +setjmp: + movl 4(%esp),%ecx + movl 0(%esp),%edx + movl %edx,0(%ecx) + movl %ebx,4(%ecx) + movl %esp,8(%ecx) + movl %ebp,12(%ecx) + movl %esi,16(%ecx) + movl %edi,20(%ecx) + movl %eax,24(%ecx) + movl $0,%eax + ret + +/************************************************************************** +LONGJMP - Non-local jump to a saved stack context +**************************************************************************/ + .globl longjmp +longjmp: + movl 4(%esp),%edx + movl 8(%esp),%eax + movl 0(%edx),%ecx + movl 4(%edx),%ebx + movl 8(%edx),%esp + movl 12(%edx),%ebp + movl 16(%edx),%esi + movl 20(%edx),%edi + cmpl $0,%eax + jne 1f + movl $1,%eax +1: movl %ecx,0(%esp) + ret + +/************************************************************************** +GLOBAL DESCRIPTOR TABLE +**************************************************************************/ + .align 4 +_gdt: +gdtarg: + .word 0x27 /* limit */ + .long _gdt /* addr */ + .word 0 + +_pmcs: + /* 32 bit protected mode code segment */ + .word 0xffff,0 + .byte 0,0x9f,0xcf,0 + +_pmds: + /* 32 bit protected mode data segment */ + .word 0xffff,0 + .byte 0,0x93,0xcf,0 + +_rmcs: + /* 16 bit real mode code segment */ + .word 0xffff,(RELOC&0xffff) + .byte (RELOC>>16),0x9b,0x00,(RELOC>>24) + +_rmds: + /* 16 bit real mode data segment */ + .word 0xffff,(RELOC&0xffff) + .byte (RELOC>>16),0x93,0x00,(RELOC>>24) + +initesp: .long 0 + .globl initeax +initeax: .long 0 + .globl initebx +initebx: .long 0 + + + .align 4 + + .section ".bss" + .p2align 3 + /* allocate a 4K stack in the bss segment */ +_stack: + .space 4096 +_estack: + diff -uNr --exclude=Config --exclude=Roms etherboot-5.0.5/src/genrules.pl etherboot-5.0.5.eb1/src/genrules.pl --- etherboot-5.0.5/src/genrules.pl Fri Aug 3 07:33:45 2001 +++ etherboot-5.0.5.eb1/src/genrules.pl Fri Jan 4 11:25:11 2002 @@ -178,8 +178,8 @@ \$(LD32) \$(LDFLAGS32) -o \$@ \$(START32) bin32/config-$key.o bin32/$key.o bin32/pci.o \$(LIBS32) @\$(SIZE32) \$@ | \$(CHECKSIZE) -bin32/$key.elf: bin32/$key.o bin32/config-$key.o bin32/pci.o \$(UBE_DEPS32) - \$(LD32) \$(LDFLAGS32) -o \$@ \$(UBE_START32) bin32/config-$key.o bin32/$key.o bin32/pci.o \$(LIBS32) +bin32/$key.elf: bin32/$key.o bin32/config-$key.o bin32/pci.o \$(ELF_DEPS32) + \$(LD32) \$(LDFLAGS32) -o \$@ \$(ELF_START32) bin32/config-$key.o bin32/$key.o bin32/pci.o \$(LIBS32) @\$(SIZE32) \$@ | \$(CHECKSIZE) bin32/$key.img: bin32/$key.o bin32/$key.tmp bin32/config-$key.o bin32/pci.o \$(STDDEPS32) diff -uNr --exclude=Config --exclude=Roms etherboot-5.0.5/src/linuxbios.c etherboot-5.0.5.eb1/src/linuxbios.c --- etherboot-5.0.5/src/linuxbios.c Wed Dec 31 17:00:00 1969 +++ etherboot-5.0.5.eb1/src/linuxbios.c Mon Jan 7 21:25:35 2002 @@ -0,0 +1,198 @@ +#include "etherboot.h" +#include "linuxbios_tables.h" + +struct meminfo meminfo; + +#undef DEBUG_LINUXBIOS + +/* FIXME should I use ipchksum here instead? + * It is the same algorithm, and reuse would save a few bytes... + */ +static unsigned long compute_checksum(void *addr, unsigned long length) +{ + /* Assumes the start is 2 byte aligned. + * This isn't exactly a problem on x86 but... + */ + unsigned short *ptr = addr; + unsigned long len; + unsigned long remainder; + unsigned long partial; + partial = 0; + len = length >> 1; + remainder = len & 1; + while(len--) { + partial += *(ptr++); + if (partial > 0xFFFF) + partial -= 0xFFFF; + } + if (remainder) { + unsigned char *ptr2 = (void *)ptr; + partial += *ptr2; + if (partial > 0xFFFF) + partial -= 0xFFFF; + } + return (~partial) & 0xFFFF; +} + +static void set_base_mem_k(struct meminfo *info, unsigned mem_k) +{ + if ((mem_k <= 640) && (info->basememsize <= mem_k)) { + info->basememsize = mem_k; + } +} +static void set_high_mem_k(struct meminfo *info, unsigned mem_k) +{ + /* Shave off a megabyte before playing */ + if (mem_k < 1024) { + return; + } + mem_k -= 1024; + if (info->memsize <= mem_k) { + info->memsize = mem_k; + } +} + +static void read_lb_memory( + struct meminfo *info, struct lb_memory *mem) +{ + int i; + int entries; + entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]); + for(i = 0; (i < entries); i++) { + if (info->map_count < E820MAX) { + info->map[info->map_count].addr = mem->map[i].start; + info->map[info->map_count].size = mem->map[i].size; + info->map[info->map_count].type = mem->map[i].type; + info->map_count++; + } + switch(mem->map[i].type) { + case LB_MEM_RAM: + { + unsigned long long high; + unsigned long mem_k; + high = mem->map[i].start + mem->map[i].size; +#if defined(DEBUG_LINUXBIOS) + printf("lb: ram start: %X%X size: %X%X high: %X%X\n", + (unsigned long)(mem->map[i].start >>32), + (unsigned long)(mem->map[i].start & 0xFFFFFFFF), + (unsigned long)(mem->map[i].size >> 32), + (unsigned long)(mem->map[i].size & 0xFFFFFFFF), + (unsigned long)(high >> 32), + (unsigned long)(high & 0xFFFFFFFF)); +#endif /* DEBUG_LINUXBIOS */ + high >>= 10; + mem_k = high; + if (high & 0xFFFFFFFF00000000ULL) { + mem_k = 0xFFFFFFFF; + } + set_base_mem_k(info, mem_k); + set_high_mem_k(info, mem_k); + break; + } + case LB_MEM_RESERVED: + default: + break; + } + } +} + + +static void read_linuxbios_values(struct meminfo *info, + struct lb_header *head) +{ + /* Read linuxbios tables... */ + struct lb_record *rec; + void *start, *end; + + start = ((unsigned char *)head) + sizeof(*head); + end = ((char *)start) + head->table_bytes; + for(rec = start; ((void *)rec < end) && + ((long)rec->size <= (end - (void *)rec)); + rec = (void *)(((char *)rec) + rec->size)) { + switch(rec->tag) { + case LB_TAG_MEMORY: + { + struct lb_memory *mem; + mem = (struct lb_memory *) rec; + read_lb_memory(info, mem); + break; + } + default: + break; + }; + } +} + + + +static unsigned long count_lb_records(void *start, unsigned long length) +{ + struct lb_record *rec; + void *end; + unsigned long count; + count = 0; + end = ((char *)start) + length; + for(rec = start; ((void *)rec < end) && + ((signed long)rec->size <= (end - (void *)rec)); + rec = (void *)(((char *)rec) + rec->size)) { + count++; + } + return count; +} + +static int find_lb_table(void *start, void *end, struct lb_header **result) +{ + unsigned char *ptr; + /* For now be stupid.... */ + for(ptr = start; (void *)ptr < end; ptr += 16) { + struct lb_header *head = (void *)ptr; + if ( (head->signature[0] == 'L') && + (head->signature[1] == 'B') && + (head->signature[2] == 'I') && + (head->signature[3] == 'O') && + (head->header_bytes == sizeof(*head)) && + (compute_checksum(head, sizeof(*head)) == 0) && + (compute_checksum(ptr + sizeof(*head), head->table_bytes) == + head->table_checksum) && + (count_lb_records(ptr + sizeof(*head), head->table_bytes) == + head->table_entries) + ) { + *result = head; + return 1; + } + }; + return 0; +} + +void get_memsizes(void) +{ + struct lb_header *lb_table; + int found; +#if defined(DEBUG_LINUXBIOS) + printf("\nSearching for linuxbios tables...\n"); +#endif /* DEBUG_LINUXBIOS */ + found = 0; + meminfo.basememsize = 0; + meminfo.memsize = 0; + meminfo.map_count = 0; + /* This code is specific to linuxBIOS but could + * concievably be extended to work under a normal bios. + * but size is important... + */ + if (!found) { + found = find_lb_table((void*)0x00000, (void*)0x01000, &lb_table); + } + if (!found) { + found = find_lb_table((void*)0xf0000, (void*)0x100000, &lb_table); + } + if (found) { + read_linuxbios_values(&meminfo, lb_table); + } + +#if defined(DEBUG_LINUXBIOS) + printf("base_mem_k = %d high_mem_k = %d\n", + meminfo.basememsize, meminfo.memsize); +#endif /* DEBUG_LINUXBIOS */ + +} + diff -uNr --exclude=Config --exclude=Roms etherboot-5.0.5/src/linuxbios_tables.h etherboot-5.0.5.eb1/src/linuxbios_tables.h --- etherboot-5.0.5/src/linuxbios_tables.h Wed Dec 31 17:00:00 1969 +++ etherboot-5.0.5.eb1/src/linuxbios_tables.h Fri Jan 4 11:27:57 2002 @@ -0,0 +1,82 @@ +#ifndef LINUXBIOS_TABLES_H +#define LINUXBIOS_TABLES_H + +#include <stdint.h> + +/* The linuxbios table information is for conveying information + * from the firmware to the loaded OS image. Primarily this + * is expected to be information that cannot be discovered by + * other means, such as quering the hardware directly. + * + * All of the information should be Position Independent Data. + * That is it should be safe to relocated any of the information + * without it's meaning/correctnes changing. For table that + * can reasonably be used on multiple architectures the data + * size should be fixed. This should ease the transition between + * 32 bit and 64 bit architectures etc. + * + * The completeness test for the information in this table is: + * - Can all of the hardware be detected? + * - Are the per motherboard constants available? + * - Is there enough to allow a kernel to run that was written before + * a particular motherboard is constructed? (Assuming the kernel + * has drivers for all of the hardware but it does not have + * assumptions on how the hardware is connected together). + * + * With this test it should be straight forward to determine if a + * table entry is required or not. This should remove much of the + * long term compatibility burden as table entries which are + * irrelevant or have been replaced by better alternatives may be + * dropped. Of course it is polite and expidite to include extra + * table entries and be backwards compatible, but it is not required. + */ + + +struct lb_header +{ + uint8_t signature[4]; /* LBIO */ + uint32_t header_bytes; + uint32_t header_checksum; + uint32_t table_bytes; + uint32_t table_checksum; + uint32_t table_entries; +}; + +/* Every entry in the boot enviroment list will correspond to a boot + * info record. Encoding both type and size. The type is obviously + * so you can tell what it is. The size allows you to skip that + * boot enviroment record if you don't know what it easy. This allows + * forward compatibility with records not yet defined. + */ +struct lb_record { + uint32_t tag; /* tag ID */ + uint32_t size; /* size of record (in bytes) */ +}; + +#define LB_TAG_UNUSED 0x0000 + +#define LB_TAG_MEMORY 0x0001 + +struct lb_memory_range { + uint64_t start; + uint64_t size; + uint32_t type; +#define LB_MEM_RAM 1 +#define LB_MEM_RESERVED 2 + +}; + +struct lb_memory { + uint32_t tag; + uint32_t size; + struct lb_memory_range map[0]; +}; + +#define LB_TAG_HWRPB 0x0002 +struct lb_hwrpb { + uint32_t tag; + uint32_t size; + uint64_t hwrpb; +}; + +#endif /* LINUXBIOS_TABLES_H */ diff -uNr --exclude=Config --exclude=Roms etherboot-5.0.5/src/ube.c etherboot-5.0.5.eb1/src/ube.c --- etherboot-5.0.5/src/ube.c Thu Dec 20 16:16:35 2001 +++ etherboot-5.0.5.eb1/src/ube.c Wed Dec 31 17:00:00 1969 @@ -1,153 +0,0 @@ -#include "etherboot.h" -#include "uniform_boot.h" - -struct meminfo meminfo; -static struct bootinfo { - unsigned base_mem_k; - unsigned high_mem_k; -} bootinfo; - - - -static unsigned long uniform_boot_compute_header_checksum( - struct uniform_boot_header *header) -{ - unsigned short *ptr; - unsigned long sum; - unsigned long len; - /* compute an ip style checksum on the header */ - sum = 0; - len = header->header_bytes >> 1; - ptr = (void *)header; - while (len--) { - sum += *(ptr++); - if (sum > 0xFFFF) - sum -= 0xFFFF; - } - return (~sum) & 0xFFFF; -} - -static void set_base_mem_k(struct meminfo *info, unsigned mem_k) -{ - if ((mem_k <= 640) && (info->basememsize <= mem_k)) { - info->basememsize = mem_k; - } -} -static void set_high_mem_k(struct meminfo *info, unsigned mem_k) -{ - /* Shave off a megabyte before playing */ - if (mem_k < 1024) { - return; - } - mem_k -= 1024; - if (info->memsize <= mem_k) { - info->memsize = mem_k; - } -} - -static void read_uniform_boot_memory( - struct meminfo *info, struct ube_memory *mem) -{ - int i; - int entries; - entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]); - for(i = 0; (i < entries); i++) { - if (info->map_count < E820MAX) { - info->map[info->map_count].addr = mem->map[i].start; - info->map[info->map_count].size = mem->map[i].size; - info->map[info->map_count].type = mem->map[i].type; - info->map_count++; - } - switch(mem->map[i].type) { - case UBE_MEM_RAM: - { - unsigned long long high; - unsigned long mem_k; - high = mem->map[i].start + mem->map[i].size; -#if defined(DEBUG_UBE) - printf("ube: ram start: %X%X size: %X%X high: %X%X\n", - (unsigned long)(mem->map[i].start >>32), - (unsigned long)(mem->map[i].start & 0xFFFFFFFF), - (unsigned long)(mem->map[i].size >> 32), - (unsigned long)(mem->map[i].size & 0xFFFFFFFF), - (unsigned long)(high >> 32), - (unsigned long)(high & 0xFFFFFFFF)); -#endif /* DEBUG_UBE */ - high >>= 10; - mem_k = high; - if (high & 0xFFFFFFFF00000000ULL) { - mem_k = 0xFFFFFFFF; - } - set_base_mem_k(info, mem_k); - set_high_mem_k(info, mem_k); - break; - } - case UBE_MEM_ACPI: - break; - case UBE_MEM_NVS: - break; - case UBE_MEM_RESERVED: - default: - break; - } - } -} - - -static void read_uniform_boot_data(struct meminfo *info, - struct uniform_boot_header *header) -{ - /* Uniform boot environment */ - unsigned long env_bytes; - char *env; - unsigned long checksum; - checksum = uniform_boot_compute_header_checksum(header); - if (checksum != 0) { - printf("Bad uniform boot header checksum!\n"); - } - if (header->arg_bytes) { - /* Ignore the command line I am passed */ - } - env = (void *)(header->env); - env_bytes = header->env_bytes; - while(env_bytes) { - struct ube_record *record; - unsigned long mem_k; - record = (void *)env; - if (record->tag == UBE_TAG_MEMORY) { - read_uniform_boot_memory(info, (void *)record); - } - env += record->size; - env_bytes -= record->size; - } -} - -void get_memsizes(void) -{ - extern unsigned long initeax; - extern unsigned long initebx; - unsigned long type; - void *ptr; -#if defined(DEBUG_UBE) - printf("\nReading bootinfo initeax = %X initebx = %X\n", - initeax, initebx); -#endif /* DEBUG_UBE */ - type = initeax; - ptr = (void *)initebx; - meminfo.basememsize = 0; - meminfo.memsize = 0; - meminfo.map_count = 0; - if (type == 0x0A11B007) { - read_uniform_boot_data(&bootinfo, ptr); - } - if (bootinfo.base_mem_k == 0) { - printf("No base memory found assuming 640K\n"); - bootinfo.base_mem_k = 640; - } -#if defined(DEBUG_UBE) - printf("base_mem_k = %d high_mem_k = %d\n", - bootinfo.base_mem_k, bootinfo.high_mem_k); -#endif /* DEBUG_UBE */ - -} - diff -uNr --exclude=Config --exclude=Roms etherboot-5.0.5/src/ube_start32.S etherboot-5.0.5.eb1/src/ube_start32.S --- etherboot-5.0.5/src/ube_start32.S Sat Jul 7 19:24:28 2001 +++ etherboot-5.0.5.eb1/src/ube_start32.S Wed Dec 31 17:00:00 1969 @@ -1,165 +0,0 @@ -/* #defines because ljmp wants a number, probably gas bug */ -/* .equ KERN_CODE_SEG,_pmcs-_gdt */ -#define KERN_CODE_SEG 0x08 - .equ KERN_DATA_SEG,_pmds-_gdt -/* .equ REAL_CODE_SEG,_rmcs-_gdt */ -#define REAL_CODE_SEG 0x18 - .equ REAL_DATA_SEG,_rmds-_gdt - .equ CR0_PE,1 - -#ifdef GAS291 -#define DATA32 data32; -#define ADDR32 addr32; -#define LJMPI(x) ljmp x -#else -#define DATA32 data32 -#define ADDR32 addr32 -/* newer GAS295 require #define LJMPI(x) ljmp *x */ -#define LJMPI(x) ljmp x -#endif - -/* - * NOTE: if you write a subroutine that is called from C code (gcc/egcs), - * then you only have to take care of %ebx, %esi, %edi and %ebp. These - * registers must not be altered under any circumstance. All other registers - * may be clobbered without any negative side effects. If you don't follow - * this rule then you'll run into strange effects that only occur on some - * gcc versions (because the register allocator may use different registers). - * - * All the data32 prefixes for the ljmp instructions are necessary, because - * the assembler emits code with a relocation address of 0. This means that - * all destinations are initially negative, which the assembler doesn't grok, - * because for some reason negative numbers don't fit into 16 bits. The addr32 - * prefixes are there for the same reasons, because otherwise the memory - * references are only 16 bit wide. Theoretically they are all superfluous. - * One last note about prefixes: the data32 prefixes on all call _real_to_prot - * instructions could be removed if the _real_to_prot function is changed to - * deal correctly with 16 bit return addresses. I tried it, but failed. - */ - - - -/************************************************************************** -START - Where all the fun begins.... -**************************************************************************/ -/* this must be the first thing in the file because we enter from the top */ - .global _start - .code32 -#ifdef IMAGE_MULTIBOOT -/************************************************************************** -XEND - Restart Etherboot from the beginning (from protected mode) -**************************************************************************/ - .globl xend -xend: -#endif -_start: - cli - - cs;lgdt gdtarg - ljmp $KERN_CODE_SEG, $1f -1: - /* reload other segment registers */ - movl $KERN_DATA_SEG, %ebp - movl %ebp,%ds - movl %ebp,%es - movl %ebp,%ss - movl %ebp,%fs - movl %ebp,%gs - - movl %esp, initesp - movl %eax, initeax - movl %ebx, initebx - - movl $_estack, %esp - - call main - /* fall through */ - - .globl exit -exit: - movl initesp, %esp - ret - - -/************************************************************************** -SETJMP - Save stack context for non-local goto -**************************************************************************/ - .globl setjmp -setjmp: - movl 4(%esp),%ecx - movl 0(%esp),%edx - movl %edx,0(%ecx) - movl %ebx,4(%ecx) - movl %esp,8(%ecx) - movl %ebp,12(%ecx) - movl %esi,16(%ecx) - movl %edi,20(%ecx) - movl %eax,24(%ecx) - movl $0,%eax - ret - -/************************************************************************** -LONGJMP - Non-local jump to a saved stack context -**************************************************************************/ - .globl longjmp -longjmp: - movl 4(%esp),%edx - movl 8(%esp),%eax - movl 0(%edx),%ecx - movl 4(%edx),%ebx - movl 8(%edx),%esp - movl 12(%edx),%ebp - movl 16(%edx),%esi - movl 20(%edx),%edi - cmpl $0,%eax - jne 1f - movl $1,%eax -1: movl %ecx,0(%esp) - ret - -/************************************************************************** -GLOBAL DESCRIPTOR TABLE -**************************************************************************/ - .align 4 -_gdt: -gdtarg: - .word 0x27 /* limit */ - .long _gdt /* addr */ - .word 0 - -_pmcs: - /* 32 bit protected mode code segment */ - .word 0xffff,0 - .byte 0,0x9f,0xcf,0 - -_pmds: - /* 32 bit protected mode data segment */ - .word 0xffff,0 - .byte 0,0x93,0xcf,0 - -_rmcs: - /* 16 bit real mode code segment */ - .word 0xffff,(RELOC&0xffff) - .byte (RELOC>>16),0x9b,0x00,(RELOC>>24) - -_rmds: - /* 16 bit real mode data segment */ - .word 0xffff,(RELOC&0xffff) - .byte (RELOC>>16),0x93,0x00,(RELOC>>24) - -initesp: .long 0 - .globl initeax -initeax: .long 0 - .globl initebx -initebx: .long 0 - - - .align 4 - - .section ".bss" - .p2align 3 - /* allocate a 4K stack in the bss segment */ -_stack: - .space 4096 -_estack: - |