From: Joshua Wise Date: Wed, 10 Sep 2008 22:24:10 +0000 (-0400) Subject: Merge ELF loader. X-Git-Url: http://git.joshuawise.com/netwatch.git/commitdiff_plain/86c89e89a88d25e85956b258005b52e0f2686b89?hp=d56898ee77b960cfe7f1d75bca2725d9d5337553 Merge ELF loader. --- diff --git a/grubload/Makefile b/grubload/Makefile index 041f09c..f0f9742 100644 --- a/grubload/Makefile +++ b/grubload/Makefile @@ -1,4 +1,4 @@ -OBJS=multiboot_c.o multiboot_asm.o console.o minilib.o loader.o +OBJS=multiboot_c.o multiboot_asm.o console.o minilib.o realmode.o loader.o CC=gcc CFLAGS=-nostdlib -I../include -I. -fno-builtin -nostdinc @@ -6,3 +6,9 @@ all: multiboot multiboot: $(OBJS) ld -o multiboot $(OBJS) -Ttext=0x100000 + +realmode.bin: realmode.asm + nasm -o realmode.bin realmode.asm + +realmode.o: realmode.bin + objcopy -I binary -B i386 -O elf32-i386 realmode.bin realmode.o diff --git a/grubload/multiboot_c.c b/grubload/multiboot_c.c index f871687..03e2143 100644 --- a/grubload/multiboot_c.c +++ b/grubload/multiboot_c.c @@ -1,5 +1,8 @@ #include "console.h" +extern char _binary_realmode_bin_start[]; +extern int _binary_realmode_bin_size; + struct mb_info { unsigned long flags; @@ -23,6 +26,8 @@ void c_start(unsigned int magic, struct mb_info *wee) unsigned short *grubptr = 0x7CFE; int i; + void (*realmode)() = 0x4000; + puts("Magic is: "); puthex(magic); puts("\nMultiboot header is: "); @@ -51,7 +56,7 @@ void c_start(unsigned int magic, struct mb_info *wee) load_elf(wee->mods[0].mod_start, wee->mods[0].mod_end - wee->mods[0].mod_start); - - while (1) - ; + puts("Now returning to real mode.\n"); + memcpy(0x4000, _binary_realmode_bin_start, (int)&_binary_realmode_bin_size); + realmode(); // goodbye! } diff --git a/grubload/realmode.asm b/grubload/realmode.asm new file mode 100644 index 0000000..b504b00 --- /dev/null +++ b/grubload/realmode.asm @@ -0,0 +1,106 @@ + [bits 32] ; Starts in 32 bit mode, then will drop back later. + org 0x4000 +entry: + cli + ; clean up 32 bit regs + mov eax, 0x0 + mov ebx, 0x0 + mov ecx, 0x0 + mov edx, 0x0 + mov esi, 0x0 + mov edi, 0x0 + mov ebp, 0x0 + mov esp, 0x0 + + lgdt [gdtp] + + mov ax, 0x10 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + + jmp 0x8:nextp ; Clear CS bits now too + +nextp: + + mov eax, cr0 + xor eax, 0x1 ; Clear PE + mov cr0, eax + + jmp 0x0:nowreal ; and jmp away + + + [bits 16] +nowreal: + mov long eax, 0x0000 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + + mov sp, 0xFFFF ; set up the stack + + mov al, 0xAB + out 0x80, al + + cli + lidt [idtp] + + mov si, RETMSG + call disp + + int 0x19 ; warm boot without clearing RAM. + call handload_drive ; hopefully shouldn't happen + ; ok, we give up + cli +halt: hlt + jmp halt + +disp: + lodsb + or al, al + jz .done + mov ah, 0x0E + mov bx, 0x0007 + int 0x10 + jmp disp +.done: + ret + +; handload_drive should be unnecessary; int 19 should take care of it for +; us... +handload_drive: + mov ax, 0x07C0 + mov es, ax + mov ax, 0x0201 ; read one sector + mov bx, 0x0000 ; to the normal location + mov cx, 0x0001 ; disk sector 1 + mov dx, 0x0080 ; drive 0 + int 0x13 + jc readerr + + mov si, READSUCC + call disp + + jmp 0x7C0:0x0 ; and return control to grub! +readerr: + mov si, READFAIL + call disp + ret + +RETMSG db "SMM installer finished, booting your system of choice.",10,13,0 +READSUCC db "Read successful; rebooting into boot sector.",10,13,0 +READFAIL db "Boot disk read failure; system halted.",10,13,0 + + +idtp db 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00 + +gdtp dw 0x1F + dd gdt + +gdt dd 0, 0 + dd 0x0000FFFF, 0x00009e00 ; CS + dd 0x0000FFFF, 0x00009300 ; DS