Re: loader.efi of 13.1

From: Tomoaki AOKI <junchoon_at_dec.sakura.ne.jp>
Date: Wed, 31 Aug 2022 13:46:21 UTC
青木@名古屋です。
関係箇所につらつらとコメントします。
(ので、野中さんのコメントからのスレッドと分けます。)

On Wed, 31 Aug 2022 14:39:02 +0900
masa@amogha.jp (丸山直昌) wrote:

> 丸山@年金生活者 です。
> 
> そろそろ古い FreeBSDを卒業して、13.1あたりに移住しようと思い、インストー
> ルを試してみたのですが、loader.efi の使い方で躓いていて、思うようなレ
> イアウトで内臓ディスクにインストールできずにいます。私が直面している状
> 況を誰にでも実験可能な形で説明するために、次のような「練習問題」を考え
> てみます。
> 
> FreeBSD 13.1 の loader.efi の使い方の練習問題
>   既にどこかにインストールしてある13.1のパーティション(amd, zfs on
>   UEFIマシン)を別のディスクにコピーして boot可能にするにはどうしたら良
>   いか。
> 
> 具体的には以下のような手順でやってみました。
> 
> 1. FreeBSD-13.1-RELEASE-amd64-dvd1.iso をdd でコピーした外付け USB ディ
>   スク(/dev/da0、つまりは「イントールメディア」)で起動し、中身が空の
>   USB ディスク(/dev/da1)に FreeBSD13.1amdを zfs でインストールする。
>   これは簡単で、
> 
> # gpart show da1
> =>      40  78140080  da1  GPT  (37G)
>         40    532480    1  efi  (260M)
>     532520      1024    2  freebsd-boot  (512K)
>     533544       984       - free -  (492K)
>     534528   4194304    3  freebsd-swap  (2.0G)
>    4728832  73410560    4  freebsd-zfs  (35G)
>   78139392       728       - free -  (364K)
> 
> のようになる。この USB ディスクを以下「インストール済みディスク」と呼
> ぶことにします。
> 
> 2.  インストール済みディスクのみを外付けデバイスとして接続してパソコン
>   を起動すると、勿論起動する。/dev/da0 となる。
> 
> 3. 内臓ディスク(ada0, gptスキーム)の空きパーティション(私の場合
>   ada0p13)を type freebsd-zfs にして、そこにda0p4のzrootをコピーする。
> 
>   zpool create NEWPOOLNAME ada0p13
>   zfs send -R zroot@SNAPSHOT | zfs recv -F NEWPOOLNAME
> 
> 4. (ada0からのbootの準備)
>   zpool set bootfs=NEWPOOLNAME/ROOT/default NEWPOOLNAME
>   (安全のため) ada0 の efi パーティション(私の場合 ada0p4)の
>     EFI/Boot/bootx64.efi を退避
>   /boot/loader.efi を ada0 の efi パーティションの
>     EFI/Boot/bootx64.efi にコピー
>   zpool export NEWPOOLNAME
>   halt -p
> 
> 以上の準備の元、すべての外付けデバイスを外して、内臓ディスクから起動してみます。

なんとなくですが、zpool createのところでキャッシュファイル
(zpool.cache)の指定が無いのが気になります。

安全策は、

 zpool create -o cachefile=/tmp/zpool.cache NEWPOOLNAME /dev/ada0p13

でpoolを作成し、exportする前に/tmp/zpool.cacheをNEWPOOL内の/etc/zfsに
コピーしておくか、

 zpool create -R /mnt NEWPOOL /dev/ada0p13

でNEWPOOLに対する操作全てが/mnt以下が/であると偽装して進むように
しておくことかと思います。
今回のようにzfs sendとzfs recvのセットでコピーする予定の
場合、上書きを避けるためにも明示的にzpool.cacheを/tmp以下に
作らせて書き戻すのが安全と思います。

 ※半端にda0としての情報が残ったzpool.cacheになっていると
  既に外されているda0を探してしまう恐れがありそうです。

