8月 072019
 

最近の FreeBSD は BIOS では PC の機能が使えなくなってきているものがちらほら出てきて、いよいよ UEFI に変えるべきかと思えてきた。
僕の持っているちょっと古いが、今でも現役の ThinkPad E145 を BIOS で利用するのは FreeBSD/amd64 10.1-RELEASE が一番良かった。その後 10.3-R -> 11.2-R にしてみると LCD の明るさが変えられなくなったりとか。
最近 11.3-R にしたら suspend して resume すると /dev/psm0 が『もう使えないよ。』みたいなエラーを吐きやがる。

psm0: failed to get status (doinitialize).
psm0: failed to enable the device (doopen).
psm0: failed to enable the device (reinitialize).

 
こんな感じ。 resume 後はもう USB なマウスを使うしか手がない。 /dev/psm0 だけでなく /dev/sysmouse (こっちはタッチパッド) も使えない状態。 moused も hald も悲しい状態。

/dev/psm0 みたいなのは BIOS べったりなので OS 的に UEFI 対応が進む FreeBSD ではいよいよ使えなくなってきているのだろうなぁ。などと、思い、それじゃ。と、いうことで UEFI で起動してみるかぁ。と、なったのであります。

 
以前、このブログでは ThinkPad E145 を BIOS+MBR の組み合わせで Windows8 と FreeBSD のマルチブートについてエントリを書いているのですが、今回はいよいよ UEFI+GPT でのブートになります。
当時 (上記 URL の記事は 2013 年 09 月に書いていますね) は、マルチブートに関する前例が中々見当たらず、インターネット上にもそれらしい記事がなかったのですが、最近は探せばちらほらと見つかるようになってきましたね。それは非常に良いことです。

と、いうことで僕もトライ。今回は、自分の今後のことも兼ねて、メモ的にその手順について書き留めておきます。まぁ、作業はほとんどが Windows10 上で行うんですけどね。

おおまかな手順は以下です。

0. Windows の回復 USB メモリの作成
1. Windows10 をまずインストール。もしくはパーティションを分割
2. FreeBSD 用 EFI パーティションを作成
3. FreeBSD/amd64 12.0-RELEASE をインストール
4. bcdedit でマルチブート設定
5. EFI パーティションにファイル設置
6. 電源投入で FreeBSD 起動

だいたいこんな感じでしょうか。では、はじまりです。

一応、断っておきますが、0 番目の「回復 USB メモリ」はもしものためにちゃんと作成しておきましょう。僕は Windows10 環境を何回もぶっ飛ばしていたりしますが、もし、そうなっても僕は責任持てません:-|。

 
1. Windows10 のインストール
新しい PC を買ってきたときや、今使っている PC には Windows10 が最初から入っていると思われます。
コントロールパネル -> コンピュータの管理 -> ディスクの管理 で、Windows10 に割り当てられているパーティションをちっこくしてあげる。詳細は書きませんけども。
新規に Windows10 をインストールする場合は C:\ を好きなサイズにして FreeBSD をインストールするスペースを残しておきます。
まず最初に Windows10 をインストールする。もしくは Windows10 がインストールされている状態。と、いうのが重要です。

 
新規に Windows10 をインストールする場合、ブート用の USB メモリを作成するところから始める人がいるかもしれませんが、僕の場合、今回は Windows のアプリで rufus と、いうのを利用しました。

バージョンにもよるかもしれませんが、 Windows10 の ISO ファイルは rufus に食わせると USB の起動イメージを BIOS+MBR で作るか UEFI+GPT で作るか指定できます。もしこの時に UEFI+GPT で作成した場合には NotePC の BIOS 設定は UEFI モードにしないとイントールできません。
Widowos10 の USB の起動イメージを BIOS+MBR で作ると、インストールした Windows10 は BIOS+MBR になってしまいます。今回は UEFI+GPT で USB 起動イメージを作成することになります。

作成した USB 起動イメージに合わせるために BIOS の設定を確認しましょう。 BIOS の設定については以前書いています。そちらを参考にしてください。

