play with uefi

47
PLAY WITH UEFI @syuu1228 13216日土曜日

Upload: takuya-asada

Post on 05-Dec-2014

4.691 views

Category:

Technology


1 download

DESCRIPTION

 

TRANSCRIPT

Page 1: Play with UEFI

PLAY WITH UEFI@syuu1228

13年2月16日土曜日

Page 2: Play with UEFI

UEFI使ったことある人 ノ

13年2月16日土曜日

Page 3: Play with UEFI

UEFI APPLICATION書いたことある人 ノ

13年2月16日土曜日

Page 4: Play with UEFI

今日は簡単なUEFI APPLICATIONを書いて遊んでみようという話です

13年2月16日土曜日

Page 5: Play with UEFI

UEFIとは何か?

• 90年代にIntelとHPにより開発された、IA32/IA64共通のブートシステム

• PCに依然として残るレガシーな仕組みであるBIOSを置き換え

• CPU非依存なアーキテクチャ

• CPU非依存なドライバ

• 128partition・over 2TBのディスクをサポートするGPTを採用

• ネットワーク対応などの多彩な機能に対応

• モジュラー型のデザイン

• 高速起動にも寄与

13年2月16日土曜日

Page 6: Play with UEFI

(U)EFIの歴史1

• 1990年代にIntel・HPがIA64アーキテクチャを設計した時に、IA32/IA64両方で使えるファームウェア仕様を作ったのが始まり

• IA64ではそれしかないので使われていたが、IA32では広まらず

•例外:2006年にリリースされたIntel MacはEFI 1.10をベースにした独自ファームウェアを採用

13年2月16日土曜日

Page 7: Play with UEFI

(U)EFIの歴史2

• EFI specificationはIntelからUnified EFI Forumへ移管→規格名がUEFIに・2.x系がリリース

• 2009年頃から2TBの壁が問題視され始め、UEFI搭載PCが普及しはじめる・OSも標準対応へ

•普通にその辺のヨ○バシでUEFI対応機買えるように←イマココ!

13年2月16日土曜日

Page 8: Play with UEFI

MBRと2TBの壁

• MBRのパーティーションテーブルでは、開始セクタ値とセクタ数が32bit(4G sectors)

• 4G sectors * 512byte = 2TB!

• パーティーションテーブル変えるかセクタサイズ変えるしかない→互換性無くなる

• バッドノウハウで回避出来ないことも無いけど…

• もうしんどいしGPTを前提としているUEFIに移行しようよ

13年2月16日土曜日

Page 9: Play with UEFI

MBRとGPTの比較

• MBRではパーティーション:4個→128個

• セクタアドレス長:32bit→64bit

• パーティーションタイプ:1byte→16byte GUID

• ブートフラグ:1byte→属性フラグ:8bytes

• パーティーション名:72bytes UTF-16

• バックアップのパーティーションテーブル領域

13年2月16日土曜日

Page 10: Play with UEFI

GPT

13年2月16日土曜日

Page 11: Play with UEFI

GPT パーティションエントリ

13年2月16日土曜日

Page 12: Play with UEFI

UEFIの見た目

• 普通のBIOSみたいな起動画面である事が多い

• デフォルト設定でOSが自動的にブートされる限り、特にBIOSブートとの見た目上の違いはない

• 但し、よく見ると全然違う:

• Boot ManagerというGRUBのブートメニューのようなものがある

• UEFI Shellというコマンドプロンプトのようなシェルがある

13年2月16日土曜日

Page 13: Play with UEFI

メインメニュー

13年2月16日土曜日

Page 14: Play with UEFI

BOOT MANAGER

ブート項目の選択画面。OSは自分のブートローダをここに登録する

13年2月16日土曜日

Page 15: Play with UEFI

BOOT MAINTENANCE MANAGER

メニューの編集、ロードするドライバの指定、任意のファイルの実行など

13年2月16日土曜日

Page 16: Play with UEFI

UEFI SHELL

コマンドプロンプト風のシェル任意のOS起動などに使用

13年2月16日土曜日

Page 17: Play with UEFI

GRUB2 FOR UEFI

13年2月16日土曜日

Page 18: Play with UEFI

UEFIからのブート

