2013-01-14 21 views
23

Sto imparando un po 'di sviluppo del sistema operativo da OSDev.org. Ho un kernel e sto provando ad avviare in GRUB Legacy (0.97) usando qemu. Tuttavia, quando digito kernel 200+9, ottengo il messaggioIl kernel semplice non si avvia in GRUB

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

Questo è quello che mi aspetto ad eccezione della parte (male). Se digito boot ora GRUB si blocca.

Penso che i numeri 0x100000, 0x44, 0x4008 rappresentino l'indirizzo iniziale del segmento .text, l'indirizzo iniziale .bss e la dimensione della sezione .bss, rispettivamente. Penso questo perché in esecuzione objdump -h l'immagine del kernel, otterrai questa uscita:

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 

Così si può vedere che i numeri che ho citato quasi corrispondono. Il problema è che invece di 100044, l'inizio di .bss è solo 44. E penso che questo sia il motivo per cui GRUB sta dicendo male. Non posso avere una sezione inferiore a 1 MB in memoria (poca memoria). Ma objdump mi sta dicendo che le mie sezioni sono sopra quella soglia, quindi non so cosa c'è che non va. Ad ogni modo, incollo il mio codice qui sotto, è relativamente breve. Anche se la mia domanda è probabilmente molto di base se hai già fatto OS DEV, quindi il codice potrebbe essere estraneo.

;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; 
} 

Qui di seguito è il mio script del linker personalizzato:

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) 
    } 
} 

E, infine, costruisco il kernel con le seguenti righe:

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 

Dove stage1 e stage2 sono file da GRUB Legacy e pad è un qualsiasi file da 750 byte (quindi stage1 + stage2 + pad ha una dimensione file di 102400 byte o 200 blocchi, motivo per cui avvio con il kernel 200 + 9).

Infine, ho eseguito il kernel in QEMU:

qemu-system-x86_64 -fda floppy.img 
+0

Repository con quell'esempio di lavoro: https://github.com/cirosantilli/x86-bare-metal-examples/tree/d217b180be4220a0b4a453f31275d38e697a99e0/multiboot/osdev –

risposta

22

+1 per bella domanda con tutti i dettagli, grazie.

Almeno sulla mia macchina generato kernel.bin esce come 4869 byte, che si adatta solo in 10 settori non 9. Inoltre, la memoria di testo VGA è a 0xb8000 non 0xb800 (un altro lo zero - 0xb800 è il segmento modalità reale, deve essere moltiplicato per 16). Con quei piccoli aggiustamenti funziona bene qui.

+0

Wow, il problema era con 0xb800 ... ho pensato che era appeso ma in realtà non stava mettendo il personaggio nel posto giusto nella memoria ... Anche se sono ancora confuso su cosa significhi allora: '<0x100000: 0x80: 0x4008> (cattivo)', dato che non dovresti essere permesso di avere un segmento in bassa memoria (se ho interpretato correttamente il significato dei numeri) ... – gsingh2011

+0

E per chiarire un po 'per altri, si avvia ancora anche se dice (male). – gsingh2011

+2

Dice '(bad)' se non si caricano abbastanza settori. Può ancora funzionare se nulla di importante risiede in quella parte. Hai provato con '200 + 10'? – Jester