grub読書がしたい1
前回までやってきたブート編を読んだ後でgrubも読みたくなったので,寄り道的な意味でgrub読書がしたいを開催.
ざっくりどういう動作をしているのかをメモ書き.まずはgrub-0.97からで.
Makefile.amにLDFLAGS = -nostdlib -Wl,-N,-Ttext,7C00と指定されている.
これはstage1のイメージファイルをビルドする時にリンカに与えるオプション.
-Ttext 7c00はリンカにこのコードは0x7c00からロードされ実行されることを伝える.
stage1.Sより
_start:は0x7c00にロードされる.いきなりafter_BPBにジャンプする.
というのも,この後で記述されているBPB(BIOS Parameter Block)をスキップするようにしているからである.
各種ヘッダ情報の領域の後でstage2のアドレスを0x8000と記述されている.
cliで割り込み禁止にする.
dlレジスタを検証,0x80であればHDDにインストールされていると認識する.そうでなければdlに0x80を代入している.
real_startにジャンプ
ds, ssを0クリア.stage1のスタックをセットし,stiで割り込みを許可する.
次に強制的にディスクの中身を参照できるかの検証をする.具体的にはboot_driveの中身をalに移し,フラグ検証をする.正しければdlにalを代入する.
もしフロッピーであればCHSモードへジャンプ.そうでなければLBAをサポートしているかの検証.ah=0x41,bx=0x55aaにしてint 0x13.
popしてpushしている.(?)これに失敗したらCHSモードへ移行.
LBAがサポートされていればLBAモードへ.LBA(Logical Block Addressing)は全てのセクタ番号に通し番号を割り振ってそれで指定する方法のことである.
lba_mode
LBAモードでstage2の準備をするラベル.最初のsiレジスタがもともとなんの値を示しているのかを調査する必要がある...
ecx = 0x10(si) 全セクタ数のセーブ
si = (Disk Address Packet)
Disk Address Packet(DAP)はHDDの読み書きやブロックの情報が入った構造体の名前である.
-1(si) = 1(non-zeroモードにしておく)?
(si) = 0x10(DAPのサイズ.元々0x10か0x18とされているらしい)
2(si) = 1(読み書きするブロック数)
8(si) = stage2_sector(HDD上の開始ブロック.stage2セクタの絶対アドレスの下位32bitを代入)
4(si):6(si) = 0000:STAGE1_BUFFERSEG(読み書き先の指定)
12(si) = 0
ah = 0x42; int 0x13(DAP情報を頼りにディスクからメモリにセクタを読む)
bx = STAGE1_BUFFERSEG
copy_bufferへジャンプ
copy_buffer
es = stage2_segment
汎用レジスタ全てとdsをpush(↓でcxとsi,dsを別に使うため退避)
cx = 0x100
ds = STAGE1_BUFFERSEG
si = di = 0
cldでsi, diをインクリメントさせるようにする
rep movswをする(movsってmov seg?)
これにより,ds:si → es:diへのコピーを行う.cx = 0x100(256)でword指定なのでつまり,STAGE1_BUFFERSEGにコピーされた1セクタ分のデータをstage2_segmentにコピーしている.
さきほど退避させたレジスタをpop
stage2_addressへジャンプ
その後ろで記述されているコードはエラー用のコードだったりなので今回は省略とした.
参考