BootManagerの設定値がデフォルトの場合

• UEFIがHDDを検出、GPTをロード

• EFI System Partitionを検索

• \EFI\BOOT\BOOTX64.EFIをロード(32bit環境ならBOOTX86.EFI)

13年2月16日土曜日

Page 19: Play with UEFI

EFI SYSTEM PARTITION

•パーティーションタイプGUIDがEFI System PartitionなFATファイルシステム

• GPTにブートセクタは無い

•ここからUEFIアプリケーションをロードする事により起動

13年2月16日土曜日

Page 20: Play with UEFI

UEFI APPLICATION

• 64bit protected modeのPEバイナリ(UEFIがx64版の場合)

•拡張子:.EFI

• UEFI APIを利用して各種処理を実装

13年2月16日土曜日

Page 21: Play with UEFI

UEFIからのブート厳密にはどうなっているか

以下のようなUEFI NVRAM variablesにより起動処理が制御される

• Boot####:ロードするUEFI applicationのPATH・又はディスクのデバイスPATH

• BootOrder:Boot####の試行順序(配列で指定)

• BootNext:次回起動時にロードするBoot####(BootOrderより優先、一度起動すると削除)

• Timeout:設定秒数だけBoot Menuを表示(自動起動を遅延)

13年2月16日土曜日

Page 22: Play with UEFI

設定例

• 起動まで10秒待つ

• ubuntu→HDD→CDROM→Network→Shellの順で試行

• ファイル指定がないドライブはEFI System Partitionの\EFI\BOOT\BOOTX64.EFIを探索

13年2月16日土曜日

Page 23: Play with UEFI

EFIBOOTMGR

• efibootmgrでブートメニューを編集

• カーネルは/sys/firmware/efi/vars/・/sys/firmware/efi/efivars/経由でUEFI NVRAM variablesへのユーザランドからのアクセスを許可している

13年2月16日土曜日

Page 24: Play with UEFI

/SYS/FIRMWARE/EFI/EFIVARS

syuu@ubuntu:~$ ls /sys/firmware/efi/efivarsBoot0000-8be4df61-93ca-11d2-aa0d-00e098032b8cBoot0001-8be4df61-93ca-11d2-aa0d-00e098032b8cBoot0002-8be4df61-93ca-11d2-aa0d-00e098032b8cBoot0003-8be4df61-93ca-11d2-aa0d-00e098032b8cBoot0004-8be4df61-93ca-11d2-aa0d-00e098032b8cBootCurrent-8be4df61-93ca-11d2-aa0d-00e098032b8c…

$ sudo cat /sys/firmware/efi/efivars/Boot0000-8be4df61-93ca-11d2-aa0d-00e098032b8c @EFI VMware Virtual SCSI Hard Drive (0.0) ?A?

13年2月16日土曜日

Page 25: Play with UEFI

UEFIの内部構造

PEI

CPU initChipset initBoard init

DXE

Load drivers

Device Drivers

Boot Manager

ServicesUEFIApps

UEFIBootloader

UEFI APIs

OS

Load UEFI apps

UEFI specificationPI specification

13年2月16日土曜日

Page 26: Play with UEFI

UEFIの内部構造

PEI

CPU initChipset initBoard init

DXE

Load drivers

Device Drivers

Boot Manager

ServicesUEFIApps

UEFIBootloader

UEFI APIs

OS

Load UEFI apps

UEFI specificationPI specification

今日はここを見ていきます

13年2月16日土曜日

Page 27: Play with UEFI

UEFI APPLICATIONの種類

•二種類のUEFI Application

•通常のUEFI Application:終了時にExit()をコールし、UEFI Shellなどに制御を戻す

• OS Loader:終了時にExitBootServices()をコールし、UEFIが利用していた資源を開放して制御をOSへ移す

13年2月16日土曜日

Page 28: Play with UEFI

MAIN() IN UEFI APPLICATION

EFI_STATUS

HelloMain ( IN EFI_HANDLE       ImageHandle,

            IN EFI_SYSTEM_TABLE *SystemTable)

引数は2個(ImageHandle、SystemTable)

ImageHandleはロードされたUEFI Applicationのイメージファイルに対するハンドル

SystemTableを経由して全てのUEFI APIへアクセス

