次に問題となるのが、BIOS である。Ultra 100 と FastTrak 100 とでは、ROM に書かれている BIOS が全く違うので、変身させる際には書き換えてやらなければならない。しかし、いま相手にしているものはオンボードであるため、BIOS が拡張カード版のように独立した ROM に書かれているわけではなく、マザーボードの BIOS に組み込まれてしまっている。従って、ちょっと工夫しないと書き換えられない。ASUS のマザーボードで使用されている AWARD の BIOS については、
AWARD BIOS を解析する に解析結果をまとめて解説したので、詳しくはそちらを参照されたい。この中の u100b20.bin というファイル(BIOS の リビジョンにより、枝番が異なる)が、Ultra 100 の BIOS である。基本的には、
これをどこかから落としてきた FastTrak の BIOS に差し替えれば良いわけだ。BIOS の構造は、事前に詳しく解析しておいたので、早い話がそれだけのこと・・・で済むはずだった。
ところが、単に差し替えただけでは読み込まれすらしない。原因を突き止めるまでに随分と苦労したのだが、分かってしまえば非常に単純でアホ臭いことだった。Ultra 100 で使用される BIOS の ROM イメージのサイズは 16kB であるのに対し、FastTrak 100 で使用される BIOS の ROM イメージのサイズは、64kB である。A7V の AWARD BIOS では、stn.bin というファイル名で ROM に格納されている System BIOS 部分が Ultra 100 の BIOS を読み込んでいるのだが、このときに ROM イメージのサイズを 16bit のレジスタで計算していたため、64kB の イメージを正しく処理できていなかったのだ。まずは、これを修正しないとどうにもならない。
拡張カードに搭載される ROM イメージの構造について簡単に説明すると、ROM イメージの先頭は 0x55 0xaa というバイト列で始まらなければならず、また ROM イメージの 3 バイト目は、
ROM イメージのサイズを 512 で割った数字でなければならないことになっている(64KB なら、0x80)。さらに、byte 単位で総和を取ったとき、結果がゼロにならないといけないというチェックサムの決まりもある。これらをチェックするのは System BIOS の仕事であり、そのために以下のようなコードがあった(なお、リストのアドレスは、A7v1003.awd の stn.bin の先頭を 0000:0000 として出したものだ。より新しいリビジョンでも問題となる部分のコードは変わっていないようだが、アドレスがずれているので注意)。
チェックサム計算ルーチン
0000:d666 | 8a 0e 02 00 | mov | cl,[0002] |
0000:d66a | 32 ed | xor | ch,ch |
0000:d66c | c1 e1 09 | shl | cx,09 |
0000:d66f | 32 c0 | xor | al,al |
0000:d671 | 02 04 | add | al,[si] |
0000:d673 | 46 | inc | si |
0000:d674 | e2 fb | loop | d671 |
0000:d676 | 3c 00 | cmp | al,00 |
0000:d678 | 75 03 | jnz | d67d |
0000:d67a | f8 | clc | |
0000:d67b | eb 01 | jmp | d67e |
0000:d67d | f9 | stc | |
|
−修正→
|
修正後
0000:d666 | 8a 0e 02 00 | mov | cl,[0002] |
0000:d66a | eb 0e | jmp | d67a |
0000:d66c | c1 e1 09 | shl | cx,09 |
0000:d66f | 32 c0 | xor | al,al |
0000:d671 | 02 04 | add | al,[si] |
0000:d673 | 46 | inc | si |
0000:d674 | e2 fb | loop | d671 |
0000:d676 | 3c 00 | cmp | al,00 |
0000:d678 | 75 03 | jnz | d67d |
0000:d67a | f8 | clc | |
0000:d67b | eb 01 | jmp | d67e |
0000:d67d | f9 | stc | |
|
赤色で記した命令で、CL に格納された ROM イメージの 3 バイト目(=イメージのサイズを 512 で割ったもの)を 9 ビット左にシフトし、512 倍して ROM イメージのサイズを計算していることが分かる。ところが、64kB のイメージが入ってきた場合には 0x80 を 512倍することになり、その結果が 0x10000 になるため、16bit レジスタである CX で演算を行った場合には 0x0000 が格納されてしまう。従って、チェックサムの検査が正しく行われず、FastTrak の BIOS は不正なものと判断されて破棄されてしまっていたわけだ。律儀に修正するのも面倒だし、あまり意味がないので、チェックサムの計算は省くようにして回避した。
このルーチン以外にも ROM イメージのサイズを 16bit レジスタで計算しているところを発見した。こちらは ROM イメージのサイズそのものを得るための重要な部分なので、ごまかしで回避するわけにもいかず、32bit レジスタで計算するように書き直した。ただ、コードのバイト数が変わるとジャンプ先アドレスの再計算が面倒なので、修正後も結果的に命令長が同じになるよう注意しながら書き換えるのだ。先頭では EDX を XOR でゼロ化し、32bit で計算しようというそぶりを見せながらも、いざ肝心なところでは 16bit で計算するという何とも意地悪なコードだ。ゼロ拡張付きの mov である movzx 命令に 32bit バレルシフタと、80386 様々である(あ、脳味噌は AMD なんだけどね)。
サイズ計算ルーチン
0000:d5e0 | 66 33 d2 | xor | edx,edx |
0000:d5e3 | 26 8a 16 02 00 | mov | dl,es:[0002] |
0000:d5e8 | c1 e2 09 | shl | dx,09 |
|
−修正→
|
修正後
0000:d5e0 | 26 66 0f b6 16 02 00 | movzx | edx,es:[0002] |
0000:d5e7 | 66 c1 e2 09 | shl | edx,09 |
|
逆アセンブラなどを使用しないで簡易的に改造するのであれば、まず A7V の BIOS から stn.bin だけを取り出し、そしてバイナリエディタなどで開いて問題のバイト列を検索すれば、修正すべき個所が見つかるだろう。その部分をガリガリと書き換えてしまえば良い(でも、間違ったところを書き換えたり、書き換えが間違っていると必ず立ち上がらなくなるので、くれぐれも慎重に!)。
これで、System BIOS が FastTrak 100 の BIOS を読み込んでくれるようになった。しかし、今度は起動時に「No FastTrak Controller Found」と出て、FastTrak 100 が存在しないことになってしまう。やはりというか、一筋縄ではいってくれない可愛くないヤツだ。
しかし、これもまた分かれば簡単なことだった。拡張カード版の FastTrak 100 は、Plug and Play の Device ID が
0x4d30 であるのに対し、オンボードの FastTrak 100 は、Device ID が
0x0d30 になっている。当然、どこかから落としてきた BIOS では 0x4d30 という Device ID を持ったデバイスの存在を期待しているため、そのままでは Plug and Play の処理において 0x0d30 という Device ID を持つ FastTrak 100 の存在を検出することができないのだ。これは、
FastTrak 100 の BIOS 中に現れる 0x4d30 を、全てバイナリエディタで 0x0d30 に書き換えてしまえば回避可能である。チェックサムの再計算は不要だ、さきほど省いてしまったから。
結果論を叙述的に記せばそれだけのことだが、ここに至るまでの血の滲むような解析作業と実験の末、