はじめに
ひさしぶりに30日でできる! OS自作入門を読み返しだした.
本ではフロッピーからOSを起動しているが,後々にUSBからOSを起動したいので,GRUBから自作OSの起動方法を調べてみた.
該当しそうな記事がいくつか見つかったので,参考に自分でも試してみた.
- Linuxをはじめよう!:1から創る自作OS 0x20
- GRUBからのブート方法,load.S,boot.cの作成
- Linuxをはじめよう!:1から創る自作OS 0x30
- Makefileの作成
- ももいろテクノロジー:GRUBで簡単なOSカーネルを動かしてみる
- ISOファイルの作成方法
- 0から作るOS開発 Grubその4 GRUBから自作OSを起動する
- VirtualBoxからISOファイルを開く方法
手元にある環境で試したので,開発環境は少し複雑で,自作OS開発はvagrant上のcentos 7で,自作OS(ISOファイル)の実行はホスト側(windows 10)のVirtual Boxで実施している.
作成手順
1. 自作OSのソースコードを作成する
GRUBから自作OSを起動するには,Multiboot Specificationの決まりに従って作成するとよいらしい.
1.1 multiboot.hをダウンロードする
https://www.gnu.org/software/grub/manual/multiboot/html_node/multiboot_002eh.html
作業フォルダのinclude/以下に保存する.
1.2 C言語を開始するためのアセンブラ部分を作成
#define ASM_FILE 1
#include "multiboot.h"
#define EXT_C(func) func
#define STACK_SIZE 0x4000
#define MULTIBOOT_HEADER_FLAGS 0x00000003
.text
.global start, _start
start:
_start:
jmp multiboot_entry
.align 4
multiboot_header:
.long MULTIBOOT_HEADER_MAGIC
.long MULTIBOOT_HEADER_FLAGS
.long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
multiboot_entry:
movl $(stack + STACK_SIZE), %esp
pushl $0
popf
pushl %ebx
pushl %eax
call EXT_C(cstart)
loop: hlt
jmp loop
.comm stack, STACK_SIZE
1.3 C言語の記述
#include "multiboot.h"
void cstart(unsigned long magic, unsigned long addr)
{
unsigned short *screen = (unsigned short *)0xb8000;
char *msg = "Starting MyOS!";
char ch;
char attr = 0x0f;
while (ch = *msg++) {
*screen++ = ((attr) << 8) | ch;
}
return;
}
(このあたりは,ほぼLinuxをはじめよう!:1から創る自作OS 0x20のまま)
2. コンパイルするためのMakefileを作成する
TARGET = myos.elf
CC = gcc
LN_S = ln -s
RANLIB = ranlib
INCLUDES = -I./include
FLAGS = -m32 -ffreestanding -fno-common -fno-builtin -fomit-frame-pointer -O2 -c
LD = ld -melf_i386 -Ttext=0x100000 --oformat elf32-i386 -o
.S.o:
${CC} ${INCLUDES} ${FLAGS} $<
.c.o:
${CC} ${INCLUDES} ${FLAGS} $<
BOOT_S = load.S
BOOT_C = boot.c
BOOT_OBJ=${BOOT_S:.S=.o} ${BOOT_C:.c=.o}
all: myos
myos: ${BOOT_OBJ}
${LD} ${TARGET} ${BOOT_OBJ}
${BOOT_OBJ}: ${BOOT_SRC}
clean::
-${RM} -f *~ *.lo *.o
(MakefileもほぼLinuxをはじめよう!:1から創る自作OS 0x30のまま)
$ make
を実行しelfファイルを作成する
3. 仮想マシンで動作確認をするためISOファイルを作成する
3.1 grub.cfgを作成する
set timeout=0
set default=0
menuentry "MyOS" {
multiboot /boot/myos.elf
boot
}
multiboot
ではなく,multiboot2 /boot/myos.elf
だと実行時にerror: no multiboot header found
エラーがでた.
3.2 ISOファイルを作成する
$ mkdir -p isofiles/boot/grub
$ cp grub.cfg isofiles/boot/grub/
$ cp myos.elf isofiles/boot/
$ grub2-mkrescue -o os.iso isofiles/
grub2-mkrescue
時に以下のエラーが発生した.
Your xorriso doesn't support '--grub2-mkrescue'. Some features are disabled. Please use xorriso 1.2.9 or later.
そこで,以下よりxorrisoをrpmでインストールした.
https://centos.pkgs.org/7/repoforge-x86_64/xorriso-1.3.6-1.el7.rf.x86_64.rpm.html
xorrisoの
rpm -Uvh
時に/usr/bin/wish is needed
といったパッケージの依存関係エラーがでた.
以下を参考にyumでtk/tclをインストールすると解消できた.
(参考)http://www.realgeek.com/forums/usr-bin-wish-339946.html
4. VirtualBoxからGRUBを起動し動作を確認する
VirtualBoxから作成したISOファイル(os.iso)を読み込み開く.
(参考)http://softwaretechnique.jp/OS_Development/Grub/grub02.html
GRUB起動後,MyOSを選択し,Starting MyOS!が表示されるのを確認した.