GRUBを使い、ブートのコードを書かずにカーネルを起動させる。
カーネルの開発に必要なもの
1. 仮想マシンにGRUBを使っているOSを入れる
自分の場合は、ubuntu-jaを使っているので、仮想マシンにもubuntu-jaをいれた。
ubuntuのディスクイメージはhttp://www.ubuntulinux.jp/downloadからダウンロードできる。
vmplayerのディスクイメージの作成と、起動は次のようにすればいい。
qemu-img create -f vmdk ubuntu.vmdk 10G vmplayer ubuntu.vmx
ubuntu.vmx
ubuntu.vmxの設定ファイルはネットに色々のっているのでコピー&ペーストで作成した。
config.version = "8" ide0:0.present = "true" ide0:0.fileName = "ubuntu.vmdk" ide1:0.present = "true" # CD-ROMを利用はこっちのコメントを外す #ide1:0.fileName = "auto detect" #ide1:0.deviceType = "atapi-cdrom" # ISOイメージを利用する場合 ide1:0.fileName = "./ubuntu-ja-6.06-desktop-i386-20060805.iso" ide1:0.deviceType = "cdrom-image" floppy0.startConnected = "FALSE" floppy0.present = "TRUE" floppy0.fileName = "/dev/fd0" floppy0.deviceType = "file" # floppy-image ethernet0.present = "true" ethernet0.connectionType = "nat" guestOS = "otherlinux" displayName = "ubuntu-ja-6.06-desktop-i386-20060805" memsize = "256" ide0:0.redo = "" ethernet0.addressType = "generated" uuid.location = "56 4d 88 72 1c 10 4d 84-57 2a ed 07 a8 ff 36 d4" uuid.bios = "56 4d 88 72 1c 10 4d 84-57 2a ed 07 a8 ff 36 d4" usb.present = "TRUE" ethernet0.generatedAddress = "00:0c:29:ff:36:d4" ethernet0.generatedAddressOffset = "0" checkpoint.vmState = "" tools.remindInstall = "TRUE"
2. GRUBのコードを手に入れる。
下のサイトに詳しい情報が書いてある。
http://www.gnu.org/software/grub/grub-legacy-download.en.html
簡単にコードを手に入れたいなら、次のようにする。
cvs -z3 -d:pserver:anonymous@cvs.savannah.gnu.org:/sources/grub co grub
3. カーネル開発に必要なファイルをコピーする
適当なディレクトリを作成し、必要なファイルをコピーする。
mkdir example-kernel cp ./grub/docs/boot.S ./example-kernel cp ./grub/docs/kernel.c ./example-kernel cp ./grub/docs/multiboot.h ./example-kernel
4. コンパイル、インストール
GCC マニュアル抜粋
- -nostdinc
- ヘッダファイルのための標準のシステムディレクトリを検索しません。‘-I’オプションによって指定したディレクトリ (またはカレントディレクトリ) のみを検索します。‘-nostdinc’ と ‘-I-’を使用することにより、インクルードファイルの検索パスを明示的に指定したディレクトリのみに限定することが可能となります。
- -nostdlib
- リンク時に、標準のシステムライブラリとスタートアップファイルを使用しません。指定したファイルのみがリンカに渡されます。
- -fno-buitin
- ビルトイン関数のうち、2つのアンダースコアで始まるもの以外を認識しなくなります。現在、この指定は_exit, abort, abs, alloca, cos, exit, fabs, labs, memcmp, memcpy, sin, sqrt, strcmp, strcpy, strlen の関数に影響を及ぼします。
- -ffreestanding
- フリースタンディング実行環境 (freestanding environment) 用にコンパイルを行います。これにより、‘-fno-builtin’ オプションが有効になり、また、 main に特別な条件は不要とみなします。
LD マニュアル抜粋
- -Ttext org
- それぞれ出力ファイルの bss、data、text セグメントに対して org を開始アドレスにする。org は16進の整数でなければならない。
- -e entry
- entryをプログラムのエントリポイントを示すシンボルとして取り扱う (デフォルトのエントリポイントを上書きする)。デフォルトと他のエントリポイントの指定方法については ld の info の *Note Entry Point:: を参照すること。
cd example-kernel gcc -c -ffreestanding -nostdinc -nostdlib -I. boot.S gcc -c -ffreestanding -nostdinc -nostdlib -I. kernel.c ld -Ttext 0x100000 -e start -o kernel kernel.o boot.o
インストール
できればフロッピーを使わずにフロッピーのイメージを作り、そのイメージにカーネルを書き込めればよかったけど、やりかたがよくわからなかった。
フロッピーディスクを入れ、次のようにする。
fdformat /dev/fd0 # フォーマット mkfs -t ext2 /dev/fd0 # ext2 でファイルシステムを作成 mkdir /mnt/floppy # マウントする場所を作成 sudo mount -t ext2 /dev/fd0 /mnt/floppy # フロッピーをマウント cp kernel /mnt/floppy/ # インストール sudo umount /mnt/floppy # アンマウント
5. GRUBのメニューの編集
GRUBのメニューを編集することによって、ブート時にロードするカーネルを選ぶことができる。
仮想マシンを起動し、カーネルが起動できるようにGRUBを編集する。
/boot/grub/menu.lst に次のコードを追加する。
title Sample Kernel root (fd0) kernel /kernel savedefault boot
他の、savedefaultをコメントにする。
6. 起動
起動にはちょっと知らないといけいなことがある。
ubuntu.vmx のフロッピーの部分を見てほしい。
floppy0.startConnected = "FALSE" floppy0.present = "TRUE" floppy0.fileName = "/dev/fd0" floppy0.deviceType = "file" # floppy-image
最初フロッピーを入れながら起動すると、ブートディスクと勘違いされるので、フロッピーを利用不可にする(フロッピーのツールバーが×になっているはず)。