【rEFInd】別ディスクのWindowsブートマネージャを起動する

# 新年のあいさつ
あけましておめでとうございます。
今年もよろしくお願いします。

# 概要
　WindowsがインストールされたPCにもうひとつの内蔵ストレージを追加し、そこにインストールしたrEFIndブートマネージャからWindowsブートマネージャを呼び出す方法を紹介します。

# 最終的な環境
```
└── NVMeディスク0
    ├── WindowsBootmgr（bootmgfw.efi）の入ったESP
    ├── Windowsファイルシステム（C:）
    └── Windows回復パーティション
└── NVMeディスク1
    ├── rEFIndのESP（vmlinuz入り）
    ├── Linux SWAP領域
    └── Linuxファイルシステム（/）
```
　まずはrEFIndが起動し、vmlinuzからLinuxを起動するか、Windowsブートマネージャー（bootmgfw.efi）から選択できる。前者を選択すれば、rEFIndはvmlinuzとinitramfsを実行してLinuxを起動するし、後者を選択すればrEFIndはbootmgfw.efiを呼び出し、Windowsが起動する。
 ※ディスク番号は0とか、1とか、順番が変わる可能性が大いにあります。（私の環境でも、いつの間にか番号が入れ替わっていました。）ファイルシステム、パーティションの指定には、UUIDやPARTUUIDを使用しましょう。

 # rEFIndについて
　今回使用するブートマネージャは、rEFIndです。
　rEFIndを選んだ理由は、GUIが綺麗というのもありますが、configファイルのサンプルに載っている情報が充実していたことが大きいです。今回の環境をつくる際にも、大いに参考になりました。
　ちなみに、minimal themeというのが人気らしいです。テーマを入れる作業は非常に簡単なので割愛します。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3735823/efb72b53-1b86-7438-cc24-e8ed0c1c3ac5.png)
（画像：https://www.rodsbooks.com/refind/ ）

 # rEFIndをインストールするまで
