Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple kernel won't boot in GRUB

Tags:

I'm learning a bit of OS development from OSDev.org. I have a kernel and I'm trying to boot in GRUB Legacy (0.97) using qemu. However, when I type kernel 200+9, I get the message

[Multiboot-elf, <0x100000:0x80:0x4008>(bad), entry=0x10000c] 

This is what I expect except for the (bad) part. If I type boot now GRUB just hangs.

I think the numbers 0x100000, 0x44, 0x4008 stand for the .text segment start address, the .bss start address, and the .bss section size, respectively. I think this because running objdump -h on the kernel image gives this output:

kernel.bin:     file format elf32-i386  Sections: Idx Name          Size      VMA       LMA       File off  Algn   0 .text         00000044  00100000  00100000  00001000  2**4                   CONTENTS, ALLOC, LOAD, READONLY, CODE   1 .bss          00004008  00100044  00100044  00001044  2**2                   ALLOC 

So you can see that the numbers I mentioned almost match up. The issue is that instead of 100044, the start of .bss is just 44. And I think this is the reason why GRUB is saying bad. I can't have a section below 1 MB in memory (low memory). But objdump is telling me my sections are above that threshold, so I don't know what's wrong. Anyway, I'll paste my code below, it's relatively short. Although my question is probably very basic if you've done OS dev before, so the code might be extraneous.

;loader.s - contains the multiboot header for grub and calls the main kernel method  global loader                           ; making entry point visible to linker global magic                            ; we will use this in kmain global mbd                              ; we will use this in kmain  extern kmain                            ; kmain is defined in kmain.cpp  ; setting up the Multiboot header - see GRUB docs for details MODULEALIGN equ  1<<0                   ; align loaded modules on page boundaries MEMINFO     equ  1<<1                   ; provide memory map FLAGS       equ  0x03;MODULEALIGN | MEMINFO  ; this is the Multiboot 'flag' field MAGIC       equ  0x1BADB002             ; 'magic number' lets bootloader find the header CHECKSUM    equ -(MAGIC + FLAGS)        ; checksum required  section .text  loader:  align 4     dd MAGIC     dd FLAGS     dd CHECKSUM  ; reserve initial kernel stack space STACKSIZE equ 0x4000                    ; that's 16k.      mov  esp, stack + STACKSIZE         ; set up the stack     mov  [magic], eax                   ; Multiboot magic number     mov  [mbd], ebx                     ; Multiboot info structure      call kmain                          ; call kernel proper      cli .hang:     hlt                                 ; halt machine should kernel return     jmp  .hang  section .bss  align 4 stack: resb STACKSIZE                   ; reserve 16k stack on a doubleword boundary magic: resd 1 mbd:   resd 1 

.

// kernel.c - Contains the main kernel method  void kmain() {   extern unsigned int magic;    if (magic != 0x2BADB002) {     // Something went wrong   }    volatile unsigned char *videoram = (unsigned char *) 0xB800;   videoram[0] = 65;   videoram[1] = 0x07; } 

Below is my custom linker script:

ENTRY (loader)  SECTIONS {     . = 0x00100000;      .text ALIGN (0x1000) : {         *(.text)     }      .rodata ALIGN (0x1000) :     {         *(.rodata*)     }      .data ALIGN (0x1000) :     {         *(.data)     }      .bss :     {         sbss = .;         *(COMMON)         *(.bss)         ebss = .;     }      /DISCARD/ : {         *(.eh_frame)         *(.comment)     } } 

And finally, I build the kernel with the following lines:

nasm -f elf -o loader.o loader.s gcc -c -o kernel.o kernel.c ld -T linker.ld -o kernel.bin loader.o kernel.o cat stage1 stage2 pad kernel.bin > floppy.img 

Where stage1 and stage2 are file from GRUB Legacy and pad is any 750 byte file (So stage1+stage2+pad have a file size of 102400 bytes, or 200 blocks, which is why I boot with kernel 200+9).

Finally, I run the kernel in qemu:

qemu-system-x86_64 -fda floppy.img 
like image 799
gsingh2011 Avatar asked Jan 14 '13 02:01

gsingh2011


People also ask

How do I boot from USB in grub rescue?

Hi, try hitting the escape key as soon as you hit the power button and then hit F9. That should take you to Boot Device Options; select your CD or USB. =)

How do I manually boot with Vmlinuz kernel?

To manually boot linux, you still need to have a bootloader. Normally you just press enter or wait for a timeout, and the default image loads. But you can specify both a kernel image to load and some parameters. At the grub prompt, type 'vmlinuz root=/dev/sda1' (not sure about the leading / on vmlinuz).


1 Answers

+1 for nice question with all the details, thank you.

At least on my machine the generated kernel.bin comes out as 4869 bytes, which only fits in 10 sectors not 9. Also, the VGA text memory is at 0xb8000 not 0xb800 (one more zero - 0xb800 is the real mode segment, has to be multiplied by 16). With those little adjustments it works fine here.

like image 143
Jester Avatar answered Oct 20 '22 06:10

Jester