Runtime Phaseとは何か
UEFIのRuntime Phaseを、OSが制御を受け取った後も残るfirmware機能として説明します。
要点
Runtime Phase は、firmwareが制御の大部分をOSへ渡した後でも、一部のfirmware機能がUEFI Runtime ServicesとしてOSから呼ばれる期間です。
簡単に言うと、boot firmwareは主導権を失いますが、firmwareが完全に消えるわけではありません。
Runtime Phaseはいつ始まるか
Runtime Phaseは、通常ExitBootServices()が成功した後として説明されます。
その前までは、boot loaderはAllocatePool()、LocateProtocol()、LoadImage()などのBoot Servicesを使えます。その後はBoot Servicesが使えなくなり、memory管理、driver、scheduler、device stackはOS側の責任になります。
ただし、variable serviceやtime serviceなど、一部のRuntime ServicesはOSから呼ばれ続ける可能性があります。
残るRuntime Services
よく出てくるAPIは次のようなものです。
GetTime()
SetTime()
GetVariable()
SetVariable()
GetNextVariableName()
ResetSystem()
UpdateCapsule()
QueryCapsuleCapabilities()
SetVirtualAddressMap()
すべてのplatformが同じ使い方をするわけではありません。特にGetVariable()とSetVariable()は、NVRAM、Secure Boot、boot option、capsule updateと強く関係します。
Boot Phaseとの違い
Boot Phaseでは、firmwareはBoot Services、protocol database、driver model、handle database、dispatcherを持っています。
Runtime PhaseではOSが主導権を持っています。firmware側に残るのは、memory mapとruntime attributeによってOSが保持したruntime entry pointだけです。
そのため、runtime driverはExitBootServices()後にBoot Servicesへ依存してはいけません。
Memory typeとの関係
Runtime codeとdataは、適切なmemory typeに置かれる必要があります。
EfiRuntimeServicesCode
EfiRuntimeServicesData
関連するdescriptorにはEFI_MEMORY_RUNTIMEが必要です。runtime contextを誤ってEfiBootServicesDataに置くと、OSがその領域をreclaimし、OS boot後にfirmware runtime pathがcrashする可能性があります。
Virtual addressへの移行
一部のOSはSetVirtualAddressMap()を呼び、Runtime Servicesをvirtual address modeへ移します。
VirtualAddressChange eventが発生したら、runtime driverは生き残る必要がある内部pointerに対してConvertPointer()を行います。
pointerを変換し忘れたり、nested pointerの変換が足りなかったりすると、OS boot後だけで問題が出ます。
よくあるdebug case
例えば、boot loader上ではfirmware variable serviceが正常に動くのに、OSに入った後のGetVariable()でpage faultするケースがあります。
原因としては、runtime private contextがBoot Services memoryに置かれていた、またはSetVirtualAddressMap()後にpointerをconvertしていなかった、などが考えられます。
Source-reading checklist
runtime pathを読む時は、次を確認します。
- MODULE_TYPEはDXE_RUNTIME_DRIVERか
- runtime code/dataのmemory typeは正しいか
- descriptorにEFI_MEMORY_RUNTIMEがあるか
- ExitBootServices()後にBoot Services APIを使っていないか
- VirtualAddressChange eventをregisterしているか
- ConvertPointer()はprivate context、global pointer、linked listをcoverしているか
- variable、flash、SMM pathはOS boot後のinputもvalidateしているか
まとめ
Runtime Phaseは、OSが制御を受け取った後も残るfirmwareの小さな部分です。Boot Phaseより範囲はかなり小さいですが、NVRAM、Secure Boot、capsule update、reset、firmware policyに関係するため重要です。runtime bugをdebugする時は、memory type、runtime descriptor、SetVirtualAddressMap()、ConvertPointer()、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.
ACPIとは: firmwareがGPIOをトグルして電源を切ってはいけない理由
なぜfirmwareがGPIOをトグルして電源を落としてはいけないのか。ACPIはfirmwareが書きOSが読む契約: テーブル、AML、電力状態、壊れたスリープ/ウェイクのデバッグ。
ExitBootServices後のRuntimeとは何か
ExitBootServices後のfirmware状態を、Boot Services終了とRuntime Services継続から説明します。
SMMアーキテクチャの全体像
SMM、SMI、SMRAM/MMRAM、Save State、lock timing、firmware debug flowを実務目線で整理します。
Biến note thành bài viết hoàn chỉnh
Notes là nơi ghi nhanh khái niệm.