GRUB/98 (PC-9800 シリーズのための GRUB)

GRUB/98 は、もともと IBM PC 互換機用に作られたブートローダである GRUB (GRand Unified Bootloader) を、 NEC PC-9800 シリーズ (Epson などの互換機も含む、以下単に 98 と表記します) 上で動作するよう移植したものです。

このドキュメントでは主に移植にあたって GRUB の内部構造に加えた変更点について記述しています。 オリジナルの GRUB のドキュメントも随時参照ください。

全般的な事柄

まず基本的に、 IBM PC と 98 では BIOS の仕様が全然違います (INT 命令を 使う点では共通ですが)。このため、特に BIOS を直接呼び出す部分 (stage1、shared_src/asm.S) はほとんどすべて書き換えています。

98 は IBM PC 互換機の世界とは異なり、I/Oポートの配置や BIOS のワークエリアが 比較的固定されています (ほとんど一社から出ていたので、当然といえば当然です)。 したがって、 GRUB/98 でもオリジナルでは BIOS を呼び出しているのを、 I/Oポートを直接アクセスしたりワークエリアを直接参照するコードで置き換えている ところがあります。

GRUB/98 では、文字表示まわりやディスクまわりなどで処理が複雑になり、 コードサイズが肥大化しがちになっていますので、これを少しでも抑えるため 随所に工夫 (?) を凝らしています。

文字表示関係

IBM PC の BIOS には、テキスト画面に文字を出力するための BIOS (INT 10h ファンクション 01h) がありますが、 98 にはこれに相当する BIOS はありません。 GRUB/98 ではテキストVRAMに文字コードを書き込むルーチンを 自前で用意することで対応しています (putchar() <shared_src/asm.S>)。このルーチンはオリジナルの putchar() と互換性を保っていますが、 この他に 98 のハードウェアを活かすべく漢字表示にも対応させています。 漢字コードは基本的に EUC-JP を使用しており、 SS2 を使用した半角片仮名の表示、 98 固有の 2バイト半角文字にも対応しています。また 2バイト文字を表示する際にも putchar() には1バイトずつ順に渡していけばよいようにしています。 さらにこのルーチンの動作を指定する次のような外部変数を定義しています (これらはすべて unsigned char 型です)。

putchar_x, putchar_y
それぞれ文字表示位置の桁位置、行位置です。 いずれも0にすると画面左上隅になります。
putchar_attribute
文字をテキストVRAMに表示する際にアトリビュート領域に書き込む値です。 初期値は 0xE1 (白、反転・下線・反転なし) です。
putchar_flags
次の記号定数のビットORです。
PUTCHAR_SJIS
これを指定すると、 putchar() は漢字コードとして EUC-JP ではなくシフトJIS を認識するようになります。
PUTCHAR_XZENKAKU
これを指定すると、 putchar() は全角文字を表示しなく なります (全角文字のコードを与えても何も表示しません)。メニュー画面で 表示領域右端で表示を切るために使います。
putchar_save
2バイト文字の1バイト目を保存する領域です。ここが 0 でないと putchar() は次に渡される文字を (それが正しいか否かに関らず) 2バイト目の文字として扱います。

このように putchar() が明確に定義された外部変数を使うことから、 98 では gotoxy()getxy() はこれらの変数を操作する マクロにしています。

メモリ関係

これも、 IBM PC の INT 12h のようにメモリサイズを取得するBIOSが 98にはありません。 98 ではBIOSのワークエリアを参照することによって メモリサイズを取得しています (get_memsize() <shared_src/common.c>)。

98 では、物理メモリ空間のアドレス 0x00F00000 〜 0x01000000 (15MB 〜 16MB) にメモリがないことがあります。セットアップメニューでは「16MBシステム空間」 と表現されていますが、簡単に言えばこの領域にはVRAMなどが割り当てられており 通常の用途には使えません。 GRUB では、アドレス 0x00100000 (1MB) から始まる 連続したメモリ空間のサイズを upper memory としていますので、 「16MBシステム空間」を「使用する」に設定している場合は、 16MB 以上メモリを塔載していても「14336K upper momory」と 表示されます (「使用しない」に設定している場合は、塔載している全メモリの 容量が表示されます)。

