起動するまでの長い道のり IPL篇(1) ディスクイメージ作成の巻
PC/ATマシンで動くOSを作る場合、PC/ATでのOS起動規格に則ってブートセクタ等を用意しなければならない。
マシンはどうやってOSを起動するか
まっさらなマシンにWindowsとかLinuxとかのインストールCDを入れて起動すると、CDがガリガリ読み込まれてインストール画面が出る。だが、まっさらなマシンに他のソフトのCDを入れて起動すると「No operating system」とかメッセージが出てそのまま止まってしまう。たとえインストールCDのファイルを別のCDに全部コピーしても、その不正コピーCDではインストール画面が立ち上がらない。上記のことはフロッピーディスクにも当てはまる。起動できるディスクと起動できないディスクがあるのだ。
起動できるディスクには、ブートセクタ(IPL)と呼ばれる領域がディスクの先頭にある。マシン(BIOS)は、接続されているFDDやHDDにブートセクタを持つディスクが入っているか確かめ、見つかればメモリに読み込んで実行する。ドライブを検索する順序は大抵フロッピー→ハードディスク→CDになっていて、普段はハードディスクにあるOSが起動される。(BIOSの設定によって順序を変えられたりもする)
IPLを作るには
IPLは、FDなどを普通にフォーマットしてファイルをコピーしても作れない。ファイルという概念は、実はファイルシステムという仕組みの上に実現されている。身近にある「本」で例えれば、ファイルは目次と見出しを付けられた章のようなものだ。
BIOSは、起動できるかどうか判断するのに本の中身(ファイル)を見ない。表紙だけを見る。エクスプローラ等では、普通、本(ディスク)の表紙までは操作できない。表紙に何かを書き込む場合には特別なツールや作業が必要となる。
IPLを作るためには恐怖のアセンブラを使う必要がある。さらに、ファイルシステムを考慮しないで「表紙」に書き込むためのdd(GNU binutilsに付属)というツールを使う。
IPLを作る
さて実際にIPLを作ってみる。IPLを作る手順は以下の通り。カッコ内は使用するツールだ。
以上の手順でいわゆる「起動ディスク」が出来上がる。今回はqemuでその起動ディスクから起動してみることにする。(なので、実際のディスクを使わずにディスクイメージファイルを作る。フロッピーを買いに走ったりしなくて良い)
以下、順を追って説明する。
コードを書く
いよいよコーディングらしいことをする。エディタでアセンブラのソースファイルを書くのだ。とりあえず以下のような内容を書き、ipl.sというファイル名で保存する。(別の名前でも良いが、日本語だけは止めておいた方が良いと思う)
それぞれのコードの意味は後日明らかになると思うので今はとにかくこれをこのまま書こう。
なお、アセンブラにはgas(GNU as)を使う。nasmが良いとかいうわがままな人は自分で頑張ろう。
# ipl.s # generate real mode code .code16 jmp begin nop # BPB name: .ascii "Name " sector_size: .word 0x0200 cluster_size: .byte 0x01 fat_pos: .word 0x0001 fat_cnt: .byte 0x02 root_size: .word 0x00e0 sector_cnt: .word 0x0b40 media_type: .byte 0xf0 fat_size: .word 0x0009 sector_cnt_pt: .word 0x0012 head_cnt: .word 0x0002 bpb_pos: .long 0x0000 sector_cnt_l: .long 0x00000b40 drive_no: .byte 0x00 reserved: .byte 0x00 ext_boot_code: .byte 0x29 volume_serial: .long 0xffffffff disk_name: .ascii "DISK " fat_name: .ascii "FAT12 " # boot begin begin: # infinite loop jmp begin # boot signature. . = 510 .short 0xaa55
アセンブルする
Cygwinシェルを起動して、ipl.sのあるディレクトリに移動し、asでアセンブルする。(Cygwinをまだインストールしていない人は、しよう)
$ as -o ipl.o ipl.s
するとipl.oというファイルができる。
バイナリ形式に変換する
諸般の事情により、アセンブルしたオブジェクトファイル(ipl.o)はまだ実行可能形式ではない。複数のオブジェクトファイルをまとめたりする場合のための情報が混じっている。これを純粋な実行コードだけの形式にしなければならない。そのためにobjcopyという変換ツールを使う。
$ objcopy -S -O binary ipl.o ipl.bin
これでipl.binというファイルができる。(因みにbinとはbinaryの略だ)
ディスクに書き出す
上記のipl.binが実際に実行されるコードになるのだが、これをエクスプローラ等でフロッピーにコピーしても起動時に実行されない。先述のようにディスクの「表紙」に書かなければならない。ddというツールを用いれば表紙に書き込める。
$ dd if=/dev/zero of=fd.img count=2880 $ dd if=ipl.bin of=fd.img conv=notrunc
1行目が空のディスクイメージ作成のためのコマンドで、2行目がIPLをディスクイメージ先頭に書き込むコマンドだ。これでfd.imgというフロッピーのディスクイメージができる。
実行する
fd.imgをqemu上の仮想マシンに挿入して実行する。(まだqemuをダウンロードしていない場合は、しよう)
IPLを作成した同じディレクトリにqemuのディレクトリがあると見なして説明する。もし別の場所にqemuがある場合は、qemuのパスの部分を読み替えて欲しい。
$ ./qemu/qemu.exe -L ./qemu -m 128 -fda fd.img
これでメモリ128Mのマシンの1番目のFDD(fda)にディスク(fd.img)を挿入して起動するというコマンドになる。
起動してきたqemuのウィンドウに「FATAL: Not a bootable disk」というエラーメッセージが出なければ成功だ。
ちなみに、qemuのウィンドウ内でマウスをクリックしたりするとカーソルが消滅して操作できなくなったりする。その場合は、qemuのウィンドウタイトルに書かれている通りCTRLキーとALTキーを同時押しすると再びカーソルが出てきて操作可能になる。