Slide 1

Slide 1 text

自己紹介 ● orumin – 学生 ● sepcamp2012, GSoC(now) ● twitter: @kotatsu_mi

Slide 2

Slide 2 text

自己紹介 ● orumin – 学生 ● sepcamp2012, GSoC(now) ● twitter: @kotatsu_mi ● 側転できなさそうな顔の人とか TL 大破とか

Slide 3

Slide 3 text

自己紹介 ● orumin – 学生 ● sepcamp2012, GSoC(now) ● twitter: @kotatsu_mi ● 側転できなさそうな顔の人とか TL 大破とか ● ておくれではない

Slide 4

Slide 4 text

ておくれではないので, みんなにわかりやすいネタ, やります 既に知ってたらごめんなさい

Slide 5

Slide 5 text

ておくれではないので, みんなにわかりやすいネタ, やります 既に知ってたらごめんなさい

Slide 6

Slide 6 text

UEFI

Slide 7

Slide 7 text

Introduction for developping UEFI app/driver

Slide 8

Slide 8 text

UEFI ● 初出 - “Play with UEFI” カーネル VM 関西 4 ● “ いじぇくと的ななにか” カーネル /VM 探検隊 第九回

Slide 9

Slide 9 text

UEFI ● ベタ C 移植 ? ● Python? ● EFI Protocol? ● なぞのシェル

Slide 10

Slide 10 text

UEFI ● わからん ● どう開発してるのか ● どう動くのか ● ておくれ

Slide 11

Slide 11 text

UEFI ● UEFI は真面目に利便性の高いもの ● ておくれてないよ !

Slide 12

Slide 12 text

UEFI( 加筆 ) ● そもそも UEFI とは, BIOS をおきかえるもの ● UEFI 自体にブートローダーやシェルのような ものが実装されている ● 自作のアプリケーション,ドライバが簡単に作 れ動かせる ← ココ重要

Slide 13

Slide 13 text

First Step

Slide 14

Slide 14 text

First Step ● まずは SDK のインストール 今回は UDK について説明します UDK は EDK(II) の stable で,現在 2014 が最新 (syuu1228 さん,情報提供ありがとうございます )

Slide 15

Slide 15 text

First Step $ mkdir ~/src $ cd ~/src $ svn co https://edk2.svn.sourceforge.net/svnroot/ edk2/trunk/edk2 $ make -C edk2/BaseTools $ cd ~/src/edk2 $ export EDK_TOOLS_PATH=$HOME/src/edk2/BaseTools $ source edksetup.sh BaseTools

Slide 16

Slide 16 text

FirstStep ● ${EDK_TOOLS_PATH}/Conf ● TOOLS_CHAIN_TAG 変数 ● ACTIVE_PLATFORM 変数

Slide 17

Slide 17 text

FirstStep ● ${EDK_TOOLS_PATH}/Conf/target.txt ● TOOLS_CHAIN_TAG 変数 -> GCC47 ● ACTIVE_PLATFORM 変数 -> FooPkg/FooPkg.dec

Slide 18

Slide 18 text

FirstStep ● ${EDK_TOOLS_PATH}/Conf/target.txt ● TOOLS_CHAIN_TAG 変数 -> GCC47 ● ACTIVE_PLATFORM 変数 -> FooPkg/FooPkg.dec ● 準備完了

Slide 19

Slide 19 text

FirstStep ● ${EDK_TOOLS_PATH}/Conf/target.txt ● TOOLS_CHAIN_TAG 変数 -> GCC47 ● ACTIVE_PLATFORM 変数 -> FooPkg/FooPkg.dec ● 準備完了 ● build コマンドでビルドしはじめる

Slide 20

Slide 20 text

Second Step

Slide 21

Slide 21 text

Second Step ● プロジェクトの設定 ● 設定ファイルは基本的には ini ファイルの変種

Slide 22

Slide 22 text

Second Step ● プロジェクトの設定 ● 設定ファイルは基本的には ini ファイルの変種 ● UNIX-Like OS で開発してても,滲み出る そこはかとない Windows っぽさ

Slide 23

Slide 23 text

Second Step ● *.dec [Defines] DEC_SPECIFICATION = 0x00010005 PACKAGE_NAME = AppPkg PACKAGE_GUID = B3E3D3D5-D62B-4497-A175-264F489D127E PACKAGE_VERSION = 0.01

Slide 24

Slide 24 text

Second Step ● たった 4 行 ● 設定ファイルのバージョン ● プロジェクト名 ● UUID ● プロジェクトのバージョン

Slide 25

Slide 25 text