なお IBM PC でも、物理メモリ空間の一部にグラフィックメモリやメモリマップド I/O のための「穴」があることがあり (GRUB のドキュメントでは ``chipset hole'' と呼ばれています)、オリジナルの GRUB でもこれに対応しています (GRUB/98 は この機構を利用しています)。

オリジナルの GRUB は BIOS のワークエリアとして 0x00000000 〜 0x00000FFF (0KB 〜 4KB) を確保していますが、 98 では BIOS のワークエリアは 0x00000000 〜 0x000005FF (0KB 〜 1.5KB) となっています。 GRUB/98 では 0x00000600 〜 0x00000FFF (1.5KB 〜 4KB) の領域をディスクのジオメトリの キャッシュやパーティションテーブルのバッファに利用しています (このため、 memcheck() <shared_src/char_io.c> のメモリ下限値を 修正しています)。

98版独自の拡張機能

GRUB/98 では、移植者の趣味(?) によって次のような機能が オリジナルの GRUB から拡張されています。

ファイルシステムの機能拡張

GNU GRUB からのバックポート

次の機能は、 GNU GRUB のファイルシステムバックエンドをバックポートすることで対応しました。

なお GNU GRUB でも FAT32 に対応していますが GRUB/98 の FAT32 サポートはそれとは関係なく独自に実装されています。

ユーザインターフェースの拡張機能

デバッグ版 stage2 (stage2_debug) で追加されたコマンド

listgeometry
GRUB/98 が認識しているディスクドライブのジオメトリ (ディスクのシリンダ数、ヘッド数、トラック当たりのセクタ数、 BIOS で使用するデバイス番号など) を一覧形式で表示します。 GRUB/98 がブートされたドライブには「(ブート)」、 GRUB/98 のカレントドライブ (ディスクにアクセスするコマンドで ディスクの指定を省略した場合に使用されるドライブ) には 「(カレント)」のマークが表示されます。
dump [= 開始アドレス [長さ]]
メモリの内容の16進ダンプを表示します。 開始アドレス を省略すると前回の続きを表示します。 長さ を省略すると128バイトと仮定します。 ダンプの出力は CTRL-C または ESC で中止できます。
poke[b|w|l] = アドレス データ...
メモリの内容を書き換えます。 poke または pokeb コマンドを使用すると バイト単位、 pokew で 16ビット単位、 pokel で 32ビット単位で書き込みます。複数のデータを指定すると 連続した領域に書き込むことができます。どこのメモリでも躊躇せずに 書き込みますので使用には十分注意してください。
debug [= [+|-][abcefgs]...]
デバッグ用の表示フラグを変更します。 + に続けてフラグを指定すると対応するデバッグ用表示が オンになり、 - に続けて指定するとオフになります。 現在次のフラグが定義されています。
フラグ表示する内容
b DISK BIOS 呼び出し前後のレジスタの値
e DISK BIOS でエラーが発生したときの BIOS の戻り値
c リムーバブルメディア (フロッピーや MO、 CD-ROM など) の交換検出
f フロッピーのフォーマット検出の詳細
g GRUB/98 のディスクジオメトリの計算の詳細
s ファイルシステムバックエンド固有のデバッグ出力
なおフラグ a を指定すると定義されているすべてのフラグを 指定したのと同じ意味になります。
message[sjis] = ファイル名
テキストファイルの内容を表示します。 sjis サフィックスを つけるとファイルの内容はシフトJISエンコーディングであると解釈します (それ以外の場合は日本語EUC)。なおファイル中でフォームフィード文字 (CTRL-L) を用いるとそこで表示を一旦停止させることができます。
initscsi
SCSI DISK BIOS の再初期化コールを行います。

注意

これらのコマンドは主にデバッグ用に実装したもので、 インタフェースは暫定的です。将来高い確率で変更される可能性があります。


tak@kmc.kyoto-u.ac.jp