Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
UEFI時代のブート 
ローダ 
@syuu1228
自己紹介 
• Software Engineer at Cloudius Systems 
(OSv) 
• FreeBSD developer (bhyve, network stack..)
UEFIのおさらい
BIOSブート 
←ディスクに1個 
• MBRからブートセクタをロード 
• プログラム領域が足りないのでMBRの次のセク 
タなどを利用して更に大きなブートローダをロー 
ド(多段ブート) 
• /bootファイルシステムをパースしてLin...
UEFIブート 
• ブートセクタなどなかった 
• EFIパーティーション(FATファイルシステム)にブートロー 
ダ(UEFIイメージ)を配置 
• NVRAMに設定がある 
→設定されたパスからブートローダをロード&実行 
• NVRAM...
BIOSのブートイメージ 
• ブートセクタなどのとても狭い領域に固定的に配 
置 
• リアルモード 
• アドレッシング出来るメモリに大きな制約 
• アセンブリ 
• 古くさいBIOSコールによる限られたAPI
UEFIイメージ 
• PEバイナリ 
(Windowsアプリと似たようなヘッダ) 
• 32/64bitプロテクテッドモード 
(※但し両対応ファームはない) 
• サイズ制限、メモリ容量制限なし 
• 全てC言語で記述可能 
• 豊富なAP...
参考:Runtime Services 
• ExitBootServices()後もUEFIがOSに対して提供するサービ 
ス 
• 最低限の機能のみ 
• Time (GetTime, SetTime...) 
• Virtual Memo...
参考:Boot Services 
• ExitBootServices()までUEFI Applicationに提供するサービス 
• Task Priority Services (RaiseTPL...) 
• Memory Servic...
参考:Procotols 
• ネットワークプロトコルスタックのことではな 
い 
• UEFI上で提供される様々なサービスの事 
• UEFI Driverを実装しUEFIへロードする事によ 
り、自作のProtocolを提供する事も可能
参考:定義されている 
Protocol 
• EFI Loaded Image 
• Device Path Protocol 
• UEFI Driver Model 
• Console Support 
• Media Access 
...
UEFIからのブート手順 
(デフォルト) 
BootManagerの設定がデフォルト値の場合 
1. UEFIがHDDを検出、GPTをロード 
2. EFI System Partitionを検索 
3. EFIBOOTBOOTX64.EFI...
UEFIからのブート手順 
(カスタム) 
以下の様な値をUEFI NVRAM variableに設定(efibootmgrなど) 
• Boot####:ロードするUEFI applicationのPATH・ 
又はディスクのデバイスPATH...
設定例 
• efibootmgrで編集 
• /sys/firmware/efi/vars, /sys/firmware/efi/efivars 
経由でUEFI NVRAM Variableへアクセス
/sys/firmware/efi/efivars 
syuu@ubuntu:~$ ls /sys/firmware/efi/efivars 
Boot0000-8be4df61-93ca-11d2-aa0d-00e098032b8c 
Boo...
Boot Manager 
ブート項目の選択画面。 
OSは自分のブートローダをここに登録する
UEFI Shell 
• 運が良ければROMに乗ってる 
無ければUSBからロード
さまざまな 
UEFIブート手順
UEFIでのLinuxブート方法(1) 
• shim→grub2→Linux bzImage 
• shim→grub2→Linux EFI Stub 
• grub2→Linux bzImage 
• grub2→Linux EFI Stu...
UEFIでのLinuxブート方法(2) 
• LinuxカーネルにEFI Stubを用意すれば直接Boot 
Managerからロード出来る 
• UEFIイメージから更に別のUEFIイメージをロー 
ド&実行できる 
• UEFI APIがサ...
なるほど~?
非対応フォーマットの 
ロード&実行 
• ヘッダのパース 
• メモリへの展開 
• CPUレジスタの初期化、辻褄合わせ 
• エントリポイントへのジャンプ 
_人人人人人人_ 
> 結構面倒 < 
‾Y^Y^Y^Y^Y‾
UEFIイメージのロード& 
実行 
• UEFIイメージファイルをロードするAPI 
にファイル名渡して終わりでは? 
_人人人人人人_ 
> 簡単そう < 
‾Y^Y^Y^Y^Y‾
ところで 
• mrubyはUEFIで動く(mruby on EFI shell)
ということは 
• mrubyにローダAPIを足せばmrubyスクリ 
プトでブートローダを簡単に実装出来 
るのでは?
UEFI APIサポートon mruby 
class BlockIoProtocol < UEFI::Protocol 
GUID = UEFI::Guid.new("964e5b21-6459-11d2-8e39-00a0c969723b"...
これを使ってmrubyでロー 
ダを書けばいいんじゃね?
Cで書く→mrubyに起こす 
• Cで書いてみた 
https://gist.github.com/syuu1228/ 
d7ce6b949cbeec887ea0
どのAPIをmrubyでどう置き 
換えれば良いのか分からない 
…(゜Д゜)
方針転換 
• 足りない機能は皆C拡張にしてしまえ 
• さっきのコードをコピペしてmrubyのクラス化 
→実行 
• 何故かエラー… 
• (゜Д゜)
む?
良くみたらsystem(3) 
あったわ 
• EDK2にはlibc + BSD socketのテスト実装が載ってる 
(非公式あつかい) 
• どうせmrubyは初めからこれをリンクしている 
• system(3)もある 
• 文字列組み立...
が… 
• mruby on EFI shellはmrubyの標準ビルドシス 
テムを迂回してEDKのビルドシステムでビルド 
されてる 
• mrubyのビルドシステムを使わないとmrbgems 
を追加出来ない 
• 殆どAPIが無い&簡単...
応急処置的に足す 
• さっきのsystem(3)を呼び出すShell.exec() 
• キーボード入力を受け付けるShell.gets() 
• Dirクラス
完成! 
• https://github.com/syuu1228/ 
mruby_on_efi_shell/blob/ 
862b7d95e399dc23744c589220e59d6e6f 
0adff3/example/bootload...
デモ
TODO 
• mrbgems問題をどうにかするべき 
• HTTPクライアントをポーティングしてカーネルもスク 
リプトも外から落としてきて実行させたい 
• ファイルシステムドライバをインストールしてext[2-4] 
の/bootからカー...
URL 
• https://github.com/syuu1228/ 
mruby_on_efi_shell/tree/devel
Upcoming SlideShare
Loading in …5
×

UEFI時代のブートローダ

18,587 views

Published on

UEFI boot loaders

Published in: Technology
  • Be the first to comment

UEFI時代のブートローダ

  1. 1. UEFI時代のブート ローダ @syuu1228
  2. 2. 自己紹介 • Software Engineer at Cloudius Systems (OSv) • FreeBSD developer (bhyve, network stack..)
  3. 3. UEFIのおさらい
  4. 4. BIOSブート ←ディスクに1個 • MBRからブートセクタをロード • プログラム領域が足りないのでMBRの次のセク タなどを利用して更に大きなブートローダをロー ド(多段ブート) • /bootファイルシステムをパースしてLinuxカー ネルを見つけてロード&実行
  5. 5. UEFIブート • ブートセクタなどなかった • EFIパーティーション(FATファイルシステム)にブートロー ダ(UEFIイメージ)を配置 • NVRAMに設定がある →設定されたパスからブートローダをロード&実行 • NVRAMに設定がない →デフォルトパスからブートローダをロード&実行 • プロテクテッドモード、UEFI API ←ディスクにn個(いくらでも)
  6. 6. BIOSのブートイメージ • ブートセクタなどのとても狭い領域に固定的に配 置 • リアルモード • アドレッシング出来るメモリに大きな制約 • アセンブリ • 古くさいBIOSコールによる限られたAPI
  7. 7. UEFIイメージ • PEバイナリ (Windowsアプリと似たようなヘッダ) • 32/64bitプロテクテッドモード (※但し両対応ファームはない) • サイズ制限、メモリ容量制限なし • 全てC言語で記述可能 • 豊富なAPI
  8. 8. 参考:Runtime Services • ExitBootServices()後もUEFIがOSに対して提供するサービ ス • 最低限の機能のみ • Time (GetTime, SetTime...) • Virtual Memory (SetirtualAddressMap...) • Variable Services (GetVariable...) • Miscellaneous Services(ResetSystem...)
  9. 9. 参考: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...)
  10. 10. 参考:Procotols • ネットワークプロトコルスタックのことではな い • UEFI上で提供される様々なサービスの事 • UEFI Driverを実装しUEFIへロードする事によ り、自作のProtocolを提供する事も可能
  11. 11. 参考:定義されている 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...
  12. 12. UEFIからのブート手順 (デフォルト) BootManagerの設定がデフォルト値の場合 1. UEFIがHDDを検出、GPTをロード 2. EFI System Partitionを検索 3. EFIBOOTBOOTX64.EFIをロード (32bit UEFIならBOOTX86.EFI)
  13. 13. UEFIからのブート手順 (カスタム) 以下の様な値をUEFI NVRAM variableに設定(efibootmgrなど) • Boot####:ロードするUEFI applicationのPATH・ 又はディスクのデバイスPATH • BootOrder:Boot####の試行順序(配列で指定) • BootNext:次回起動時にロードするBoot#### (BootOrderより優先、一度起動すると削除) • Timeout:設定秒数だけBoot Menuを表示(自動起動を遅 延)
  14. 14. 設定例 • efibootmgrで編集 • /sys/firmware/efi/vars, /sys/firmware/efi/efivars 経由でUEFI NVRAM Variableへアクセス
  15. 15. /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) ?
  16. 16. Boot Manager ブート項目の選択画面。 OSは自分のブートローダをここに登録する
  17. 17. UEFI Shell • 運が良ければROMに乗ってる 無ければUSBからロード
  18. 18. さまざまな UEFIブート手順
  19. 19. UEFIでのLinuxブート方法(1) • shim→grub2→Linux bzImage • shim→grub2→Linux EFI Stub • grub2→Linux bzImage • grub2→Linux EFI Stub • gummiboot→Linux EFI Stub • Linux EFI Stub ←SecureBoot
  20. 20. UEFIでのLinuxブート方法(2) • LinuxカーネルにEFI Stubを用意すれば直接Boot Managerからロード出来る • UEFIイメージから更に別のUEFIイメージをロー ド&実行できる • UEFI APIがサポートしていないバイナリフォー マットよりもサポートが容易 サポートすることによるデメリットも少ない
  21. 21. なるほど~?
  22. 22. 非対応フォーマットの ロード&実行 • ヘッダのパース • メモリへの展開 • CPUレジスタの初期化、辻褄合わせ • エントリポイントへのジャンプ _人人人人人人_ > 結構面倒 < ‾Y^Y^Y^Y^Y‾
  23. 23. UEFIイメージのロード& 実行 • UEFIイメージファイルをロードするAPI にファイル名渡して終わりでは? _人人人人人人_ > 簡単そう < ‾Y^Y^Y^Y^Y‾
  24. 24. ところで • mrubyはUEFIで動く(mruby on EFI shell)
  25. 25. ということは • mrubyにローダAPIを足せばmrubyスクリ プトでブートローダを簡単に実装出来 るのでは?
  26. 26. UEFI APIサポートon mruby class BlockIoProtocol < UEFI::Protocol GUID = UEFI::Guid.new("964e5b21-6459-11d2-8e39-00a0c969723b") define_variable(:revision, :u64) define_variable(:media, :p) define_function(:reset, :e, [:p, :b]) define_function(:read_blocks, :e, [:p, :u32, :u64, :u64, :p]) end class Media < UEFI::Protocol define_variable(:media_id, :uint32) end handles = UEFI::BootService.locate_handle_buffer(BlockIoProtocol::GUID) handle = handles.first puts "handle: #{handle}" ptr = UEFI::BootService.handle_protocol(handle, BlockIoProtocol::GUID) bp = BlockIoProtocol.new(ptr) media = Media.new(bp.media) puts "media_id: #{media.media_id}"
  27. 27. これを使ってmrubyでロー ダを書けばいいんじゃね?
  28. 28. Cで書く→mrubyに起こす • Cで書いてみた https://gist.github.com/syuu1228/ d7ce6b949cbeec887ea0
  29. 29. どのAPIをmrubyでどう置き 換えれば良いのか分からない …(゜Д゜)
  30. 30. 方針転換 • 足りない機能は皆C拡張にしてしまえ • さっきのコードをコピペしてmrubyのクラス化 →実行 • 何故かエラー… • (゜Д゜)
  31. 31. む?
  32. 32. 良くみたらsystem(3) あったわ • EDK2にはlibc + BSD socketのテスト実装が載ってる (非公式あつかい) • どうせmrubyは初めからこれをリンクしている • system(3)もある • 文字列組み立てて渡せば一行のCコードでバイナリ実行 できんじゃん… • 何を苦労していたんだろう
  33. 33. が… • mruby on EFI shellはmrubyの標準ビルドシス テムを迂回してEDKのビルドシステムでビルド されてる • mrubyのビルドシステムを使わないとmrbgems を追加出来ない • 殆どAPIが無い&簡単に足せない…
  34. 34. 応急処置的に足す • さっきのsystem(3)を呼び出すShell.exec() • キーボード入力を受け付けるShell.gets() • Dirクラス
  35. 35. 完成! • https://github.com/syuu1228/ mruby_on_efi_shell/blob/ 862b7d95e399dc23744c589220e59d6e6f 0adff3/example/bootloader.rb
  36. 36. デモ
  37. 37. TODO • mrbgems問題をどうにかするべき • HTTPクライアントをポーティングしてカーネルもスク リプトも外から落としてきて実行させたい • ファイルシステムドライバをインストールしてext[2-4] の/bootからカーネルをロードしたい • ブートしたらツイートしたい • もうちょっと整備すると結構便利になると思う
  38. 38. URL • https://github.com/syuu1228/ mruby_on_efi_shell/tree/devel

×