Second Step ● *.dsc [Defines] PLATFORM_NAME = AppPkg PLATFORM_GUID = 0458dade-8b6e-4e45-b773-1b27cbda3e06 PLATFORM_VERSION = 0.01 DSC_SPECIFICATION = 0x00010006 OUTPUT_DIRECTORY = Build/AppPkg SUPPORTED_ARCHITECTURES = IA32|IPF|X64 BUILD_TARGETS = DEBUG|RELEASE SKUID_IDENTIFIER = DEFAULT

Slide 26

Slide 26 text

Second Step ● プロジェクト名 ● UUID(*.dec とは違うもの ) ● プロジェクトのバージョン ● 設定ファイルのバージョン ● ビルドの出力先 ● ターゲットアーキテクチャ ● ビルドターゲット

Slide 27

Slide 27 text

Second Step ● まだまだ続く

Slide 28

Slide 28 text

Second Step [LibraryClasses] UefiApplicationEntryPoint| MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf ShellCEntryLib| ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf UefiDriverEntryPoint| MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf

Slide 29

Slide 29 text

Second Step ● この LibraryClasses セクションは, foo|path/to/libraryfolder という形 ● foo はなんでも良いけれど, UDK 内の既存プ ロジェクトに従ったほうが良い

Slide 30

Slide 30 text

Second Step ● 最初の 3 つはエントリポイントについての ライブラリをプロジェクトに読み込む ● これをしないとエントリポイントつくれない ● 3 つのエントリポイントの違いは後ほど

Slide 31

Slide 31 text

Second Step BaseLib|MdePkg/Library/BaseLib/BaseLib.inf BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf UefiLib|MdePkg/Library/UefiLib/UefiLib.inf PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf MemoryAllocationLib| MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf UefiBootServicesTableLib| MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf UefiRuntimeServicesTableLib| MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf

Slide 32

Slide 32 text

Second Step ● その他必要ライブラリのみなさん ● 必ずしもこれらが必要なわけではない ● UDK 内の既存プロジェクトとそのヘッダを 見てどんなユーティリティがあるか判断

Slide 33

Slide 33 text

No content

Slide 34

Slide 34 text

Second Step [Components] AppPkg/Applications/Hello/Hello.inf …

Slide 35

Slide 35 text

Second Step ● [Components] セクション ● プロジェクトを更にモジュール毎に分割した 小さいプロジェクトの設定ファイルのパス この設定ファイルは *.inf

Slide 36

Slide 36 text

Second Step ● dsc ファイルについて最後に ● libc とか web socket を使う場合だけ !include StdLib/StdLib.inc !include AppPkg/Applications/Sockets/Sockets.inc ● この 2 行で設定の読み込みが必要

Slide 37

Slide 37 text

Second Step

Slide 38

Slide 38 text

Second Step [Defines] INF_VERSION = 0x00010006 BASE_NAME = Hello FILE_GUID = a912f198-7f0e-4803-b908-b757b806ec83 MODULE_TYPE = UEFI_APPLICATION VERSION_STRING = 0.1 ENTRY_POINT = ShellCEntryLib

Slide 39

Slide 39 text

Second Step ● inf ファイルの [defines] セクション ● dsc の [defines] と大差なし ● ポイントは,ここで MODULE_TYPE と ENTRY_POINT を指定

Slide 40

Slide 40 text

Second Step ● MODULE_TYPE は UEFI_APPLICATION か UEFI_DRIVER ● ENTRY_POINT は dsc ファイルに書いて 読み込んだ 3 つ, ShellCLibEntryPoint UefiApplicationEntryPoint UefiDriverEntryPoint

Slide 41

Slide 41 text

Second Step [Sources] Hello.c [Packages] MdePkg/MdePkg.dec ShellPkg/ShellPkg.dec [LibraryClasses] UefiLib ShellCEntryLib

Slide 42

Slide 42 text

Second Step ● リンク / コンパイルするソース全て ● 使用するライブラリを含むパッケージの プロジェクト設定へのパス ● LibraryClasses ここでは, dsc に既に書いたので省略形で 記述

Slide 43

Slide 43 text

Second Step ● dsc の Components でモジュール分割するほどのプ ロジェクトでなければ, dsc のほうに MODULE_TYPE やら ENTRY_POINT や ら書いてしまって, inf には [Sources] だけというのも可能 ● inf を応用して,ソースコードだけ別フォルダに 分けるときに使うという使用方法もあり

Slide 44

Slide 44 text

エントリポイントについて UefiApplication 〜は UEFI の API 独自の作法に 従うエントリポイント EFI_IMAGE_HANDLE,EFI_SYSTEM_TABLE という型の引数で呼ばれる

Slide 45

Slide 45 text