> 
> Consoles: EFI console
>     Reading loader vars from /efi/freebsd/loadef.env
> Setting currdev disk0p4:
> FreeBSD/amd64 EFI loader, Revision 1.1
> 
>    Command line arguments:
>    Image base: 0xd0998000
>    EFI version: 2.31
> 
> 等と表示されます。続いてさらに画面半分ほどのメッセージが表示された後、
> 
> ERROR: cannot open /boot/lua/loader.lua: no such file or directory.
> 
> Type '?' for a list of commands,'help' for more detailed help.
> OK
> 
> となって止まります。ここで
> 
> OK lsdev
> 
> とやると ada0p12(古い FreeBSDで作った zfs) と ada0p13(今回作った
> FreeBSD13.1の zfs) にある zfs のプール名は zfs devices として正しく表
> 示されます。ここで Google 検索で見つけた
> 
> 	https://www.ish.org/blog/?p=968
> 
> を手がかりに以下のようにしてみました。 
> 
> OK set currdev=zfs:NEWPOOLNAME/ROOT/default:
> OK unload
> OK boot
> 
> すると、何やら起動作業と思われる動作が進行し、画面には色々表示されるの
> ですが、
> 
> mountroot> 
> 
> で止まってしまいます。不思議なことに、 mountroot> プロンプトの少し前に
> 以下のように表示されているのに mount できていません。
> 
> Loader variables:
>   vfs.root.mountfrom=zfs:NEWPOOLNAME/default
> 
> ここの最後にコロン(:)が無いのも不思議です。仕方ないので
> 
> mountroot> zfs:NEWPOOLNAME/ROOT/default:
> 
> とやってみますが、うまくゆきません。お手上げです。

これ、最後の「:」があってはまずいのでは?
問題はvfs.root.mountfromがzfs:NEWPOOLNAME/defaultに
なっているところで、mountroot> プロンプトのところでの
入力内容の最後の「:」を外してみては?

あと、ada0p12が純粋なデータプールではなくRoot on ZFSのプール
だった場合、通常のboot1.efiやloader.efiでは致命的です。

 ※別のドライブなら問題ないのですが、同じada0なのが
  致命的にまずいです。

どうしても物理的にこういう構成になるなら、唯一の解決策は、

 ・Bug 207940 [1]の最新のパッチを適用したboot1.efiを
  使用し、起動時に正しいプールを指定する。 デフォルト
  ではada0p12の方が選択されていると思いますので、
  切り替えます。

 ・NEWPOOLNAME内の/boot/loader.efiで明示的に
  vfs.root.mountfrom="zfs:NEWPOOLNAME/ROOT/default"
  のように正しい/のデータセットを指定する。

かと思います。

13.1なら、標準のboot1.efiは
 1.それ自体が読み込まれた物理ドライブで最初に見つけた
  /boot/loader.efiの存在するZFSプール
 2.無ければ、同じドライブで最初に見つけた/boot/loader.efiの
  存在するUFSパーティション
 3.どちらもなければ、UEFIファームウェアが認識した順番に
  別の物理ドライブで1.と2.を繰り返す。
 4.それでも無ければ失敗。
という挙動をします。 基本的にloader.efiでもこのあたりは
同様と思います。 が、loader.efiには野中さんのパッチ相当の
プール/パーティション選択機能もそれを提供するパッチも
存在しません。

つまり、同じドライブで先に見つかる筈のada0p12に/boot/loader.efiが
あるとそこから起動しようとしてしまいますが、ここのバージョンが
/boot/lua/loader.luaができる前のものだと当然見つかりません。
...が、releng/12.0でもloader.luaは存在しますね...。
標準でビルド/インストールされたかの記憶は定かではありませんが、
ソースとしては存在します。 [2]

一時的にでもada0p12から起動できなくなってもよければ、
ada0p12のプールの/boot/loader.efiをリネームしてしまえば
大丈夫かもしれませんが、現状のloader.efiだとbootfs属性が
設定されたプールが先にあるとアウトの可能性も。


[1] https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=207940

[2] https://cgit.freebsd.org/src/tree/stand/lua/loader.lua?h=releng/12.0


> 
> なお、上の OK プロンプトのところで上記 ish.org のブログに書いてある
> 
>   free-module-options
> や
>   start
> 
> は unknown commandとなるので、 12.x と 13.1 では loader.efi の仕様が違っ
> ているようです。
> 
> どなたかお助けください。
> 
> --------
> 丸山 直昌 まるやま なおまさ
> メールアドレス: masa@amogha.jp
> 


-- 
青木 知明  [Tomoaki AOKI]    <junchoon@dec.sakura.ne.jp>