13年2月16日土曜日

Page 29: Play with UEFI

UEFI SYSTEM TABLE

UEFI Applicationに対して公開するインタフェースが全て詰め込まれた構造体

Unified Extensible Firmware Interface Specification

80 June 27, 2012 Version 2.3.1, Errata C

the revision level of the table at the point when the capabilities were added to the UEFI specification.

Note: Unless otherwise specified, UEFI uses a standard CCITT32 CRC algorithm with a seed polynomial value of 0x04c11db7 for its CRC calculations.

Note: The size of the system table, runtime services table, and boot services table may increase over time. It is very important to always use the HeaderSize field of the EFI_TABLE_HEADER to determine the size of these tables.

4.3 EFI System Table UEFI uses the EFI System Table, which contains pointers to the runtime and boot services tables. The definition for this table is shown in the following code fragments. Except for the table header, all elements in the service tables are pointers to functions as defined in Section 6 and Section 7. Prior to a call to ExitBootServices(), all of the fields of the EFI System Table are valid. After an operating system has taken control of the platform with a call to ExitBootServices(), only the Hdr, FirmwareVendor, FirmwareRevision, RuntimeServices, NumberOfTableEntries, and ConfigurationTable fields are valid.

EFI_SYSTEM_TABLE

SummaryContains pointers to the runtime and boot services tables.

Related Definitions#define EFI_SYSTEM_TABLE_SIGNATURE 0x5453595320494249#define EFI_2_31_SYSTEM_TABLE_REVISION ((2<<16) | (31))#define EFI_2_30_SYSTEM_TABLE_REVISION ((2<<16) | (30))#define EFI_2_20_SYSTEM_TABLE_REVISION ((2<<16) | (20))#define EFI_2_10_SYSTEM_TABLE_REVISION ((2<<16) | (10))#define EFI_2_00_SYSTEM_TABLE_REVISION ((2<<16) | (00))#define EFI_1_10_SYSTEM_TABLE_REVISION ((1<<16) | (10))#define EFI_1_02_SYSTEM_TABLE_REVISION ((1<<16) | (02))#define EFI_SYSTEM_TABLE_REVISION EFI_2_30_SYSTEM_TABLE_REVISION#define EFI_SPECIFICATION_VERSION EFI_SYSTEM_TABLE_REVISION#define EFI_SYSTEM_TABLE_REVISION EFI_2_31_SYSTEM_TABLE_REVISION

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;

EFI System Table

Version 2.3.1, Errata C June 27, 2012 81

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;

ParametersHdr The table header for the EFI System Table. This header contains

the EFI_SYSTEM_TABLE_SIGNATURE and EFI_SYSTEM_TABLE_REVISION values along with the size of the EFI_SYSTEM_TABLE structure and a 32-bit CRC to verify that the contents of the EFI System Table are valid.

FirmwareVendor A pointer to a null terminated string that identifies the vendor that produces the system firmware for the platform.

FirmwareRevision A firmware vendor specific value that identifies the revision of the system firmware for the platform.

ConsoleInHandle The handle for the active console input device. This handle must support EFI_SIMPLE_TEXT_INPUT_PROTOCOL and EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.

ConIn A pointer to the EFI_SIMPLE_TEXT_INPUT_PROTOCOL interface that is associated with ConsoleInHandle.

ConsoleOutHandle The handle for the active console output device. This handle must support the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.

ConOut A pointer to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL interface that is associated with ConsoleOutHandle.

StandardErrorHandleThe handle for the active standard error console device. This handle must support the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.

StdErr A pointer to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL interface that is associated with StandardErrorHandle.

RuntimeServices A pointer to the EFI Runtime Services Table. See Section 4.5.

BootServices A pointer to the EFI Boot Services Table. See Section 4.4.

NumberOfTableEntriesThe number of system configuration tables in the buffer ConfigurationTable.

ConfigurationTable A pointer to the system configuration tables. The number of entries in the table is NumberOfTableEntries.

4.4 EFI Boot Services Table UEFI uses the EFI Boot Services Table, which contains a table header and pointers to all of the boot

services. The definition for this table is shown in the following code fragments. Except for the table

