GRUBからカーネルを起動する

Multiboot Specification(マルチブート仕様)について

GRUB(Grand Unified Bootloader)は、「Multiboot Specification」に準拠したブートローダーです。

Multiboot Specificationとは、ブートローダーとOS間のインターフェースを規定するものであり、自作OS(または自作カーネル)をMultiboot Specificationに準拠させることで、GRUBから自作OSを起動することが可能となります。

参考:Multiboot Specification version 0.6.95


自作OS(自作カーネル)をMultiboot Specificationに準拠させる。

ここでは、最小構成のカーネルとして以下のファイルを用意します。


multiboot.h
loader.S 
kernel.c
Makefile

マルチブートヘッダの作成する。

マルチブート用のヘッダーファイル「multiboot.h」を作成します。


$ cat multiboot.h 
#define MULTIBOOT_HEADER_MAGIC          0x1BADB002
#define MULTIBOOT_HEADER_FLAGS          0x00000000
#define MULTIBOOT_HEADER_CHECKSUM       -(MULTIBOOT_HEADER_MAGIC+MULTIBOOT_HEADER_FLAGS)
#define KERNEL_STACK_SIZE               0x100000

カーネルローダに適用する。

カーネルのファイル先頭部分(カーネルローダ)をMultiboot Specificationに準拠させます。


$ cat loader.S 
#include "multiboot.h"

.text
.code32                 /* 32bit-protectmode */
.intel_syntax noprefix  /* Intel-style, not use AT&T-style */

.global _start
_start:
        jmp entry
        .align 4
        .long MULTIBOOT_HEADER_MAGIC
        .long MULTIBOOT_HEADER_FLAGS
        .long MULTIBOOT_HEADER_CHECKSUM

entry:
        push    ebx   /* push multiboot_info structure pointer */
        push    eax   /* push MBOOT_HEADER_MAGIC */
        jmp     main  /* jmp kernel main */

自作OS(自作カーネル)を用意する。

ここでは、文字列を出力するだけのカーネルを用意しています。


$ cat kernel.c 
#include "multiboot.h"

void
main(void)
{
    unsigned short *screen = (unsigned short *)0xB8000;
    char *msg = "Start kernel!";
    char ch; 
    
    while((ch=*msg++))
        *screen++ = ((0x0F)<<8) | ch;

    while(1);
}

Makefileの作成

カーネルを「elf形式」で作成して、「0x100000」に配置する必要があります。


$ cat Makefile 
CC     = gcc
CFLAGS = -pipe -ffreestanding -fno-common -fno-builtin \
         -fomit-frame-pointer -Os -Wall -c
LD     = ld -nostdlib --oformat binary

all: kernel.elf

kernel.elf: kernel.o loader.o
        $(LD) -Ttext=0x100000 --oformat elf32-i386 -o kernel.elf \
        loader.o kernel.o

loader.o: loader.S
        $(CC) $(CFLAGS) -o loader.o loader.S

%.o: %.c
        $(CC) $(CFLAGS) -masm=intel $*.c

.PHONY: clean
clean:
        rm -f *.o
        rm -f *.elf

以上の作業が完了した後、makeコマンドを実行して「kernel.elf」を作成します。


GRUBブートイメージに自作OSを導入する。

イメージファイル(GRUBブートフロッピーの作成)に自作OSを配置して、GRUBから起動できるように設定します。


grub.conf(memu.lst)について

GRUBの起動設定はgrub.conf(またはmemu.lst)で行います。

なお、VineLinuxやCentOSのGRUBでは、grub.confのみ参照しているようです。

念のため、grub.confとmenu.lstを両方用意しておきます


$ cat grub.conf
# デフォルト起動メニュー 
default=0
# メニュー選択タイムアウト
timeout=0

# booting menu
title osname
root (fd0)
kernel /kernel.elf
boot

イメージファイルに配置する。

イメージファイルをマウントして、自作OSとGRUB設定ファイルを配置します。


$ mkdir floppy
# sudo mount -t vfat -o loop fd.img ./floppy
# sudo cp kernel.elf ./floppy/.
# sudo cp grub.conf ./floppy/boot/grub/grub.conf
# sudo cp grub.conf ./floppy/boot/grub/menu.lst
# sudo umount ./floppy

以上で作成した「fd.img」をVirtualBoxなどの仮想化ソフトウェアから起動すると、自作OSを起動させることができます。


関連ページ