i386 32 ビット用の非常に基本的なカーネルを作成しようとしています。JamesM のカーネル チュートリアルに従っています。私のカーネルコード自体は現在ほとんど何もしていません.私が苦労しているのは、私が選択した上位半分のフォーマットをgrubに正しくロードさせようとすることです.
それを行うためのアドバイスはこの回答で説明されており、私は上半身裸骨で大まかに作業しています。私のテスト環境は bochs で、grub フロッピー (0.97/legacy) を使用しています。
私が何をしようとしているのかを理解してもらうために、ほとんど何もしない非常に単純な「メイン」ルーチンを用意しました。
[section .text]
align 4
; setting up entry point for linker
start equ (start_vma - 0xBFF00000)
; entry point
start_vma:
push ebx
mov eax, 0xCCCCCCCC
hlt
この手法により、次のことが得られます。
bjdump -x kernel | grep "start"
start address 0x00100000
c0000000 g .text 00000000 start_vma
00100000 g .text 00000000 start
次に、リンカー スクリプトを使用して LMA (物理アドレス ロード ポイント) を 1MB に設定し、VMA を 3GB に設定しました。
OUTPUT_FORMAT(elf32-i386)
ENTRY(start)
KERNEL_MBOOT = 0x400;
KERNEL_VMA = 0xC0000000;
KERNEL_LMA_OFFSET = 0xBFF00000;
PHDRS
{
headers PT_PHDR PHDRS ;
mboot PT_LOAD FILEHDR ;
text PT_LOAD FILEHDR ;
data PT_LOAD ;
}
SECTIONS
{
. = KERNEL_MBOOT;
.mboot : AT(KERNEL_VMA - KERNEL_LMA_OFFSET)
{
*(.mboot)
} : mboot
. = KERNEL_VMA;
.text : AT(ADDR(.text)+ADDR(.mboot) - KERNEL_LMA_OFFSET)
{
code = .; _code = .; __code = .;*/
*(.text)
*(.rodata*)
} : text
.data ALIGN (0x1000) : AT(ADDR(.data) - KERNEL_LMA_OFFSET)
{
data = .; _data = .; __data = .;
*(.data)
*(.rodata)
} : data
.bss : AT(ADDR(.bss) - KERNEL_LMA_OFFSET)
{
bss = .; _bss = .; __bss = .;
*(.bss)
*(COMMON)
ebss = .;
} : data
end = .; _end = .; __end = .;
}
または、少なくともそう信じています。説明。確かに、これは私のオブジェクトにあるものです:
$ objdump -h kernel.bin
file format elf32-i386
Sections:
Idx Name Size VMA LMA File off Algn
0 .mboot 0000000c 00000400 00100000 00000400 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .text 0000002e c0000000 00100400 00001000 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
2 .data 00000001 c0001000 00101000 00002000 2**12
CONTENTS, ALLOC, LOAD, DATA
3 .bss 00004000 c0001020 00101020 00002001 2**5
ALLOC
この.mboot
セクションには、マルチブート ヘッダーのみが含まれます。実際、mbchk を実行すると、次のようになります。
kernel: The Multiboot header is found at the offset 1024.
kernel: Page alignment is turned on.
kernel: Memory information is turned on.
kernel: Address fields is turned off.
kernel: All checks passed.
全体として、これは有効なように見えますが、まったく何もしない elf カーネルを起動する必要があります。
ただし、実際には起動していません。代わりに、grub は次のように文句を言います。
エラー 28: 選択した項目がメモリに収まりません
x64 fedora で gcc 4.7.2 を使用してビルドしています。
CFLAGS=-nostdlib -fno-builtin -fno-stack-protector -ffreestanding -m32
LDFLAGS=-melf_i386 -Tlink.ld
link.ld
上記に含めたスクリプトはどこにありますか。
私の質問は、カーネルがメモリに収まるとgrubに信じ込ませるために、上記で何が間違っているのですか? 私が試してみました:
- VMA_OFFSET フィールドを変更して VMA を LMA と一致させます。つまり、すべてを 1MB の物理および仮想でロードします。違いはありません。つまり、同じエラーが発生します。
- LMA を 1MB 未満にします。grub エラー 7 を引き起こします: 予想どおり、1MB 未満をロードできません。
- お茶やコーヒーをガブガブ飲む。
これらのことはどれもうまくいきませんでした。明らかな何かが欠けているような気がしますが、それが何であるかはわかりません。
更新: grub マルチブート elf 行を見ると、次のようになります。
[Multiboot-elf, <0xffc00:0x40c:0x0>
重要なことに、この質問で紹介されている行のようなもの、つまりentry=
一部が必要です。
とにかく、私は初期化領域を提供することを検討しました:
[section .init]
; setting up entry point for linker
; entry point
start:
push ebx
mov eax, 0xCCCCCCCC
; jmp later
hlt
私は次のようにリンクしました:
.init : AT(ADDR(.mboot) + (KERNEL_VMA - KERNEL_LMA_OFFSET))
{
*(.init)
} : init
与えるには:
Idx Name Size VMA LMA File off Algn
1 .init 0000000c 00100000 00100400 00001000 2**0
これには約 1M の VMA/LMA があるため、これはロードされるはずですが、選択したアイテムがメモリに収まらないという苦情がまだあります。