biosbootからロードされたboot loaderプログラムは、最初にsrt0.S内にあるstartupルーチンが走り、boot loaderプログラムが動作するための初期化処理を行ないます。そして初期化終了後、startup ルーチン内からboot関数が呼ばれます。
biosbootからロードされたboot loaderプログラムは、最初にsrt0.S内にあるstartupルーチンが走り、boot loaderプログラムが動作するための初期化処理を行ないます。そして初期化終了後、startup ルーチン内からboot関数が呼ばれます。
biosbootがスタックに格納した、BOOTMAGICの値が正しいかチェックします。BOOTMAGICはMakeから渡される定数であり、sys/arch/i386/stand/Makefile.incに0xc001d00dと定義されています。しかし、BOOTMAGICの値が正しくなくても特にエラーにしたりはしていないようです。
stackに格納されている、起動ドライブ番号をedx レジスタにストアします。
セグメントの設定とリアルモードに移行処理を行うので割込み禁止にします。この後、boot関数をcallするまで割込み禁止になります。
Gdtrの内容を、GDTR(Global Descriptor Table Register)にセットします。これにより、gdtにあるSegment Descriptor Tableが有効になり、これ以降プロテクトモード用のセグメントが扱えるようになります。
設定後は各セグメントはSelectorと呼ばれる値でアクセスすることになり、各セレクタ値のアクセス範囲・アクセス属性は下記のようになります。
 
	    cr0 レジスタのPE bitを1にしてプロテクトモードに移行します。
jumpを実行し、パイプラインのクリアとCode Segment(CS) Registerをプロテクトモード用の値に再設定を行います。jump後Code Segment(CS) Registerはセレクタ値32bit code(0x8)で動作するようになります。
CS以外のセグメントレジスタを32bit data(0x10)に設定します。
sp レジスタをBOOTSTACKに設定します。Stackは0xfffcになります。
設定後、各レジスタの設定値は下記のようになります。
 
	    起動ドライブ番号をStackに格納し、起動ドライブ番号をbios_bootdevに格納します。
pmm_initをcallして割込みの設定をします。
読込んだbootプログラムはELF形式であり、幾つかのセッションに分かれている。この中の未初期化データセッションである、bss領域をゼロクリアする。
elfは幾つかのセッションに分かれている。
と言いましたが、これらのセッション情報はelf Headerに書かれています。elf Headerの情報は、objdump コマンドの"-h"オプションを使うことによって、可読可能な形式で見ることが出来きます。
例えば、bootのelf Header情報を表示させるには、objdumpを使えば必要な情報を見ることができます。
# objdump -h /usr/src/sys/arch/i386/stand/boot/obj/bootreadelf コマンドを使用すれば、さらに詳しい情報も見る事もできます。
# readelf -a /usr/src/sys/arch/i386/stand/boot/obj/boot
objdump コマンドを使用して、bootのマッピングを表示すると、下記のようになります。
boot:     file format elf32-i386
Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         0000858f  00040120  00040120  00000120  2**4
                  CONTENTS, ALLOC, LOAD, CODE
  1 .rodata       00001dae  000486c0  000486c0  000086c0  2**5
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .data         00000110  0004a470  0004a470  0000a470  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  3 .bss          000011c8  0004a580  0004a580  0000a580  2**5
                  ALLOC
      これを視覚化すると下記のようになります。
 
	図を見ると分かるようにbbsの最初のアドレスには_edata、最後のアドレスには_endと言うラベルが定義されています(これらのラベルは、objdump -x bootで見ることが出来る)。bbsをクリアするには( _end - _edata )でオフセットを求め、_edataからオフセット分クリアすれば出来ますね。
boot関数をcallする。
本来、boot関数からkernelに移行してしまうので、_rtt関数が呼ばれることは無い。( と思う ;-) )