Personal tools
You are here: Home ブログ 学習経過 ブートローダー(その1)
« December 2010 »
Su Mo Tu We Th Fr Sa
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  
Recent entries
sysfs tips 02 ohyama 2010-09-09
sysfs tips ohyama 2010-09-02
Haskell で周波数スペクトルを得る ohyama 2010-07-29
Haskell で線形識別関数の学習を行う ohyama 2010-07-19
Haskell で逆行列を求める ohyama 2010-07-16
Recent comments
Re:vim に lisp 機能をつける t.mimori 2010-12-16
Re:Haskell で周波数スペクトルを得る H.OHYAMA 2010-08-01
Re:lkml でお勉強 (その1-1) Hiroyasu OHYAMA 2009-08-21
Re:lkml でお勉強 (その1-1) kosaki 2009-08-20
Re:vim に lisp 機能をつける ohyama 2008-05-08
Categories
学習経過
GNU/Linux
 
Document Actions

ブートローダー(その1)

初回である今回は、自分が作ろうとしているブートローダはどんなものか。という事から、ブートシーケンスの流れをおさらいする。
次回以降で、実際に手を動かした結果を見せながら、今回話す道をなぞってゆく事にする。又、前回同様にフロッピーディスクからブートを行う前提で話しを進める。

尚、ここで言うブートローダーは、フロッピーの先頭セクタを読み込むところから、圧縮カーネルイメージを展開し、処理をカーネルに渡すところまでの処理を行うプログラムを指す。
ブートローダの主な仕事は次の通りである。
1) 圧縮カーネルイメージの読み込み
2) カーネルへ渡すパラメータの設定
3) プロテクトモードへの移行
4) カーネルイメージの展開・読み込み

では。ブートシーケンスの流れを細かく追ってゆく。
PCの電源を投入すると、BIOSがハードウェアのチェックを行い、結果を 0x00000 - 0x00600 の予約領域に書き込む。そしてブートデバイスを選定すると、そのデバイスの先頭セクタの内容を先頭セグメントの 0x07C0 に内容が読み込まれる(ブートシーケンスにおける Linux のメモリレイアウトについては、Documentation/i386/boot.txt に詳しい記述が存在する)。
1セクタ分しか存在しないこの領域で出来る事は少ないので、ここには次のブート処理が書かれたデータを読み込み、そこに移動するという内容を記載する。BIOS には、02 interrupt 0x13 において、フロッピーディスクから ES: BX で指定されたアドレスにデータを初期化するインターフェイスが存在する。これを用いて、ディスクに存在するブートプログラムをメモリに読み込み、処理を実行する。

ただ、リアルモードにおけるアドレスバスは、20bit しか存在しないので、1MBを優に越える圧縮カーネルイメージを置くことはできない。
なので、圧縮カーネルイメージは1MBを越える領域に対して転送を行う必要がある。これを行う為に、087 interrupt 0x15 のBIOSコールを呼び出し、拡張メモリ領域に対してデータ転送を行う。これにより、24bit 幅のメモリ領域に対してデータ転送が可能となる。しかし、メモリ転送なので、リアルモードにおけるメインメモリに圧縮カーネルイメージをいったん読み込む必要がある。これを実現させる為に、小さなバッファ領域をメインメモリ中に作成し、そこにディスクに存在する圧縮カーネルイメージを読み込み、データ転送を行い、再びバッファにデータよ読み込むという動作を繰り返すテクニックを使う。

ここまではそんなに面倒な事ではない。しかし、次に難敵が立ちはだかる。カーネルパラメータの初期化である。
ブートローダーは、Linux(カーネル)に対して値を渡すために、4KBのカーネルパラメータ領域を作成し、初期化を行う必要がある。
各パラメータのオフセットと内容は、Documentation/i386/zero-page.txt に書かれている。

この敵を倒すと、次に謎な敵が一匹姿を表す。A20 アドレスバスについてである。
x86 において、A20 を無効化されている場合がある。何故このような事がされているかというと、8086 において 0xFFFF0 + 0x00010 のアドレスは、0x00000 とされる事を利用して、0x9A000 以降に存在するBIOS予約領域と 0x00000 のBIOS領域を連続領域として扱う事を考案し、プログラムの命令数を減らすという事を行っていたらしい。昔の人が考える事は、現代に生きる自分が素直に理解できるものでは必ずしもないらしい。
いづれにしろ、昔の遺産を引き継ぐために、x86 で、A20 の21bit目のアドレスバスを無効化しているらしい。A20 のライン制御はキーボードコントローラを用いて行われる。
以下のコードは、arch/i386/boot/setup.S を抜粋したものである。ここで、A20ラインを有効にしている。

<pre class="literal-block">
    movb    $0xD1, %al            # command write
    outb    %al, $0x64
    movb    $0xDF, %al            # A20 on
    outb    %al, $0x60
</pre>

ここでいよいよ、CR0レジスタの最下位ビットをオンにし、プロテクトモードに切替える。
そして、先ほど拡張メモリ領域に転送したカーネルイメージを展開し、展開したアドレスにジャンプして、startup_32() を呼び出す。

ここまでが、簡単なブートの流れである。次回以降、ここで解説した内容のプログラムを動かしながらソースを読んでゆく。

Category(s)
学習経過
The URL to Trackback this entry is:
http://dev.ariel-networks.com/Members/ohyama/30fc30c830ed30fc30fc-305d306e1/tbping
Add comment

You can add a comment by filling out the form below. Plain text formatting.

(Required)
(Required)
(Required)
(Required)
(Required)
This helps us prevent automated spamming.
Captcha Image


Copyright(C) 2001 - 2006 Ariel Networks, Inc. All rights reserved.