このページは、技術書典6にて頒布した、OS Girlsを購入してくださった皆さま向けに情報を提供するページです。
pdf版の書籍は、BOOTHで販売しています。
かんたん後払いで購入いただいたみなさまは、技術書典のマイページからpdfをダウンロードできるはずです。詳細は、技術書典運営による案内ツイートを参考にしてください。
「そういえば先輩、今まで教えていただいたプログラムなんですけど、家に帰ってからちょっと遊んでみたいなあって思ったんですが、データをいただけたりしますか?」
突然思い出したように声をかけてきたアキに驚き、音声が認識されるまで数秒のディレイがあったものの、カオルが反応する。
「もちろん。実はここから全部見れるようにしておいたから、家に帰ってからアクセスするといい。」
https://github.com/hikalium/os-girls-examples
「ありがとうございます!ところでこれ、動かすのに何か準備が必要だったりしますか?」
「そうだね、macOSを使っているなら私と一緒だから、最初のサンプルコードと一緒に書いておいた解説を読んでくれればだいたいわかると思う。LinuxとかWindowsだとまた別の手順が必要になるんだけど、それは余裕があったら追記しておくよ。リナがはやくLinux対応しろってうるさいんだよねえ…。」
「先輩Linux大好きですもんねー!あ、そういえばあのペンギンのマスコットって、もしかして?」
リナが放置していったカバンに視線を向けつつアキが尋ねる。
「いや、あれはこの前水族館に行った時に私がプレゼントした。単純にペンギンが好きみたい。」
「なるほど?どっちが先なのか、ちょっと気になりますけど…。」
まあ考えても仕方ないかー、と、アキは自分のディスプレイに向き直った。
「ねえカオル、ところでさっき二人にやらせてた、Hello, world!のefi.h
ってどんなやつなの?あと、なんでbuild.sh
なんて回りくどいことしたわけ?」
学校から駅へと続く道でリナが尋ねた。
「あー、efi.h
の中身はこんな感じ。解説はまた今度話すよ。」
そういってカオルは歩きながらPCを操作してリナに渡した。
#include <stdint.h>
typedef void* Handle;
typedef uint64_t UINTN;
struct TableHeader {
uint64_t signature;
uint32_t revision;
uint32_t header_size;
uint32_t crc32;
uint32_t reserved;
};
class SimpleTextInputProtocol;
class RuntimeServices;
class BootServices;
class ConfigurationTable;
int main();
struct SimpleTextOutputProtocol {
uint64_t _buf;
uint64_t (*output_string)(SimpleTextOutputProtocol*, const wchar_t*);
uint64_t (*test_string)(SimpleTextOutputProtocol*, wchar_t*);
uint64_t (*query_mode)(SimpleTextOutputProtocol*,
wchar_t*,
uint64_t* columns,
uint64_t* rows);
uint64_t (*set_mode)(SimpleTextOutputProtocol*, uint64_t);
uint64_t (*set_attribute)(SimpleTextOutputProtocol*, uint64_t Attribute);
uint64_t (*clear_screen)(SimpleTextOutputProtocol*);
};
struct SystemTable {
TableHeader header;
wchar_t* firmware_vendor;
uint32_t firmware_revision;
Handle console_in_handle;
SimpleTextInputProtocol* con_in;
Handle console_out_handle;
SimpleTextOutputProtocol* con_out;
Handle standard_error_handle;
SimpleTextOutputProtocol* std_err;
RuntimeServices* runtime_services;
BootServices* boot_services;
UINTN number_of_table_entries;
ConfigurationTable* configuration_table;
};
SystemTable *efi_system_table;
void EFIPutChar(wchar_t c) {
wchar_t buf[2];
buf[0] = c;
buf[1] = 0;
efi_system_table->con_out->output_string(efi_system_table->con_out, buf);
}
void puts(const char *s) {
while(*s) {
EFIPutChar(*s);
s++;
}
}
void efi_main(Handle image_handle, SystemTable* system_table) {
efi_system_table = system_table;
main();
for(;;);
};
「ふーん、結構短いんだ。これならあたしでも説明できそう。」
「そう?じゃあ明日の説明は任せた。」
「おっけい、どうせUEFI Spec読めば一発でしょ。で、build.sh
は?」
「それの横。」
set -x
/usr/local/opt/llvm/bin/clang++ \
-target x86_64-pc-win32-coff \
-fno-stack-protector -fshort-wchar \
-mno-red-zone \
-nostdlibinc \
-Wall -std=c++17 \
-c -o BOOTX64.o ${@:1}
/usr/local/opt/llvm/bin/lld-link \
-subsystem:efi_application -nodefaultlib \
-entry:efi_main BOOTX64.o -out:BOOTX64.EFI
「んー、意外と長かった。確かにこれは手打ちさせるのつらそう。」
「うん、それもあるけど、学校のPCはMacだから、デフォルトでLLVMが入ってるじゃない?あれ、劣化版LLVMで、PEバイナリを吐けないんだよ…。」
「まじか。やっぱりAppleさんやることが違いますね。LLVMはクロスコンパイルが容易なのがいいところなのに。」
「ほんとそう。AppleはLLVMの生みの親なのに、ひどいことするよね。で、デフォルトだとうまく行かないから、Homebrewで入れたLLVMを使いたいんだけど、そうするとパスの問題が出てくるじゃん?」
「あー、またタイプ数増えてつらいね。しかも自明じゃないし。」
「そうそう。だから、シェルスクリプトを用意したわけ。うまくやれば、WindowsとかLinuxでも操作を共通化できるしね。まだやってないけど。」
「まー、部員が増えたらでいいんじゃない?あたしたち卒業しちゃいそうだけど。」
「ね。あの2人の気が乗ったら、いつかやってもらおうか。」
「それはよさそう。」
「あと、USBメモリも私が用意したのを使わせたのは、FATでフォーマットさせるのが面倒だったからなんだよね。」
「確かに。ところで、USBメモリ何個もってるの?」
「うーんと、秘密。リナの方がいっぱいもってるでしょ?」
「かもね。じゃあ、また明日!バーイ!」
カオルは無言で手を振り返し、反対側のホームへと消えていった。
v1.0.1のp16は
s/elf.h/efi.h/
かと思われます。電子版でも同様でv1.0.0の頃からそのままかと思われます: https://twitter.com/MuneOiz/status/1119492415587438592