osdev-jpでは、OS開発に有用な情報を収集し公開しています
Takym
最近の自己紹介は https://takym.github.io に書いています。 下記の情報はかなり古いため注意してください。
今現在はOS開発の為の準備を進めています。 Takym は「たかやま」と読みます。
最近は .NET ランタイムを他のOS無しで動かす方法に興味があります。
名前 | リポジトリ | 説明 | 備考/状態 |
---|---|---|---|
Exyzer | https://github.com/YigtyORG/Exyzer | CPU の動きを理解する為のウェブアプリです。 | 開発継続中 |
OSDeveloper | https://github.com/Takym/OSDeveloper | OSの開発ができるIDEになる予定でした。OSを自作したら別の形を模索して再開するかもしれません。 | 開発中断 |
少しまとめてみましたが、完全では無いです。
低レイヤ技術に関する自分用のメモです。 間違い等がありましたら、ご指摘お願いいたします。 このメモでは、CPU は基本的に x86_32 または x86_64 を想定しています。
NASM_PREFIX
にインストール先ディレクトリを記入する。C:\cygwin
にインストールする。PYTHON_HOME
にインストール先ディレクトリを記入する。 git submodule add https://github.com/tianocore/edk2.git modules/edk2
cd modules/edk2
git checkout edk2-stable202208
git submodule update --init --recursive
edksetup.bat Rebuild
edksetup.bat
modules/edk2/Conf/tools_def.txt
から /WX
を全て削除する。modules/edk2/Conf/target.txt
の TOOL_CHAIN_TAG
を VS2019
に設定する。 modules\edk2\edksetup.bat
build
- Done -
と表示され、modules/edk2/Build/EmulatorIA32/DEBUG_VS2019
が生成されれば成功。
<!– 5. EDK II LIBC をインストールする方法
bat
git submodule add https://github.com/tianocore/edk2-libc.git modules/edk2-libc
git submodule update --init --recursive
–>
Windows 10 (1709 ビルド 16299.1087) での EDK II (vUDK2018) の自分の環境では上手くできたインストール方法です。
C:\nasm\
%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
してテストする。a
を設定した場合は、範囲は a + 0x0FFF
までとなる。0x54321
を設定したい場合は 0x54
を書き込むだけで良い。
0x54FFF
までとなり、使わない 3294 バイト分の領域まで確保されてしまう。(中略)
if (limit > 0xFFFFF) {
ar |= 0x8000; // G-bit = 1
limit /= 0x1000;
}
(中略)
0x03C7
にパレット番号を指定して、0x03C9
で読み込む。(RGBの順番で1バイトずつ)0x03C8
でパレット番号を指定して、0x03C9
で書き込む。(RGBの順番で1バイトずつ)(中略)
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を引く
}
(中略)
fn main() {
println!("Hello, World!!");
}
ExitBootServices
を呼び出してUEFIを停止させなければならない。
CR0
レジスタの値を書き換える等をしたら、CPUの動作モードを変更する事ができる。CR0
の値と0x00000001
の論理和を取り代入すると、プロテクトモードに移行する事ができる。
CR0
の一番右側のビットが1
ならプロテクトモード、0
ならリアルモード。far JMP
という命令を呼び出せば、パイプラインをフラッシュ(初期化)させる事ができ、安全に動作モードを移行させられる。(中略)
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
(中略)
far JMP
は使われていない。far JMP
を利用してカーネル本体を呼び出しているからだろうか?far JMP
を呼ぶ事が推奨されている。0
に初期化する。
UEFIアプリケーションの開発をする時には必ずしも EDK を使う必要は無い。
最初は絶対に必要な物だと勘違いしていたが、
例えば EDK II に付属している Uefi.h
は
UEFIの仕様に合わせてインターフェースを公開しているだけであって、仕様書を見ながら自ら定義する事もできる。
EDK II に入っているソースコードは UEFI の実装の一つである。
Legacy BIOS に関する興味深い資料を見つけた。 https://www.glamenv-septzen.net/view/614