これはNetBSD Advent Calendar 2017の21日めの記事です。
最近のPCは従来BIOSと呼ばれていたOSを起動する仕組みに、U-EFIという新しい方式に変わりつつあります。 U-EFIになることで機能的にもできることが色々増えたりするのですが、ユーザー側から見てもっともわかりやすい変更は以下の点でしょう。
従来のBIOSではmbrというディスク管理の仕組みで記録された情報で起動していましたが、これはパーティション情報として格納できる最大値が2TBであったため、これ以上大きなディスクを正しく扱えませんでした。 既に一部のノートパソコン、特にタブレットPC等はレガシーBIOS互換機能が無く従来のMBR形式では起動できないマシンが存在します(MicrosoftのSurface系がそうらしい)。 また、Intelは2020年にレガシーBIOS互換機能のサポートを中止するという話もあります。
ということで、来るべきレガシーBIOS無し時代に向けて、U-EFI環境にNetBSDをインストールしてみます。
実はNetBSD 8.0(まだBETAで正式リリース前)以降、NetBSD/amd64ではU-EFIで起動するインストールメディアイメージが提供されています。 例えばdaily snapshotでは、http://nycdn.netbsd.org/pub/NetBSD-daily/netbsd-8/201712201920Z/images/の下にあるNetBSD-8.0_BETA-amd64-uefi-install.img.gzがそれです(daily snapshotは更新されていくため、日付部分は変わって行き、しばらくすると参照できなくなるので注意)。
これをdd(1)等でUSBに書き込んでやればU-EFIブートでNetBSDが起動し、今までどおりのNetBSDインストーラsysinst(8)が起動します。やったね!
しかしここで、大きな問題があります。少なくとも2017/12現在のNetBSD 8.0_BETAではsysinstでインストールを始めると従来通りの方法でdisklabelを書き、なぜかmbrでboot loaderがインストールされます。つまり、U-EFI boot環境に対応していません(たぶん。対応済みだったらごめんなさい)。これでは仮にインストールが終わっても、マシンによってはリブート後に起動できないというとても悲しい事態に陥ります。
ではどうするか。インストールイメージは使わず、NetBSDではお馴染みの手動コマンドによる設定と展開を行います。
手動インストール作業自体はOSは何でもいいのですが、ファイルやツールの準備も含めて全部既に動作しているNetBSD/amd64 8.0_BETA上で行います(旧バージョンのNetBSD 7.1等の場合でもたぶん同じように実行できますが、一部別途build toolsが必要かもしれません。また、amd64以外では未確認)。
まずディスクとして利用するUSBメモリを初期化します。USBメモリは購入時はFAT32等のシングルパーティションとなっていてこれでは使えないので以下の様に3つのパーティションを作ります。
従来のmbrパーティションでは、disklabelでBSDラベルを追加していましたが、U-EFIではdkを増やしていく形になるようです。/var等他にパーティションを分けたい場合はこのdkを増やして対応します。
# gpt show sd0 start size index contents 0 1 MBR 1 63 Unused 64 59391936 1 MBR part 12 # gpt destroy sd0 gpt: /dev/rsd0d: Device doesn't contain a GPT # dd if=/dev/zero of=/dev/sd0d count=1 1+0 records in 1+0 records out 512 bytes transferred in 0.014 secs (36571 bytes/sec) # gpt create sd0 # gpt add -s 64m -t efi -l EFISYSTEM sd0 /dev/rsd0d: Partition 1 added: c12a7328-f81f-11d2-ba4b-00a0c93ec93b 34 131072 # gpt add -s 24G -t ffs -l ROOT sd0 /dev/rsd0d: Partition 2 added: 49f48d5a-b10e-11dc-b99b-0019d1879648 131106 50331648 # gpt add -s 4G -t swap -l SWAP sd0 /dev/rsd0d: Partition 3 added: 49f48d32-b10e-11dc-b99b-0019d1879648 50462754 8388608
途中でddを実行しているのは既にかかれているmbrを消すためです。他にマシな消し方がありそうですが、ここでは先頭セクタを0クリアしてます。 dk0のEFI Systemパーティションはそんなに容量は必要無いので、ここでは64MB指定しています。 dk1とdk2の容量は結構適当です。
U-EFI SystemパーティションはU-EFIで決められたフォーマットであるFATでフォーマットします。ここにブートローダを置きます。
# newfs_msdos /dev/rdk0 /dev/rdk0: 130904 sectors in 16363 FAT16 clusters (4096 bytes/cluster) MBR type: 6 bps=512 spc=8 res=1 nft=2 rde=512 mid=0xf0 spf=64 spt=32 hds=64 hid=0 bsec=131072
次にboot loader本体をここにコピーします。 従来はこれをgrubやrEFInd等で別途用意する必要があったようですが、NetBSD/amd64 8.0以降ではこのブートローダは既にシステムの一部として用意されています。既にNetBSD/amd64 8.0で作業している場合、以下のファイルが該当します。
# file /usr/mdec/*efi /usr/mdec/bootia32.efi: PE32 executable (EFI application) Intel 80386 (stripped to external PDB), for MS Windows /usr/mdec/bootx64.efi: PE32+ executable (EFI application) x86-64 (stripped to external PDB), for MS Windows
他のarchやバージョンの場合、このファイルはインストールするディストリビューションファイルのうち、boot.tgzから展開できます。
# mkdir /tmp/efiboot # tar zxf (where/to/)base.tgz -C efiboot ./usr/mdec
これらをEFI Systemパーティションの以下のようにコピーします。
# mount -t msdos /dev/dk0 /mnt # mkdir -p /mnt/EFI/boot/ # cp (where/to/efiboot)/usr/mdec/*.efi /mnt/EFI/boot/ # umount /mnt
また、gptの起動設定を行います。
# gpt biosboot -A -c /usr/mdec/gptmbr.bin sd0 # gpt set -a bootme -i 2 sd0
ここから先はほぼいつものNetBSDと同じです。dk1をffsにフォーマットしてディストリビューションファイルを展開、最低限のシステム設定を行います。
# newfs -O 2 /dev/rdk1 # mount /dev/dk1 /mnt # tar zxpf (where/to/binary/sets/)kern-GENERIC.tgz -C /mnt # tar zxpf (where/to/binary/sets/)base.tgz -C /mnt # tar zxpf (where/to/binary/sets/)etc.tgz -C /mnt : (必要なsets分) # cp /mnt/usr/mdec/boot /mnt/ # mkdir /mnt/kern /mnt/proc # cd /mnt/dev # ./MAKEDEV all # cd /mnt/etc # cat > fstab <<EOF NAME=ROOT / ffs rw,log,noatime 1 1 NAME=SWAP none swap sw,dp 0 0 kernfs /kern kernfs rw ptyfs /dev/pts ptyfs rw procfs /proc procfs rw tmpfs /var/shm tmpfs rw,-m1777,-sram%25 EOF
さらにrc.confに色々設定してrc_configured=YESにすればマルチユーザーモードで起動するようになります。
書き込んだイメージを使って起動してみます。なお、順序不定です。
電源ON->F2キーでBIOS設定メニューを出し、Save & Exit項目のBOot OverrideでUSBメモリを選ぶとそこから起動できました。
但しこのPC(タブレット)の画面は縦長(800x1280pixel)でキーボードをつけると常に横向きになってしまいます。また、画面も800x600と認識していること、内蔵無線NICも見えないなど、NetBSDをちゃんと動かすことは今のところ難しそうです。
このマシンはMBRブートとEFIブートが排他のようで、BIOS設定でどちらかでしか起動できないようです。いつもはMBRブートで使っているので、メニューからEFIブートを有効に切り替えます。なお、この状態では内蔵SSDにMBRでインストールしてあるNetBSDが起動できません。
EFIブートでNetBSDが起動することは確認できました。2560x1440pixelという高解像度液晶もintelfb/i915drmkmsで認識されてます(GENERICでは字がとても小さい…)。
ただし。一見MBRブートと同じに見えて、EFIブートの時は内蔵の無線NICのiwm(4)が使えません。EFIの場合ハードウェアの初期化が異なるのだと思いますが詳細は分かりません。今回はNetBSD 8.0_BETAですが、-currentだと改善されてるのかもしれません。
色々と今年ありましたが、それでも圧倒的なパフォーマンスを誇るRyzenマシンです。当然今時のMotherboard, かなり派手なUEFI-BIOS設定画面です。Bootデバイスの優先順位等もマウスでドラッグアンドドロップでできてしまいます。
起動してみると特に問題なくloginプロンプトまで進みました。各種デバイスの細かいところまでは見ていませんが、とりあえず最低限は使えそうです。なお、Ryzen7は内蔵VideoChipなんてないのでこのマシンはPCIeのRadeon HD 5000シリーズを載せています。世代的にアンバランスですが、NetBSDで真っ当に使える外付けVideoではこのあたりが限界だったりします。
若干意味がわからない部分も残っているのですが、とりあえずU-EFI環境で起動できるNetBSD/amd64のUSBメモリが作れました。こいつを持ち歩けば新しいマシンを触れる機会があればとりあえずNetBSDの起動確認に使えるんじゃないかと思います(もちろん、起動設定変更してもいい場合に限りますが)。