grub読書がしたい2
grub読書,前回はMBRに格納されているはずのstage1部分を読んで,stage2にジャンプするところに至った.今回はその続きから.
stage2_address(つまり0x8000)はstart.Sから.スタックやレジスタは前回から引き継いでいる状態になる.
dxを退避させてドライブ情報をセーブする
"Loading stage2"を出力
di = firstlist - 8(BOOTSEC_LISTSIZE)?(bootloopの準備)
ebp = (di)(第2セクタのセクタ番号をセーブ)
bootloop
4(di)を見て,読むべきセクタ数を確認する.0であればこれ以上はないとしてbootitにジャンプ.まだ読むべきセクタがある判定になったらそのまま下に続いていく.
-1(si) != 0ならLBAで読みにいく.(-1(si)はstage1で謎に1をセットしていたところが関与していそう)
===== ちょっとどういうことか理解できてないエリア =====
ebx = (di)(論理セクタのスタート位置をロード?)
al = 0x7f(Phoenix EDDにより最大値は0x7fに制限されている)
4(di) > 0x7f であれば ax = 4(di)(全セクタ数と比較している)
4(di) - ax
(di) + eax(論理セクタスタートに足す)
===== =====
bootit
改行を出力し,dxにpush.(dlにはブートするドライブが入っているはず)
stage1.5が定義されてたら0x2200(stage1.5のmain)に,そうでなければ0x8200(stage2のmain)にジャンプ
main in stage2.asm.Sに記述.
ljmpでcodestartにジャンプ.この時点ではまだリアルモードになっている.割り込みの禁止を行う.
ds = ss = es = 0
ebp = esp = STACKSEG(0x2000 - 0x10)(リアルモード/BIOSスタックの設定)
割り込みの許可
real_to_prot(プロテクトモードへの移行)
割り込みの禁止
GDTレジスタの読み込み
cr0 | 0x1でプロテクトモードにする
プロテクトセグメント(protcseg)へljmp
protcseg
ds = es = fs = gs = ss = PROT_MODE_DSEG(セグメントレジスタへのリロード)
STACKSEG = (esp)(リターンアドレスをSTACKSEGに設置する)
esp = ebp = protstack
(esp) = STACKOFF(さきほど設定したリターンアドレスを設置する)
ret
.code32
bss領域を0クリアする(具体的にはbssの最初と最後を読み込んで差分の分だけrep stosbをする)
init_bios_infoへcall(ここからCコードになる)
init_bios_info in common.c
mbi.mem_lower = get_memsize(0)
mbi.mem_upper = get_memsize(1)
ここでのmbiはMultiBoot Infoの構造体の略称.get_memsizeはgrub/asmstub.cに記載.
0の時には640 * 1024,それ以外の時には3 * 1024 * 1024(3MB)
boot_driveとinstall_partitionを保存
ディスク情報を取りに行き,cdrom_driveをboot_driveにする.(CDROMドライブと書いてあるけれど...)
cmainへ