エントリポイントについて ● ShellCLib 〜の場合は普通の main から スタート ● ほぼ完全にコード変更なしに pure C が動作 ● UEFI Protocol(API) を呼ぶのがちと面倒

Slide 46

Slide 46 text

エントリポイントについて ● UefiDriver 〜はいわずもがな, UEFI ドライバを記述するときの エントリポイント ● 引数は UefiApplication 〜と同様 ● ドライバはこれしかない ● UnEntryPoint の設定も必要

Slide 47

Slide 47 text

Let's coding

Slide 48

Slide 48 text

Let's coding ● さあ後はコーディングするだけ ! ● inf に適宜ソースファイル追加しつつ コーディングしましょう

Slide 49

Slide 49 text

Let's coding ● さあ後はコーディングするだけ ! ● inf に適宜ソースファイル追加しつつ コーディングしましょう ● Happy Hacking!!!

Slide 50

Slide 50 text

おわり

Slide 51

Slide 51 text

なワケないでショー !?

Slide 52

Slide 52 text

なワケないでショー !?

Slide 53

Slide 53 text

Let's coding ● UEFI Protocol について ● UEFI の API のこと ● なんで Protocol なんでしょうね ● データ駆動型 API です

Slide 54

Slide 54 text

Let's coding ● 基本的には, HandleProtocol() で特定の デバイス等の Handle を取得 ● その Handle を OpenProtocol() にぶちこんで Protocol 構造体にデータを詰め込んでもらう ● 構造体に詰められた関数ポインタを通して API コール

Slide 55

Slide 55 text

No content

Slide 56

Slide 56 text

Let's coding typedef struct { EFI_TABLE_HEADER Hdr*; CHAR16 *FirmwareVendor; UINT32 FirmwareRevision; EFI_HANDLE ConsoleInHandle; EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn; EFI_HANDLE ConsoleOutHandle; EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut;

Slide 57

Slide 57 text

Let's coding EFI_HANDLE StandardErrorHandle; EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *StdErr; EFI_RUNTIME_SERVICES *RuntimeServices; EFI_BOOT_SERVICES *BootServices; UINTN NumberOfTableEntries; EFI_CONFIGURATION_TABLE *ConfigurationTable; } EFI_SYSTEM_TABLE; ●

Slide 58

Slide 58 text

Let's coding EFI_HANDLE StandardErrorHandle; EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *StdErr; EFI_RUNTIME_SERVICES *RuntimeServices; EFI_BOOT_SERVICES *BootServices; UINTN NumberOfTableEntries; EFI_CONFIGURATION_TABLE *ConfigurationTable; } EFI_SYSTEM_TABLE; ●

Slide 59

Slide 59 text

Let's coding ● gST,gRS,gBS … 既に宣言 ● gBS が特に重要 LocateHandle() , Open/CloseProtocol() 他にも LoadImage() , StartImage() ExitBootServices() 等 ● 最悪 EFI_SYMPLE_FILE_SYSTEM_PROTOCOL と EFI_BOOT_SERVICES だけでブートローダ書ける

Slide 60

Slide 60 text

● ドライバの場合,加えてヘッダで自身の プロトコルのデータ構造を公開 ● DRIVER_BINDING_PROTOCOL で プロトコルをデバイスに対して使えるかの チェック,プロトコル開始時の資源確保, プロトコル終了時の資源解放を記述

Slide 61

Slide 61 text

Let's coding ● 実際のコードを見てみよう https://github.com/tianocore/edk2-FatPkg *.dec と *.dsc と *.inf が設定, Fat.h に各種宣言, Fat.c が EntryPoint 他にも Fat.c でつかわれる Lock が Misc.c デバイスのアロケートを Init.c Read/Write を ReadWrite.c… という具合

Slide 62

Slide 62 text

おわりに ● 駆け足だったので伝わらない部分もあったはず ● スライド上げとくのでどうぞ読み直して下さい ● デモ用意できませんでした ● 最小限のプロジェクトのテンプレートを GitHub に上げとく ( 予定 )

Slide 63

Slide 63 text

おわりに ● UDK は VisualStudio でも使えます (Windows ユーザーさんどうぞ ) ● UNIX Like な OS で動作させる前提のツールは gnu-efi のほうが楽かもしれません GrowBuffer() や LocateHandlebyDiskSignature() とか ● rEFInd とか参考にしてね ! http://sourceforge.net/projects/refind/files/

Slide 64

Slide 64 text

余談 ● Hibernation 中の swap パーティションの snapshot を UEFI app で弄ったりして, secure boot の secure さを壊せるのでは ? https://lkml.org/lkml/2013/8/22/218 ● 発端 http://lists.opensuse.org/opensuse-kernel/ 2013-09/msg00068.html