　まずは、ディスク0のみ刺した状態で、Windowsを通常通りインストールします。
　[ArchWikiのインストールガイド](https://wiki.archlinux.jp/index.php/%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%82%AC%E3%82%A4%E3%83%89)に従って、ArchLinuxをインストールします。すると、本稿の「最終的な環境」と同じパーティション構成になっていると思います。

# ブートエントリを確認してみる
　ArchLinuxのインストーラには、efibootmgrが付属しています。これを使って、ブートエントリを確認してみます。
```
$ efibootmgr -v
BootCurrent: 0000
Timeout: 0 seconds
BootOrder: 0000
Boot0000* Windows Boot Manager  HD(1,GPT,xx-xx-xx,xxxx,xxxx)/\EFI\Microsoft\Boot\bootmgfw.efixx...xx
      dp: xx xx ... xx xx / xx xx ... xx xx / xx xx xx xx
    data: xx xx xx ... xx xx xx
```
　「dp」というのがbootmgfwに至るまでのデバイスパス、「data」というのがbootmgfw.efiに渡しているオプションです。dataをUTF-8で読んでみたところ、どうやらWindows側で付けている、bootmgfw.efi自身のIDのようです。
　このブートエントリから少なくとも、「UEFIは起動時、bootx64.efiではなく、bootmgfw.efiを呼び出している」ということが分かります。

# rEFIndをインストールする
　まずは、pacmanで公式リポジトリからrEFIndをダウンロード、インストールします。
```
# pacman -S refind
```
　すると、`/usr/share/refind/`に、rEFIndに関するファイルがたくさん入っています。
```
$ ls /usr/share/refind/
drivers_x64  fonts  icons  keys  refind.conf-sample  refind_x64.efi  tools_x64
```
　Windowsに勝手にブートエントリが削除された場合に備え、rEFIndをNVMeディスク1のデフォルトの起動オプション（`ESP/EFI/BOOT/bootx64.efi`）にしておきます。（ESPのマウントポイントは`/boot/`）

```
# cp /usr/share/refind/refind_x64.efi /boot/EFI/BOOT/bootx64.efi
# cp -r /usr/share/refind/icons /boot/EFI/BOOT/
```
　ここからrEFIndのconfigを書いていくのですが、まずはrEFIndのconfigのサンプルファイルを読んでみます。
# refind.conf-sampleを読んでみる
　rEFIndがダウンロードされたディレクトリに、configのサンプルが入っています。
```
$ cat /usr/share/refind/refind.conf-sample | less
```
## 自動スキャン設定
```
# Which types of boot loaders to search, and in what order to display them:
#  internal      - internal EFI disk-based boot loaders
#  external      - external EFI disk-based boot loaders
#  optical       - EFI optical discs (CD, DVD, etc.)
#  netboot       - EFI network (PXE) boot options
#  hdbios        - BIOS disk-based boot loaders
#  biosexternal  - BIOS external boot loaders (USB, eSATA, etc.)
#  cd            - BIOS optical-disc boot loaders
#  manual        - use stanzas later in this configuration file
#  firmware      - boot EFI programs set in the firmware's NVRAM
# Note that the legacy BIOS options require firmware support, which is
# not present on all computers.
# The netboot option is experimental and relies on the ipxe.efi and
# ipxe_discover.efi program files.
# On UEFI PCs, default is internal,external,optical,manual
# On Macs, default is internal,hdbios,external,biosexternal,optical,cd,manual
#
#scanfor internal,external,optical,manual,firmware
```
　これについては好みの範疇ですが、私はrootが指定されていないLinuxの起動オプションなどが追加されてしまうのは嫌なので、スキャンするのはmanualだけにしておこうと思います。

## ブートオプション
```
# Sample manual configuration stanzas. Each begins with the "menuentry"
# keyword followed by a name that's to appear in the menu (use quotes
# if you want the name to contain a space) and an open curly brace
# ("{"). Each entry ends with a close curly brace ("}"). Common
# keywords within each stanza include:
#
#  volume    - identifies the filesystem from which subsequent files
#              are loaded. You can specify the volume by filesystem
#              label, by partition label, or by partition GUID number
#              (but NOT yet by filesystem UUID number).
#  loader    - identifies the boot loader file
#  initrd    - Specifies an initial RAM disk file
#  icon      - specifies a custom boot loader icon
#  ostype    - OS type code to determine boot options available by
#              pressing Insert. Valid values are "MacOS", "Linux",
#              "Windows", and "XOM". Case-sensitive.
#  graphics  - set to "on" to enable graphics-mode boot (useful
#              mainly for MacOS) or "off" for text-mode boot.
#              Default is auto-detected from loader filename.
#  options   - sets options to be passed to the boot loader; use
#              quotes if more than one option should be passed or
#              if any options use characters that might be changed
#              by rEFInd parsing procedures (=, /, #, or tab).
#  disabled  - use alone or set to "yes" to disable this entry.
#
# Note that you can use either DOS/Windows/EFI-style backslashes (\)
# or Unix-style forward slashes (/) as directory separators. Either
# way, all file references are on the ESP from which rEFInd was
# launched.
（略）
```
　ここに書いてある`volume`の設定が今回の肝です。今回は、PARTUUIDを使ってパーティションを指定しました。

# refind.confを書く
　新規設定ファイルを作成します。
```
# vim /boot/EFI/BOOT/refind.conf
```
## 雑多な設定
```
timeout 10
scanfor manual
```
　`timeout`は20もいらないので、10にしておきます。`scanfor manual`で自動スキャンを切ります。
## Linuxのブートエントリ
　まずは、ファイルシステムのUUIDを確認しておきましょう。
```
$ ls -l /dev/disk/by-uuid/
```
　rootファイルシステムのUUIDを控えておきます。
```
menuentry "Arch Linux" {
    icon   /EFI/BOOT/icons/os_arch.png
    ostype "Linux"
    loader /vmlinuz-linux
    initrd /initramfs-linux.img
    options "root=UUID=xxxx-xxxx-xxxx-xxxx rw"
    submenuentry "Boot using fallback initramfs" {
        initramfs /initramfs-linux-fallback.img
    }
    submenuentry "Boot to terminal" {
        add_options "systemd.unit=multi-user.target"
    }
}
```
　ほぼサンプル通りです。`vmlinuz-linux`などがrEFIndと同じパーティションに入っているので、`volume`の設定は不要です。ハイバーネートを使う場合は、オプションに`resume`も渡しましょう。

## Windowsのブートエントリ
　ファイルシステムのUUIDでは指定できないみたいなので、PARTUUIDで指定します。
　PARTUUIDを確認します。
```
$ ls -l /dev/disk/by-partuuid/
```
　WindowsのESPのPARTUUIDを控えておきます。
```
menuentry "Windows 11" {
    icon /EFI/BOOT/icons/os_win8.png
    ostype "Windows"
    volume xxxx-xxxx-xxxx-xxxx-xxxx
    loader \EFI\Microsoft\Boot\bootmgfw.efi
}
```
　`icon`の`/EFI/`は、rEFIndの入っているESPから生えています。`loader`の`\EFI\`は、Windows側のESPから生えています。

　以上でrEFInd側の設定は完了です。次に、efibootmgrで、NVRAMへのrEFIndのブートエントリの追加を行います。

# NVRAMへのrEFIndのブートエントリの追加
```
# efibootmgr --create --disk /dev/nvmeXn1 --part 1 --loader /EFI/BOOT/bootx64.efi --label "rEFInd Boot Manager" --unicode 
```
　このコマンドで、ブートエントリを作成します。ブートエントリが作成されたかどうか確認しておきましょう。
```
$ efibootmgr -u
BootCurrent: 0000
Timeout: 0 seconds
BootOrder: 0000
Boot0000* Windows Boot Manager  HD(1,xxxxxxxx)/\EFI\Microsoft\Boot\bootmgfw.efi????
Boot0001* UEFI OS       HD(1,xxxxxxxx)/\EFI\BOOT\BOOTX64.EFI
```
　ちなみに、余計なブートエントリがあった場合は、次のコマンドで削除できます。
```
# efibootmgr --delete-bootnum --bootnum XXXX
```
　BootOrderを設定します。
```
# efibootmgr --bootorder 0001,0000
```
　これで、電源ボタンを押したあとに最初に起動するefiファイルがrEFIndのものに変わりました。コマンドに余計なスペースなどあると動作しないので、注意しましょう。

# 動作確認
　Linuxは、全く問題なく起動しました。
　Windowsに関しては、起動の動作が不自然（いつもは表示されない田マークが表示される）ということがあったが、なんとか起動しました。

# ブートエントリが勝手に削除された場合
　rEFIndを別ディスクにインストールしたことで、rEFIndのファイル自体が削除されるリスクは低減されたと思います。（悪名高きWindows Updateで吹き飛ばされる可能性は残っているようですが・・・）
　しかし、NVRAMは共用なので、勝手に書き換えられることが予想されます。ブートエントリが削除された場合は、以下の手順に従います。
　まず、各マザーボードのファームウェアで指定されたキー（私の使用しているMSIのものの場合「F11」）を連打し、ブートメニューに入ります。rEFIndが入っているパーティションの`bootx64.efi`を選択して、Linuxを起動します。その後、本稿「NVRAMへのrEFIndのブートエントリの追加」と同じ手順を踏み、ブートエントリを追加しなおせば復旧できます。

# まとめ
* 別ディスクからWindowsブートマネージャを呼び出すことができた
* ブートエントリが削除された場合の復帰も容易
* Windowsブートマネージャの動作が少し変

# 参考
* refind.conf-sample
* man efibootmgr
* https://wiki.archlinux.jp/index.php/REFInd
* https://wiki.archlinux.jp/index.php/%E6%B0%B8%E7%B6%9A%E7%9A%84%E3%81%AA%E3%83%96%E3%83%AD%E3%83%83%E3%82%AF%E3%83%87%E3%83%90%E3%82%A4%E3%82%B9%E3%81%AE%E5%91%BD%E5%90%8D
* https://zenn.dev/karaage0703/articles/0ca67e19aa772e#linux%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB