FreeBSDのboot1.efiがもう使われていなかった件

UEFI環境でのFreeBSD (x64)のブートは、下表の手順で行われるとされている。manにも書かれている由緒正しい手順だ。

  1. UEFI:/EFI/BOOT/BOOTX64.EFI
    • UEFIシステム起動時に実行されるブートローダ
  2. ファーストステージ: boot1.efi (man)
    • freebsd-zfs, freebsd-ufsパーティションを探し、次のステージを起動するブートローダ。パーティション探索は、自身が読み込まれたストレージ→UEFIのブートオーダーに沿ったストレージの順に行われる。
  3. ファイナルステージ: loader.efi (man)
    • 環境変数currdev, loaddevで指定されたストレージからカーネルを起動する。
  4. カーネル

ファームウェア(UEFI)がEFIシステムパーティションのBOOTX64.EFIを起動し、それがboot1.efiを起動し、さらにloader.efiに処理が移り、最終的にカーネルが立ち上がる流れとなっている。スタンドアローンなFreeBSD環境では、boot1.efiがBOOTX64.EFIとしてコピーされるので、実際はBOOTX64.EFI→loader.efi→カーネルの順で起動、、、ということになっている。

言葉を濁してるのは、まぁお察しのとおり、manの説明と現状の実装が異なってるから。どうやらFreeBSD 12.0-RELEASEあたりで、BOOTX64.EFIとしてloader.efiが使われるようになったらしい(当該コミット)。この辺は現在絶賛過渡期のようで、ESP生成まわりを大きく作り変えたパッチも存在している。

試しにFreeBSD 12.2-RELEASEのインストーラが作ったESPをマウントし、BOOTX64.EFIとloader.efiのハッシュを比較すると見事に同じということが分かる。

というわけで、現実はファーストステージをすっ飛ばし、ファイナルステージブートローダがいきなり動き出す。

これでも大抵の環境では問題ない一方、現状、loader.efiは別ディスクのFreeBSDパーティションの探索を行わないようなので、そのようなストレージ構成だとFreeBSDのブートができない。こいつぁ困ったぜ。

回避策としては、手動でBOOTX64.EFIをboot1.efiにするか、あるいはloader.efiのままプロンプトでcurrdevを手動で指定し、zfs.koをカーネルを手動で読み込んでやればいい。前者の方が明らかに簡単ですな。

loader.efiのソースを見てたら、まだmanに載ってない方法が使えそうな気がするので、後日試す予定。

参考サイト