ExitBootServices後のRuntimeとは何か
ExitBootServices後のfirmware状態を、Boot Services終了とRuntime Services継続から説明します。
要点
Runtime after ExitBootServices は、boot loaderがExitBootServices()を正常に呼び終えた後の状態です。この時点からUEFI Boot Servicesは使えなくなり、OSが自分の方式でsystemを管理し始めます。
これはUEFI boot flowの中でも非常に重要な境界です。
ExitBootServices後に何が変わるか
ExitBootServices()の前は、firmwareはBoot Services、protocol database、handle database、各種allocation APIを提供しています。
ExitBootServices()が成功した後は、次のようになります。
Boot Services: 無効
Protocol database: 以前と同じ使い方はできない
Firmware driver model: 主制御層ではなくなる
OS memory manager: 所有権を持つ
Runtime Services: preserveされた部分だけが残る
この境界の後にBoot Servicesを呼ぶcodeがあれば、かなり危険な兆候です。
EBS後のmemory map
EBS後、OSはBoot Services memoryをreclaimできます。
例:
EfiBootServicesCode
EfiBootServicesData
これらの領域は、もうfirmware専用ではありません。一方で、EfiRuntimeServicesCodeやEfiRuntimeServicesDataのようなruntime領域は、runtime descriptorに従ってOSが保持する必要があります。
残るRuntime Services
EBS後も、platformがsupportしていればOSはRuntime Servicesを呼べます。
例:
GetVariable()
SetVariable()
GetTime()
SetTime()
ResetSystem()
UpdateCapsule()
SetVirtualAddressMap()
ただし、これらはruntime条件で動く必要があります。Boot Servicesや完全なDXE handle databaseがまだある、という前提は置けません。
SetVirtualAddressMapとの関係
EBS後、OSはSetVirtualAddressMap()を呼び、runtime descriptorのvirtual mappingをfirmwareへ渡すことがあります。
その時、firmware runtime codeはVirtualAddressChange eventを処理し、生き残るpointerをConvertPointer()で変換します。
OSがvirtual runtime modeへ移った後もpointerがphysical addressのままだと、後のruntime callでcrashする可能性があります。
よくある失敗パターン
よくあるのは、private contextを普通のAllocatePool()で確保し、結果としてEfiBootServicesDataに置いてしまうケースです。EBS前は問題なく動きます。EBS後、OSがそのmemoryをreclaimします。
その後OSがGetVariable()などのRuntime Serviceを呼ぶと、firmwareが失われたcontextを読み、page faultを起こします。
Debug時の確認点
kernel起動後に問題が出る場合、次を確認します。
ExitBootServices()は成功したか
最後のmemory mapは正しいか
runtime descriptorにEFI_MEMORY_RUNTIMEがあるか
OSはSetVirtualAddressMap()を呼んだか
VirtualAddressChange handlerは動いたか
runtime pointerはConvertPointer()されたか
EBS後にBoot Services APIを呼んでいないか
これにより、boot loaderの問題、firmware runtimeの問題、OS mappingの問題を分けやすくなります。
Source-reading checklist
EBS後のruntime codeを読む時は、次を確認します。
- Boot Services dataへのpointerを保存していないか
- runtime allocationのmemory typeは何か
- runtime serviceがprotocolやhandle databaseに依存していないか
- convertが必要なglobal pointerやlinked listがないか
- SetVirtualAddressMap後のerror pathをlogできるか
- capsule、variable、reset pathはruntime contextで動くか
まとめ
ExitBootServices()後、firmwareは完全なboot environmentではなくなります。OSがsystemを所有し、Boot Servicesは終了し、runtimeとして保持された一部だけが残ります。boot後の問題をdebugする時は、memory type、runtime descriptor、SetVirtualAddressMap()、ConvertPointer()、そしてEBS後にBoot Servicesを使っていないかを重点的に確認します。
この記事が役に立ったら
ファームウェア、BIOS/UEFI、組み込みシステムを学んでいる人に共有したり、作者を応援したりできます。
Nội dung liên quan
Một số bài viết, ghi chú hoặc project có liên quan đến nội dung bạn vừa đọc.
ExitBootServicesとは
ExitBootServicesはファームウェアからOSへの引き渡しの境界である。この呼び出しの後、Boot Servicesは停止し、OSがmemoryとplatformの制御を引き継ぐ。
UEFI Runtime Driverとは?
UEFI Runtime DriverはDXE_RUNTIME_DRIVERを使ってコードとデータをExitBootServices後も存続させる。ランタイムメモリ、ConvertPointer、EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE、EBS後の制限事項を解説。
Runtime Phaseとは何か
UEFIのRuntime Phaseを、OSが制御を受け取った後も残るfirmware機能として説明します。
Biến note thành bài viết hoàn chỉnh
Notes là nơi ghi nhanh khái niệm.