[kernel-ml 89] PC 移植記 (1)

Naitoh Ryuichi (night@bfree.rim.or.jp)
Mon, 08 Apr 1996 23:30:11 +0900

前回のミーティング議事録でも書きましたが、B-Free OS を IBM-PC 互換機に
移植することになりました。

私は、PC 用のソースファイルの管理環境を新しく作りました。
今は、 boot プログラムを移植する作業を開始しています。

とりあえず、作業の進捗状況を kernel-ML に上げていきたいと思います。

この (多分、作業日記としてあとにもっと続く) メイルは、次の目的で作成し
ました。

1) 作業状況と共にあとからプログラムを理解するための便宜を図る。
このメイルは、プログラムの内容の説明も兼ねています。とは言っても、
プログラムの中身は変更する可能性がありますから、最新のプログラムの
中身を反映しているとは限りません。ま、参考程度でしょう。

2) 私の備忘録
作業状況/プログラムの説明をすることによって、あとから自分で参照する
ためのものです。これまで PC9801 版を作っていた時に失敗したと思った
のが、作業の内容を書き残さなかったことです。そのため、自分でも何故、
こうしたのか分からなくなった部分があります。
プログラム中のコメントでは、処理の内容までは書いてあっても、どうし
てこうしたのかまでは書いてありませんので。。。

もちろん、流量が去年の 11 月で止ってしまったこの kernel-ML の活性化を
図るためでもあります。

-----------------------------------------------------------------------

初回の今回は、1stboot プログラムの移植です。

B-Free OS の boot プログラムを簡単に説明します。
boot プログラムは ROM BIOS に入っている IPL が読み込む 1stboot と
1st boot が読み込む 2ndboot の2 つに分かれています。
なぜ、このように 2 つに分かれているかというと IPL が読み込むプログラム
のサイズが 512 バイトと非常に小さいからです。boot は、まず 1st boot が
BIOS を使って 2ndboot を読み込み、2ndboot が OS を読み込むという 2 段
階で実行します。

IBM-PC では、IPL が読み込む boot プログラムには、以下の制限があります。

o サイズが 512 バイト以下
o 8086 モードで動く
o 512 バイトの領域の最後が 0xAA55 で終っていること

特に、最後の制限は重要です。このマークがないと IPL は boot プログラム
と認識しません。私は、最初このマークがあることを知らず、boot プログラ
ムをなぜ IPL が読み込まないのか不思議でした。なお、PC9801 の場合には、
このようなマークはありません。
別冊インタフェースの BootStrap Project 2 No.1 の 5 ページ目には、この
マークの他に boot プログラムがジャンプ命令で始まっていることも IPL が
読み込むための条件に入っていました。しかし、この条件は少なくとも私の
IBM-PC 互換機の場合には当てはまらないようです(Linux のブートプログラム
もジャンプ命令で始まっていないことを見ると他のマシンでも同様のようです)。

IBM-PC 互換機の場合、IPL は boot プログラムを次のアドレスへロードしま
す。

ロードアドレス セグメント 0x07C0
オフセット 0x0000

この位置だと後の OS をロードするときに不都合なので、次のアドレスへ
1st boot プログラムを丸ごと移動します。

ロードアドレス セグメント 0x7000
オフセット 0x0000

移動するためのプログラム片は、次のとおりです。

entry first_boot

.org 0x0000
first_boot:
mov ax,#0x07c0
mov ds,ax
mov ax,#0x7000
mov es,ax
mov cx,#256
sub si,si
sub di,di
cld
rep
movsw
jmpi #restart, #0x7000
restart:

註釈を加えると、この部分については Linux のソースの一部をそのまま持っ
てきました。偶然にも 1st boot の移動する先も同じでした。
最後の jmpi の行は、0x7000:0x0000 というアドレスへセグメント間ジャンプ
するための命令です。

自分自身を 0x7000:0x0000 へコピーした後、1st boot はメッセージを出力し
ます。

1st boot for btron/386(PC)

メッセージを出力するための関数は、print です。
print では、文字列を出力するための BIOS コールとして、次のものを使用し
ました。なお、PC9801 版では、適当な BIOS コールがなかっため、直接 VRAM
に書き込んでいます。

o 文字列の出力(カーソル移動つき)
BIOS コール int 0x10
BIOS コード AH = 0x13, AL = 0x01
機能: ES:BP で指した文字列を CX で指定した長さだけ
出力する。このとき、AL レジスタの中身が文字の
属性となる。出力する位置は DH が行番号、DL が
桁番号となる。BL レジスタは、表示するページ番
号を示す。

o カーソル位置の検出
BIOS コール int 0x10
BIOS コード AH = 0x03
機能: 現在のカーソル位置を返す。カーソル位置は、 DH
が行番号、DL が桁番号となる。

print 関数は、次のようになりました。

!
! print --- 文字列をコンソールに表示する。
!
! 引数:
! bx 表示する文字列のアドレス
! 文字列は、<長さ>:1バイト
! <文字列>:最大255バイト
! となっている。
print:
push ax
push bx
push cx
push dx

push bx
mov ah,#0x03 ! get cursor pos
xor bh,bh
int 0x10
pop bx

xor cx, cx
movb cl, (bx)
inc bx
mov bp, bx
mov bx, #0x0007
mov ax, #0x1301
int 0x10
pop dx
pop cx
pop bx
pop ax
ret

1st boot プログラムではサイズが限られているので、push/pop の行は余分か
もしれません。これらは、1st boot プログラムが大きくなってしまったときに
まっさきに削る部分でしょう。
出力するメッセージは、次のように指定します。

message: .byte 28
.ascii "1st boot for btron/386(PC)"
.byte 13, 10

最後の行の「.byte 13, 10」は、改行を示します。

とりあえず、「PC 移植記」第1回は、ここまでとします。
次回は、2nd boot の読み込み処理です。

最後に、この 1st boot プログラムを作成するにあたっての参考文献を書いて
おきます。

「別冊インタフェース ブートストラップ Project-2 No.1
特集 PC&DOS/V BIOS サービスの全貌」
CQ 出版社

---
B-Free プロジェクト実行中! 詳細はこの WWW へ 
-> (http://www.st.rim.or.jp/~isoyama/b-free)

内藤隆一 (ggc00661@niftyserve.or.jp/night@bfree.rim.or.jp)