Files
ecd57bceee Drop the kms hook when the proprietary NVIDIA driver handles early KMS (#6791)
* Drop the kms hook when the proprietary NVIDIA driver handles early KMS

install/hardware/nvidia.sh early-loads nvidia_drm (modeset=1) for early KMS,
but HOOKS still carried the kms hook, so autodetect pulled nouveau and
~100 MB of its GSP firmware into every initramfs for a driver that never
runs. On a Limine UKI setup that meant a 256 MB image where ~144 MB is
normal, doubled again by the fallback history on /boot.

Filter kms out of HOOKS when nvidia_drm is in MODULES (nvidia.conf sorts
before this drop-in) and every PCI display controller is NVIDIA. Hybrid
systems keep kms so the iGPU retains early KMS at the LUKS prompt.

Verified on an RTX 4090 (nvidia-open-dkms 610.57.04): UKI shrinks
256,183,296 -> 144,066,048 bytes, nouveau and its firmware gone, the
nvidia-utils GSP blobs and all four nvidia modules retained, Plymouth
still owns the LUKS prompt via nvidia_drm.

Fixes #6790

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Address review: quote literals, harden PCI detection, add shell tests

Quote fixed string literals in the [[ ]] comparisons per AGENTS.md, and
read the PCI tree through OMARCHY_PCI_DEVICES_PATH, the same seam
bin/omarchy-hw-nvidia already uses.

Require a positively identified NVIDIA display controller before dropping
kms: an empty or unreadable PCI tree previously counted as "no non-NVIDIA
GPU" and would have dropped the hook. Unexpected trees now keep kms.

Cover the conditional in test/shell.d/nvidia-kms-hook-test.sh: nvidia-only,
hybrid, no nvidia_drm, MODULES unset under set -u, audio-function-only,
empty tree, and a device directory missing its sysfs attributes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Treat unreadable PCI devices as inconclusive and make the test hermetic

A device whose class/vendor attributes cannot be read could be another
GPU, so skipping it let a readable NVIDIA GPU beside it drop kms without
having verified the whole tree. Count it as a non-NVIDIA sighting so kms
stays, and cover the mixed case in the test.

The test also sourced the host's /etc/vconsole.conf under set -u, where a
valid KEYMAP-only file makes the XKBLAYOUT expansion fail in the subshell
and ties the result to the machine running it. Predefine XKBLAYOUT and
FILES before sourcing the config.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Rebuild existing initramfses once the kms hook no longer applies

The settings package deploys the new omarchy_hooks.conf conditional, but
nothing rebuilds the initramfs when only a mkinitcpio drop-in changes, so
existing NVIDIA-only installs would carry nouveau's ~100 MB of GSP
firmware until their next kernel update. Following the precedent of
1784476564, add a migration that rebuilds via limine-mkinitcpio — once
per machine, and only where evaluating the installed drop-ins shows the
conditional actually dropped kms, so hybrid machines, non-NVIDIA
machines, and user-edited configs are left alone.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Document the mid-sourcing MODULES caveat in the kms conditional

A later-sorting drop-in that resets MODULES outright (as
surface_device_modules.conf does) would strip nvidia_drm after kms was
already dropped. Every machine Omarchy writes such a file for is hybrid
Intel and keeps kms through the PCI scan, but that is worth stating so
the invariant is not broken by accident.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: David Heinemeier Hansson <david@hey.com>
2026-08-13 10:48:18 +02:00

53 lines
2.5 KiB
Plaintext

HOOKS=(base udev plymouth keyboard autodetect microcode modconf kms keymap consolefont block encrypt filesystems fsck btrfs-overlayfs)
# The proprietary NVIDIA driver does early KMS itself: nvidia.conf (written by
# install/hardware/nvidia.sh, sourced before this file) early-loads nvidia_drm
# with modeset=1. Keeping the kms hook on such a system makes autodetect pull
# in nouveau — and ~100 MB of its GSP firmware — for a driver that never runs.
# Drop kms only when nvidia_drm is early-loaded and NVIDIA owns every display
# controller. Hybrid systems keep kms: their iGPU still needs it for early
# KMS at the LUKS prompt. So does anything unexpected, like a PCI tree that
# cannot be read.
#
# This reads MODULES midway through mkinitcpio's drop-in sourcing, so a
# later-sorting drop-in that resets MODULES outright — surface_device_modules.conf
# does — would strip nvidia_drm after kms was already dropped. Every machine
# Omarchy writes such a file for carries an Intel iGPU, which keeps kms here
# through the scan below; keep it that way.
if [[ " ${MODULES[*]:-} " == *" nvidia_drm "* ]]; then
_omarchy_nvidia_gpu=0
_omarchy_other_gpu=0
for _omarchy_pci in "${OMARCHY_PCI_DEVICES_PATH:-/sys/bus/pci/devices}"/*; do
if [[ ! -r $_omarchy_pci/class || ! -r $_omarchy_pci/vendor ]]; then
# An unreadable device could be another GPU. Inconclusive keeps kms.
_omarchy_other_gpu=1
continue
fi
[[ $(<"$_omarchy_pci/class") == "0x03"* ]] || continue
if [[ $(<"$_omarchy_pci/vendor") == "0x10de" ]]; then
_omarchy_nvidia_gpu=1
else
_omarchy_other_gpu=1
fi
done
if ((_omarchy_nvidia_gpu && !_omarchy_other_gpu)); then
_omarchy_hooks=()
for _omarchy_hook in "${HOOKS[@]}"; do
[[ $_omarchy_hook == "kms" ]] || _omarchy_hooks+=("$_omarchy_hook")
done
HOOKS=("${_omarchy_hooks[@]}")
fi
unset _omarchy_nvidia_gpu _omarchy_other_gpu _omarchy_pci _omarchy_hooks _omarchy_hook
fi
# Bundle vconsole.conf so Plymouth uses the configured keyboard layout at the
# LUKS prompt, but only when that layout types Latin letters. Passphrases are
# Latin characters, so bundling a Hebrew/Greek/Cyrillic/Arabic layout would
# make the correct passphrase untypeable and lock the user out.
if [[ -f /etc/vconsole.conf ]]; then
case $(. /etc/vconsole.conf && echo "${XKBLAYOUT%%,*}") in
af | am | ara | bd | bg | by | et | ge | gr | il | in | iq | ir | kg | kh | kz | la | lk | mk | mm | mn | mv | np | rs | ru | sy | th | tj | ua) ;;
*) FILES+=(/etc/vconsole.conf) ;;
esac
fi