header, all elements in the EFI Boot Services Tables are prototypes of function pointers to functions

13年2月16日土曜日

Page 30: Play with UEFI

CONOUT, CONIN, STDERR

#include <Library/UefiApplicationEntryPoint.h>#include <Library/UefiLib.h> EFI_STATUS EFIAPIUefiMain (IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable){ SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Hello World\r\n"); return EFI_SUCCESS;}

•コンソールへの入出力API

•文字エンコーディングはUTF-16を使用

13年2月16日土曜日

Page 31: Play with UEFI

RUNTIME SERVICES

• ExitBootServices()後もUEFIがOSに対して提供するサービス

•最低限の機能のみ

• Time (GetTime, SetTime...)

• Virtual Memory (SetirtualAddressMap...)

• Variable Services (GetVariable...)

• Miscellaneous Services(ResetSystem...)

13年2月16日土曜日

Page 32: Play with UEFI

BOOT SERVICES

• ExitBootServices()までUEFI Applicationに提供するサービス

• Task Priority Services (RaiseTPL...)

• Memory Services (AllocatePages...)

• Event & Timer Services (CreateEvent, SetTimer...)

• Protocol Handler Services (HandleProtocol...)

• Image Services (LoadImage, StartImage...)

• Miscellaneous Services (Stall, CopyMem...)

• Open and Close Protocol Services (OpenProtocol...)

• Library Services (LocateProtocol...)

• 32bit CRC Services (CalculateCrc32...)

13年2月16日土曜日

Page 33: Play with UEFI

PROCOTOLS

•ネットワークプロトコルスタックのことではない

• UEFI上で提供される様々なサービスの事

• UEFI Driverを実装しUEFIへロードする事により、自作のProtocolを提供する事も可能

13年2月16日土曜日

Page 34: Play with UEFI

定義されているPROTOCOL

• EFI Loaded Image

• Device Path Protocol

• UEFI Driver Model

• Console Support

• Media Access

• PCI Bus Support

• SCSI Driver Models and Bus Support

• iSCSI Boot

• USB Support

• Debugger Support

• Compression Algorithm

• ACPI Protocols

• TCP/IP, IPSec, FTP

• ARP & DHCP

• UDP & MTFTP

• etc...

13年2月16日土曜日

Page 35: Play with UEFI

PROTOCOL利用例#define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID \{ \0x964e5b22, 0x6459, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} \}EFI_GUID gEfiSimpleFileSystemProtocolGuid = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol;EFI_FILE_HANDLE Root;EFI_FILE_HANDLE CurDir;EFI_FILE_HANDLE FileHandle;CHAR16 *FileName = L”hoge.txt”;

gBS->HandleProtocol (DeviceHandle,&gEfiSimpleFileSystemProtocolGuid,&Vol

);

Vol->OpenVolume (Vol, &Root);

CurDir->Open (CurDir,&FileHandle,FileName,EFI_FILE_MODE_READ,0

);

•ProtocolのHandleを経由してAPIコール13年2月16日土曜日

Page 36: Play with UEFI

よくみると

•さっき出てきたConOutとかもProtocol

• HandleProtocolとかしなくてもすぐ呼べるようにSystemTableにポインタが最初から用意されてるだけ

13年2月16日土曜日

Page 37: Play with UEFI

UEFIのSDK

• EDK II:オープンソースで開発されているUEFI実装で、デファクトスタンダードググってすぐ出てくるのはこれ。但し、ビルド方法のドキュメントをよく見るとtrunkをチェックアウトしている。そして、trunkだと色々と地雷があって頻繁に踏む…

• UDK2010:Intelが作っているEDK IIのstableリリース。地雷を踏みたくなかったらこっちを使ったほうが良いのだが、EDK IIにしか無い機能も色々と存在。

• gnu-efi:EDK IIはUEFIファームウェアのソースコードを全て含んでいるが、こちらはUEFI Applicationを実装するためだけのLightweightな実装。シンプル簡単お手軽で普通のMakefileも使えるし、LinuxやOSXユーザにとってはこっちの方が使いやすそう。 …だが、これでも色々と踏んだ…

13年2月16日土曜日

Page 38: Play with UEFI

OVMF FOR QEMU/KVM

