[英]Simple kernel won't boot in GRUB
I'm learning a bit of OS development from OSDev.org . 我正在从OSDev.org学习一些OS开发。 I have a kernel and I'm trying to boot in GRUB Legacy (0.97) using qemu.
我有一个内核,我正在尝试使用qemu在GRUB Legacy(0.97)中启动。 However, when I type
kernel 200+9
, I get the message 但是,当我输入
kernel 200+9
,我收到了消息
[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. 如果我现在键入
boot
GRUB就会挂起。
I think the numbers 0x100000, 0x44, 0x4008 stand for the .text segment start address, the .bss start address, and the .bss section size, respectively. 我认为数字0x100000,0x44,0x4008分别代表.text段起始地址,.bss起始地址和.bss段大小。 I think this because running
objdump -h
on the kernel image gives this output: 我认为这是因为在内核映像上运行
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
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.
问题是,而不是100044,.bss的开头只有44个。我认为这就是GRUB说错的原因。 I can't have a section below 1 MB in memory (low memory).
我的内存不足1 MB(低内存)。 But objdump is telling me my sections are above that threshold, so I don't know what's wrong.
但objdump告诉我我的部分超过了这个门槛,所以我不知道出了什么问题。 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.
虽然我的问题可能是非常基本的,如果你以前做过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;
}
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). 其中stage1和stage2是来自GRUB Legacy的文件,pad是任何750字节的文件(So stage1 + stage2 + pad的文件大小为102400字节,或200块,这就是我用内核200 + 9启动的原因)。
Finally, I run the kernel in qemu: 最后,我在qemu中运行内核:
qemu-system-x86_64 -fda floppy.img
+1 for nice question with all the details, thank you. +1以获得所有细节的好问题,谢谢。
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). 至少在我的机器上生成的
kernel.bin
是4869字节,只适合10个不是9的扇区。另外,VGA文本内存是0xb8000
而不是0xb800
( 0xb800
一个零 - 0xb800
是实模式段,必须乘以16)。 With those little adjustments it works fine here. 通过这些小调整,它在这里工作正常。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.