こちらの記事を参考にいたしました! 良記事ありがとうございます。
前回は、01 日めということで M1 Mac にビルドツール(llvm 等)をインストールして、C 言語で書かれた UEFI プログラムを実行できるようにしました。
本日は、UEFI の SDK である「EDK II」を導入していきたいと思います。
Github からリポジトリをクローンしてビルドします。
$ git clone https://github.com/tianocore/edk2.git
$ git submodule init
$ git submodule update
$ cd BaseTools/Source/C
$ make
# (※不確かなメモ※)
# VSCode で MikanOS のソースを見たときにヘッダーファイルが見つからない警告が出るのが
# 私の精神衛生上良くないので、こんな感じでインクルードパスを指定した。
$ vim ~/.zshrc
export CPATH=$CPATH:$HOME/Code/edk2/MdePkg/Include
export CPATH=$CPATH:$HOME/Code/edk2/MdePkg/Include/X64
EDK II を使って MikanLoaderPkg (day02a) をビルドする。 (私は書籍と違うディレクトリにソースを展開しているのでその辺りはうまく読み替える必要がある)
# OS プロジェクトのタグを切り替えておく
$ cd ~/Code/mikanos
$ git checkout dosbook_day02a
# EDK にプロジェクトのシンボリックリンクを張る
$ cd ~/Code/edk2
$ ln -s ~/Code/mikanos/MikanLoaderPkg .
# こんな感じになるはず
$ ls -l
:
lrwxr-xr-x 1 roca staff 39 3 27 10:56 MikanLoaderPkg -> /Users/roca/Code/mikanos/MikanLoaderPkg
:
# ビルド前の準備(ツールチェーンの指定は後半のテーブルを参照)
$ source edksetup.sh
$ vim ./Conf/target.txt
# ビルド!!
$ build
$ ls -l ./Build/MikanLoaderX64/DEBUG_CLANGPDB/X64/Loader.efi
-rw-r--r-- 1 roca staff 6160 3 27 11:24 ./Build/MikanLoaderX64/DEBUG_CLANGPDB/X64/Loader.efi
Mac 上で開発をする場合、ツールチェインの指定が書籍と異なるので注意。
ちなみに、TOOL_CHAIN_TAG とはビルドに使用するコンパイラなどの指定のことらしい。 今の私の環境だと具体的には macOS@11.2.3 / llvm@11.1.0 なので、「CLANGPDB」を指定するのが正解みたい。
設定項目 | 設定値 |
---|---|
ACTIVE_PLATFORM | MikanLoaderPkg/MikanLoaderPkg.dsc |
TARGET | DEBUG |
TARGET_ARCH | X64 |
TOOL_CHAIN_TAG | CLANGPDB |
(./Conf/tools_def.txt 抜粋)
# CLANG38 -Linux- Requires:
# Clang v3.8, LLVMgold plugin and GNU binutils 2.26 targeting x86_64-linux-gnu, aarch64-linux-gnu or arm-linux-gnueabi
# Clang v3.9 or later, LLVMgold plugin and GNU binutils 2.28 targeting x86_64-linux-gnu, aarch64-linux-gnu or arm-linux-gnueabi
# Optional:
# Required to build platforms or ACPI tables:
# Intel(r) ACPI Compiler from
# https://acpica.org/downloads
# CLANGPDB -Linux, Windows, Mac- Requires:
# Clang 9 or above from http://releases.llvm.org/
# Optional:
# Required to compile nasm source:
# nasm compiler from
# NASM -- http://www.nasm.us/
# Required to build platforms or ACPI tables:
# Intel(r) ACPI Compiler from
# https://acpica.org/downloads
あとは例によって QEMU で動作確認していきます。
いつもどおり、起動ディスクイメージ(disk.img)を作成してもいいですし、ローカルディレクトリを起動ディスクに見せかけて起動してもいいかもしれない。
# なんか適当な場所で。
$ mkdir -p ./DISK/EFI/BOOT/
$ cp $HOME/Code/edk2/Build/MikanLoaderX64/DEBUG_CLANGPDB/X64/Loader.efi ./DISK/EFI/BOOT/
# 起動!
$ qemu-system-x86_64 \
-drive if=pflash,file=$HOME/Code/mikanos-build/devenv/OVMF_CODE.fd \
-drive if=pflash,file=$HOME/Code/mikanos-build/devenv/OVMF_VARS.fd \
-hda fat:rw:./DISK
おぉー。
(2021/03/30 追記: 以下、day02b について。)
EFI_STATUS gBS->GetMemoryMap (
IN OUT UINTN *MemoryMapSize,
OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
OUT UINTN *MapKey,
OUT UINTN *DescriptorSize,
OUT UINT32 *DescriptorVersion
);
引数 | 型 | 用途 |
---|---|---|
MemoryMapSize | UINTN* | (入力)メモリマップ書き込み用のメモリ領域のサイズ (出力) 実際のメモリマップの大きさ |
MemoryMap | EFI_MEMORY_DESCRIPTER* | 実際のメモリマップが書き込まれたあとのアドレス |
MapKey | UINTN* | メモリマップを識別するための値。メモリマップに変化があったら値が変わる。 |
DescriptorSize | UINTN* | メモリディスクリプタのサイズ。 |
DescriptorVersion | UINT32 | メモリディスクリプタのバージョン。 |
typedef struct {
///
/// Type of the memory region.
/// Type EFI_MEMORY_TYPE is defined in the
/// AllocatePages() function description.
///
UINT32 Type;
///
/// Physical address of the first byte in the memory region. PhysicalStart must be
/// aligned on a 4 KiB boundary, and must not be above 0xfffffffffffff000. Type
/// EFI_PHYSICAL_ADDRESS is defined in the AllocatePages() function description
///
EFI_PHYSICAL_ADDRESS PhysicalStart;
///
/// Virtual address of the first byte in the memory region.
/// VirtualStart must be aligned on a 4 KiB boundary,
/// and must not be above 0xfffffffffffff000.
///
EFI_VIRTUAL_ADDRESS VirtualStart;
///
/// NumberOfPagesNumber of 4 KiB pages in the memory region.
/// NumberOfPages must not be 0, and must not be any value
/// that would represent a memory page with a start address,
/// either physical or virtual, above 0xfffffffffffff000.
///
UINT64 NumberOfPages;
///
/// Attributes of the memory region that describe the bit mask of capabilities
/// for that memory region, and not necessarily the current settings for that
/// memory region.
///
UINT64 Attribute;
} EFI_MEMORY_DESCRIPTOR;
フィールド名 | 型 | 説明 |
---|---|---|
Type | UINT32 | メモリ領域の種別 |
PhysicalStart | EFI_PHYSICAL_ADDRESS | メモリ領域先頭の物理メモリアドレス |
VirtualStart | EFI_VIRTUAL_ADDRESS | メモリ領域先頭の仮想メモリアドレス |
NumberOfPage | UINT64 | メモリ領域の大きさ(4KiB ページ単位) |
Attribute | UINT64 | メモリ領域が使える用途を示すビット集合 |
# OSのソース準備
$ cd ~/Code/mikanos
$ git checkout osbook_day02b
# EDK II 実行準備
$ cd ~/Code/edk2
$ source ./edksetup.sh
$ build
# 起動ディスクイメージの作成(省略)
# QEMU実行
$ qemu-system-x86_64 \
-drive if=pflash,file=$HOME/Code/mikanos-build/devenv/OVMF_CODE.fd \
-drive if=pflash,file=$HOME/Code/mikanos-build/devenv/OVMF_VARS.fd \
-hda ./disk.img
QEMU 実行画面の様子。
取得できた mmap の内容。
Index, Type, Type(name), PhysicalStart, NumberOfPages, Attribute
0, 3, EfiBootServicesCode, 00000000, 1, F
1, 7, EfiConventionalMemory, 00001000, 9F, F
2, 7, EfiConventionalMemory, 00100000, 700, F
3, A, EfiACPIMemoryNVS, 00800000, 8, F
4, 7, EfiConventionalMemory, 00808000, 8, F
5, A, EfiACPIMemoryNVS, 00810000, F0, F
6, 4, EfiBootServicesData, 00900000, B00, F
7, 7, EfiConventionalMemory, 01400000, 2B36, F
8, 4, EfiBootServicesData, 03F36000, 20, F
9, 7, EfiConventionalMemory, 03F56000, 276E, F
10, 1, EfiLoaderCode, 066C4000, 2, F
11, 4, EfiBootServicesData, 066C6000, A, F
12, 9, EfiACPIReclaimMemory, 066D0000, 1, F
13, 4, EfiBootServicesData, 066D1000, 1BB, F
14, 3, EfiBootServicesCode, 0688C000, A8, F
15, A, EfiACPIMemoryNVS, 06934000, 12, F
16, 0, EfiReservedMemoryType, 06946000, 1C, F
17, 3, EfiBootServicesCode, 06962000, 10A, F
18, 6, EfiRuntimeServicesData, 06A6C000, 5, F
19, 5, EfiRuntimeServicesCode, 06A71000, 5, F
20, 6, EfiRuntimeServicesData, 06A76000, 5, F
21, 5, EfiRuntimeServicesCode, 06A7B000, 5, F
22, 6, EfiRuntimeServicesData, 06A80000, 5, F
23, 5, EfiRuntimeServicesCode, 06A85000, 7, F
24, 6, EfiRuntimeServicesData, 06A8C000, 8F, F
25, 4, EfiBootServicesData, 06B1B000, 730, F
26, 7, EfiConventionalMemory, 0724B000, 4, F
27, 4, EfiBootServicesData, 0724F000, 6, F
28, 7, EfiConventionalMemory, 07255000, 1, F
29, 4, EfiBootServicesData, 07256000, 7C5, F
30, 7, EfiConventionalMemory, 07A1B000, 1, F
31, 3, EfiBootServicesCode, 07A1C000, 17F, F
32, 5, EfiRuntimeServicesCode, 07B9B000, 30, F
33, 6, EfiRuntimeServicesData, 07BCB000, 24, F
34, 0, EfiReservedMemoryType, 07BEF000, 4, F
35, 9, EfiACPIReclaimMemory, 07BF3000, 8, F
36, A, EfiACPIMemoryNVS, 07BFB000, 4, F
37, 4, EfiBootServicesData, 07BFF000, 201, F
38, 7, EfiConventionalMemory, 07E00000, 8D, F
39, 4, EfiBootServicesData, 07E8D000, 20, F
40, 3, EfiBootServicesCode, 07EAD000, 20, F
41, 4, EfiBootServicesData, 07ECD000, 9, F
42, 3, EfiBootServicesCode, 07ED6000, 1E, F
43, 6, EfiRuntimeServicesData, 07EF4000, 84, F
44, A, EfiACPIMemoryNVS, 07F78000, 88, F
45, 6, EfiRuntimeServicesData, FFC00000, 400, 1