* Bochs BIOS の動作などのまとめ [#h4808cf3] このページはBochsのBIOS(rombios.c)についてまとめたページです。~ 参考にしたバージョンは以下の通りです。~ $Id: rombios.c,v 1.160 2006/01/25 17:51:49 vruppert Exp $ * もくじ [#mab3844d] ただし、リンクは使用できません。URLに「#」がつくだけです。 #contents ---- ** EBDA (Extended BIOS Data Area) [#gea8ae43] BIOSが使用するデータバッファです。~ 最大でどのくらい使われるのか分かりませんが、大きくても40KB~63KBくらいでしょう。~ 640KBの低位メモリの高位(0x000A6000~0x000AFFFFなど)が使われます。~ -Bochs BIOSでは、1KBを確保しているようです。~ -Bochs BIOSを見ると、40:0Eh(0x0000040E)にセグメントが書き込まれているようです。~ --CD-ROMブート時に使用しているみたい? --int 74hのルーチンから使用しているみたい? -自由に使えるメモリの最大値はint 12hで確認する必要がある。 ~ ** CMOS RAM の意味 (Bochs用) [#aa96121b] |RAMアドレス|用途/意味|備考| |0x10|フロッピーディスクドライブのタイプ(high4bits:#0,low4bits:#1)|| |0x12|ハードディスクタイプ(high4bits:#0,low4bits:#1)|| |0x19|ハードディスク#0の拡張タイプ|2Fh(47)固定?| |0x1A|ハードディスク#1の拡張タイプ|| |0x1B~23|ハードディスクパラメータ#0|| |0x24~2C|ハードディスクパラメータ#1|| |0x2D|b5(0x20):CDブート非対応コンパイル時のブートシーケンス(=0:C,A/=1:A,C)|| |0x38|3rd(high4bits) boot device|[[値の意味はこちら>#cmos]]| |0x38|FDブート時のboot signature disableの値(bit0)|=0:enable,=1:disable| |0x39~3A|ATA driver: the translation policy is defined|| |0x3D|1st(high4bits)/2nd(low4bits) boot device|[[値の意味はこちら>#cmos]]| *** 1st/2nd/3rd boot device [#cmos] |値|意味| |0|デバイス未定義(終了?)| |1|フロッピーディスクドライブ #0| |2|ハードディスクドライブ #0| |3|CD-ROMドライブ| ~ ** Power On Boot時の一連の動作 [#f9fb0651] + F000:E05BhへFAR JMP + DMACの初期化 + CMOSのシャットダウンステータスによって分岐 + (==0なら:) 割り込みに禁止し + スタックの設定,BIOSコミュニケーションエリア(seg:0040h)の初期化 + biosメッセージの表示 + 割り込みベクタテーブルのゼロ初期化 + BIOSコミュニケーションエリアの初期値設定とベクタの設定 -- word [40:13h] = 639; + int 17,18,19,1C,12,11,15hベクタの設定 + EBDA setup? -- byte [#EBDA_SEG:0] = #EBDA_SIZE; -- word [40:0eh] = #EBDA_SEG; + PITの初期値設定(18.2Hz)とint 08hベクタの設定(1chは初期化済) + Keyboard(int 09,16hベクタの設定) + Keyboard関連のコミュニケーションエリアへの書き込み -- byte [40:17~19,71,97h], 0h; -- byte [40:96h], 10h; -- word [40:1a,1c,80h], 1eh; -- word [40:82h], 3eh; + キーボードの初期化処理 + ;; mov CMOS Equipment Byte to BDA Equipment Word -- ax = [40:10h]; al = 14h; outpb(70h, al); al = inp(71h); [40:10h] = ax; + パラレルポートのスキャン&設定(0378,0278h) + シリアルポートのスキャン&設定(03F8,02F8,03E8,02E8h) + CMOS/RTCのint 1A,4A,70hベクタを設定 + timer_tick_postの呼び出し + PS/2マウス,FPU,VIDEOBIOSのint 74,75,10hベクタを設定 + PICの初期化 -- マスクレジスタはマスタ:B8h,スレーブ:8Fhのようだ。 + PCIBIOSによるIOMEM/IRQSの初期化? + 外部ROMのスキャン&CRC検査&実行 -- VGABIOS.BINも実行されint 10hベクタが変更されビデオモード番号が03hに設定される? + ROMBIOS.Cのバナー表示 + フロッピーディスクの設定(CMOSから読み込んでコミュニケーションエリアに設定するだけ) -- byte [40:3e,3f,40,41,42,43,44,45,46,47,48,8bh], 0; -- CMOS(10h)の上位,下位4bitをチェックしてドライブが存在すれば[40:8f]の相当のビットを7に変更して書き込み -- byte [40:90,91,92,93,94,95], 0; -- al = 2h; outp (0ah, al); -- int 1e,40(int13_diskette?),0ehベクタの設定 -- ret + ハードディスクドライブの設定(CMOSから読み込んでパラメータをコピー?) -- outp(3f6h, 0ah); -- byte [40:74,77,8c,8d,8eh], 0; -- byte [40:75h], 1; byte [40:76h], c0h; -- int 13,76,41,46hベクタの設定 -- ;; move disk geometry data from CMOS to EBDA disk parameter table(s) -- CMOS(12h)の状態に従って分岐 -- 拡張タイプの時はCMOS(19,1ah)に従う(=47(user definable?)でないとHALT?) --- CMOS(1b~23,24~2ch)にユーザーパラメータ? -- ATA/ATAPIドライバの初期化と存在チェック + CDエミュレーションの初期化? + boot試行(int 19hの発行) ~ ---- ** int 19hの動作 [#k837fc7d] + int19_relocated: がint 19h;で呼ばれる + ds = 0; + 1st-3rd boot device をチェック(push 1~3;call _int19_fucntion;add sp,2;test ax,ax; jnz boot_setup;) -- 戻り値:bl = boot drive; ax = error (="0") or boot segment (exp:07C0h) -- すべてのdeviceでbootが失敗するとint18_handlerがnear jmpで呼ばれる(int 18hをフックしても…無効?orz) + どれかのboot deviceが認識されるとboot_setup:に実行が移行する(dl=device,ax=segment) + dl = bl(boot device); eax = eax(segment)<<4; [ret_ip], ax; eax = eax>>4; ax &= f000h; [ret_cs], ax; ax = 0; es = 0; bp = 0; ax = aa55h; iret(to IPL code); ~ ---- ** _int19_functionの動作 [#j782cd7e] -結局、やっていることは指定されたブート順番の時のデバイスから、ブートできる場合はブートセグメントに読み込んで、ドライブ番号とブートセグメントを返すだけ(cd-romブート時はまた別のfunctionを呼んでいる)。 -- ''nika'' SIZE(10){2006/08/10 (木) 21:04:34} -あれ、FDブート/HDブートの時はint 13hされるように見えるが、なぜかシングルステップ例外での監視時には検出されていないなぁ。int 19hの中でTFをクリアしているわけでも無いのになぁ。ってことはここがカギかな?。 -- ''nika'' SIZE(10){2006/08/10 (木) 21:19:22} -int 13hをフックしてみたが、もろに無視されてbootできてしまった。メッセージ表示するためだけにフックしてチェインしていたつもりだったが表示されなかったので、int 13hを実行したら即(もちろんcliで)hltを実行させるようにしても普通に起動され…。何故だろう…。何かが干渉でもしているのか・・・? -- ''nika'' SIZE(10){2006/08/11 (金) 00:19:11} #comment static int int19_function(char bseqhr); // リターン値: ax = BOOTセグメント, bl = ドライブ番号 Bit32u int19_function(bseqnr) Bit8u bseqnr; { Bit16u ebda_seg=read_word(0x0040,0x000E); Bit16u bootseq; Bit8u bootdrv; Bit8u bootcd; Bit8u bootchk; Bit16u bootseg; Bit16u status; Bit8u lastdrive=0; // BX_ELTORITO_BOOTをdefineしないでコンパイルした場合(古い方法) // CMOS(0x2D)のbit5をDLのbit7にロードする. // これはINT 13hの呼び出し時にセットされる(?) (0=フロッピーディスク A:, 0x80=HDD C:) // 0: ブートする順番はC:が最初でその後にA: // 1: ブートする順番はA:が最初でその後にC: // BX_ELTORITO_BOOTをdefineしてコンパイルした場合 // CMOS(0x3Dと0x38)の内容で以下のように指定する // CMOS(0x3D)の下位4bit : 1st boot device // CMOS(0x3D)の上位4bit : 2nd boot device // CMOS(0x38)の上位4bit : 3rd boot device // boot device の割り当て: // 0x00 : 未定義 // 0x01 : フロッピーディスク(A:) // 0x02 : ハードディスク(C:) // 0x03 : CD-ROM(D:) // その他 : ブート中断 // ブートデバイスの順番を取得 bootseq=inb_cmos(0x3d); bootseq|=((inb_cmos(0x38) & 0xf0) << 4); // bseqhrはboot device の順番(1st/2nd/3rd) if (bseqnr==2) bootseq >>= 4; if (bseqnr==3) bootseq >>= 8; if (bootseq<0x10) lastdrive = 1; bootdrv=0x00; bootcd=0; switch(bootseq & 0x0f) { case 0x01: bootdrv=0x00; bootcd=0; break; case 0x02: bootdrv=0x80; bootcd=0; break; case 0x03: bootdrv=0x00; bootcd=1; break; default: return 0x00000000; } // CDからブートすることができる場合 if (bootcd != 0) { status = cdrom_boot(); // 失敗した場合 if ( (status & 0x00ff) !=0 ) { print_cdromboot_failure(status); print_boot_failure(bootcd, bootdrv, 1, lastdrive); return 0x00000000; } // 成功した場合はセグメントとドライブ値を設定 bootseg = read_word(ebda_seg,&EbdaData->cdemu.load_segment); bootdrv = (Bit8u)(status>>8); } // ハードディスクかフロッピーディスクから起動する場合 if (bootcd == 0) { bootseg=0x07c0; ASM_START push bp mov bp, sp mov ax, #0x0000 mov _int19_function.status + 2[bp], ax mov dl, _int19_function.bootdrv + 2[bp] mov ax, _int19_function.bootseg + 2[bp] mov es, ax ;; segment ;; BootSegment:0x07c0 mov bx, #0x0000 ;; offset mov ah, #0x02 ;; function 2, read diskette sector mov al, #0x01 ;; read 1 sector mov ch, #0x00 ;; track 0 mov cl, #0x01 ;; sector 1 mov dh, #0x00 ;; head 0 int #0x13 ;; read sector ;; あれ? int13hを使ってる…orz jnc int19_load_done mov ax, #0x0001 mov _int19_function.status + 2[bp], ax int19_load_done: pop bp ASM_END // 失敗した場合 if (status != 0) { print_boot_failure(bootcd, bootdrv, 1, lastdrive); return 0x00000000; } } // CMOS(0x38)でフロッピーディスクブートが指定された場合のみ、signuatureをチェックする // bootchk = 1 : signature check disabled // bootchk = 0 : signature check enabled if (bootdrv != 0) bootchk = 0; else bootchk = inb_cmos(0x38) & 0x01; // CDブート時はsignatureチェックをしない if (bootcd != 0) bootchk = 1; if (bootchk == 0) { if (read_word(bootseg,0x1fe) != 0xaa55) { print_boot_failure(bootcd, bootdrv, 0, lastdrive); return 0x00000000; } } // 起動メッセージの表示 print_boot_device(bootcd, bootdrv); // リターン値としてブートセグメントを返す return (((Bit32u)bootdrv) << 16) + bootseg; } ** [#c03f658f] ''(書きかけ)'' ~ ~ ~ ---- * FDCのレジスタ [#jb063922] |IOアドレス(FDC#1/#2)|レジスタ名|読み書き|意味|備考| |3F0/370h|ステータスレジスタA|R||| |3F1/371h|ステータスレジスタB|R||| |3F2/372h|ディジタルアウトプットレジスタ|W||| |3F3/373h|テープドライブレジスタ|RW||| |3F4/374h|メインステータスレジスタ|R||| |3F4/374h|データレートセレクトレジスタ|W||| |3F5/375h|データレジスタ(FIFO)|RW||| |3F7/377h|ディジタルインプットレジスタ|R||| |3F7/377h|コンフィグレーションコントロールレジスタ|W||| ~ ~ ---- * こめんとらん [#h40440ee] #comment ----