Successfully reported this slideshow.
Your SlideShare is downloading. ×

Play with UEFI

Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Loading in …3
×

Check these out next

1 of 47 Ad

More Related Content

Slideshows for you (20)

Viewers also liked (20)

Advertisement

Similar to Play with UEFI (20)

More from Takuya ASADA (20)

Advertisement

Recently uploaded (20)

Play with UEFI

  1. 1. PLAY WITH UEFI @syuu1228 13年2月16日土曜日
  2. 2. UEFI使ったことある人 ノ 13年2月16日土曜日
  3. 3. UEFI APPLICATION書いたこと ある人 ノ 13年2月16日土曜日
  4. 4. 今日は簡単なUEFI APPLICATIONを 書いて遊んでみようという話です 13年2月16日土曜日
  5. 5. UEFIとは何か? • 90年代にIntelとHPにより開発された、IA32/IA64共通のブートシステム • PCに依然として残るレガシーな仕組みであるBIOSを置き換え • CPU非依存なアーキテクチャ • CPU非依存なドライバ • 128partition・over 2TBのディスクをサポートするGPTを採用 • ネットワーク対応などの多彩な機能に対応 • モジュラー型のデザイン • 高速起動にも寄与 13年2月16日土曜日
  6. 6. (U)EFIの歴史1 • 1990年代にIntel・HPがIA64アーキテクチャを設計した時に、 IA32/IA64両方で使えるファームウェア仕様を作ったのが始 まり • IA64ではそれしかないので使われていたが、IA32では広まら ず • 例外:2006年にリリースされたIntel MacはEFI 1.10をベースに した独自ファームウェアを採用 13年2月16日土曜日
  7. 7. (U)EFIの歴史2 • EFI specificationはIntelからUnified EFI Forumへ移管 →規格名がUEFIに・2.x系がリリース • 2009年頃から2TBの壁が問題視され始め、UEFI搭載PCが 普及しはじめる・OSも標準対応へ • 普通にその辺のヨ○バシでUEFI対応機買えるように←イ マココ! 13年2月16日土曜日
  8. 8. MBRと2TBの壁 • MBRのパーティーションテーブルでは、開始セクタ値とセクタ数が 32bit(4G sectors) • 4G sectors * 512byte = 2TB! • パーティーションテーブル変えるかセクタサイズ変えるしかない→ 互換性無くなる • バッドノウハウで回避出来ないことも無いけど… • もうしんどいしGPTを前提としているUEFIに移行しようよ 13年2月16日土曜日
  9. 9. MBRとGPTの比較 • MBRではパーティーション:4個→128個 • セクタアドレス長:32bit→64bit • パーティーションタイプ:1byte→16byte GUID • ブートフラグ:1byte→属性フラグ:8bytes • パーティーション名:72bytes UTF-16 • バックアップのパーティーションテーブル領域 13年2月16日土曜日
  10. 10. GPT 13年2月16日土曜日
  11. 11. GPT パーティションエントリ 13年2月16日土曜日
  12. 12. UEFIの見た目 • 普通のBIOSみたいな起動画面である事が多い • デフォルト設定でOSが自動的にブートされる限り、特にBIOSブ ートとの見た目上の違いはない • 但し、よく見ると全然違う: • Boot ManagerというGRUBのブートメニューのようなものがある • UEFI Shellというコマンドプロンプトのようなシェルがある 13年2月16日土曜日
  13. 13. メインメニュー 13年2月16日土曜日
  14. 14. BOOT MANAGER ブート項目の選択画面。 OSは自分のブートローダをここに登録する 13年2月16日土曜日
  15. 15. BOOT MAINTENANCE MANAGER メニューの編集、ロードするドライバの指 定、任意のファイルの実行など 13年2月16日土曜日
  16. 16. UEFI SHELL コマンドプロンプト風のシェル 任意のOS起動などに使用 13年2月16日土曜日
  17. 17. GRUB2 FOR UEFI 13年2月16日土曜日
  18. 18. UEFIからのブート BootManagerの設定値がデフォルトの場合 • UEFIがHDDを検出、GPTをロード • EFI System Partitionを検索 • EFIBOOTBOOTX64.EFIをロード (32bit環境ならBOOTX86.EFI) 13年2月16日土曜日
  19. 19. EFI SYSTEM PARTITION • パーティーションタイプGUIDがEFI System Partitionな FATファイルシステム • GPTにブートセクタは無い • ここからUEFIアプリケーションをロードする事により 起動 13年2月16日土曜日
  20. 20. UEFI APPLICATION • 64bit protected modeのPEバイナリ (UEFIがx64版の場合) • 拡張子:.EFI • UEFI APIを利用して各種処理を実装 13年2月16日土曜日
  21. 21. UEFIからのブート 厳密にはどうなっているか 以下のようなUEFI NVRAM variablesにより起動処理が制御される • Boot####:ロードするUEFI applicationのPATH・ 又はディスクのデバイスPATH • BootOrder:Boot####の試行順序(配列で指定) • BootNext:次回起動時にロードするBoot####(BootOrderより優 先、一度起動すると削除) • Timeout:設定秒数だけBoot Menuを表示(自動起動を遅延) 13年2月16日土曜日
  22. 22. 設定例 • 起動まで10秒待つ • ubuntu→HDD→CDROM→Network→Shellの順で試行 • ファイル指定がないドライブはEFI System PartitionのEFIBOOTBOOTX64.EFIを探索 13年2月16日土曜日
  23. 23. EFIBOOTMGR • efibootmgrでブートメニューを編集 • カーネルは/sys/firmware/efi/vars/・/sys/firmware/efi/efivars/経由でUEFI NVRAM variablesへのユーザランドからのアクセスを許可している 13年2月16日土曜日
  24. 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. 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. 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. 27. UEFI APPLICATIONの種類 • 二種類のUEFI Application • 通常のUEFI Application:終了時にExit()をコールし、 UEFI Shellなどに制御を戻す • OS Loader:終了時にExitBootServices()をコールし、 UEFIが利用していた資源を開放して制御をOSへ移す 13年2月16日土曜日
  28. 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. 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. 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. 31. RUNTIME SERVICES • ExitBootServices()後もUEFIがOSに対して提供するサービス • 最低限の機能のみ • Time (GetTime, SetTime...) • Virtual Memory (SetirtualAddressMap...) • Variable Services (GetVariable...) • Miscellaneous Services(ResetSystem...) 13年2月16日土曜日
  32. 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. 33. PROCOTOLS • ネットワークプロトコルスタックのことではない • UEFI上で提供される様々なサービスの事 • UEFI Driverを実装しUEFIへロードする事により、自作の Protocolを提供する事も可能 13年2月16日土曜日
  34. 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. 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. 36. よくみると • さっき出てきたConOutとかもProtocol • HandleProtocolとかしなくてもすぐ呼べるように SystemTableにポインタが最初から用意されてるだけ 13年2月16日土曜日
  37. 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. 38. OVMF FOR QEMU/KVM • EDK II上でビルドできるQEMU・KVM用のUEFI実装 • コマンド一発でビルド&実行まで簡単に出来る • QEMUでdebugconを有効にするとUEFIからのデバッグ出力が得られる • シリアルコンソールを有効にするとVGA側と同等の出力が得られる • ちょっと設定すればgdbも繋がるはず • stable版じゃないのが激しく気になるけどそんなもん存在しないので見なか ったことにするしか… 13年2月16日土曜日
  39. 39. EDK IIにしかないもの • ここまで見てきたように、UEFIのAPIは標準CのAPIと互換性 がない • 通常のOSで動作しているアプリケーションを移植するのが 面倒 • libcとPOSIX APIの一部とBSD Socketを移植してしまえ! →Python移植できちゃいました →mrubyも移植できちゃいました 13年2月16日土曜日
  40. 40. EDK II使ってTWITTERクライ アントを移植してみた • 組み込みとかで使いやすそうなPureC実装のTwitterクライ アント「Twitter4C」を利用 https://github.com/Plemling138/Twitter4C • Makefileじゃなくて独自形式の.infというビルドスクリプト を定義 • ダメそうなところを一つづつ潰して行ったら動いた https://gist.github.com/syuu1228/4965390 13年2月16日土曜日
  41. 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. 42. ダメポイント2 • なんか知らんけどTRUE/FALSEがredefinedになるので +#if 0 #define TRUE 1 #define FALSE 0 +#endif 13年2月16日土曜日
  43. 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. 44. ダメポイント4 • なんか知らんけどリクエストトークンの取得に失敗してしまって、認証のところまで行けない • めんどくせぇからアクセストークンとか一切をソースコードにベタ埋め込みしてみた a->user_id = "ほげほげ"; a->access_token = "ほげほげ"; a->access_secret = "ほげほげ"; a->pin = "2630697"; 13年2月16日土曜日
  45. 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. 46. ツイートできた! • OSを起動しなくてもツイート出来る そう、UEFIならね • もっと頑張ればPythonやmruby経由でもツイート出来る はず 13年2月16日土曜日
  47. 47. まとめ • UEFIならリアルモードのアセンブリゴリゴリ書いた り、サイズに悩んだりしないでも気軽にCでOSレス環 境向けのプログラムを書くことが出来ます • EDK IIを使えば標準C APIを使ってプログラミング出来 ます • なので、みんなも色々移植してみよう 13年2月16日土曜日

×