techical.txt

			   September 4 2000

                        takamiti@tsden.org
                         extipl@tsden.org
                http://www.tsden.org/takamiti/extipl/


==============================================================================
1. はじめに
2. 一般的な IPL 動作時のメモリマップ
3. scorpius の動作概要
4. 任意のハードディスクからブートさせるための布石
==============================================================================

[1] はじめに

このドキュメントは extipl が内蔵する scorpius(ソース名は antares.asm) と呼ば
れるものの内部動作を解説したものです。
ver.4x では内蔵する唯一のものでしたが、ver.5 では特に指定しない限りインストー
ルされません。しかし、内蔵する全ローダの仕様はこれが起点になっていますし、基
本的な処理も受け継がれています。新たに追加された gemini, taurus, aquila 等の
ソースを解析する時の参考になると思います。


[2] 一般的な IPL 動作時のメモリマップ

scorpius はハードディスクのブートセクタに置かれる master-IPL で、system ROM
の IPLルーチンにより 0x07C00 番地にロードされ制御が移されます。この 0x07C00 
番地は通常ディスクに書かれた IPL を読み込むために使われます。scorpius は自分
が起動させる OS ローダのためにこの領域を避け、自分自身を 0x0600 番地に移動し、
仕事を開始します。0x0600 番地で走る時のメモリマップは次のようになっています。

        |                      |
        ^                      ^
        |----------------------|
        |                      |
        |     512 byte         | <- scorpius が OS ローダを読み込む場所
        |                      |             （最初は自分もここに読まれる）
0x07C00 +======================+ <- scorpius の stack 領域の上限
        |                      |             （起動時に sp にセットする値）
        ^                      ^
        |------------------55AA| <- boot 標識 0xAA55
0x007BE |______64_byte_________| <- partition table 作業領域
        |                      |
        |     446 byte         | <- scorpius の code & data 領域
        |                      |
0x00600 +======================+
        |                      |
        ^                      ^
        |                      |
        |                      | <- このあたりはシステム予約の作業領域や
        |                      | <- 割り込みベクタテーブルがある。
0x00000 +----------------------+
/////////////////////////////////////////////////////////////////////////



[3] scorpius の動作概要

