diary/Kojima

○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 オプションを指定してください。



トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2021-12-17 (金) 16:35:43