3

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 があるため、これはロードされるはずですが、選択したアイテムがメモリに収まらないという苦情がまだあります。

4

2 に答える 2