-
Notifications
You must be signed in to change notification settings - Fork 5
Takym
Takym edited this page Sep 13, 2020
·
42 revisions
OS開発・低レイヤの知識はまだまだ浅いです。OS開発ではあまり使いませんがC#が得意です。今はOS開発の為の準備を進めています。 Takymは「たかやま」と読みます。
名前 | プロジェクト ページ | 説明 | 備考/状態 |
---|---|---|---|
OSDeveloper | GitHub | OSの開発ができるIDEになる予定でした。 | 開発中断 |
syswiki | GitHub | 自分で集めた低レイヤに関する情報を保存する予定でした。 | 中止しました。 |
OS開発・低レイヤの知識はまだまだ浅いです。OS開発ではあまり使いませんがC#が得意です。今はOS開発の為の準備を進めています。 Takymは「たかやま」と読みます。
名前 | プロジェクト ページ | 説明 | 備考/状態 |
---|---|---|---|
OSDeveloper | GitHub | OSの開発ができるIDEになる予定でした。OS自作後に再開するかもしれません。 | 開発中断 |
syswiki | GitHub | 自分で集めた低レイヤに関する情報を保存する予定でした。 | 中止しました。 |
低レイヤに関する自分用のメモです。Slack等で流れた会話を自分なりに要約しています。間違い等がありましたら、教えてください。
- このメモで特に指定が無ければ、CPUはx86_32かx86_64を指します。
Windows 10 (1709 ビルド 16299.1087) での EDK II (vUDK2018) の自分の環境では上手くできたインストール方法です。
- vUDK2018 からツールキットをダウンロードする。
- NASM をインストールする。(インストール先のパスは空白を含めると上手く読み込めなくなる)
- 例:
C:\nasm\
- 例:
- 環境変数の NASM_PREFIX と PATH に NASM のインストール先のディレクトリを追加する。
- Microsoft Visual Studio 2017 の「C++ によるデスクトップ開発」をインストールする。
- Cygwin か MinGW をインストールする? (必要かどうかは試していません。)
- ダウンロードしておいたツールキットを適当なディレクトリに配置する。
- ここでは便宜的に
%WORKSPACE%
呼ぶ。
- ここでは便宜的に
-
%WORKSPACE%\BaseTools\Bin\Win32
内に edk2-BaseTools-win32 からダウンロードしてきたツールを入れる。 -
edksetup.bat
を実行。 -
%WORKSPACE%\Conf\tools_def.txt
から/WX
を全て削除。 -
%WORKSPACE%\Conf\target.txt
のTOOL_CHAIN_TAG
をVS2017
に変更する。 -
build
してテストする。
- GNU GLOBAL:GNU製のコードリーディングを手伝ってくれるツール。タグ付けしてくれるのが特徴。
- カーネルソースツアー
- Vimでコードリーディング
- GDTのG-bitフラグが立っている場合、4KB(=0x1000bytes)単位で設定できる様になる。
- ただし、リミットに
a
と設定した場合はa+0xFFF
と復元されて、4095バイトだけはみ出してしまう。 - これは例えば、
0x54321
をリミットにしたい場合、G-bitを1にして0x54
だけを書き込める様にする為。(残りの0x321
の領域は無視されない) - Haribote OS では以下の様に設定されている。
(中略)
if (limit > 0xFFFFF) {
ar |= 0x8000; // G-bit = 1
limit /= 0x1000;
}
(中略)
- 取得する場合は
0x03C7
にパレット番号を指定して、0x03C9
で読み込む。(RGBの順番で1バイトずつ) - 設定する場合は
0x03C8
でパレット番号を指定して、0x03C9
で書き込む。(RGBの順番で1バイトずつ) - パレット番号は0~255の8ビットまで、RGBの一つの要素は0~63の6ビットまで。
- 予めカラーパレットに以下の様に設定すれば、8ビットでIIRRGGBBの様に指定できる。(Iで明暗度(Intensity)を指定できる)
(中略)
int i, j;
io_out8(0x03C8, 0);
for (i = 0; i < 256; ++i) {
j = (((i >> 6) & 3) + 1) * 4; // IIのビットを取得、0b00の時は4、0b01の時は8、0b10の時は12、0b11の時は16
io_out8(0x03C9, (((i >> 4) & 3) + 1) * j - 1); // RRのビットを取得して書き込み、1~4の値にjを掛けて1を引く
io_out8(0x03C9, (((i >> 2) & 3) + 1) * j - 1); // GGのビットを取得して書き込み、1~4の値にjを掛けて1を引く
io_out8(0x03C9, (((i >> 0) & 3) + 1) * j - 1); // BBのビットを取得して書き込み、1~4の値にjを掛けて1を引く
}
(中略)
- カラーパレットの書き込み中は割り込みを禁止した方が良い。
- ※僕はまだRustを弄った事が無いので間違った情報を含んでいる可能性が充分あります。
- 参考スライド
- 利点と欠点
- 低レイヤ界で結構人気があるコンパイル型プログラミング言語。
- 命令型言語と関数型言語を混ぜた感じ。
- メモリ解放等がコンパイル時に静的に行われる(確認される)ので、効率が良く安全。
- 静的解析を行うので、コンパイルが通るまでが大変。ただし、不具合は出にくくなる。
- 以下は hello world プログラムの例。
fn main() {
println!("Hello, World!!");
}
- HLT命令はリング3で動きそうな処理の命令だが、動かない。
- この命令はリング0では確実に動く。(リング1、リング2で動くかどうかは知らない)
- リング3で動かせないのは、アプリケーション上で実行させるとOSや他のアプリケーションが困るから。
- 何故かと言うと、HLT命令はCPUを止める命令であり、マルチタスクの場合は時間の無駄になってしまう。
- CPUを停止させる位なら、他のアプリやOSに処理を渡した方が効率的になる。
- ブート処理を行ったら必ず
ExitBootServices
を呼び出してUEFIを停止させなければならない。- UEFIが裏で何をしているか分からない為、OSの実行中にUEFI何か処理を行うと危険だから。
- ブートローダーとカーネルは分ける必要は無く、UEFIアプリとしてOSを開発しても良い。
-
CR0
レジスタの値を書き換える等をしたら、CPUの動作モードを変更する事ができる。 -
CR0
の値と0x00000001
の論理和を取り代入すると、プロテクトモードに移行する事ができる。-
CR0
の一番右側のビットが1
ならプロテクトモード、0
ならリアルモード。
-
- CPUにはパイプラインと呼ばれる機能があり、命令の実行中に次の命令を先に読み込んでおき、高速に実行できる様にしている。
- 動作モードを変更した後はこのパイプラインを初期化しなければならない。
-
far JMP
という命令を呼び出せば、パイプラインをフラッシュ(初期化)させる事ができ、安全に動作モードを移行させられる。 - Haribote OSでは以下の様にして動作モードを移行させている。
(中略)
LGDT [GDTR0] ; 暫定GDTを設定
MOV EAX,CR0
AND EAX,0x7fffffff ; bit31を0にする(ページング禁止のため)
OR EAX,0x00000001 ; bit0を1にする(プロテクトモード移行のため)
MOV CR0,EAX
JMP pipelineflush
pipelineflush:
MOV AX,1*8 ; 読み書き可能セグメント32bit
MOV DS,AX
MOV ES,AX
MOV FS,AX
MOV GS,AX
MOV SS,AX
(中略)
GDT0:
RESB 8 ; ヌルセレクタ
DW 0xffff,0x0000,0x9200,0x00cf ; 読み書き可能セグメント32bit
DW 0xffff,0x0000,0x9a28,0x0047 ; 実行可能セグメント32bit(bootpack用)
DW 0
GDTR0:
DW 8*3-1
DD GDT0
(中略)
- 注:Haribote OSのパイプラインのフラッシュ(初期化)には
far JMP
は使われていない。 -
実機では無くQEMU ではパイプラインのフラッシュ処理を挟まなくても正常に実行できた。
- この後に
far JMP
を利用してカーネル本体を呼び出しているからだろうか? - 無駄な遅延処理を挟んでみる実験をしたけど、これでも動作した。
- もしかしたら、正常に動作している様に見えて、実は不具合が発生しているかもしれない。
- この後に
- Intelのマニュアル(SDMのVol.3の9.1.1)にはモードの移行後は
far JMP
を呼ぶ事が推奨されている。 - 内部動作的な部分は記載されていなかった。