[[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の部分を取り除く必要があります。
ここから、元の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 オプションを指定してください。

#comment

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS