2016/10/12

NetBSD/i386のMBRにパッチをあててみる

何度もエラーに遭遇しながら、ようやくUSB-HDDにNetBSD/i386 7.0.1をインストールできましたが起動してくれません。パーティション選択メニューが出ているところを見ると、少なくともNetBSD/i386が提供するMBRに制御は移っているようです。

NetBSD/i386のMBRのソースを読んでみることにしました。もしかすると起動しない原因が分かるかもしれません。まずNetBSDのcvswebで公開されているmbr.Sを入手します。FreeBSD/i386のmbrに比べると、条件アセンブルの指定が多いのでロジックを追いかけるときに注意する必要がありそうです。

ソースを読む時の心構えというほどのことでもありませんが、動作している状況を意識してからロジックを追うようにした方が早く内容を理解できると思います。これまでMBRの動作を見ている限りでは、次のようなロジックになっていると想像できます。
  1. パーティション選択メニューを表示する
  2. キー入力を待つ
  3. 選択されたパーティションのPBRに制御を移す
1番目の処理はラベルbootsel_menuで始まるあたりがそうだと思います。そして2番目はラベルwait_key付近がそうでしょう。そしてキー入力があったらラベルcheck_keyに飛ぶので、ここを詳しく読んでみます。
/*
 * We have a keycode, see what it means.
 * If we don't know we generate error '?' and go ask again
 */
check_key:
/*
 * F1-F10 -> boot disk 0-9. Check if the requested disk isn't above
 * the number of disks actually in the system as stored in 0:0475 by
 * the BIOS.
 * If we trust loc 475, we needn't check the upper bound on the keystroke
 * This is always sector 0, so always read using chs.
 */
    subb    $KEY_DISK1, %al
    cmpb    0x0475, %al
    jae    boot_ptn
    addb    $0x80, %al
    pop    %dx            /* dump saved drive # */
    push    %ax            /* replace with new */
#ifdef NO_CHS
    xorl    %ebp, %ebp        /* read sector number 0 */
    jmp    boot_lba
#else
    movw    $chs_zero, %si        /* chs read sector zero info */
    jmp    read_chs
#endif
入力されたスキャンコードを変換してBDA(BIOS Data Area)の0x0475の値と比較しています。何故このロジックが必要なのか不明ですが、比較結果に問題がなければラベルboot_ptnに飛び、(何かが?)問題ならラベルboot_lbaread_chsに制御が移るようです。

ここはNO_CHSの定義で条件アセンブルされていますが、どうもNO_CHSは未定義のようなのでラベルread_chsの方が使われているようです。これは従来のCHS形式でINT 13Hを呼び出すので「8GBの壁」問題を起こす可能性がありそうです。これはセクタ0を読んで制御を移す処理のようなので、PCの観察者からするとパーティション選択メニューが再表示されるように見えます。これは僕が体験したエラー情況と整合します。つまり問題はjae boot_ptnで分岐しなかったことにあると考えられます。いったい0x0475に格納されている値が何だったのか知りたいところですが、デバッグ環境が無いのでこれ以上の調査はできません。

あまり推奨できる方法ではありませんが、バイナリエディタHxDを使ってjae boot_ptnjmp boot_ptnに変更するパッチをあてて対処しようと思います。i386は条件分岐命令jaeが0x73で無条件分岐命令が0xEBなので、該当アドレスが見つかれば対応できます。NetBSD/i386の環境があればスマートに作業できると思うのですが、あまり環境が整っていないので泥臭い方法で対処しました。

HxDでセクタ0の16進ダンプを見ながらmbr.Sを参照しつつハンド逆アセンブルして該当アドレスを見つけました。アドレスが分かれば変更するのは1バイトだけなので、すぐに出来ます。こういう荒業は何が起きるか分からないので注意に注意を重ねて実行しなければなりません。今回はUSB-HDDが潰れても別に構わないので、多少心理的負担は少なくてすみました。

いよいよパッチをあてたUSB-HDDをdynabook SS SX/15Aに接続して電源を入れてみます。今度こそ上手くいって欲しいものです。ここしばらくは、上手くいって欲しいと願いながら電源を入れて、エラーがでたりすることが多かったので、だんだん疲れてきました。

0 件のコメント:

コメントを投稿