ブートローダーのお話
ブートローダーと聞いてみなさんはピンとくるでしょうか?
私はなんとなくは解っているけど、詳しくはよく知らない程度の認識でした。
いつもメインで使っているノートPCはLinux(Fedora15)とwindwosのデュアルブートで動いており、
しかし、このGRUBがどう動いているのかをまったく理解してない……
自分の使っているシステムなのに、動作をわかっていないのはどうなのか?
ってな感じで興味本位ですが、GRUBまたは、ブートローダーや、MBRについて調べてみました。
まず、ブートローダーとは何か?
ブートローダーとは、OSを起動するためのプログラムです。そのままです。
今回の例ではGRUBというブートローダがWindowsやLinuxのOSの起動を手助けするわけです。
ちなみに、ブートローダの種類としては、GRUBの他にもLILOやWindowsで使われているBootStrapLoaderなどがあります。
・BootStrapLoader (Windows)
次に、MBRについて調べてみます。
MBRとは?
MBRとは、マスター・ブート・レコード、ハードディスクの先頭、コンピューター起動時BIOSから呼びだされるプログラムが入っているところです。
先ほどでてきたブートローダというプログラムを格納しておく512Bの領域のことです。
なぜMBRのような領域が必要なのか?
PCの電源を入れてBIOSが起動した後に、OSは一人でにいきなり立ち上がることができません。
PCはメモリ上にある実行コードだけを実行することができます。
しかし、OSはHDDなどに格納されており、電源を入れた直後にはOSはメモリ上には存在しません。
PCのハードウェアだけではHDDに格納されているOSをメモリに読む込むような高度なことはできません。
ここで『オペレーティングシステムをメモリにロードするためには、オペレーティングシステムがメモリに存在していなければならない』というパラドックスが生じます。
このパラドックスの解決方法がこのMBRに入っているブートローダなのです。
BIOSはMBRという領域に入っている小さなプログラム(ブートローダ)を実行し、そのプログラムに次のプログラムを実行してもらい、最終的にOSを呼び出すような感じで多段階ブートしていきます。
GRUBはこのMBRの部分に格納されているブートローダです。正確にはstage1というブートプログラムが格納されています。
起動イメージとしては、
BIOS → MBR内のブートローダ(GRUB stage1) → 2次ブートローダ(GRUB stage2) → OS
って感じかな?
ではここからが本題。
GRUBとは?
GNU GRUB(GRand Unified Bootloader)はGNUにて開発されている高機能なブートローダ。
何が高機能なのか?
・ Multiboot Specification (マルチブート使用)
・ファイルシステムを理解できる
ふむふむ。マルチブート使用はなんとなく理解できる。
このGRUBというブートローダはLinuxやWindowsのように複数のOSを選んでブートすることができるということだよね。
次のファイルシステムを理解できる……
どうゆうこっちゃ!?
よくよく調べていくとLILOを理解するとGRUBのファイルシステムを理解できるというのが理解しやすい。変な言葉遊びみたいだ。
LILOもGRUBと同じようなLinux用のブートローダである。
LILOはブートイメージの保存場所をセクタ位置として認識している。GRUBはセクタ位置ではなくファイル名で読み込める。
ブートイメージの再構築やlilo.confなどの設定ファイルを書き換えた場合は、/sbin/liloコマンドで変更をLILOに通知しなければならない
例1:LILO起動
0x0000 0x1234
MBR(LILO) → ブートイメージ → 起動
例1を見てみる。ブートイメージは0x1234という場所にあるとする。
BIOSから実行されたLILOはブートイメージがある0x1234というセクタの場所を記録している。
この記録されている0x1234セクタの場所からイメージを読み込むのである。
したがって、ブートイメージを再構築したり、場所を変更した場合にはliloにその事を通知してあげなければOSをブートすることができなくなる。
例2:起動失敗
0x0000 0x1234 | 0x5678
MBR(LILO) → なし → ※エラー(ブートできない) | ブートイメージ
ブートイメージなどを再構築するとHDDのセクタの位置は変わってしまう。位置が変わった状態を例2で見てみる。
さきほどの例でliloコマンドを実行しないと、LILOはブートイメージの保存場所を0x1234のままだと思ってしまう、実際は0x5678に保存されている。
例2のようになっているとすると0x1234にはブートイメージがないのに、変更が通知されていないので0x1234を読みに行ってしまい、ブートイメージを読み込むことができない。軽い迷子ですな。
LILOは設定ファイルなどを変更するとliloコマンドで通知しなければいけないという手間がかかる。
liloコマンドを実行し忘れたら致命的…
で、これを踏まえた上でGRUBとLILOを比べてみる。今出てきたLILOを見てみればわかると思うが、LILOではファイルシステムを理解できていない。LILOはセクタの位置を記録しているだけだから。ファイルシステムを理解できていたら、カーネルの再構築やlilo.confの設定ファイルを置き換えてセクタ位置が変わってしまっても、ファイル名から起動ができるはずだからである。
……
ピンときましたでしょうか?
GRUBは設定ファイルを変更してもカーネルを再構築してもその変更後のセクタ位置などをGRUBに教えてあげなくても通常通りOSを起動することができる。
これはGRUBがファイルシステムを理解できているからこそセクタ位置などに関係なく実行できるわけです。
しかし、stage2の保存されているセクタの位置をstage1が記憶しているので、stage2のセクタ位置が変わってしまった場合はロードがうまくいかない。
これでGRUBの高機能のファイルシステムを理解できるがわかったと思います。
こんな回りくどく説明しなくても、普通にファイルシステムを理解できるんだろ?ってわかるのが普通かな?
私は理解できなかったので、理解できたときは頭に電球が付きました。
GRUBの動き
GRUBはインストールされると、MBRにstage1という512Byteのプログラムをコピーします。
/boot/grub/に実際のstage1ファイルが格納されています。
※stage1は全く同じファイルをコピーするのではなく、少し変更されたstage1がMBRに格納される。
変更される個所は、
・ 元々 MBR に記録されていた BPB とパーティション テーブルを反映する。
・ ブート ドライブの種別を記録する
・ /boot/grub/stage2 の先頭セクタ位置 (LBA) 情報を記録する。
PCの電源が立ち上がり、stage1がメモリにロードされると次にstage1からstage2がロードされる。
stage2からOSが起動されるという仕組みだ。
ファイルシステムを認識できるのはstage2であり、stage2がHDD内のmenu.lst(=>grub.conf)ファイルを見つけ出して、
grub.confファイルを読み込みOSの選択画面を表示させる。
stage1の構成
0000000 48eb 0090 0000 0000 0000 0000 0000 0000
0000010 0000 0000 0000 0000 0000 0000 0000 0000
*
0000030 0000 0000 0000 0000 0000 0000 0000 0203
0000040 00ff 8000 0001 0000 0800
[0203] GRUBバージョン
[8000] stage2をロードする番地
[00010000] stage2の先頭セクタ位置
[0800] stage2が使用するセグメント値
stage1の動作
BIOSによって0x07c00にロードされたstage1は以下の動作を行う。
1.stage1の先頭部分はジャンプ命令。メインとなるプログラムがある位置へジャンプ
2.指定BootDrive番号を参照し、0xff(無効ドライブ)でないことを確認。自分の無効ドライブになってない?
3.stage2の先頭512バイトをメモリの0x8000へロードする
4.stage2へジャンプし、制御をstage2へ渡す。
こっからstage2の動作も調べようと思ったのですが、まだ調べていません。
なので、詳細はインターネットで探すか、この後にstage2がOSを呼び出すんだなぁ、ってことにしといてください。
最後にMBRの 仕組みについて
MBRの構造は下記のようになっている。
ブートローダ(446)|パーティションテーブル(16*4)|シグネチャ(2) = 合計512byte
最初のブートローダ446バイトはもう何回も登場したGRUBなどのプログラムが入る。
次に出てくるパーティションテーブルは、HDD内のパーティションがブート可能な領域なのか?パーティションの開始位置はどこか?などのパーティション情報が入っている。
全部で4つあり、パーティションの制限が4つまでとなっているらしい。拡張パーティションを使えばもっと増やせるが。
最後のシグネチャーは0xaa55が入っている。この値が入っていないと正当なディスクと認められず起動できない。
パーティションテーブルの構造
bootflag(1)
パーティション開始位置[CHS](3)
パーティションタイプ(1)
パーティション終了位置[CHS](3)
パーティション開始位置[LBA](4)
パーティション層セクター数[LBA](4)
bootflagには0x00ブート不可-x80ブート可能のどちらかが入っている。
パーティションの位置が2種類あるが、CHS形式でのパーティションの位置とLBA形式の位置とがある。
現在はLBAのパーティション位置を参照する。CHSでは容量の問題がある。
パーティションタイプはどのOS・ファイルシステムが使用されているかを示す。
grub.conf
[参照サイト]
default=0
timeout=5
splashimage=(hd0,0)/grub/splash.xpm.gz
hiddenmenu
title Fedora (2.6.34.7-66.fc13.i686.PAE)
root (hd0,2)
kernel /vmlinuz-2.6.34.7-66.fc13.i686.PAE ro root=/dev/mapper/VolGroup-lv_root rd_LVM_LV=VolGroup/lv_root rd_LVM_LV=VolGroup/lv_swap rd_NO_LUKS rd_NO_MD rd_NO_DM LANG=ja_JP.UTF-8 KEYTABLE=jp106 rhgb quiet
initrd /initramfs-2.6.34.7-66.fc13.i686.PAE.img
title Windows XP
root (hd0,0)
chainloader +1
default=0:
制限時間後に、1番目のOSを起動させる。この例では、windowsXP
timeout=5:
制限時間。5秒でdefaultのOSを起動させる
splashimage=:
OS選択画面で表示させる背景画像
hiddenmenu:
メニューを表示させない
title:
OS選択画面上で表示される文字列
root:
どのパーティション上のOSか。
例:root(hd0,0) 1つ目のHDD内の最初のパーティション
kernel:
呼び出されるカーネル。 ro root=で、どのデバイスをルートディレクトリに指定するのか。
initrd:
[参照サイト]
RAM上に展開されるファイル
WindowsXPの欄にあるchainloader+1とは(hd0,0)のパーティションの先頭にある、
Wundows用のブートローダであるIPLを起動する。
後半かなり手抜きになった気がするけど疲れてしまったのでおしまいにします。
本当はもう少し書きたいこともあったのだが、頭があれで何も浮かんできません。
stage1のプログラム載せたり、アセンブラで書かれているstage1を解析がんばったり……
この記事で間違ってることや、他の情報がある方はコメントください。
参照サイトをリンクしとくので興味ある人はどうぞ。
↓↓他のサイトも↓↓。