• EDK II上でビルドできるQEMU・KVM用のUEFI実装

• コマンド一発でビルド&実行まで簡単に出来る

• QEMUでdebugconを有効にするとUEFIからのデバッグ出力が得られる

• シリアルコンソールを有効にするとVGA側と同等の出力が得られる

• ちょっと設定すればgdbも繋がるはず

• stable版じゃないのが激しく気になるけどそんなもん存在しないので見なかったことにするしか…

13年2月16日土曜日

Page 39: Play with UEFI

EDK IIにしかないもの

•ここまで見てきたように、UEFIのAPIは標準CのAPIと互換性がない

•通常のOSで動作しているアプリケーションを移植するのが面倒

• libcとPOSIX APIの一部とBSD Socketを移植してしまえ!→Python移植できちゃいました→mrubyも移植できちゃいました

13年2月16日土曜日

Page 40: Play with UEFI

EDK II使ってTWITTERクライアントを移植してみた

•組み込みとかで使いやすそうなPureC実装のTwitterクライアント「Twitter4C」を利用https://github.com/Plemling138/Twitter4C

• Makefileじゃなくて独自形式の.infというビルドスクリプトを定義

•ダメそうなところを一つづつ潰して行ったら動いたhttps://gist.github.com/syuu1228/4965390

13年2月16日土曜日

Page 41: Play with UEFI

ダメポイント1

•このプログラム、メッセージが日本語だ…

if(access_token == NULL) { //リクエストトークン取得 if(errcode = Twitter_GetRequestToken(c, r), errcode < 0) {- printf("リクエストトークンの取得でエラーが発生しています\n");- printf("エラーコード:%d\n", errcode);+ printf("error occured during get request token\n");+ printf("error code:%d\n", errcode); exit(0); }

13年2月16日土曜日

Page 42: Play with UEFI

ダメポイント2

•なんか知らんけどTRUE/FALSEがredefinedになるので

+#if 0 #define TRUE 1 #define FALSE 0+#endif

13年2月16日土曜日

Page 43: Play with UEFI

ダメポイント3

•微妙な型のズレ

//時間を取得してタイムスタンプと一意な値をセット gettimeofday(&tv, NULL);- sprintf(tstamp, "%ld", tv.tv_sec);+ sprintf(tstamp, "%d", tv.tv_sec); - sprintf(nonce_tmp, "%ld", tv.tv_usec);+ sprintf(nonce_tmp, "%d", tv.tv_usec); base64_encode(nonce_tmp, strlen(nonce_tmp), nonce, 128); URLEncode(nonce, nonce_urlenc);

13年2月16日土曜日

Page 44: Play with UEFI

ダメポイント4• なんか知らんけどリクエストトークンの取得に失敗してしまって、認証のところまで行けない

• めんどくせぇからアクセストークンとか一切をソースコードにベタ埋め込みしてみた

a->user_id = "ほげほげ"; a->access_token = "ほげほげ"; a->access_secret = "ほげほげ"; a->pin = "2630697";

13年2月16日土曜日

Page 45: Play with UEFI

ハマりポイント

• X64で試してたら、UEFI Application側のバイナリのABIに誤りでもあるのか、gethostbyname()するとUEFI側が謎の死を遂げるとかいう悲惨な目にあった

• ググってたらビルドオプション変えたら動いたとか、IA32なら行けたとか書いてあったので順に試したRe: [edk2] OVMF x64 - CR has Bad Signature:http://bit.ly/Yi3N8Y

• ビルドオプション変えてもダメだったので、IA32にした(これだと実機のUEFIはX64なので困るんだが。。。。

13年2月16日土曜日

Page 46: Play with UEFI

ツイートできた!

• OSを起動しなくてもツイート出来るそう、UEFIならね

•もっと頑張ればPythonやmruby経由でもツイート出来るはず

13年2月16日土曜日

Page 47: Play with UEFI

まとめ

• UEFIならリアルモードのアセンブリゴリゴリ書いたり、サイズに悩んだりしないでも気軽にCでOSレス環境向けのプログラムを書くことが出来ます

• EDK IIを使えば標準C APIを使ってプログラミング出来ます

•なので、みんなも色々移植してみよう

13年2月16日土曜日