さてと。これで Windows10 のインストールが無事に完了しました。

 
2. FreeBSD 用 EFI 領域の確保
FreeBSD を ISO イメージから起動してメニューの [install] を選択して進めていくと、 Windows10 がインストールされているにも関わらず FreeBSD しかブートしない NotePC になってしまいます。 bsdinstall を利用して (それはつまりは FreeBSD をフツーにインストールする。と、いうことです) FreeBSD をインストールすると既に存在する Windows10 の EFI パーティションを上書きしてしまうからなんですね。

フツーの人 (それは takawata さん みたいにマニアではない人のこと;-) は FreeBSD はフツーにインストールすると思います。

しかし、フツーにインストールすると既にある EFI パーティションを上書きして潰してしまうので、新規に 100MB 程 EFI パーティションを作成してあげます。

Windows10 は既に起動しているはずなので、以下のコマンドを管理者権限の DOS プロンプトから実行します。

c:\ diskpart
DISKPART> list disk
DISKPART> select disk 0
DISKPART> list part
DISKPART> 
DISKPART> create partition efi size=100
DISKPART> format quick fs=fat32 label="FreeBSD-EFI"
DISKPART> assign letter="S"
DISKPART> 
DISKPART> list vol
DISKPART> list part
DISKPART> exit

 
簡単にコマンドイメージだけ書きました。

1). diskpart.exe を管理者権限で実行
2). 対象とするディスク番号を選択
3). ディスクのパーティション状況を確認
4). いよいよ create partition で EFI パーティションを 100MB で作成
5). fat32 でフォーマットして、ラベルは FreeBSD-EFI とする (お好きな文字列をどうぞ)
6). assign letter=”S” でおまじない;-)

 
これで FreeBSD の bsdinstall がアクセスする EFI パーティションが作成できました。 FreeBSD を何回インストールしても、インストール後に NotePC を再起動すると Windows10 が起動する状態になります。

上記 takawata さん の URL ではこの工程がないので Windows 側の EFI パーティションを守るために bsdinstall を利用しないで make buildworld しているんですね。あ。 takawata さんは『マニア』なのかもしれないですが、 make buildworld が好きな人なのですね。きっと;-)。

それにしても bsdinstall が既存の EFI パーティションを上書きしてしまうのが問題なんですね。メニューで上書きするかしないか選択できるようにすれば良いのに・・。

と、いうことで次は FreeBSD のインストールです。

 
3. FreeBSD のインストール
今回は FreeBSD-12.0-RELEASE-amd64-bootonly.iso をチョイスしました。もう、面倒なので Windows10 上で、やはり rufus を使い USB 起動イメージを作成しました。
FreeBSD の場合は、今度は BIOS+MBR でしか作成できません。なので、FreeBSD インストール時には今度は BIOS の設定を Legacy モードにする必要があります。

あとはフツーにインストール。パーティション分割のところで GPT を選択し、更に [Manual] を選択してHDD (最近は SSD か;-) の空き領域にインストールします。

インストールが完了してリブートします。 2. のところで書いた通り、先に FreeBSD 用 EFI パーティションを作成していると bsdinstall を利用しても Windows10 側の EFI パーティションはつぶれてないので、この時点で再起動後は Widnows10 が起動するはずです。
もし FreeBSD が起動してしまった場合は Windows10 がつぶれてしまった。と、いうことです。回復 USB メモリなどから Windows10 を復旧しましょう。

 
4. bcdedit でマルチブート設定
FreeBSD インストール後に再起動したら Windows10 が起動しましたが、インストールした FreeBSD はしっかり残っております。起動させるために Windows10 側で bcdedit を利用してエントリを作成してあげます。

以前、このブログでも BIOS+MBR 環境のときに bcdedit を利用して、Windows Boot Manager から Windows と FreeBSD をブートしていましたが、 UEFI+GPT の場合は Windows Boot Manager が利用できません。 UEFI+GPT でのマルチブート環境は Firmware Windows Boot Manager を利用してブートすることになります。

そもそも「Firmware Windows Boot Manager」とはなんぞや?と、なるのですが、簡単に言うと BIOS(UEFI) のブートセレクタです。
例えば HDD からブートするとか、CD や USB メモリからブートするとか、選択する画面は Fn キーを押してメニューを出しますが、それをどうやら「Firmware Windows Boot Manager」というようです。
CD や USB・HDD からブートするのと同じレベルのメニューに “FreeBSD” や “Windows Boot Manager” メニューが存在している状態になります。