0x0600 に移動した scorpius は次のような手順でアクティブ領域を探しそこからブ
ートするか、あるいはユーザの領域選択を待って該当 OS をブートさせます。なお、
この説明は概念的なもので、実際のプログラムの動作とは厳密には違っています。

    (1) フロッピードライブのモータが off になるまでの間、シフトキーが押されるか
        どうかをチェックします。
                もし、シフトキーが押されたならば (3) に飛びます。

    (2) partition table からアクティブ領域を探します。
                もし、アクティブ領域があれば (4.5) に飛びます。
                しかし、アクティブ領域のブートセクタの内容が正規のブートプロ
                グラムと認められないときには警告のベルを鳴らして (3) に移り領
                域選択状態になります。

    (3) 該当ハードディスクのパーティションテーブルをダンプし、選択プロンプト
        "Boot #?:?.?" を出します。プロンプト に続く数字は HD ユニット番号とパ
        ーティションテーブルの階層、アクティブ領域の番号です。全領域非アクティ
        ブならば領域番号は原則として "1" となります。

    (4) キー入力を待ち、押されたキーを次の順序でチェックします。

        (4.1) 押されたキーが "0", "1"〜"4" ならば選択された番号を表示し、次の
              キー入力を待つために (4) に戻ります。

        (4.2) 押されたキーが <Enter>, <End> ならば(4.3)以降の処理を行いますが、
              これら確定キーに該当しなければ警告のベルを鳴らし (4) に戻ります。

        (4.3) 選択された番号が "0" ならば、BIOS から見える次のハードディスクの
              先頭セクタを 0x07C00 番地に読み、パーティションテーブルだけを
              0x07BE 番地にコピーし、(3) に戻ります。その際に各変数はそれぞれ
              の状態に合わせて再設定されます。

        (4.4) "1"〜"4" が選択されたが、該当する領域が使用されていなければ警告
              のベルを鳴らして (4) に戻ります。

        (4.5) 選択された領域が 拡張領域ならば、拡張領域内の先頭セクタを 0x07C00
              番地に読み、パーティションテーブルだけを 0x07BE 番地にコピーし、
              階層テーブル表示のプロンプトを更新して (3) に飛びます。

        (4.6) 該当領域の先頭セクタの内容（OS のブートローダ）を 0x7C00 番地に
              読み込みます。
                        | (2) からここに飛び込んだ場合には期待しているレジスタ
                        | の値が下記 (b) には該当しませんので <Enter> キー
                        | が押された時と同様に処理されます。

          (a) 押されたキーが <Enter> ならば、、、
                0x7C00 に読み込まれたブートセクタの末尾の 0xAA55 を見て、正規ブ
                ートセクタであることを確認してから (5) に飛びます。
          (b) 押されたキーが <End> ならば、、、
                <Enter> キー同様に正規のブートセクタであることを確認します。そ
                してブート対象としているハードディスクドライブが 1 台目で基本領
                域の時に限り、選択された領域に active flag をセットしたものをマ
                スタブートセクタに書き戻してから (5) に飛びます。

    (5) 0x7C00 に jump することにより該当 OS のブートプログラムを起動させます。こ
        の時各レジスタ値は以下のような意味を持っています。
            ax, bx, cx, dh, di, bp = 無意味
	    dl = DISK BIOS から見たドライブ番号 (0x80, 0x81, ..)
            ds = scorpius のデータセグメント値　(0x0000)
            si = 起動したローダの置かれた領域を示すポインタ
                 起動領域番号を n とすれば si の持つ値は次の式で表されます。

                     si = 0x07BE + 16 * (n - 1)
                                              (n は 1 .. 4 の値を取る)

                 これにより起動された OS のローダは ds:si の示す番地を手がかり
                 にして自分の置かれた領域の情報を取り出すことができます。
                 また、このときにポインタ ds:si の示す番地にはアクティブ領域で
                 あることを OS のローダに知らせるために MSB をセットします。
                 この ds:si の値は IBM の技術資料でも保証されています。


[4] 任意のハードディスクからブートさせるための布石

scorpius は ROM BIOS を使い、上記のような手順で OS をブートしますが、もし起動
したい OS のローダさえ対応しているならば BIOS 経由で 2台目以降として認識され
るハードディスクからもブートさせることができます。ほとんどの OS は 1 台目のハ
ードディスクからしかブートできませんので過度の期待はしない方がよいかも知れませ
ん。

ここでは、scorpius が 2 台目以降のハードディスクから読み込んだことを OS のブー
トローダにしらせるからくりについて説明します。まず、いまさらの事でしょうが、１
つのパーティションを表す情報は次のような構造体と等価です。

            typedef unsigned char byte;

            typedef struct {
                byte head;
                byte sector;
                byte cyl;
            } hd_addr;

            typedef struct {
                byte                bootind;        <<--- active flag
                hd_addr             start;
                byte                systemind;
                hd_addr             end;
                unsigned long       start_sector;
                unsigned long       nr_sectors;
            } partition;

ここで、ブート可能なパーティションであることを示す partition.bootind の内容は
通常 0x80（ブート可）あるいは 0x00（ブート不可）の2つの値しか持ちません。
scorpius も 1 台目からブートしたときには選択された領域の partition.bootind を
0x80 にセットして OS のローダに制御を渡します。しかし、2 台目から起動したなら
ば、この値を 0x81 として読み込んだローダに制御を渡します。
つまり、scorpius 経由で呼び出された OS のローダは partition.bootind の MSB を
マスクした値を見れば BIOS が認識しているハードディスクの何台目から自分が読ま
れたのかを知ることができます。
しかし、起動したハードディスクが IDE type なのか SCSI type なのかを知る事はで
きません。このあたりは OS のローダの仕事になります。また、実際に BIOS からみて
最初のハードディスク以外からブートできるかは、scoprius から制御を渡された OS
側のローダに依存することを忘れないでください。

========
/*  $Id: techical.txt,v 1.1.1.1 2000/11/29 11:58:19 takamiti Exp $  */
# end of technical.txt
