2013-01-14 1 views
23

J'apprends un peu de développement d'OS de OSDev.org. J'ai un noyau et j'essaye de démarrer dans GRUB Legacy (0.97) en utilisant qemu. Cependant, quand je tape kernel 200+9, je reçois le messageLe noyau simple ne démarrera pas dans GRUB

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

Voilà ce que je pense à l'exception de la partie (mauvais). Si je tape boot maintenant GRUB se bloque juste.

Je pense que les nombres 0x100000, 0x44, 0x4008 représentent l'adresse de début de segment .text, l'adresse de début .bss et la taille de section .bss, respectivement. Je pense que cela, car l'exécution objdump -h sur l'image du noyau donne cette sortie:

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 

vous pouvez donc voir que les chiffres que je mentionnés correspondent presque. Le problème est qu'au lieu de 100044, le début de .bss est juste 44. Et je pense que c'est la raison pour laquelle GRUB dit mauvais. Je ne peux pas avoir une section inférieure à 1 Mo en mémoire (mémoire insuffisante). Mais objdump me dit que mes sections sont au-dessus de ce seuil, donc je ne sais pas ce qui ne va pas. Quoi qu'il en soit, je vais coller mon code ci-dessous, c'est relativement court. Bien que ma question soit probablement très simple si vous avez déjà fait des dev de système d'exploitation, le code pourrait être superflu.

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

Ci-dessous mon script linker personnalisé:

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

Et enfin, je construis le noyau avec les lignes suivantes:

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 

Où stage1 et stage2 sont fichier de Grub Legacy et pad est un fichier de 750 octets (donc stage1 + stage2 + pad ont une taille de fichier de 102400 octets, soit 200 blocs, c'est pourquoi je démarre avec le noyau 200 + 9).

Enfin, je lance le noyau dans qemu:

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

Repository avec ce travail exemple: https://github.com/cirosantilli/x86-bare-metal-examples/tree/d217b180be4220a0b4a453f31275d38e697a99e0/multiboot/osdev –

Répondre

22

+1 pour la question agréable avec tous les détails, je vous remercie.

Au moins sur ma machine le produit kernel.bin sort que 4869 octets, ce qui correspond seulement dans 10 secteurs non 9. En outre, la mémoire de texte VGA est à 0xb8000 pas 0xb800 (plus d'un zéro - 0xb800 est le segment en mode réel, doit être multiplié par 16). Avec ces petits ajustements cela fonctionne bien ici.

+0

Wow, la question était avec 0xb800 ... Je pensais qu'il était suspendu mais ce n'était vraiment pas mettre le personnage au bon endroit dans la mémoire ... Bien que je suis encore confus au sujet de ce que cela signifiait alors: '<0x100000: 0x80: 0x4008> (mauvais)', puisque vous ne devriez pas être autorisé à avoir un segment en mémoire basse (si j'ai bien interprété la signification des nombres) ... – gsingh2011

+0

Et pour clarifier un peu pour les autres, ça démarre encore bien qu'il dise (mauvais). – gsingh2011

+2

Il est dit '(mauvais)' si vous ne chargez pas assez de secteurs. Cela peut encore fonctionner si rien d'important ne réside dans cette partie. Avez-vous essayé avec '200 + 10'? – Jester

Questions connexes