繁体   English   中英

简单内核无法在GRUB中启动

[英]Simple kernel won't boot in GRUB

我正在从OSDev.org学习一些OS开发。 我有一个内核,我正在尝试使用qemu在GRUB Legacy(0.97)中启动。 但是,当我输入kernel 200+9 ,我收到了消息

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

这是我所期望的,除了(坏)部分。 如果我现在键入boot GRUB就会挂起。

我认为数字0x100000,0x44,0x4008分别代表.text段起始地址,.bss起始地址和.bss段大小。 我认为这是因为在内核映像上运行objdump -h会产生以下结果:

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

所以你可以看到我提到的数字几乎匹配。 问题是,而不是100044,.bss的开头只有44个。我认为这就是GRUB说错的原因。 我的内存不足1 MB(低内存)。 但objdump告诉我我的部分超过了这个门槛,所以我不知道出了什么问题。 无论如何,我会在下面粘贴我的代码,它相对较短。 虽然我的问题可能是非常基本的,如果你以前做过OS开发,所以代码可能是无关紧要的。

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

下面是我的自定义链接器脚本:

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

最后,我用以下几行构建内核:

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

其中stage1和stage2是来自GRUB Legacy的文件,pad是任何750字节的文件(So stage1 + stage2 + pad的文件大小为102400字节,或200块,这就是我用内核200 + 9启动的原因)。

最后,我在qemu中运行内核:

qemu-system-x86_64 -fda floppy.img

+1以获得所有细节的好问题,谢谢。

至少在我的机器上生成的kernel.bin是4869字节,只适合10个不是9的扇区。另外,VGA文本内存是0xb8000而不是0xb8000xb800一个零 - 0xb800是实模式段,必须乘以16)。 通过这些小调整,它在这里工作正常。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM