Operating Systems Development Series | |
Bootloaders 3
このシリーズは、オペレーティングシステムの開発を一から実演し、教えることを目的としています。 注意:この章は近々更新される予定で、誤りを修正し、トピックに関するより詳細な情報を提供します。 はじめにようこそ前回のチュートリアルでは、様々なプロセッサモードと簡単な BIOS インタラプトを取り上げました。 また、リアルモードでのセグメント:オフセットアドレッシングを取り上げ、リアルモードの詳細について説明しました。また、ブートローダに謎の「OEM パラメータブロック」を追加し、画面上に文字列を印刷する機能 を追加しました このチュートリアルでは、アプリケーションプログラミングと システムプログラミングの違いを表す、さまざまな「リング」を見ていきます。 また、シングルステージとマルチステージのブートローダについて、それぞれの長所と短所を説明します。 最後に、BIOS 割り込み 0x13、OEM パラメータブロック、プログラムの読み込み、ロード、実行につ いて説明します。このプログラムは、セカンドステージブートローダとなります。セカンドステージブートローダは、32 ビット環境を設定し、C カーネルをロードする準備をします。 準備はいいですか? The Rings of Assembly Languageアセンブリ言語では、「リング0プログラム」、「このプログラムはリング3で動作しています」という言葉を使うことがあります。 リングの違い(とその内容)を理解することは、OS開発において有益なことです。リング - 理論さて、リングとは何でしょうか?リング」とは、アセンブリ言語では、プログラムがシステムに対して持つ保護と制御のレベルを表します。リングは4つあります。リング0、リング1、リング2、リング3です。リング0はシステム内の全てを制御することができ、リング3は制御しにくい。 リング番号が小さいほど、ソフトウェアが制御できる範囲が広くなる(保護レベルが低くなる)。 リングは概念ではなく、プロセッサー・アーキテクチャに組み込まれている。 コンピュータが起動するとき、ブートローダが実行されるときでさえ、プロセッサはリング0です。DOSアプリケーションなど、ほとんどのアプリケーションはリング3で実行されます。つまり、Ring 0で動作するオペレーティングシステムは、通常のRing 3のアプリケーションよりもはるかに多くの制御を行うことができるのです。 リングの切り替えリングはプロセッサ・アーキテクチャの一部であるため、プロセッサは必要なときに状態を変更します。 変更するのは...
マルチステージブートローダシングルステージブートローダブートローダ、およびブートセクタのサイズはわずか512バイトであることを忘れないでください。ブートローダが、その同じ512バイトの中で、カーネルを直接実行する場合、それはシングルステージブートローダと呼ばれます。しかし、問題はその大きさです。512バイトの中にいろいろなことができる余地はほとんどないのです。16ビットのブートローダで32ビットのカーネルをセットアップし、ロードし、実行するのは非常に困難です。これには、エラー処理コードは含まれません。これには、以下のコードが含まれます。GDT、IDT、A20、PMode、32ビットカーネルのロードと検索、カーネルの実行、エラー処理。これらのコードをすべて512バイトに収めることは不可能です。このため、シングルステージのブートローダは、16ビットのカーネルをロードして実行しなければなりません。 この問題から、ほとんどのブートローダはマルチステージローダになっています。 マルチステージブートローダマルチステージブートローダは、1つの512バイトのブートローダ(シングルステージローダ)で構成されていますが、別のローダ(セカンドステージブートローダ)をロードして実行します。セカンドステージブートローダは通常16ビットですが、(前のセクションで挙げた)すべてのコードとそれ以上のコードが含まれます。32ビットカーネルをロードして実行することができます。これがうまくいくのは、512バイトの制限がブートローダだけだからです。ブートローダがセカンドステージローダ用のセクタをすべてきちんとロードしていれば、セカンドステージローダはサイズに制限がありません。このため、カーネルのセットアップが非常に簡単になります。 ここでは、2ステージブートローダを使用します。 ディスクからセクタをロードするブートローダは512バイトに制限されていることを忘れないでください。前のセクションで述べたように、2ステージのブートローダを使用するつもりです。つまり、Stage 2 のプログラム(カーネルローダー)をロードして実行するために、ブートロー ダーが必要なのです。もし望むなら、The Stage 2 ローダーは、あなた自身の "Choose your Operating System" と "Advanced Options" メニューを含めることができる場所です :) 。さあ、欲しいでしょ :) BIOS割り込み(INT) 0x13 Function 0 - フロッピーディスクをリセットするBIOS割り込み0x13は、ディスクアクセスに使用されます。INT 0x13, Function 0を使用すると、フロッピーディスクドライブをリセットできます。 これは、フロッピーコントローラがどこから読み込もうと、すぐにディスク上の最初のセクタに移動することを意味します。
INT 0x13/AH=0x0 - DISK : DISK SYSTEMのRESET
を返します。 これは完全な例です。これはフロッピーディスクドライブをリセットし、エラーが発生した場合に再試行します。 なぜ、この割り込みが重要なのか?セクタを読み込む前に、セクタ0から始まることを確認する必要があります。これは良くないことで、再起動するといつでも変わってしまう可能性があるからです。ディスクをセクタ0にリセットすることで、毎回同じセクタを読み込んでいることを確認できます。
INT 0x13/AH=0x02 - DISK : セクタをメモリに読み込む
を返します。 さて、これは考えるべきことがたくさんあります。簡単なものもあれば、もっと説明すべきものもあります。 もう少し詳しく見てみましょう。 シリンダーとは何ですか?シリンダーとは、ディスク上の同じ半径のトラックの集まりです。 これをよりよく理解するために、絵を見てみましょう。 ![]() 上の図を見て、思い出してください。
これは何を意味するのでしょうか。シリンダーナンバーは、基本的に1枚のディスクのトラックナンバーを表します。 フロッピーディスクの場合は、読み出すトラックを表します。 まとめると、1セクタあたり512バイト、1トラックあたり18セクタ、1面あたり80トラックということになります。 これは読み取りを開始する最初のセクタです。覚えておいてください。つまり、この値は 0 から 17 の間にしかないのです。現在のトラック番号を増やし、セクタ番号が正しく設定されていることを確認し、正しいセクタを読み取る必要があります。 この値が18より大きい場合、フロッピー・コントローラは例外を発生させます。この例外に対応するハンドラがないため、CPUは2つ目の例外を生成し、最終的にトリプルフォルトを引き起こします。 フロッピーディスクには2つのヘッド、または側面があることを忘れないでください。ヘッド0は表側で、そこにはセクタ0があります。このため、私たちはヘッド0から読み取ることになります。 この値が2より大きい場合、ヘッドが存在しないため、フロッピーディスクコントローラは例外を生成します。ハンドラが存在しないため、CPUは2つ目の故障例外を生成し、最終的にTriple Faultに至ります。 ドライブ番号とは何ですか?ドライブ番号0は通常、フロッピーディスク・ドライブを表します。ドライブ番号1は通常5-1/4 "フロッピーディスクドライブを表します。 今回はフロッピーなので、フロッピーディスクから読み出したい。そのため、読み出し先のドライブ番号は0となります。 ES:BXには、セクタを読み込むセグメント:オフセットのベース・アドレスが格納されます。ベースアドレスは読み出しの開始アドレスを表していることに注意してください。 それでは、セクタを読み込んでみましょう。 セクタの読み込みとロードディスクからセクタを読み取るには、まずフロッピーディスクドライブをリセットし、そのまま読み取ります。
注意:セクタの読み込みに問題があり、そこにジャンプして実行しようとすると、CPUはセクタが読み込まれているかどうかにかかわらず、そのアドレスの命令を実行します。 これは通常、CPUが無効/アンカット命令またはメモリの終端に遭遇することを意味し、両方ともトリプルフォールトになります。 上記のコードでは、生のセクタを読み取って実行するだけなので、我々のニーズには無意味です。 一つには、現在、PartCopyは512バイトだけコピーするように設定されています。つまり、「どこで、どのように、未加工セクタを作成するのか? また、このRawセクターは存在しないので、「ファイル名」を与えることはできません。単なるロー・セクタです。 最後に、私たちは現在、FAT12ファイルシステム用にブートローダを設定しています。Windowsは、セクタ2と3から特定のテーブル(ファイルアロケーションテーブル)を読み取ろうとします。しかし、生セクタでは、これらのテーブルは存在しないため、Windowsはゴミのような値(あたかもそれがテーブルであるかのように)を取ります。その結果、Windowsでフロッピーディスクを読み込むと、ファイルやディレクトリの名前が壊れていたり、サイズが大きかったりします(3.14MBのフロッピーに2.5Gバイトのファイルを見たことがありますか? 私はあります)。 もちろん、私たちはこの方法でセクタをロードする必要があります。しかし、その前に、ファイルを正しく読み込むために、ファイルの開始セクタ、セクタ数、ベースアドレスなどを調べなければなりません。これが、ディスクからファイルをロードするための基本です。 これについては、次に説明します。 Navigating The FAT12 FileSystemOEM パラメータブロック - 詳細前回の記事で、私たちはコード中に醜いテーブルを捨てました。それは何だったのでしょうか?そうそう...この多くはとてもシンプルです。では、これを詳しく分析してみましょう。 bpbBytesPerSectorは、1つのセクタを表すバイト数を表します。通常フロッピーディスクでは512バイトです。 bpbSectorsPerClusterは1クラスタあたりのセクタ数を示します。ここでは、1クラスタあたり1セクタとします。 Reserved Sectorは、FAT12に含まれないセクタ数、つまりRoot Directoryに含まれないセクタです。 この場合、ブートローダを含むブートセクタは、このディレクトリに含まれません。このため、bpbReservedSectorsは1でなければなりません。 これは、予約セクタ(Our bootloader)にファイルアロケーションテーブルが含まれないことも意味します。 bpbNumberOfFATsは、ディスク上のファイルアロケーションテーブル(FAT)の数を表します。FAT12ファイルシステムは常に2つのFATを持っています。 通常、これらのFATテーブルを作成する必要があります。しかし、ここではVFDを使用しているため、Windows/VFDがディスクをフォーマットする際に、これらのテーブルを作成してもらうことができます。 注:これらのテーブルは、エントリを追加または削除したときにも、Windows/VFDによって書き込まれます。 フロッピーディスクは、Root Directory内に最大224個のディレクトリを持ちます。 また、フロッピーディスクには2880個のセクタがあることを忘れないでください。 Media Descriptor Byte(bpbMedia)は、ディスクに関する情報を含むバイトコードです。 このバイトは、Bit Patternです。
以前のチュートリアルを思い出してください/1トラックあたり18セクタあります。 bpbHeadsPerCylinderは、単にシリンダーを表す2つのヘッドがあることを表しています。 (シリンダーが何かわからない場合は、「BIOS Interrupt (INT) 0x13」セクションのセクタの読み方を読んでください)。 これは、物理ディスクの先頭とボリュームの先頭からのセクタ数を表しています。 フロッピーディスクドライブはドライブ0であることを思い出してください。 Boot Signitureは、このBIOS Parameter Block(このOEMテーブル)の種類とバージョンを表しています。 値は、以下の通りです。
シリアルナンバーは、フォーマットするユーティリティによって割り当てられます。シリアル・ナンバーは、そのフロッピー・ディスクに固有のものであり、同じものは2つとないはずです。 Microsoft、PC、DR-DOSでは、シリアルナンバーは現在の時刻と日付から次のように算出される。 シリアルナンバーは上書きされるから、好きなものを入れればいいんだ。 ボリュームラベルは、ディスクに何が入っているかを示す文字列である。OSによっては、これを名前として表示するものもあります。注:この文字列は11バイトでなければなりません。それ以上でも以下でもない。 ファイルシステム(Filesystem)文字列も同じ目的で使用されるが、それ以上ではな い。注:この文字列は、8バイトでなければなりません。 Demoわあ、たくさんあるね。以下は、このチュートリアルで開発したブートローダで、すべてをまとめています。注意: このデモは *そのままでは* 動きません。元々デモ用として作られたもので、このままではビルドできません。このチュートリアルを更新し、次回のシリーズ改訂時にデモをビルド可能にする予定です。
まとめディスクの読み込みとBIOSパラメータブロック(BPB)について、かなり詳しく説明しました。さらに、すべてを組み合わせた簡単なデモも作成しました。 また、アセンブリ言語のリングの違いを見て、私たちのOSはリング0であり、他の多くのプログラムとは異なることを学びました。これにより、アプリケーションプログラムにはない、より特別な命令を使うことができるようになりました。 これで、セカンドステージローダを見つけてロードするのに必要なものはすべて揃いました。次のチュートリアルでは、FAT12に関するすべてのことを学び、セカンドステージをロードします。待ち遠しいですね。:) それではまた次回。 |