○CPU用firmwareの読み込み
最近は Meltdown や Spectre といった CPU レベルでのセキュリティホールが見つかり、 それを修正するために CPU 用の firmware が頻繁に更新されています。
Plamo Linuxでは、Intel用のfirmwareは microcode_intel パッケージとして、 AMD 用の firmware は linux_firmware パッケージとして提供し、 それぞれ /lib/firmware/{intel,amd}-ucode/ ディレクトリに収めています。
firmware は、モジュールドライバと同様、 必要に応じてカーネルが(ファイルシステムから)自動的に読み込むものの、 CPU用のfirmwareはCPUが動き始めた直後に適用する必要があるため、 initrdの仕組みを利用して、 すなわちcpioアーカイブをramfs上に展開して読み込むようになっています。
そのためには、CPU用firmwareをcpioアーカイブ化しなければなりません。 カーネルがramfsのどこからCPU用firmwareを読み込むかはあらかじめ決まっており、 Intel用のfirmwareは kernel/x86/microcode/GenuineIntel.bin、 AMD用は kernel/x86/microcode/AuthenticAMD.bin です。
# ソースコード的には /usr/src/linux/arch/x86/kernel/cpu/microcode のあたり
そこで、/lib/firmware/{intel,amd}-ucode/ 以下の firmware を、 これらのファイルに集めます。
$ mkdir -p kernel/x86/microcode $ cat /lib/firmware/intel-ucode/* > kernel/x86/microcode/GenuineIntel.bin $ cat /lib/firmware/amd-ucode/* > kernel/x86/microcode/AuthenticAMD.bin
次にこれらのファイルをcpioアーカイブにまとめ、/boot ディレクトリにコピーします。
$ find . | cpio -ov -Hnewc > ../cpu_firmware.cpio $ sudo cp ../cpu_firmware.cpio /boot
このファイルを grub.cfg の initrd= ... 行に設定します。
115 echo 'Linux 5.1.5-plamo64 をロード中...' 116 linux /boot/vmlinuz-5.1.5-plamo64 root=UUID=47749fa2-16d6-4b5a-bb44-9538e8605ac3 ro net.ifnames=0 quiet 117 echo '初期 RAM ディスクをロード中...' 118 initrd /boot/cpu_firmware.cpio /boot/initrd.img-5.1.5-plamo64
この設定でカーネルを起動すれば、カーネルは ramfs 上の kernel/x86/microcode/ に firmware を収めたファイルがあるかを調べ、動作しているCPU用のfirmwareが見つかれば まずそれを適用した上で起動処理を行います。 そのため、firmware の適用は dmesg の先頭で報告されます。
[ 0.000000] microcode: microcode updated early to revision 0x27, date = 2019-02-26 [ 0.000000] Linux version 5.1.5-plamo64 (kojima@pl71_0513) (gcc version 8.3.0 (GCC)) #1 SMP PREEMPT Thu May 30 20:36:40 JST 2019 [ 0.000000] Command line: BOOT_IMAGE=/boot/vmlinuz-5.1.5-plamo64 root=UUID=47749fa2-16d6-4b5a-bb44-9538e8605ac3 ro net.ifnames=0 quiet [ 0.000000] KERNEL supported cpus: [ 0.000000] Intel GenuineIntel [ 0.000000] AMD AuthenticAMD ...
cpu_firmware.cpio は initrd と合体させることも可能です。 その場合、gzip で圧縮した initrd の先頭に、 無圧縮の cpu_firmware.cpio を追加します。
# cd /boot # cat cpu_firmware.cpio initrd.img-5.1.5-plamo64 > temp.img # mv temp.img initrd.img-5.1.5-plamo64
こうしておけば、firmwareのcpioアーカイブを別途読み込ませる必要なく、 initrd と共に読み込まれるようになります。
なお、この処理は、mkinitramfs-0.4 以降の mkinitramfs にはあらかじめ組み込まれているので、 このバージョン以降の mkinitramfs を使う場合、特に気にする必要はありません。
○initrd ファイルの展開方法
cpu_firmware.cpio を先頭に結合したinitrd ファイルは、無圧縮のcpioアーカイブ(CPU用firmware)と gzipで圧縮したcpioアーカイブ(本来のinitrd)が連結された状態になっているので、 そのままではCPU用firmwareの部分しか見えません。
$ cpio -t < /boot/initrd.img-5.1.5-plamo64 . kernel kernel/x86 kernel/x86/microcode kernel/x86/microcode/GenuineIntel.bin kernel/x86/microcode/AuthenticAMD.bin 5018 ブロック
ここから、元のinitrdを取り出すには、CPU用firmwareの部分を取り除く必要があります。 そのためには dd コマンドで読み飛ばすのが簡単です。 その際、CPU用firmwareのサイズ(上記例では5018ブロック)が必要になります。
$ dd if=/boot/initrd.img-5.1.5-plamo64 skip=5018 | zcat | cpio -t . init lib64 etc etc/lvm etc/lvm/cache etc/lvm/cache/.cache etc/lvm/lvm.conf ... bin/cp bin/cat bin/sh 34624+1 レコード入力 34624+1 レコード出力 17727818 bytes (18 MB, 17 MiB) copied, 0.190163 s, 93.2 MB/s 52169 ブロック
上記で指定した -t オプションはアーカイブに含まれるファイルの確認です。 実際にファイルを取り出したい場合は -ivd オプションを指定してください。