ThunkPad の場合 (Lenovo の PC の場合) は電源投入時に F12 キーを押すとブートセレクタが現れます。メーカによっては F2 キーだったり F8 キーだったりするかもしれません。

これから、このブートセレクタに bcdedit でメニューを登録していきます。

 
まず、管理者権限の DOS プロンプトでフツーに bcdedit と叩くと「Windows Boot Manager」のメニュー画面の情報が出力されます。僕の知っていた bcdedit はこの、オプションなし状態の出力でした。

「Firmware Windows Boot Manager」の項目を表示するには以下のコマンドを打ちます。

C:\Windows\system32> bcdedit
C:\Windows\system32> 
C:\Windows\system32> bcdedit /enum firmware
C:\Windows\system32> bcdedit /enum all

 
/enum オプションをつけて、そのあとに firmware とすると「Firmware Windows Boot Manager」の項目を表示します。 all と打つと「Firmware Windows Boot Manager」と「Windows Boot Manager」の全ての項目を表示します。ここ、重要ですからね;-)。

まず、「Firmware Windows Boot Manager」に FreeBSD のメニューを追加します。

C:\Windows\system32> bcdedit /copy "{bootmgr}" /d "FreeBSD"
*** ここで UUID が表示される ***
C:\Windows\system32> bcdedit /set {UUID} device partition=\Device\HarddiskVolume2
C:\Windows\system32> bcdedit /set {UUID} path \EFI\FreeBSD\Boot\bootx64.efi
C:\Windows\system32> bcdedit /set fwbootmgr displayorder {UUID} /addfirst

 
以下のような雰囲気です。

1). /copy で “FreeBSD” というエントリを作成。このときに FreeBSD の UUID が割り当てられる
2). エントリ中に device を設定 (省略可)
3). エントリ中に path を設定
4). エントリ中の順番を設定

最後の 4). のエントリについて先に説明します。 /addlast で最後に追加することもできます。その場合 F12 キーを押さない場合は Windows10 が起動します。 /addfirst を指定すると先頭に追加され、 F12 キーを押さない場合は FreeBSD がブートするようになります。お好みで;-)。

上記コマンドを投入したあと、再度 bcdedit /enum firmware を叩いてみましょう。以下は抜粋です。

C:\Windows\system32> bcdedit /enum firmware

ファームウェアのブート マネージャー
--------------------------------
identifier              {fwbootmgr}
displayorder            {bootmgr}
                        {dd655fef-3160-11e9-8f42-a6c75caf7b54} <- 先頭に追加
                        {dd655fe9-3160-11e9-8f42-a6c75caf7b54}
                        {dd655fea-3160-11e9-8f42-a6c75caf7b54}
timeout                 2
<--- 略 --->
Windows ブート マネージャー                                       <- 今回追加
--------------------------------
identifier              {dd655fef-3160-11e9-8f42-a6c75caf7b54}
device                  partition=\Device\HarddiskVolume2
path                    \EFI\FreeBSD\Boot\bootx64.efi
description             FreeBSD
locale                  ja-JP
inherit                 {globalsettings}
badmemoryaccess         Yes
default                 {current}
resumeobject            {dd655fed-3160-11e9-8f42-a6c75caf7b54}
displayorder            {current}
toolsdisplayorder       {memdiag}
timeout                 30
<--- 略 --->

 
このあとに説明しますが、UEFI+GPT の場合、OS をブートさせるためには EFI パーティションにファイルを一個置いてあげる必要があります。FreeBSD の場合は、インストールされている FreeBSD の /boot/boot1.efi を上記エントリの device と path に指定したところに正しく置いてあげる必要があります。

記載内容を間違えると「Firmware Windows Boot Manager」で “FreeBSD” を選択しても何もアクションが起きません。

そして、この内容が、BIOS+MBR の頃のように

device                  partition=c:\
path                    \bootx64.efi

 
などと記載していると「Windows Boot Manager」側で認識して、ブートすると 0x000007d みたいなエラーが出力されます。

記載した内容と設置した場所を正しく一致させましょう。

 
ちなみに作成したエントリを消す bcdedit は以下になります。書いては消して、また書いて、ブートしないのでまた書いて・・。などと、いうとき用です;-)。

