UEFI Advent Calender 12日目だったoruminです
盛大に遅刻かましてもはや遅刻とさえ言えない感じです。
UEFIのアプリケーション、まずどう作るかわからない方も多いかと思います。
まず、UEFIが実行できる実行形式について、これはWindowsと同じPEバイナリです。
また、EDKのようなツールキットを用いる必要がありますが、
今回はgnu-efiで説明します。
gnu-efiとは、BSDLなEFIアプリケーション開発用ライブラリです。
LinuxやBSDでの開発に親和性が高いと思われます。
これは最近だとaptやpacmanでそのままバイナリインストールが可能です。
そして、次にこのようなファイルを用意します
前者がUEFIでのHello, World!です。efi_mainがエントリポイント、
ImageHandleもSystemTableもUEFIのAPI(Protocol)を呼び出し、使うのに必要なパラメータとなります。
今回は、gnu-efiの初期化をしてから文字列を出力するだけなので特に使用していません。
デバッグ文字列出力は
後者のMakefileについては、書いてある通りです。
ライブラリとインクルードファイルの指定、
それにリンカスクリプトやスタートアップルーチンはgnu-efiのものを使うように指定。
shared objectな実行ファイルを作ってから、
objcopyコマンドで必要な部分を抜き出す(ELFヘッダは要らないので)
という流れになります。
CFLAGSについては、色々ごちゃっと指定してますが、
まず必須なのは-fPICと-fshort-wchar、そしてx86_64であれば-DEFI_FUNCTION_WRAPPERだけで、あとのは特段必ず指定しないといけないものではないです。
さて、これでmakeをしますと、hello.efiが作成されるので、
あとはEFIシステムパーティション直下にでも置いてあげて、起動時にUEFI Shellを立ち上げてから
hello.efi
とコマンドを入力してみてください。Hello, EFI!と文字列が出たら成功です!
UEFIの開発やProtocolについては、1日目の記事の最後に書いたドキュメントがオススメですが、
リファレンスよりも手軽にProtocolの型や名前だけ把握するには、
Phoenixのwikiが便利です。
盛大に遅刻かましてもはや遅刻とさえ言えない感じです。
UEFIのアプリケーション、まずどう作るかわからない方も多いかと思います。
まず、UEFIが実行できる実行形式について、これはWindowsと同じPEバイナリです。
また、EDKのようなツールキットを用いる必要がありますが、
今回はgnu-efiで説明します。
gnu-efiとは、BSDLなEFIアプリケーション開発用ライブラリです。
LinuxやBSDでの開発に親和性が高いと思われます。
これは最近だとaptやpacmanでそのままバイナリインストールが可能です。
そして、次にこのようなファイルを用意します
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include<efi.h> | |
#include<efilib.h> | |
EFI_STATUS | |
efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) | |
{ | |
InitializeLib(ImageHandle, SystemTable); | |
Print(L"Hello, EFI!\n"); | |
return EFI_SUCCESS; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ARCH = x86_64 | |
EFIROOT = /usr | |
HDDRROOT = $(EFIROOT)/include/efi | |
INCLUDES = -I. -I$(HDDRROOT) -I$(HDDRROOT)/$(ARCH) -I$(HDDRROOT)/protocol | |
CRTOBJS = $(EFIROOT)/lib/crt0-efi-$(ARCH).o | |
CFLAGS = -O2 -fPIC -Wall -fshort-wchar -fno-strict-aliasing -fno-merge-constants -mno-red-zone | |
ifeq ($(ARCH),x86_64) | |
CFLAGS += -DEFI_FUNCTION_WRAPPER | |
endif | |
CPPFLAGS = -DCONFIG_$(ARCH) | |
FORMAT = efi-app-$(ARCH) | |
INSTALL = install | |
LDFLAGS = -nostdlib | |
LDSCRIPT = $(EFIROOT)/lib/elf_$(ARCH)_efi.lds | |
LDFLAGS += -T $(LDSCRIPT) -shared -Bsymbolic -L$(EFIROOT)/lib $(CRTOBJS) | |
LOADLIBS = -lefi -lgnuefi $(shell $(CC) -print-libgcc-file-name) | |
prefix = | |
CC = $(prefix)gcc | |
AS = $(prefix)as | |
LD = $(prefix)ld | |
AR = $(prefix)ar | |
RANLIB = $(prefix)ranlib | |
OBJCOPY = $(prefix)objcopy | |
%.efi: %.so | |
$(OBJCOPY) -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel \ | |
-j .rela -j .reloc --target=$(FORMAT) $*.so $@ | |
%.so: %.o | |
$(LD) $(LDFLAGS) $^ -o $@ $(LOADLIBS) | |
%.o: %.c | |
$(CC) $(INCLUDES) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ | |
TARGETS = hello.efi | |
all: $(TARGETS) | |
clean: | |
rm -f $(TARGETS) |
前者がUEFIでのHello, World!です。efi_mainがエントリポイント、
ImageHandleもSystemTableもUEFIのAPI(Protocol)を呼び出し、使うのに必要なパラメータとなります。
今回は、gnu-efiの初期化をしてから文字列を出力するだけなので特に使用していません。
デバッグ文字列出力は
SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Hello, EFI!\n");でも良いのですが。
後者のMakefileについては、書いてある通りです。
ライブラリとインクルードファイルの指定、
それにリンカスクリプトやスタートアップルーチンはgnu-efiのものを使うように指定。
shared objectな実行ファイルを作ってから、
objcopyコマンドで必要な部分を抜き出す(ELFヘッダは要らないので)
という流れになります。
CFLAGSについては、色々ごちゃっと指定してますが、
まず必須なのは-fPICと-fshort-wchar、そしてx86_64であれば-DEFI_FUNCTION_WRAPPERだけで、あとのは特段必ず指定しないといけないものではないです。
さて、これでmakeをしますと、hello.efiが作成されるので、
あとはEFIシステムパーティション直下にでも置いてあげて、起動時にUEFI Shellを立ち上げてから
hello.efi
とコマンドを入力してみてください。Hello, EFI!と文字列が出たら成功です!
UEFIの開発やProtocolについては、1日目の記事の最後に書いたドキュメントがオススメですが、
リファレンスよりも手軽にProtocolの型や名前だけ把握するには、
Phoenixのwikiが便利です。