TL;DR
BIOS がブータブルディスクを見つけたときに実行されるコード。OS カーネルをメモリに読み込み、カーネルを動かせる状態に CPU を整えてから制御を渡す。
仕組み
BIOS はディスクを見つけると、その先頭 512 バイトに保存された実行可能コード、つまりブートローダに制御を移す。しかし、多くのブートローダは 512 バイトより大きい。そのため、512 バイトに収まる一次ブートローダと、それが読み込む二次ブートローダの 2 段階に分けることが多い。
ブートローダが行うことは、大きく次の 3 つである。
- ディスクから OS カーネルを見つけ出し、メモリに読み込む。
- CPU を 16 bit のリアルモードから 32 bit のプロテクトモードへ、さらに 64 bit のロングモードへ切り替える。16 bit 時代の古い OS にも対応するので、最初はリアルモードで動く。
- メモリマップなどの情報を BIOS から聞き出し、OS カーネルに渡す。
例
ブートローダの実装にはアセンブリが必要になる。そのため、Rust には、カーネルの前に自動でブートローダを置いてくれる bootimage のようなツールがある。ただし、bootimage は BIOS にしか対応しておらず、UEFI には対応していない。後述の Multiboot にも準拠していない。
1995 年には、Multiboot というブートローダの公開標準規格が策定された。Multiboot はブートローダと OS のインタフェースを定めており、Multiboot に準拠したブートローダは、準拠したすべての OS を読み込める。リファレンス実装は、Linux のブートローダのデファクトスタンダードである GNU GRUB である。OS カーネルを Multiboot に準拠させるには、カーネルファイルの先頭に Multiboot header を挿入するだけでよい。
注意点
Multiboot と GNU GRUB には、次の問題がある。
- 32 bit のプロテクトモードしかサポートしていない。64 bit のロングモードに切り替えるための CPU の設定は、カーネル側で行う必要がある。
- カーネルではなくブートローダがシンプルになるように設計されている。たとえば、カーネルを通常とは異なるデフォルトページサイズでリンクしないと、GNU GRUB は Multiboot header を見つけられない。また、カーネルに渡されるブート情報は抽象化されておらず、アーキテクチャに依存する構造を多く含む。
- どちらもドキュメントが充実していない。
- カーネルファイルからブータブルディスクのイメージを作るには、ホストシステムに GRUB がインストールされている必要がある。そのため、Mac や Windows 上で OS を開発するのが難しくなる。