More Related Content Similar to Play with UEFI Similar to Play with UEFI (20) More from Takuya ASADA (20) Play with UEFI5. UEFIとは何か?
• 90年代にIntelとHPにより開発された、IA32/IA64共通のブートシステム
• PCに依然として残るレガシーな仕組みであるBIOSを置き換え
• CPU非依存なアーキテクチャ
• CPU非依存なドライバ
• 128partition・over 2TBのディスクをサポートするGPTを採用
• ネットワーク対応などの多彩な機能に対応
• モジュラー型のデザイン
• 高速起動にも寄与
13年2月16日土曜日
6. (U)EFIの歴史1
• 1990年代にIntel・HPがIA64アーキテクチャを設計した時に、
IA32/IA64両方で使えるファームウェア仕様を作ったのが始
まり
• IA64ではそれしかないので使われていたが、IA32では広まら
ず
• 例外:2006年にリリースされたIntel MacはEFI 1.10をベースに
した独自ファームウェアを採用
13年2月16日土曜日
7. (U)EFIの歴史2
• EFI specificationはIntelからUnified EFI Forumへ移管
→規格名がUEFIに・2.x系がリリース
• 2009年頃から2TBの壁が問題視され始め、UEFI搭載PCが
普及しはじめる・OSも標準対応へ
• 普通にその辺のヨ○バシでUEFI対応機買えるように←イ
マココ!
13年2月16日土曜日
8. MBRと2TBの壁
• MBRのパーティーションテーブルでは、開始セクタ値とセクタ数が
32bit(4G sectors)
• 4G sectors * 512byte = 2TB!
• パーティーションテーブル変えるかセクタサイズ変えるしかない→
互換性無くなる
• バッドノウハウで回避出来ないことも無いけど…
• もうしんどいしGPTを前提としているUEFIに移行しようよ
13年2月16日土曜日
9. MBRとGPTの比較
• MBRではパーティーション:4個→128個
• セクタアドレス長:32bit→64bit
• パーティーションタイプ:1byte→16byte GUID
• ブートフラグ:1byte→属性フラグ:8bytes
• パーティーション名:72bytes UTF-16
• バックアップのパーティーションテーブル領域
13年2月16日土曜日
12. UEFIの見た目
• 普通のBIOSみたいな起動画面である事が多い
• デフォルト設定でOSが自動的にブートされる限り、特にBIOSブ
ートとの見た目上の違いはない
• 但し、よく見ると全然違う:
• Boot ManagerというGRUBのブートメニューのようなものがある
• UEFI Shellというコマンドプロンプトのようなシェルがある
13年2月16日土曜日
14. BOOT MANAGER
ブート項目の選択画面。
OSは自分のブートローダをここに登録する
13年2月16日土曜日
16. UEFI SHELL
コマンドプロンプト風のシェル
任意のOS起動などに使用
13年2月16日土曜日
18. UEFIからのブート
BootManagerの設定値がデフォルトの場合
• UEFIがHDDを検出、GPTをロード
• EFI System Partitionを検索
• EFIBOOTBOOTX64.EFIをロード
(32bit環境ならBOOTX86.EFI)
13年2月16日土曜日
19. EFI SYSTEM PARTITION
• パーティーションタイプGUIDがEFI System Partitionな
FATファイルシステム
• GPTにブートセクタは無い
• ここからUEFIアプリケーションをロードする事により
起動
13年2月16日土曜日
20. UEFI APPLICATION
• 64bit protected modeのPEバイナリ
(UEFIがx64版の場合)
• 拡張子:.EFI
• UEFI APIを利用して各種処理を実装
13年2月16日土曜日
21. UEFIからのブート
厳密にはどうなっているか
以下のようなUEFI NVRAM variablesにより起動処理が制御される
• Boot####:ロードするUEFI applicationのPATH・
又はディスクのデバイスPATH
• BootOrder:Boot####の試行順序(配列で指定)
• BootNext:次回起動時にロードするBoot####(BootOrderより優
先、一度起動すると削除)
• Timeout:設定秒数だけBoot Menuを表示(自動起動を遅延)
13年2月16日土曜日
22. 設定例
• 起動まで10秒待つ
• ubuntu→HDD→CDROM→Network→Shellの順で試行
• ファイル指定がないドライブはEFI System PartitionのEFIBOOTBOOTX64.EFIを探索
13年2月16日土曜日
23. EFIBOOTMGR
• efibootmgrでブートメニューを編集
• カーネルは/sys/firmware/efi/vars/・/sys/firmware/efi/efivars/経由でUEFI NVRAM
variablesへのユーザランドからのアクセスを許可している
13年2月16日土曜日
24. /SYS/FIRMWARE/EFI/EFIVARS
syuu@ubuntu:~$ ls /sys/firmware/efi/efivars
Boot0000-8be4df61-93ca-11d2-aa0d-00e098032b8c
Boot0001-8be4df61-93ca-11d2-aa0d-00e098032b8c
Boot0002-8be4df61-93ca-11d2-aa0d-00e098032b8c
Boot0003-8be4df61-93ca-11d2-aa0d-00e098032b8c
Boot0004-8be4df61-93ca-11d2-aa0d-00e098032b8c
BootCurrent-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日土曜日
25. UEFIの内部構造
PI specification UEFI specification
UEFI APIs UEFI
Services
Device Apps
Drivers
Boot UEFI
PEI DXE Bootl OS
Manager
oader
Load drivers Load UEFI apps
CPU init
Chipset init
Board init
13年2月16日土曜日
26. UEFIの内部構造
PI specification UEFI specification
今日はここを見ていきます
UEFI APIs UEFI
Services
Device Apps
Drivers
Boot UEFI
PEI DXE Bootl OS
Manager
oader
Load drivers Load UEFI apps
CPU init
Chipset init
Board init
13年2月16日土曜日
27. UEFI APPLICATIONの種類
• 二種類のUEFI Application
• 通常のUEFI Application:終了時にExit()をコールし、
UEFI Shellなどに制御を戻す
• OS Loader:終了時にExitBootServices()をコールし、
UEFIが利用していた資源を開放して制御をOSへ移す
13年2月16日土曜日
28. 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日土曜日
29. #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))
UEFI SYSTEM TABLE
#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 System Table
EFI_HANDLE ConsoleOutHandle;
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut;
EFI_HANDLE StandardErrorHandle;
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *StdErr;
EFI_RUNTIME_SERVICES *RuntimeServices;
80 EFI_BOOT_SERVICES June 27, 2012 *BootServices; Version 2.3.1, Errata C
UINTN NumberOfTableEntries;
EFI_CONFIGURATION_TABLE *ConfigurationTable;
} EFI_SYSTEM_TABLE;
Parameters
UEFI Applicationに対して公開するインタフェースが全て
Hdr 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.
13年2月16日土曜日 FirmwareRevision A firmware vendor specific value that identifies the revision of
30. CONOUT, CONIN, STDERR
#include <Library/UefiApplicationEntryPoint.h>
#include <Library/UefiLib.h>
EFI_STATUS
EFIAPI
UefiMain
(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
{
SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Hello Worldrn");
return EFI_SUCCESS;
}
•コンソールへの入出力API
•文字エンコーディングはUTF-16を使用
13年2月16日土曜日
31. RUNTIME SERVICES
• ExitBootServices()後もUEFIがOSに対して提供するサービス
• 最低限の機能のみ
• Time (GetTime, SetTime...)
• Virtual Memory (SetirtualAddressMap...)
• Variable Services (GetVariable...)
• Miscellaneous Services(ResetSystem...)
13年2月16日土曜日
32. 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日土曜日
33. PROCOTOLS
• ネットワークプロトコルスタックのことではない
• UEFI上で提供される様々なサービスの事
• UEFI Driverを実装しUEFIへロードする事により、自作の
Protocolを提供する事も可能
13年2月16日土曜日
34. 定義されているPROTOCOL
• EFI Loaded Image • USB Support
• Device Path Protocol • Debugger Support
• UEFI Driver Model • Compression Algorithm
• Console Support • ACPI Protocols
• Media Access • TCP/IP, IPSec, FTP
• PCI Bus Support • ARP & DHCP
• SCSI Driver Models and Bus Support • UDP & MTFTP
• iSCSI Boot • etc...
13年2月16日土曜日
35. 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日土曜日
36. よくみると
• さっき出てきたConOutとかもProtocol
• HandleProtocolとかしなくてもすぐ呼べるように
SystemTableにポインタが最初から用意されてるだけ
13年2月16日土曜日
37. 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日土曜日
38. OVMF FOR QEMU/KVM
• EDK II上でビルドできるQEMU・KVM用のUEFI実装
• コマンド一発でビルド&実行まで簡単に出来る
• QEMUでdebugconを有効にするとUEFIからのデバッグ出力が得られる
• シリアルコンソールを有効にするとVGA側と同等の出力が得られる
• ちょっと設定すればgdbも繋がるはず
• stable版じゃないのが激しく気になるけどそんなもん存在しないので見なか
ったことにするしか…
13年2月16日土曜日
39. EDK IIにしかないもの
• ここまで見てきたように、UEFIのAPIは標準CのAPIと互換性
がない
• 通常のOSで動作しているアプリケーションを移植するのが
面倒
• libcとPOSIX APIの一部とBSD Socketを移植してしまえ!
→Python移植できちゃいました
→mrubyも移植できちゃいました
13年2月16日土曜日
40. EDK II使ってTWITTERクライ
アントを移植してみた
• 組み込みとかで使いやすそうなPureC実装のTwitterクライ
アント「Twitter4C」を利用
https://github.com/Plemling138/Twitter4C
• Makefileじゃなくて独自形式の.infというビルドスクリプト
を定義
• ダメそうなところを一つづつ潰して行ったら動いた
https://gist.github.com/syuu1228/4965390
13年2月16日土曜日
41. ダメポイント1
• このプログラム、メッセージが日本語だ…
if(access_token == NULL) {
//リクエストトークン取得
if(errcode = Twitter_GetRequestToken(c, r), errcode < 0) {
- printf("リクエストトークンの取得でエラーが発生していますn");
- printf("エラーコード:%dn", errcode);
+ printf("error occured during get request tokenn");
+ printf("error code:%dn", errcode);
exit(0);
}
13年2月16日土曜日
42. ダメポイント2
• なんか知らんけどTRUE/FALSEがredefinedになるので
+#if 0
#define TRUE 1
#define FALSE 0
+#endif
13年2月16日土曜日
43. ダメポイント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日土曜日
44. ダメポイント4
• なんか知らんけどリクエストトークンの取得に失敗してしまって、認証のところまで行けない
• めんどくせぇからアクセストークンとか一切をソースコードにベタ埋め込みしてみた
a->user_id = "ほげほげ";
a->access_token = "ほげほげ";
a->access_secret = "ほげほげ";
a->pin = "2630697";
13年2月16日土曜日
45. ハマりポイント
• 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日土曜日
46. ツイートできた!
• OSを起動しなくてもツイート出来る
そう、UEFIならね
• もっと頑張ればPythonやmruby経由でもツイート出来る
はず
13年2月16日土曜日
47. まとめ
• UEFIならリアルモードのアセンブリゴリゴリ書いた
り、サイズに悩んだりしないでも気軽にCでOSレス環
境向けのプログラムを書くことが出来ます
• EDK IIを使えば標準C APIを使ってプログラミング出来
ます
• なので、みんなも色々移植してみよう
13年2月16日土曜日