|
1: 2005-07-21 (木) 15:48:00 |
| + | どうすればIPL(ブートローダー)を作ることができるでしょう? |
| | | |
| + | BIOSは初期化やチェックを行った後、OS(とは限らないが)を起動すべく探しに行きます。 |
| + | |
| + | BIOSの設定次第ではありますが、まずはFDのブートセクターの読み込みを試みます。 |
| + | |
| + | FDのブートセクターにプログラムが書かれていれば、それを読み込んで実行します。 |
| + | |
| + | 具体的な流れをすこし見てみましょう。 |
| + | |
| + | ***IPLの読み込み [#d2371b22] |
| + | BIOSは初期化やチェックを終えると、FDのブートセクタ(セクター0)部分を読み込みます。 |
| + | 読み込まれたデータは、メモリの0x0000:0x7c00に転送され、読み込みが終わるとこの0x0000:0x7c00にジャンプし、実行を開始します。( |
| + | [[OS-Wiki参照:http://community.osdev.info/index.php?cmd=read&page=IPL]]) |
| + | |
| + | 通常、ブートセクタのサイズは512KBしかありません。IPLもその中に収めなくてはなりませんので、普通に「ファイルxxx.xxxを読み込め!」ということはできません。 |
| + | |
| + | (普通、「ファイルxxx.xxxを読め」等の動作が出来るのはDOSやLinux等のOSの機能です。まだIPLではOSもなんにもありません。そもそも「ファイル」という概念すら使うことが出来ないのです。この時点で使える方法はBIOSに収められている関数を呼び出したり直接機械語でFDを動かしたりして、セクター単位で読み込むことしかできません。) |
| + | |
| + | (ちゃんと調査していないので間違っているかもしれませんが、MS-DOSなどにこの実例があります。MS-DOSのカーネル(OS本体)は、IO.SYSとMSDOS.SYSというファイルです。当然DOSのIPLもこの二つを読み出します。しかし、実際にはこの二つはファイルであってファイルではありません。この二つのファイルがあるセクタを直接読み出しているのです。そのため、MS-DOSの起動ディスクでIO.SYS等をコピーしたり上書きしたりすると、たとえ内容が同じでも起動ができなくなってしまいます。実際にファイルの内容が書かれているセクターがずれてしまうためです。) |
| + | |
| + | |
| + | **FAT12 [#q6fb032e] |
| + | 通常、もっとも簡単にできるFDのフォーマットはFAT12です。 |
| + | (Windowsから普通にフォーマットすれは自動的にそうなる) |
| + | |
| + | FAT12でのIPLはどうなっているでしょう。 |
| + | |
| + | K氏のheboosのIPLではこうなっていました。 |
| + | |
| + | JMP boot |
| + | NOP |
| + | DB 'heboOS ' |
| + | DW 512 |
| + | DB 1 |
| + | DW 1 |
| + | DB 2 |
| + | DW 00e0H |
| + | DW 2880 |
| + | DB 0f0H |
| + | DW 9 |
| + | DW 18 |
| + | DW 2 |
| + | DD 0 |
| + | DD 2880 |
| + | DB 0,0 |
| + | DB 29H |
| + | DD 0ffffffffH |
| + | DB 'heboOS ' |
| + | DB 'FAT12 ' |
| + | |
| + | これを[[OS-WikiのIPLのページ:http://community.osdev.info/index.php?cmd=read&page=IPL]]と照らし合わせるとこうなります。 |
| + | |
| + | |
| + | | JMP boot| | ;jmp命令用の空き| |
| + | | NOP| |以下の「名前」の先頭は3バイト目からと決まっているらしい。JMP命令は2バイトにしかならないため、1バイト稼いでおく?| |
| + | | DB| 'heboOS '| ;名前(たいていはファイルシステムの名前か、もしくはOSの名前が入る。ATでBIOSを使ってこの部分を読みこむと、たいていごみデータに置換される。)| |
| + | | DW| 512| ;セクタサイズ(一般的には512か1024)| |
| + | | DB| 1| ;クラスタサイズ(1クラスタが何セクタで構成されているか)| |
| + | | DW| 1| ;FATがどこから格納されているか(このBPBセクタからの相対セクタ番号で)~(別の言い方をすると、「予約セクタ」がいくつあるかを表します)| |
| + | | DB| 2| ;FATがいくつあるか(一般的には2)| |
| + | | DW| 00e0H| ;ルートディレクトリの長さ(32バイト単位)| |
| + | | DW| 2880| ;このドライブ(FDの場合はディスク、HDDの場合はパーティション)の総サイズ(セクタ数で)| |
| + | | DB| 0f0H| ;メディアのタイプ(一般に1440KB-FDの場合は0xf0を、HDDの場合は0xf8を書いておけば問題はなさそう)| |
| + | | DW| 9| ;FATの長さ(1つ分の長さをセクタ数で)| |
| + | | DW| 18| ;1トラックにいくつのセクタがあるか(一般に1440KB-FDの場合は18)| |
| + | | DW| 2| ;ヘッドの数はいくつか(一般に1440KB-FDの場合は2)| |
| + | | DD| 0| ;このBPBセクタはデバイスの先頭から数えてどこにあるか(HDDのパーティション開始位置を表すために用いられる、セクタ単位、一般に1440KB-FDの場合は0)| |
| + | | DD| 2880| ;| |
| + | | DB| 0,0| ;よくわからないけどとりあえず0にしておくといいらしい| |
| + | | DB| 29H| ;よくわからないけどとりあえず0x29を書くらしい| |
| + | | DD| 0ffffffffH| ;0xffffffffを書いておくといいらしい(たぶんボリュームシリアル番号)| |
| + | | DB| 'heboOS '| ;ディスクの名前、もしくはパーティションの名前、ボリュームラベルのコピー| |
| + | | DB| 'FAT12 '| ;"FAT12"(46 41 54 31 32 20 20 20)か、"FAT16"(46 41 54 31 36 20 20 20)が入る| |
| + | |
| + | |
| + | |
| + | これらの後に実際に動作するコードを書き込むようです。(つまりJMP BOOT の飛び先) |
| + | |
| + | |
| + | **ブートローダーとは? [#w350392d] |
| + | MS-DOSのような小さなOS、あるいはほとんど変更がされないOSの場合は、このIPL(たった512バイト)のプログラムでも直接読み込むことができます。 |
| + | |
| + | しかし、たとえばLinux等のように、頻繁にアップデートが行われるようなものの場合はこの仕組みでは大変です。可能なら''ファイル''として読み込みを行いたいですね。 |
| + | |
| + | しかし、ファイルを扱えるようにするにはOSと同等のファイルシステム管理プログラムが必要になります。これをIPLに収めるのはなかなか大変です。 |
| + | |
| + | そこでLinux等の場合は、IPLで一旦''ブートローダー''という小さなOSモドキをロードして実行させます。この段階では少なくとも512バイトという制限はありませんから、それなりに大きくできます。 |
| + | |
| + | このブートローダーという小さなOSにファイルシステムと同じようなプログラムを搭載させ、OS本体はファイルとして読み込むようにしておけば、OS本体そのものは単に特定のディレクトリに決まった名前でコピーさえすれば読み込めるようになるので、アップデートが楽になるという寸法です。 |
| + | |
| + | ですから、厳密にはIPLとブートローダーは別のものです。MS-DOSやOSASKなどのように小さい、あるいはイメージディスクでの配布が前提のものなどは、ブートローダーはいらないorIPLと兼用ということになります。 |
| + | |
| + | |
| + | **具体的にはドコがどう読まれているのか [#q3308d17] |
| + | FD(まあHDもそうかもしれんが)を読む場合、当然「どこの部分をいくつ読め!」という命令が必要になる。FDは具体的にはどういう構造になっているのだろう? |
| + | |
| + | |
| + | |
| + | |
| + | |
| + | |
| + | |
| + | |
| + | |
| + | |
| + | |
| + | |
| + | |
| + | |
| + | |
| + | **どのセクタを読む? [#xdf94b04] |
| + | 先のIPLの先頭にはジャンプ命令があります。ここからジャンプした先にセクタを読む命令を書いておけばそれを読んでくれますが、どのセクタを読めばいいでしょう。 |
| + | |
| + | FDのセクタは予約されたものがあるのでこれ以降のデータ領域にOSを書き込み、それを読み込むことになります。FDのFAT構造はこうなります。 |
| + | |
| + | |IPL|予約領域|FAT領域|ルートディレクトリ領域|データ領域| |
| + | |
| + | IPLはかならずセクター0なのでいいのですが、FAT領域は何番から何番なのでしょう。 |
| + | 間違い!。 セクターは、「1」からスタートするみたい。 |
| + | |
| + | |
| + | |
| + | COLOR(red){うーん。ずばり書いてある資料がないなぁ。フォーマットによって多少変化するのか。このFAT12の場合だと・・・・上記のBPBから算出できると?。} |
| + | |
| + | |
| + | DW 1;FATがどこから格納されているか(このBPBセクタからの相対セクタ番号で) |
| + | |
| + | ということは、BPBがあるブートセクタは0。相対的に1ってことは、「セクター1〜」ということかな? |
| + | |
| + | DW 9 ;FATの長さ(1つ分の長さをセクタ数で) |
| + | |
| + | なんだから、9セクターあると。さらに |
| + | |
| + | DB 2 ;FATがいくつあるか(一般的には2) |
| + | |
| + | なんだから、9x2で18。ってことは、FAT領域は「セクター1〜セクター18」で、データ領域は「セクター19〜おしまいまで」ってことでいいのかな? |
| + | |
| + | どうもちがうみたいだ。FATが二個。これ、一個は非常時用の予備?らしいぞ。 |
| + | だから、FAT領域は「セクター2〜セクター10まで」ってことかな。 |
| + | |
| + | |
| + | |
| + | |
| + | **データ(OS)の格納 [#bb1eaeeb] |
| + | 全てセクター単位で読み書きするってんなら、このFAT12の配置は無視できなくもない。 |
| + | |
| + | (セクター1のIPLだけはダメ) |
| + | |
| + | しかし、さしたる理由もなく独自書きしてもあとでこまるので、面倒でもFAT12の形式を踏むのがいいと思う。 |
| + | |
| + | たとえば、OSが8KBあったとする。1セクタ=512Bだから、 |
| + | |
| + | 8000÷512=15.6 |
| + | |
| + | つまり、16セクターあれば書き込めるわけだ。 |
| + | |
| + | IPL以外の場所(たとえばセクター2〜とか、とりあえずFAT領域を避けてセクター11〜とか)から適当に順番に書き込むことはできるし、わかっていれば読み込むこともできる。 |
| + | |
| + | しかし、例えばセクター11〜セクター27までにOSを書き込んだとして、この位置を上書きされてしまったら大変だ。特定のセクターだけは書き込みできないようにしなければいけない。 |
| + | |
| + | いろいろな方法があるようだが、一番簡単なのは、「そのセクターはファイルxxxが使用中だよ」ということにしてしまうのが順当。(MS-DOSなんかのIO.SYSやMSDOS.SYSなんかはこの方法のようだ) |
| + | |
| + | |
| + | **FATのファイル管理の原理 [#maa6157d] |
| + | 例えが適当かどうかわからないが、FAT12等のファイルシステムは、ちょうど表計算ソフトのように細切れのマスがある。(1つ1つのマスは格納できる大きさが決まっている。また、1つ1つ固有の番号が振られている) |
| + | |
| + | たとえば上記の例だと、FAT領域に、 |
| + | |
| + | -名前は「xxxxxx.xxx」だよ |
| + | -このファイルはxxxxだよ。(各種属性等が書かれている) |
| + | -このファイルは、FATの「11・12・13・14・・・・・25・26・27」に書かれているよ。 |
| + | |
| + | という情報を書き込んでおけば、「なんちゃってファイル」として扱われ、意図的に上書きをしなければ安全ということになるはず。 |