Mac+dockerでMikanOSを作る
詰まったところを書いていく
環境構築はこの神記事
2章までは難なく進んだ
3章
3章のカーネルからピクセルを描くのところで縞々にならない。
このためブートローダのPrintデバッグ。
具体的にはカーネル呼び出しが成功しているのかが気になったので
EFI_STATUS tmp = root_dir->Open(
root_dir, &kernel_file, L"\\kernel.elf",
EFI_FILE_MODE_READ, 0);
if (tmp != EFI_SUCCESS) {
Print(L"failed\n");
}else {
Print(L"success\n");
}
こんな感じのコードを書いた。
参考までにOpen関数はこんな感じになっている
/**
Opens a new file relative to the source file's location.
@param This A pointer to the EFI_FILE_PROTOCOL instance that is the file
handle to the source location. This would typically be an open
handle to a directory.
@param NewHandle A pointer to the location to return the opened handle for the new
file.
@param FileName The Null-terminated string of the name of the file to be opened.
The file name may contain the following path modifiers: "\", ".",
and "..".
@param OpenMode The mode to open the file. The only valid combinations that the
file may be opened with are: Read, Read/Write, or Create/Read/Write.
@param Attributes Only valid for EFI_FILE_MODE_CREATE, in which case these are the
attribute bits for the newly created file.
@retval EFI_SUCCESS The file was opened.
@retval EFI_NOT_FOUND The specified file could not be found on the device.
@retval EFI_NO_MEDIA The device has no medium.
@retval EFI_MEDIA_CHANGED The device has a different medium in it or the medium is no
longer supported.
@retval EFI_DEVICE_ERROR The device reported an error.
@retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
@retval EFI_WRITE_PROTECTED An attempt was made to create a file, or open a file for write
when the media is write-protected.
@retval EFI_ACCESS_DENIED The service denied access to the file.
@retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the file.
@retval EFI_VOLUME_FULL The volume is full.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_FILE_OPEN)(
IN EFI_FILE_PROTOCOL *This,
OUT EFI_FILE_PROTOCOL **NewHandle,
IN CHAR16 *FileName,
IN UINT64 OpenMode,
IN UINT64 Attributes
);
やはり呼び出しに失敗していたのでなぜだろうかと考えていたら,run_qemu.shに引数を渡すのを忘れていた(run_qemu.shの呼び出しをショートカットにしたまま2章から変更しなかったのが原因)
ちなみにカーネルのロードに失敗した場合のosbook_day03aの表示が
dockerで一通りやったら私のmacで再現可能かやってみる。
(^- osbook_day04dで上と全く同じようなデバッグが可能なエラー処理が追加された...)
git tagで切り替えているので全員が同じコードを手にすることを考えると書籍に行番号があってもいいと思ったり
一連の流れ
- メモリマップの取得
- メモリマップの保存
- グラフィックの設定変数の取得
- カーネルファイルの取得
- カーネルファイルのメモリ確保,読み込み
- ブートサービスの停止
- カーネルの起動
個人的には関数ポインタで起動するのが面白いと感じた。
UefiMainの引数が気になる
4章
まずピクセルを描くにあたってUEFIでは4種類のフォーマットがあるが,今回は簡単な2種類のみ
この2種類はRGBかBGRかの違いしかないのでクラスを継承することで必要な関数を提供する。
(c++の仮装関数は初めてだがrustでいうトレイトだとわかった。)
ピクセル座標は4byteであることに注意。これは1byte分を予約領域として保持しているためである。
インスタンス生成でnewを普通に使うと怒られる。なぜならメモリ管理自体がOSの機能であるからである。
そのため配置newというのを使う。これと配列を組み合わせることによってインスタンス生成を行う。
カーネルを読み込む際にサイズ情報が必要だが,これは読み込まないとわからないというジレンマがある。このため一時領域に一度読み込んでから,サイズ情報を抜き出しメモリ上に実際に読み込むということを行う。
感想
なんだか追えているのか追えていないのかわからない。
仮想アドレスはOSが提供するからこのelfは物理アドレスに等しいと考えていいのか?