これからX64向けのUEFIバイナリをビルドしようとしている人々へ

EDK2向けに記事を書くけど、他のSDKを使う場合でも同じ問題が生じると思うので、gnu-efiな人達も読んでおいて下さい。
なお、この問題はIA32では確認できないのですが、どうしてそうなるのか僕はx86のABIにあまり詳しくないので良く分かりません。IA32だと吐くバイナリのABIがちゃんと合うとかそういうことかなーと思ってます。

EDK2だとツールチェインとしてmingwを使う場合の説明が本家のドキュメントに乗ってますが、x64環境だとWindowsUnixではlongの長さが違うとかの理由で(64ビット - Wikipedia)libc・posix apibsd socketなどのライブラリを提供するStdLibのビルドが通りません(手直しする事も可能かと思いますが、オススメはしません)。

そこで、ドキュメントを読んでみるとホストOS向けのgcc 4.4-4.6を使う方法が紹介されているんですが、実はこれでバイナリをビルドすると微妙にABIが合わないみたいなんです
結果として、あなたのUEFIアプリケーションはUEFIファームウェアで微妙に実行できた後に、どこかのAPIを叩いた瞬間にUEFIファームウェアがエラーを起こし実行が停止され、マシンはフリーズしたようになってしまいます。(その顛末についてはこちらで若干紹介している
なんという悲劇。

これを回避するには、Conf/tools_def.txtのCFLAGSを設定している項目で、以下の様な感じに"-mabi=ms"を指定してあげる必要があります。
この場合はGCC44の設定になってますが、設定する場所は自分の使うツールチェインに合わせてください。

DEFINE GCC44_X64_CC_FLAGS            = DEF(GCC44_ALL_CC_FLAGS) -mabi=ms -m64 "-DEFIAPI=__attribute__((ms_abi))" -DNO_BUILTIN_VA_FUNCS -mno-red-zone -Wno-address -mcmodel=large

これで全てが解決する模様です。
恐らく、mingwだと最初からmabi=msで問題が起きないのかなー、などと予想しています。が、そこも未調査なので勘違いかもしれません。

参考:このへんでも話題になってる


追記:
Twitterでそもそもgnu-efiはX64に対応できていないのでは、というご指摘を受けました。
こちらでの確認は出来ていませんが、これから使おうとしている方はその点を注意して見てみたほうがいいかもしれません。