TSLとは何か
UEFIのTSLを、OSローダーの実行、Boot Servicesの利用、ExitBootServices準備という流れで説明します。
要点
TSL は Transient System Load の略で、OSローダーは動いているが、firmwareからOSへの引き渡しがまだ完全には終わっていない時間帯を指します。
UEFIの流れでは、TSLはBDSの後に来ます。BDSはboot optionを選び、LoadImage()でboot loaderを読み込み、StartImage()で実行します。firmware側から見ると、boot loaderの実行が始まった時点でTSLに入ったと考えられます。
Boot flowの中の位置
簡単に見ると、次のような流れです。
Reset Vector -> SEC -> PEI -> DXE -> BDS -> TSL -> ExitBootServices -> OS Runtime
TSLはPEIやDXEのような独立したfirmware phaseではありません。boot loaderがUEFI servicesを使いながら、kernel、memory map、initrd、ACPI table pointer、OSへ渡す情報を準備し、最後にExitBootServices()を呼ぶまでの区間です。
Boot loaderがまだ使えるもの
TSLでは、boot loaderはまだBoot Servicesを呼び出せます。
よく出てくるAPIは次の通りです。
GetMemoryMap()
AllocatePages()
AllocatePool()
LocateProtocol()
HandleProtocol()
LoadImage()
StartImage()
ExitBootServices()
そのため、DXEやBDSまでは正常に見えても、boot loaderからkernelへ移る直前だけで問題が出ることがあります。
よくある誤解
TSLに入ったからといって、OSが完全に動いているわけではありません。kernel imageはmemory上に置かれているかもしれませんが、ExitBootServices()が成功するまでは、firmwareのBoot Servicesはまだ存在しています。
また、TSLとBDSも別物です。BDSはfirmwareがboot targetを選ぶ処理です。TSLはboot loaderがOSを準備している状態です。
Memory mapとの関係
TSLで重要なのは、最後のmemory mapを取得することです。
boot loaderは通常、GetMemoryMap()を呼び、MapKeyを受け取り、その同じMapKeyを使ってExitBootServices()を呼びます。
この2つの呼び出しの間にallocation、log出力、file I/O、protocol callなどが入りmemory mapが変わると、ExitBootServices()はEFI_INVALID_PARAMETERを返すことがあります。
Debug時に見るポイント
boot loaderまでは起動するがkernelに入らない場合、次の順に切り分けます。
Boot#### selected?
Device Path connected?
LoadImage() success?
StartImage() success?
Boot loader got memory map?
ExitBootServices() success?
Kernel entry reached?
どこでlogが途切れるかを見ると、調査範囲をかなり絞れます。
実例
boot loaderがGetMemoryMap()の後にdebug logを追加したとします。そのlog処理が内部でbufferをallocateすると、古いMapKeyは無効になります。
結果としてExitBootServices()が失敗します。しかしlogを消すと再現しなくなるため、TSL周辺ではよくあるdebug trapになります。
Source-reading checklist
TSL周辺のsourceを読む時は、次を確認します。
- boot loaderはどこでmemory mapを取得しているか
- GetMemoryMap()後にallocationがないか
- ExitBootServices()のretry処理は正しいか
- LoadImage()とStartImage()を別々にlogしているか
- ACPI pointer、initrd、kernel command lineのmemory typeは何か
- ExitBootServices()後にBoot Services APIを呼んでいないか
まとめ
TSLはfirmware boot policyからOS runtimeへ移るための中間領域です。boot loaderはまだUEFI Boot Servicesを使えますが、最終目的はExitBootServices()を成功させ、kernelへ制御を渡すことです。boot問題をdebugする時は、memory map、MapKey、LoadImage()、StartImage()、kernel handoffを丁寧に確認する必要があります。
この記事が役に立ったら
ファームウェア、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の制御を引き継ぐ。
BDS to TSL Handoffとは?
BIOS/UEFIのBDS to TSL handoffを説明します。BootOrder、Boot####、Device Path、ConnectController、LoadImage、StartImageを扱います。
ExitBootServices後のRuntimeとは何か
ExitBootServices後のfirmware状態を、Boot Services終了とRuntime Services継続から説明します。
Biến note thành bài viết hoàn chỉnh
Notes là nơi ghi nhanh khái niệm.