・UEFI対応関連メモ(その2)
UEFIなBIOSは、起動対象のHDDのEFI System Partition(ESP、最近はPartition IDがUUIDになっていて、C12A7328-F81F-11D2-BA4B-00A0C93EC93B なるIDらしい)のEFI/以下にあるディレクトリに収められた efi 形式のブートローダを調べる。
efi 形式のブートローダは拡張子が .efi で、ファイルフォーマットはWindows用のPE(Portable executable)になっている必要がある。
$ file /mnt/64Pkgs/Plamo-6.x/x86/EFI/BOOT/BOOTx64.efi /mnt/64Pkgs/Plamo-6.x/x86/EFI/BOOT/BOOTx64.efi: PE32+ executable (EFI application) x86-64 (stripped to external PDB), for MS Windows
UEFI BIOSは、ブート対象なHDDのESP上にある任意のブートローダを起動できるけれど、 どのブートローダを起動するかは、マザーボード側のメモリ(NVRAM)に記録されている。
# 優先順位も記録されているらしい
この「マザーボード側のメモリに記録」するというのがクセモノで、 いわゆるセキュア・ブートの機能を有効にすると、メモリを変更することができなくなって、 あらかじめ登録済みのOS(Windows)しか起動できなくなる。
一方、セキュア・ブートは設定していなくても、マザーボード側のメモリを書きかえるには、 カーネル経由でそれらを操作する必要があり、Linuxの場合、CONFIG_EFI_VARS が有効になっていないとUEFI BIOSのメモリにアクセスできない。
# アクセスできる場合は /sys/firmware/efi 以下に情報が出る。
また、カーネルのビルドオプションで CONFIG_EFI_VARS を指定していても、 UEFIではなく従来のMBR経由で起動した場合は、カーネルがEFIが有効だと認識せず /sys/firmware/efi は出てこない。
カーネルのEFI機能が無効な状態でも、GPTパーティションにgrubをインストールはできるものの、マザーボード側のメモリに自身を登録することができないので、再起動時には自動起動できず、(マザーボード側の)UEFI シェルからブート先として指定してやる必要がある。UEFIシェルから起動してやるとカーネル側もEFIを認識する(/sys/firmware/efi/が現われる)ので、grubconfig で再インストールしてやれば、次からは自動的にgrubの起動メニューが表示されるようになる。
ちなみに、マザーボード側のメモリを操作するためのコマンドがefivarとefibootmgrで、これらはカーネルの/sys/firmware/efi 経由でマザーボード側のメモリを操作するらしい。
メモリに登録されているブートローダが起動対象に指定したデバイスに無かった場合、マザーボードのUEFIシェルは、起動対象のデバイスのESPを調べ、そのパーティションの /EFI/BOOT/ ディレクトリにある bootx64.efi(64ビットモード)か bootia32.efi(32ビットモード)をブートローダと見なす。ESPの/EFI/BOOT/にこれらのファイルが無かった場合、UEFIシェルはそのデバイスを起動対象とは見なさない。
# このあたりはマザーボード(メーカー)のUEFI BIOSの実装に依存する模様
UEFI対応のgrubをインストールすると、/EFI/grub/grubx64.efi に本体を置くけれど、 /sys/firmware/efi が無いとこのブートローダをマザーボードのUEFI BIOSメモリに記録できないので、 再起動時にはうまく起動できなくなるので、念のため本体のコピーを /EFI/BOOT/bootx64.efi にコピーしておくのが吉。ただし、別のOSとDual Bootな環境になっている場合は、すでに /EFI/BOOT/bootx64.efi があったりするので、単純に書き替えるのは危険かも。
# bootx64.efi にしていない場合でも、UEFI shellからそのブートローダを指定して起動することはできる
なお、このあたりの実験はVirtualBoxのEFI機能で試しているので、マザーボードによって使える機能は異なっている模様。
# VirtualBoxのは最小規模の実装だと思っているのだけれど。。