I am new to Gentoo and I am setting up an installation on removable USB media to test before migrating from my current distro and I stumbled upon a problem, the ucode update mechanism.
On my Thinkpad (Intel core 5 125H), when I have both `sys-firmware/intel-microcode` and `sys-kernel/linux-firmware` installed, and I use a dist-kernel with UKI/ukify, I see both Intel and AMD microcode being passed to ukify as separate --microcode= arguments during kernel installation.
When this happens and my `emerge sys-kernel/gentoo-kernel` log shows both --microcode= appended to the ukify command, I observe that the kernel is created only with AMD microcode (.ucode section and by objdump and cpio listing).
What I understand is:
(1) emerge sys-kernel/gentoo-kernel invokes installkernel
Code: Select all
...
Installing the kernel via installkernel ...
Reading /etc/kernel/install.conf...
/etc/kernel/install.conf configures layout=uki
/etc/kernel/install.conf configures initrd_generator=ugrd
/etc/kernel/install.conf configures uki_generator=ukify
Code: Select all
Running /usr/lib/kernel/preinst.d/05-check-chroot.install 6.18.18-gentoo-dist-hardened /usr/src/linux-6.18.18-gentoo-dist-hardened/arch/x86/boot/bzImage...
Chroot detected
Hook /usr/lib/kernel/preinst.d/05-check-chroot.install finished successfully
Code: Select all
Running /usr/lib/kernel/preinst.d/35-amd-microcode.install 6.18.18-gentoo-dist-hardened /usr/src/linux-6.18.18-gentoo-dist-hardened/arch/x86/boot/bzImage...
Generating AMD CPU Microcode early initramfs image...
Created temporary directory: /var/tmp/portage/sys-kernel/gentoo-kernel-6.18.18/temp/tmp.E70c4PlpwO
Created microcode archive at: /boot/amd-uc.img
Cleaned up temporary directory: /var/tmp/portage/sys-kernel/gentoo-kernel-6.18.18/temp/tmp.E70c4PlpwO
Hook /usr/lib/kernel/preinst.d/35-amd-microcode.install finished successfully
Running /usr/lib/kernel/preinst.d/35-intel-microcode.install 6.18.18-gentoo-dist-hardened /usr/src/linux-6.18.18-gentoo-dist-hardened/arch/x86/boot/bzImage...
Generating Intel CPU Microcode early initramfs image...
...
iucode_tool: Writing selected microcodes to: /boot/intel-uc.img
Hook /usr/lib/kernel/preinst.d/35-intel-microcode.install finished successfully
...
Code: Select all
...
Running /usr/lib/kernel/preinst.d/60-ukify.install 6.18.18-gentoo-dist-hardened /usr/src/linux-6.18.18-gentoo-dist-hardened/arch/x86/boot/bzImage...
Calling ukify with arguments: build --linux=/usr/src/linux-6.18.18-gentoo-dist-hardened/arch/x86/boot/bzImage --uname=6.18.18-gentoo-dist-hardened --output=/var/tmp/portage/sys-kernel/gentoo-kernel-6.18.18/temp/installkernel.staging.D3eBtXM/uki.efi --microcode=/boot/intel-uc.img --microcode=/boot/amd-uc.img --initrd=/var/tmp/portage/sys-kernel/gentoo-kernel-6.18.18/temp/installkernel.staging.D3eBtXM/initrd --cmdline=@/etc/kernel/cmdline --config=/etc/kernel/uki.conf
Using config file: /etc/kernel/uki.conf
+ sbsign --key /etc/kernel/db.key --cert /etc/kernel/db.crt /usr/src/linux-6.18.18-gentoo-dist-hardened/arch/x86/boot/bzImage --output /var/tmp/portage/sys-kernel/gentoo-kernel-6.18.18/temp/linux-signedvwgcs7_8
Signing Unsigned original image
+ sbsign --key /etc/kernel/db.key --cert /etc/kernel/db.crt /var/tmp/portage/sys-kernel/gentoo-kernel-6.18.18/temp/ukiowq90lci --output /var/tmp/portage/sys-kernel/gentoo-kernel-6.18.18/temp/installkernel.staging.D3eBtXM/uki.efi
Signing Unsigned original image
Wrote signed /var/tmp/portage/sys-kernel/gentoo-kernel-6.18.18/temp/installkernel.staging.D3eBtXM/uki.efi
Hook /usr/lib/kernel/preinst.d/60-ukify.install finished successfully
...
I saw that installkernel collects preinst hooks from /etc/kernel/preinst.d first, then /usr/lib/kernel/preinst.d and its dropindirs_sort() helper stops at the first same-named file it finds, and only emits it if it is executable [1]
Because of that, creating an empty non-executable file at:
Code: Select all
/etc/kernel/preinst.d/35-amd-microcode.installWhat confused me is that setting Microcode=/boot/intel-uc.img in /etc/kernel/uki.conf is ignored by this approach (which is what I am used to with the tooling). My current understanding is that this is because ukify gives command-line options precedence over config-file settings, so if the hooks add --microcode= on the command line, that would explain why the Microcode= entry appears to be ignored [2] and that ukify is not using 'append' mode for options on the --microcode ConfigItem that would presumably cause only the last item to be respected (I have not verified that in practice however static reading of the code suggests it) [3]. Lastly 60-ukify.install hook may append more than 1 --microcode option [4] (also observed in the actual log pasted above).
So my questions are:
1. Is this expected behavior when both `sys-firmware/intel-microcode` and `sys-kernel/linux-firmware` are installed (both are needed for obvious reasons on my machine)?
2. Is masking /usr/lib/kernel/preinst.d/35-amd-microcode.install with an empty non-executable file in /etc/kernel/preinst.d the correct local override here?
3. Did I miss something completely and this approach or my analysis is wrong?
Thanks for your time reading this post.
[1] installkernel upstream source, hook search order and masking logic
ebuild: https://gitweb.gentoo.org/repo/gentoo.g ... -66.ebuild
Upstream: https://github.com/projg2/installkernel-gentoo
dropindirs_sort invocation: https://github.com/projg2/installkernel ... #L284-L286
[2] ukify man page, config file vs command line precedence
https://man7.org/linux/man-pages/man1/ukify.1.html
[3] ukify microcode var doesnt use action append
https://github.com/systemd/systemd/blob ... 1969-L1975
[4] installkernel 60-ukify.install microcode= option generation
https://github.com/projg2/installkernel ... ll#L68-L70
