TSLとは何か

UEFIのTSLを、OSローダーの実行、Boot Servicesの利用、ExitBootServices準備という流れで説明します。

更新 約 3 分
Đọc bằng 日本語 Tiếng Việt English
Firmware Flow cover

要点

TSLTransient 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、MapKeyLoadImage()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.

Biến note thành bài viết hoàn chỉnh

Notes là nơi ghi nhanh khái niệm.