OSDev.org https://forum.osdev.org/ |
|
Booting non-ELF kernel with GRUB tutorial https://forum.osdev.org/viewtopic.php?f=1&t=21260 |
Page 1 of 1 |
Author: | gedd [ Tue Dec 01, 2009 11:08 am ] |
Post subject: | Booting non-ELF kernel with GRUB tutorial |
Here are 2 basic tutorials to make GRUB booting non-ELF kernel, one for flat binary and one for PE format kernel. Both have been tested on windows Prerequisites - A correct floppy with GRUB installed to match this menu.cfg Code: default=0 timeout=0 title DNA Workstation root (fd0) kernel /init.bin - nasm - Visual C++ [Express edition is enough and free] Flat binary kernel the code init.asm Code: [map all init.map] ;Nasm directive to produce map file bits 32 ;necessary to avoid Nasm to produce 16 bits code MULTIBOOT_HEADER_MAGIC equ 0x1BADB002 ;magic number, GRUB search for it in the first 8k ;of the specified file in GRUB menu MULTIBOOT_HEADER_FLAGS equ 0x00010000 ;FLAGS[16] say to GRUB we are not ;an ELF executable and the fields ;header adress, load adress, load end adress; ;bss end adress and entry adress will be available ;in Multiboot header CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) LOADBASE equ 0x00100000 ;Must be >= 1Mo STACK_SIZE equ 0x4000 _start: jmp multiboot_entry ;if you want use you own bootloader align 4 ;Multiboot header must be 32 ;bits aligned to avoid error 13 multiboot_header: dd MULTIBOOT_HEADER_MAGIC ;magic number dd MULTIBOOT_HEADER_FLAGS ;flags dd CHECKSUM ;checksum dd LOADBASE + multiboot_header ;header adress dd LOADBASE ;load adress dd 00 ;load end adress : not necessary dd 00 ;bss end adress : not necessary dd LOADBASE + multiboot_entry ;entry adress multiboot_entry: mov esp, stack + STACK_SIZE ;Setup the stack push 0 ;Reset EFLAGS popf push ebx ;Push magic number and push eax ;multiboot info adress ;which are loaded in registers ;eax and ebx before jump to ;entry adress ;[LOADBASE + multiboot_entry] ;call EXT_C(main) ; !! commented ;main (unsigned long magic, unsigned long addr) ;your kernel entry point mov edi, 0xB8000 ;Msg to check the boot was OK mov esi, hello add esi, LOADBASE ;hello is just an offset msg: mov byte al, [esi] cmp al, '\0' je loop mov ah, 0xa0 mov word [edi], ax add edi, 2 inc esi jmp msg loop: hlt ;Halt processor jmp loop _edata: hello: db "Hello world from GRUB and flat binary kernel !\0" align 4 times (128) db 0x00 ;foo data stack: align 4 times (STACK_SIZE) db 00 _end: -Assemble with nasm : nasm -f bin -o init.bin init.asm -copy init.bin at the floppy root -test PE Kernel This is a bit more complicated First you must setup a Visual C++ project named init like as describe in the famous BrokenThorn tutorials Setup Visual c++ Some modificatione are required C/C++ in code generation set Enable Function level linking to yes (/Gy) Linker in command line set /ALIGN=1024 and add in Optimisation-> Functions order : @order.txt (@ is to avoid LNK warning) Add a txt file order.txt (without @), leave blank Add init .h file Code: /* _emit is DB equivalent but not DD equivalent exist so we define it ourself */ #define dd(x) \ __asm _emit (x) & 0xff \ __asm _emit (x) >> 8 & 0xff \ __asm _emit (x) >> 16 & 0xff \ __asm _emit (x) >> 24 & 0xff #define KERNEL_STACK 0x00104000 /* This is the one of most important thing to be able to load a PE kernel with GRUB. Because PE header are in the begining of the file, code section will be shifted. The value used to shift the code section is the linker align option /ALIGN:value. Note the header size sum is larger than 512, so ALIGN value must be greater */ #define ALIGN 0x400 /* Must be >= 1Mo for GRUB Base adress from advanced libker option */ #define LOADBASE 0x100000 #define HEADER_ADRESS LOADBASE+ALIGN #define MULTIBOOT_HEADER_MAGIC 0x1BADB002 #define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 #define MULTIBOOT_HEADER_FLAGS 0x00010003 #define STACK_SIZE 0x4000 #define CHECKSUM -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) void main(unsigned long, unsigned long); Add init.cpp file Code: // init.cpp : définit le point d'entrée pour l'application console. // #include "init.h" __declspec(naked) void multiboot_entry(void) { __asm{ align 4 multiboot_header: dd(MULTIBOOT_HEADER_MAGIC) ; magic number dd(MULTIBOOT_HEADER_FLAGS) ; flags dd(CHECKSUM) ; checksum dd(HEADER_ADRESS) ; header address dd(LOADBASE) ; load address dd(00) ; load end address : not used dd(00) ; bss end addr : not used dd(HEADER_ADRESS + 0x20) ; entry_addr : equ kernel entry ; 0x20 is the size of multiboot heeader kernel_entry: mov esp, KERNEL_STACK ;Setup the stack push 0 ;Reset EFLAGS popf push ebx ;Push multiboot info adress push eax ;and magic number ;which are loaded in registers ;eax and ebx before jump to ;entry adress ;[HEADER_ADRESS + 0x20] call main ;kernel entry halt: jmp halt ; halt processor } } void main(unsigned long magic, unsigned long addr) { char *string = "Hello World from GRUB and PE kernel !", *ch; unsigned short *vidmem = (unsigned short *) 0xB8000; int i; if (magic == MULTIBOOT_BOOTLOADER_MAGIC){ for(ch = string, i = 0; *ch; ch++, i++) vidmem[i] = (unsigned char) *ch | 0xA000; }else { // DO SOMETHING } } Build Take a look at your map file, it should be like this : Code: init Timestamp is 4b1549e9 (Tue Dec 01 17:52:57 2009) Preferred load address is 00100000 Start Length Name Class 0001:00000000 000000a5H .text CODE 0002:00000000 00000026H .rdata DATA Address Publics by Value Rva+Base Lib:Object 0000:00000000 ___safe_se_handler_count 00000000 <absolute> 0000:00000000 ___safe_se_handler_table 00000000 <absolute> 0001:00000000 ?multiboot_entry@@YAXXZ 00100400 f init.obj 0001:00000040 _main 00100440 f init.obj 0002:00000000 ??_C@_0CG@IINAHCGJ@Hello?5World?5from?5GRUB?5and?5PE?5ker@ 00100800 init.obj entry point at 0000:00000000 Static symbols Put this in your order.txt ?multiboot_entry@@YAXXZ This ensure that when your kernel will growing, the multiboot_entry function will be at the beginning of file - build - copy the output file in the floppy root - test This is not a perfect tutorial but it is quite good to begin Please report me any error, suggestion and your test result |
Author: | madeofstaples [ Tue Dec 01, 2009 12:04 pm ] |
Post subject: | Re: Booting non-ELF kernel with GRUB tutorial by a prick |
Interesting, but I was a little disappointed that none of your comments or your tutorial in general made you sound like a prick, as promised by the thread title. It looks like a useful tutorial, I admit I skimmed it a bit because I'm not currently working on anything related, but I may save a copy for reference later. The only thing I did notice is that you should use the hlt instruction between the "halt" label and "jmp halt" command in init.cpp; perhaps disabling maskable interrupts with cli before the "halt" label. |
Author: | gedd [ Tue Dec 01, 2009 12:36 pm ] |
Post subject: | Re: Booting non-ELF kernel with GRUB tutorial by a prick |
The prick was a reference from another thread wich have been locked. Few year ago hlt instruction doesn't work fine in some virtualizer, it's an hold habit tu use infinite loop. The forgoten CLI is clearly a mistake |
Author: | neon [ Tue Dec 01, 2009 1:02 pm ] |
Post subject: | Re: Booting non-ELF kernel with GRUB tutorial by a prick |
Id remove that "reference" from the thread title. Its nice that you are sharing self written tutorials, I would keep it at that |
Author: | Love4Boobies [ Mon Jan 11, 2010 12:07 pm ] |
Post subject: | Re: Booting non-ELF kernel with GRUB tutorial |
Can you really be far even as decided half as much to use go wish for that? |
Author: | gedd [ Tue Jan 12, 2010 2:37 am ] |
Post subject: | Re: Booting non-ELF kernel with GRUB tutorial |
Sorry for my question but i'm not understand your sentence I 'm not english, can you rewrite ? |
Page 1 of 1 | All times are UTC - 6 hours |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |