借り初めのひみつきち

仮ブログです。

最小の UEFI Hello World

UEFI は実行ファイルに PE/COFF という形式を採用しています。

PE/COFF 形式はご存知の方も多いかと思いますが Windows で現在主流の実行ファイル形式で、名前の通り昔 UN*X で使われていた COFF 形式の派生です。
COFF から PE/COFF になる際にオリジナルの COFF の機能のいくつかは廃れ、逆に Windows に必要な情報がいくつか追加されました。その際、元の COFF にあった廃れたフィールドはそのまま残し、新たに追加されたフィールドは Optional Header に追記する形で拡張されました。
またその後 Windows の進化に合わせて PE/COFF にも新しい機能が追加されたり廃れたりしました。
このような経緯のため PE/COFF のヘッダーにはほとんど使われていないフィールドが多数存在します。*1

また、 PE/COFF は DOS や古い Windows との互換性のために DOS Stub というダミーの DOS プログラムが含まれています。*2


UEFI では仕様を決める際に実行形式として PE/COFF を利用することが決まりました。
Windows のために色々な機能がてんこ盛りされた PE/COFF ですが UEFI ではほとんどの機能が不要なので使われていません。
つまり、適当なツールで適当に生成された UEFI の PE/COFF には無駄がたくさん詰まってるということになります。


というわけで、最小の UEFI Hello World に挑戦してみたのが以下になります。345 バイトになりました。

github.com

これ以上小さくするには使われていないヘッダフィールドに別のヘッダーを埋め込むようなテクニックが必要になりますが、 BaseOfCode を 0x1000 より小さくするのが難しそうだったのでヘッダーに埋め込むのは無理かもしれません。


ところで、 PE/COFF には無駄がたくさん詰まっているということは偉い人も気づいていたようで、 EFI の初期化環境である PEI 仕様では TE (Terse Executable) という形式がサポートされています。
TE 形式は PE/COFF から DOS Stub を廃止して COFF Header と Optional Header から最小限の重要な情報だけを抜粋した独自のヘッダーに差し替えたものです。

f:id:neriring16:20191104194532p:plain:w300

UEFI BIOS ROM イメージをダンプしてみると TE 形式のファイルが埋め込まれているのが確認できます。

f:id:neriring16:20191104195304p:plain:w300


PE 形式から TE 形式にコンバートするだけで COFF Header と Optional Header の無駄なフィールドがほとんど消えて数百バイト節約でき、理論上 Hello world が 120 バイト前後まで小さくできます。
しかし、試しに手元でバイナリーをいじってみたところうまく実行できませんでした。
ヘッダーの書き方が悪かったのか、それとも通常の EFI Application 実行環境ではサポートされていないのかいまのところ不明です。

*1:ただし明確に使用しないと明言されているフィールドは少なく、使われているのかどうか不明なフィールドも多数存在します。

*2:多くの場合 DOS Stub はメッセージを出すだけの小さなプログラムですが、 EXE 形式で実現可能なプログラムは何でも入れることができるのでまれに DOS Stub の部分だけでひとつのアプリケーションになっている場合もありました。