C:\Windows\system32> bcdedit /delete {UUID} /f
C:\Windows\system32> bcdedit /set {fwbootmgr} displayorder {UUID} /remove

 
一行目は bcdedit /copy “{bootmgr}” で作成したエントリ全てを消すコマンドです。このコマンドを実行すると「ファームウェアのブートマネージャー」からも削除されます。
二行目のコマンドは「ファームウェアのブートマネージャー」から削除するときのみ利用するコマンドです。例えば /addlast で一番最後に登録したけど、やっぱり /addfirst で先頭に登録したい。などとうとき、二行目のコマンドを実行したあとに再度 bcdedit /set fwbootmgr displayorder を叩く。と、いうときに利用します。

bcdedit で「Firmware Windows Boot Manager」に登録するコマンドはこんな感じでしょうか。

 
5. EFI パーティションにファイル設置
さてと。あと少しで環境が整います。 EFI パーティションに FreeBSD がブートするための boot1.efi を書き込んで上げます。他の PC 上で動作している FreeBSD から /boot/boot1.efi を持ってきて Windows10 側に保存して上げましょう。

まず、diskpart.exe でボリュームの確認です。

c:\ diskpart
DISKPART> list disk
DISKPART> select disk 0
DISKPART> list vol
  Volume ###  Ltr Label        Fs    Type        Size     Status     Info
  ----------  --- -----------  ----  ----------  -------  ---------  --------
  Volume 0         回復           NTFS   Partition    499 MB  正常
  Volume 1     C                NTFS   Partition    213 GB  正常         ブート
  Volume 2                      NTFS   Partition    574 MB  正常
  Volume 3                      FAT32  Partition    100 MB  正常         システム
  Volume 4         FREEBSD-EFI  FAT32  Partition    100 MB  正常         非表示
DISKPART>

 
EFI バーティションは Windows10 が作成したもの (Volume3) と FreeBSD インストール時に作成したもの (Volume4) と二つありますが、どっちを利用しても問題ありません。

Windows10 で EFI パーティションをマウントするためには以下のコマンドを利用します。

C:\Windows\system32> mountvol
C:\Windows\system32> mountvol z: /S
C:\Windows\system32> mountvol z: /D
C:\Windows\system32> mountvol z: \\?\Volume{874c2b19-1ada-4089-9a27-de7f61f38177}\
C:\Windows\system32> mountvol z: /D

 
mountvol.exe コマンドですが、オプションなしで実行するとヘルプと、下のほうにボリュームの一覧が表示されます。
Windows10 が作成した EFI パーティションを z:\ に mount する場合には二行目のコマンドを打ちます。
FreeBSD のインストール時に作成した EFI パーティションをマウントするには四行目のコマンドを利用します。 mountvol のオプションなしで実行した場合に下のほうに「現在のマウント ポイントとボリューム名の考えられる値:」で表示されたマウントポイントの *どれか* を指定します。
diskpart.exe の list vol や list part と見比べてじっくりと判断してください;-)。

ちなみに mountvol z: /D はumount するオプションです。

 
今回は FreeBSD インストール時に作成した EFI パーティションは利用せず、Widnows10 側の EFI パーティションを利用します。

C:\Windows\system32> mountvol
C:\Windows\system32> mountvol z: /S
C:\Windows\system32> z:\
z:\> mkdir EFI\FreeBSD\Boot 
z:\> cd EFI\FreeBSD\Boot 
z:\> copy c:\boot1.efi ./bootx64.efi
z:\> dir
z:\> c:\
C:\Windows\system32> exit

 
mountvol で Widnows10 の EFI パーティションを z: に mount します。 z:\ に行くと既に EFI というディレクトリが掘られています。そこに FreeBSD 用のディレクトリを作成し、c:\ に置いた boot1.efi という FreeBSD から引っこ抜いてきたファイルを bootx64.efi として保存します。
途中、ls ではなく dir コマンドで色々確認しつつ作業を行ってください。 設置場所は bcdedit コマンドで指定した device と path の各オプションと一致していることが重要です。

