もちろん、そのまま Main.c
を写経して clang
に通しても
$ clang -c Main.c Main.c:1:10: fatal error: 'Uefi.h' file not found #include <Uefi.h> ^~~~~~~~ 1 error generated.
となる。ansible
によって $HOME/edk2
の下に EDK II が準備されているので、ここに移動して
ln -s $HOME/git_work/osbook/day02a/MikanLoaderPkg ./
みたいなことをする。そして、次に
$ source edksetup.sh Using EDK2 in-source Basetools WORKSPACE: /home/xxx/edk2 EDK_TOOLS_PATH: /home/xxx/edk2/BaseTools CONF_PATH: /home/xxx/edk2/Conf Copying $EDK_TOOLS_PATH/Conf/build_rule.template to /home/xxx/edk2/Conf/build_rule.txt Copying $EDK_TOOLS_PATH/Conf/tools_def.template to /home/xxx/edk2/Conf/tools_def.txt Copying $EDK_TOOLS_PATH/Conf/target.template to /home/xxx/edk2/Conf/target.txt
だが、「開発者コマンドプロンプト for VS 201X」のような気持ちになるな。
とりあえずこの呪文を唱えると $HOME/edk2/BaseTools/BinWrappers/PosixLike/build
が見えるようになる。変な generic な名称のコマンドがグローバルに見えているのだろうかと最初不安になった・・・(本の脚注にひっそりと説明されている)。
そんなわけで build
すると clang
に謎のインクルードパスが渡った状態で色々コンパイルが走り、途中で nasm
の文字を見ながらビルド行程が進む。
できあがった Loader.efi
を使って
sh run_qemu.sh Loader.efi
などで UEFI ブートすると「Hello, Mikan World!」が出る。
Print
関数の定義は
find MdePkg/Include/ -name "*.h" | xargs grep -n Print
で簡単に見つかって、MdePkg/Include/Library/UefiLib.h
の中で
UINTN EFIAPI Print ( IN CONST CHAR16 *Format, ... );
のように定義されている。対応する実装は MdePkg/Library/UefiLib/UefiLibPrint.c
のほうで
UINTN
EFIAPI
Print (
IN CONST CHAR16 *Format,
...
)
{
VA_LIST Marker;
UINTN Return;
VA_START (Marker, Format);
Return = InternalPrint (Format, gST->ConOut, Marker);
VA_END (Marker);
return Return;
}
そして
UINTN InternalPrint ( IN CONST CHAR16 *Format, IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Console, IN VA_LIST Marker ) { ... if (Console != NULL && Return > 0) { Status = Console->OutputString (Console, Buffer); if (EFI_ERROR (Status)) { Return = 0; } } ... return Return;
となっている。本の p.43 でやっている内容が可変引数の関数化されていることが分かる。これで第 2 章前半(〜p.55)は終わり。