You are not logged in.
Hi, I wrote two hooks to limit the firmware included in the initramfs if you're using early KMS with i915 or nvidia-open. I have both enabled because of quirks with my laptop. They decreased the size of generated UKIs from 118 MiB to 55 MiB (both zstd compressed). Boot times according to systemd-analyze went down by about eight seconds. The large change is because of secure boot, I think. This continued working with the new Nvidia driver 580 update.
This should continue to work till Nvidia or Intel change their firmware naming schemes. Intel's is probably stable. I think Nvidia is only likely to when they release new GPUs.
nvidia-open-kms
#!/usr/bin/env bash
build() {
local nvidia_modules=(nvidia nvidia_modeset nvidia_drm nvidia_uvm)
# If autodetect isn't set, pull in all firmware
if [ -z "${mkinitcpio_autodetect}" ]; then
map add_module "${nvidia_modules[@]}"
return
fi
# using add_module on dependencies that are not nvidia*. This will recursively pull in all needed .ko files.
map add_module \
$(modinfo -k $KERNELVERSION -F depends "${nvidia_modules[@]}" | tr "\n," "\n" | grep -v nvidia)
# gsp_tu10x.bin for TU1XX and GA100, gsp_ga10x.bin for newer cards that work with nvidia-open
# See open-gpu-kernel-modules/kernel-open/common/inc/nv-firmware.h (580.76.05)
local ADD_GSP_TU=0
local ADD_GSP_GA=0
while IFS= read -r line; do
echo $line | grep -qE ' (TU1[0-9]{2})|(GA100)' && ADD_GSP_TU=1 || ADD_GSP_GA=1
done < <(lspci -d '10de:*:0300') # 10de for NVIDIA, 0300 for graphics controllers
if [ "$ADD_GSP_GA" -eq 0 ] && [ "$ADD_GSP_TU" -eq 0 ]; then
warning "Unrecognized GPUs. Including all firmware."
map add_module "${nvidia_modules[@]}"
return 0
fi
local fw_dir=$(modinfo -k $KERNELVERSION -F firmware nvidia | head -n1 | cut -d/ -f1-2)
if [ "$ADD_GSP_TU" -eq 1 ]; then
add_firmware "${fw_dir}/gsp_tu10x.bin"
fi
if [ "$ADD_GSP_GA" -eq 1 ]; then
add_firmware "${fw_dir}/gsp_ga10x.bin"
fi
# using install_modules here to avoid automatic firmware inclusion
install_modules $(modinfo -k $KERNELVERSION -F filename "${nvidia_modules[@]}")
}
help() {
cat <<HELPEOF
Adds nvidia modules for early KMS, and includes only the right firmware files for
your cards when autodetect is active.
HELPEOF
}
i915-kms
#!/usr/bin/env bash
build() {
# If autodetect isn't set, pull in all firmware
if [ -z "${mkinitcpio_autodetect}" ]; then
add_module i915
return
fi
# There should be a line showing the firmware loaded, at least with loglevel >=3.
# Extracting the family, like tgl, cml, adlp. Relying on the firmware names being consistent
# across kernel versions
local fw_family=$(journalctl -kg 'i915.*Finished loading DMC' | grep -oP '[a-z0-9_]+\.bin' | cut '-d_' -f1)
if [ -z "${fw_family}" ]; then
warning "Unable to parse the log to determine the chip family. Adding all i915 firmware."
add_module i915
return 0
fi
# Manually adding dependencies. This will pull in firmware for those.
local dependencies=$(modinfo -k $KERNELVERSION -F depends i915 | tr ',' ' ')
map add_module $dependencies
# A DMC file was found in the log. This should be sufficient for early KMS.
# Using install_modules to sidestep the automatic firmware inclusion.
local fw_file=$(modinfo -k $KERNELVERSION -F firmware i915 | sort -u | \
grep -E "${fw_family}_dmc.*")
map add_firmware ${fw_file}
install_modules "$(modinfo -k $KERNELVERSION -F filename i915)"
}
help() {
cat <<HELPEOF
Adds i915 for early KMS, includes only necessary firmware when autodetect is active.
HELPEOF
}
Tested to ensure no modules are excluded using
comm -3 <(lsinitcpio /tmp/old.uki | sort -u) <(lsinitcpio /tmp/new.uki | sort -u)
usr/lib/firmware/i915/adlp_dmc.bin
usr/lib/firmware/i915/adlp_dmc_ver2_16.bin
usr/lib/firmware/i915/adlp_guc_69.0.3.bin
usr/lib/firmware/i915/adlp_guc_70.1.1.bin
usr/lib/firmware/i915/adlp_guc_70.bin
usr/lib/firmware/i915/adls_dmc_ver2_01.bin
usr/lib/firmware/i915/bmg_dmc.bin
usr/lib/firmware/i915/bxt_dmc_ver1_07.bin
usr/lib/firmware/i915/bxt_guc_70.1.1.bin
usr/lib/firmware/i915/bxt_huc_2.0.0.bin
usr/lib/firmware/i915/cml_guc_70.1.1.bin
usr/lib/firmware/i915/cml_huc_4.0.0.bin
usr/lib/firmware/i915/dg1_dmc_ver2_02.bin
usr/lib/firmware/i915/dg1_guc_70.bin
usr/lib/firmware/i915/dg1_huc.bin
usr/lib/firmware/i915/dg2_dmc_ver2_08.bin
usr/lib/firmware/i915/dg2_guc_70.bin
usr/lib/firmware/i915/dg2_huc_gsc.bin
usr/lib/firmware/i915/ehl_guc_70.1.1.bin
usr/lib/firmware/i915/ehl_huc_9.0.0.bin
usr/lib/firmware/i915/glk_dmc_ver1_04.bin
usr/lib/firmware/i915/glk_guc_70.1.1.bin
usr/lib/firmware/i915/glk_huc_4.0.0.bin
usr/lib/firmware/i915/icl_dmc_ver1_09.bin
usr/lib/firmware/i915/icl_guc_70.1.1.bin
usr/lib/firmware/i915/icl_huc_9.0.0.bin
usr/lib/firmware/i915/kbl_guc_70.1.1.bin
usr/lib/firmware/i915/kbl_huc_4.0.0.bin
usr/lib/firmware/i915/mtl_dmc.bin
usr/lib/firmware/i915/mtl_gsc_1.bin
usr/lib/firmware/i915/mtl_guc_70.bin
usr/lib/firmware/i915/mtl_huc_gsc.bin
usr/lib/firmware/i915/rkl_dmc_ver2_03.bin
usr/lib/firmware/i915/skl_dmc_ver1_27.bin
usr/lib/firmware/i915/skl_guc_70.1.1.bin
usr/lib/firmware/i915/skl_huc_2.0.0.bin
usr/lib/firmware/i915/tgl_dmc_ver2_12.bin
usr/lib/firmware/i915/tgl_guc_69.0.3.bin
usr/lib/firmware/i915/tgl_guc_70.1.1.bin
usr/lib/firmware/i915/tgl_guc_70.bin
usr/lib/firmware/i915/tgl_huc_7.9.3.bin
usr/lib/firmware/i915/tgl_huc.bin
usr/lib/firmware/i915/xe2lpd_dmc.bin
usr/lib/firmware/i915/xe3lpd_dmc.bin
usr/lib/firmware/nvidia/580.76.05/gsp_ga10x.bin
Diff between the old and new mkinitcpio .conf files:
7c7
< MODULES=(i915 nvidia nvidia_drm nvidia_modeset nvidia_uvm)
---
> MODULES=()
53c53
< HOOKS=(base udev autodetect block keyboard microcode modconf encrypt filesystems fsck)
---
> HOOKS=(base udev autodetect block keyboard microcode modconf encrypt filesystems fsck nvidia-open-kms i915-kms)
Final sanity check to ensure firmware and modules were included:
lsinitcpio /tmp/new.uki | grep -E 'i915|nvidia'
etc/modprobe.d/nvidia.conf
usr/lib/firmware/i915/
usr/lib/firmware/i915/kbl_dmc_ver1_04.bin
usr/lib/firmware/nvidia/
usr/lib/firmware/nvidia/580.76.05/
usr/lib/firmware/nvidia/580.76.05/gsp_tu10x.bin
usr/lib/modprobe.d/nvidia-sleep.conf
usr/lib/modprobe.d/nvidia-utils.conf
usr/lib/modules/6.16.0-arch2-1/extramodules/nvidia-drm.ko
usr/lib/modules/6.16.0-arch2-1/extramodules/nvidia-modeset.ko
usr/lib/modules/6.16.0-arch2-1/extramodules/nvidia-uvm.ko
usr/lib/modules/6.16.0-arch2-1/extramodules/nvidia.ko
usr/lib/modules/6.16.0-arch2-1/kernel/drivers/gpu/drm/i915/
usr/lib/modules/6.16.0-arch2-1/kernel/drivers/gpu/drm/i915/i915.ko
If you'd like to try this out, create a new directory, like:
test/install
Copy your mkinitcpio.conf to test/, the two hooks above to test/install. Modify test/mkinitcpio.conf to remove i915 and the nvidia modules from the MODULES array, then generate a new UKI or initramfs with mkinitcpio: (use -g instead of -U if you're not using a UKI)
mkinitcpio -c test/mkinitcpio.conf -D /usr/lib/initcpio -D test/ -U /tmp/new.uki
Finally you can run the tests above to see if the right modules and firmware were copied to the initramfs: the comm -3 output should show no new files in the new image, and lsinitcpio + grep should show at least one XXX_dmc.... file for i915, and at least one of gsp_tu10x.bin and gsp_ga10x.bin if you're using nvidia-open.
Let me know if you found this useful, thanks.
Last edited by gtnq (2025-08-15 07:43:38)
Offline