ちなみに mountvol で EFI パーティションをマウントしていると bcdedit /enum firmware で確認した場合の device パラメータの表示が変わってきます。 mountvol で mount している状態のほうが確認しやすいです。

 
さてと。これで全ての準備が整いました。Windows10 側でリブートしましょう。 /addfirst を指定した場合は NotePC 再起動後にスルスルっと FreeBSD が起動するようになります。

やったっ!!

もし FreeBSD が起動しなかった場合は bootx64.efi の設置場所が bcdedit で指定したものと合っているかじっくりと確認してください。

僕の場合ですが、大失敗・・。 copy c:\boot1.efi ./bootx64efi とやっていました・・。orz
これじゃ起動しません。rename bootx64efi bootx64.efi として事なきを得、無事に FreeBSD が起動したのでありました。ふぅ。そして、パチパチパチ。

 
6. 電源投入で FreeBSD 起動
さてと。僕の場合 ThinkPad E145 は FreeBSD メインで利用し、時々 Windows10 を利用する形態なので bcdedit /set fwbootmgr displayorder {UUID} /addfirsst で登録しました。これだと電源投入後はサクっと FreeBSD が起動します。

Windows10 を起動したいときには NotePC の電源投入後に F12 キーを押してブートセレクタを表示して「Windows Boot Manager」を選択すると Windows10 が起動するようになります。

 
さてと。最後に FreeBSD 12.0-RELEASE についてちょっと書いておきます。

今まで僕はずっと BIOS+MBR な FreeBSD しか使ったことがなかったのですが、今回初めて UEFI+GPT な FreeBSD を使うことになります。
一番上で書いた /dev/psm0 が resume 後に psm0: failed to get status となって使えなくなった事象は解決しました。やっぱり FreeBSD の ACPI 周りはどんどん UEFI に傾倒して行っているのね。と、再確認できました。

あと、ThunkPad E145 など AMD のグラフィックスチップ使っている PC 限定かもしれませんが、グラフィックスチップは graphics/drm-fbsd12.0-kmod で認識しています。今までは radeonkms.ko を指定していましたが、これを利用するとカーネルパニック頻発です。 amdgpu にしたら安定しました。 UEFI ブートとは相性が良くないみたいですね。 pkg-message にも書かれています。

しかし、 UEFI にしても acpi_video.ko が使えない状態なのは変わらず。なので、ディスプレーの明るさは変えられません。 AMD グラフィックスチップの悲劇か・・。

 
とまぁ、ツラツラと書いてみましたが UEFI+GPT にした PC において Windows と FreeBSD のマルチブートについて書いてみましたが、大きな点としては

1). bsdinstall は Windows 側の EFI パーティションを潰してしまう
2). 「Windows Boot Manager」ではなく「Firmware Windows Boot Manager」でマルチブートを実現

でしょうかね。

1). のほうは僕も過去に実はずいぶんとハマりました。どうして Windows10 が起動しないのだっ!!?? みたいな・・。知っている人はちらほらいるみたいですが、僕は Slack のとあるコミュニティで FreeBSD のエラい人に教えてもらいました。 FreeBSD のインストールのために EFI パーティションを一個作成する。ってことがミソですね。

ちなみにですが、/boot/boot1.efifat が、ここで書いてきた FreeBSD インストール前に作成した EFI パーティションの中身です。
bsdinstall が Windows10 側の EFI パーティションを boot1.efifat で上書きしています。 FreeBSD インストール前に EFI パーティションを作成すると bsdinstall は FreeBSD インストール前に作成した EFI パーティションに対して /boot/boot1.efifat が書き込まれ Windows10 側の EFI パーティションは無傷です。

mountvol z: \?\hoge\ で FreeBSD 側 EFI パーティションも mount できるので確認してみるのも良いかも。

2). のほうはある意味目ウロコですね。 Windows Boot Manager を捨ててその一個前のフェーズで FreeBSD をブートしてしまう。 grub とか、他のブートマネージャは不要で bcdedit でなんとかしてしまう。ってことになりますね。

FreeBSD インストール前に EFI パーティションを一個作って、 bcdedit /enum firmware のコマンド群で制御。

この二つが今回は大きな収穫でした。これで UEFI な PC でもマルチブートは大丈夫っ!! 新しい NotePC 買おうかなー;-)。