Linux firmware split in Noble and Resolute

As you may already know, the change to Linux firmware packaging is no longer exclusive to Resolute; it is available for 24.04, too.

$ ( source /etc/os-release ; echo $PRETTY_NAME )
Ubuntu 24.04.4 LTS
$ dpkg -l | grep linux-firmware | wc -l
19

The main purpose of this split is to improve the update process and remove the need to re-download a single, huge package repeatedly. While theoretically the split also allows for the removal of unused firmware blobs, this is not supported yet. There are no appropriate tools yet to help users keep the necessary packages. Please bear with us as we continue improving the firmware delivery mechanism. Please do not try to remove “unused” packages unless you are ready to deal with consequences.

Tips and tricks for explorers

We understand that some of you may want to experiment with an unsupported configuration by removing not needed Linux firmware packages. We would like to stress this one more time: Linux firmware package removal is not supported yet and your system may become unbootable. Of course, some of you will experiment anyway, and we would love to hear your feedback. So here are a few helpful tips that may prevent you from “bricking” your computer.

Do not follow guides for any other operating systems; they are not applicable to Ubuntu.

Even though it exists in the repositories, do NOT try using isenkram. It has no information about Ubuntu Linux firmware packages and it may break your system or create a FrankenUbuntu.

If you dare to go further, please make sure all Linux firmware packages are downloaded locally to the archives cache before experimenting:

$ ls -lh /var/cache/apt/archives/linux-firmware*.deb

If any of these are missing, fetch them again using sudo apt install --download-only PACKAGE-NAME before doing anything else. That will let you do a simple sudo apt install PACKAGE-NAME offline, if necessary.

Do not remove linux-firmware-misc package.

apt-file helps a lot. Install it with sudo apt install apt-file and make sure to refresh its database: sudo apt-file update.

Also, do not forget to rebuild the initramfs after removing the blobs; this will help you detect failures earlier. Once your system is rebooted, always check dmesg output for firmware: failed to load:

$ sudo dmesg | grep 'firmware: failed to load'

Here be dragons: guesstimating the unused blobs

By default, the system has the linux-firmware meta package installed, which prevents the removal of the component packages. In order to be able to remove anything, you need to install linux-firmware-minimal:

$ sudo apt install linux-firmware-minimal

With linux-firmware-minimal installed, you can remove individual components without breaking dependencies.

To be safe, before removing any packages, prepare a list of the files your machine is currently using. Obviously, it is not safe to remove any of those. The approach is simple: query the loaded modules; each one provides a list of firmware files it may load at runtime and map those to package names. Let’s start with the list of firmware blobs:

$ function fwf() { for mod in $(lsmod | awk 'NR>1 { print $1 }'); do modinfo "$mod" | awk '/^firmware:/ {print $2}'; done | sort -u; }
$ fwf

Once you know the firmware blob filenames, use apt-file to find the corresponding package name. Do not forget to run sudo apt-file update to have an up-to-date mapping of filenames and packages. The following snippet produces the list of firmware packages that you must retain to keep currently connected peripherals running (it takes a while to look up every single file, so please be patient):

$ function fwf2deb { apt-file find "$(basename "$1")" | awk -F: '{ print $1 }'; }
$ fwf | while read file; do fwf2deb "$file"; done | sort -u

Now you have the list of packages you should always keep installed. As it relies on modinfo metadata, it may not be 100% accurate. Another way to map firmware packages to kernel modules is to check the “Description” field:

$ apt-cache --no-all-versions show linux-firmware-qualcomm-graphics | sed -n '/^Description/,/^[A-Z]/ { /^Description/ { p; d; }; /^[A-Z]/q; p; }'
Description-en: Firmware for Qualcomm graphics and video processors
 This package provides firmware used by Linux kernel drivers
 adreno, iris, and venus.
Description-md5: a22ae4f27c95f83524ccbcb499f8adeb

As we can see linux-firmware-qualcomm-graphics provides firmware blobs for kernel modules adreno, iris, and venus. If you have those loaded, you need to keep this package. Automating such checks is slightly out of scope for this post, though. The list in the description is hand curated, so it may be slightly more accurate than modinfo meta data. Anyway, you should always check dmesg output for firmware: failed to load, this is the best and most accurate signal of missing firmware blob.

However, it may not be a good idea to purge everything else right now. Carefully review the packages you think you may not need and remember to always keep linux-firmware-misc. Looking at the remaining packages, there may be some obvious candidates. For example, if you have an integrated Intel video card, -amd-graphics, -nvidia-graphics, and -qualcomm-graphics may not be used -- if you have no plans to connect an external GPU, of course. The same logic can be applied to the -marvell-prestera, -marvell-wireless, -mellanox-spectrum, -netronome, and -qlogic components. You likely know whether or not you have that hardware. When in doubt, check the lspci and lsusb output for the “Vendor” information.

The usual disclaimer: if you ever add new hardware, remember to make sure you have the necessary firmware packages installed. It is now up to you to keep them in sync with hardware changes.

To test the changes, make sure initramfs is up to date (update-initramfs -u) and reboot. Check dmesg output for firmware: failed to load and use apt-file search BASENAME to see the package name if any firmware files are missing.

Please let us know about your experience; we would love to hear your opinion.

10 Likes

Very nice write-up. Much appreciated. Thanks for that!

1 Like

Just for information, dpkg has a built-in search:

dpkg -l 'linux-firmware*'

Great news that had to be tested immediately. For this I have created a small script to determine the required packages for the device. The packages linux-firmware-minimal and linux-firmware-misc will also be listed.

#!/bin/bash

if [ "$EUID" -ne 0 ]; then
  echo "run as root"
  exit 1
fi

PCI_INFO=$(lspci 2>/dev/null | tr '[:upper:]' '[:lower:]')
USB_INFO=$(lsusb 2>/dev/null | tr '[:upper:]' '[:lower:]')
MODULES=$(lsmod | awk '{print $1}')

repo_pkgs=$(apt-cache pkgnames | grep '^linux-firmware-')

for pkg in $repo_pkgs; do
    case "$pkg" in
        *-raspi*|*-snapdragon*|*-ti*|*-arm*|*-mellanox*|*-netronome*|*-qlogic*)
            continue
            ;;
    esac

    match=0
    case "$pkg" in
        *amd-graphics*)
            echo "$PCI_INFO" | grep -qE "vga.*(amd|ati|radeon)" && match=1
            ;;
        *amd*)
            echo "$PCI_INFO" | grep -q "amd" && match=1
            ;;
        *intel-graphics*)
            echo "$PCI_INFO" | grep -qE "vga.*intel" && match=1
            ;;
        *intel-wireless*)
            echo "$PCI_INFO" | grep -qE "network.*intel" && match=1
            ;;
        *intel*)
            (echo "$PCI_INFO" | grep -qE "vga.*intel|network.*intel" || echo "$MODULES" | grep -qE "iwlwifi|i915|xe") && match=1
            ;;
        *nvidia*)
            (echo "$PCI_INFO" | grep -q "nvidia" || echo "$MODULES" | grep -qE "nvidia|nouveau") && match=1
            ;;
        *realtek*)
            (echo "$PCI_INFO" | grep -q "realtek" || echo "$USB_INFO" | grep -q "realtek" || echo "$MODULES" | grep -qE "r8169|rtw|rtl") && match=1
            ;;
        *mediatek*)
            (echo "$PCI_INFO" | grep -q "mediatek" || echo "$USB_INFO" | grep -q "mediatek" || echo "$MODULES" | grep -qE "mt76|mt79") && match=1
            ;;
        *broadcom*)
            (echo "$PCI_INFO" | grep -q "broadcom" || echo "$MODULES" | grep -qE "brcm|tg3") && match=1
            ;;
        *qualcomm*|*atheros*)
            (echo "$PCI_INFO" | grep -qE "qualcomm|atheros" || echo "$MODULES" | grep -q "ath") && match=1
            ;;
        *misc*|*minimal*)
            match=1
            ;;
    esac

    if [ "$match" -eq 1 ]; then
        echo "$pkg"
    fi
done

Then let’s go.

the device:

mario@mario-Vivobook ~ > inxi -Fz
System:
  Kernel: 7.2.4-x64v3-xanmod1 arch: x86_64 bits: 64
  Desktop: Budgie v: 10.9.1 Distro: Ubuntu Budgie 24.04.5 LTS (Noble Numbat)
Machine:
  Type: Laptop System: ASUSTeK product: Vivobook Go E1504FA_E1504FA v: 1.0
    serial: <superuser required>
  Mobo: ASUSTeK model: E1504FA v: 1.0 serial: <superuser required>
    UEFI: American Megatrends LLC. v: E1504FA.320 date: 06/22/2026
Battery:
  ID-1: BAT0 charge: 9.5 Wh (25.3%) condition: 37.5/41.9 Wh (89.4%)
    volts: 11.8 min: 11.8
CPU:
  Info: quad core model: AMD Ryzen 3 7320U with Radeon Graphics bits: 64
    type: MT MCP cache: L2: 2 MiB
  Speed (MHz): avg: 3261 min/max: 425/4152 cores: 1: 4152 2: 4152 3: 2370
    4: 4152 5: 4152 6: 2370 7: 2371 8: 2370
Graphics:
  Device-1: AMD Mendocino driver: amdgpu v: kernel
  Device-2: IMC Networks USB2.0 HD UVC WebCam driver: uvcvideo type: USB
  Display: x11 server: X.Org v: 21.1.11 driver: X: loaded: amdgpu
    unloaded: fbdev,modesetting,vesa dri: radeonsi gpu: amdgpu resolution:
    1: 1920x1080~60Hz 2: 1920x1080~60Hz
  API: EGL v: 1.5 drivers: kms_swrast,radeonsi,swrast
    platforms: gbm,x11,surfaceless,device
  API: OpenGL v: 4.6 compat-v: 4.5 vendor: amd mesa
    v: 25.2.8-0ubuntu0.24.04.2 renderer: AMD Radeon 610M (radeonsi
    raphael_mendocino LLVM 20.1.2 DRM 3.64 7.2.4-x64v3-xanmod1)
Audio:
  Device-1: AMD Rembrandt Radeon High Definition Audio driver: snd_hda_intel
  Device-2: AMD ACP/ACP3X/ACP6x Audio Coprocessor driver: snd_pci_acp6x
  Device-3: AMD Family 17h/19h HD Audio driver: snd_hda_intel
  API: ALSA v: k7.2.4-x64v3-xanmod1 status: kernel-api
  Server-1: PipeWire v: 1.0.5 status: active
Network:
  Device-1: Realtek RTL8821CE 802.11ac PCIe Wireless Network Adapter
    driver: rtw88_8821ce
  IF: wlan0 state: up mac: <filter>
Bluetooth:
  Device-1: IMC Networks Bluetooth Radio driver: btusb type: USB
  Report: hciconfig ID: hci0 state: up address: <filter> bt-v: 4.2
Drives:
  Local Storage: total: 476.94 GiB used: 82.68 GiB (17.3%)
  ID-1: /dev/nvme0n1 vendor: Samsung model: MZVL4512HBLU-00BTW
    size: 476.94 GiB
Partition:
  ID-1: / size: 91.11 GiB used: 33.09 GiB (36.3%) fs: ext4 dev: /dev/nvme0n1p1
  ID-2: /boot/efi size: 1.05 GiB used: 298.4 MiB (27.8%) fs: vfat
    dev: /dev/nvme0n1p2
  ID-3: /home size: 273.95 GiB used: 30.98 GiB (11.3%) fs: ext4
    dev: /dev/nvme0n1p3
Swap:
  ID-1: swap-1 type: zram size: 5.91 GiB used: 0 KiB (0.0%) dev: /dev/zram0
Sensors:
  System Temperatures: cpu: 57.0 C mobo: N/A gpu: amdgpu temp: 50.0 C
  Fan Speeds (rpm): N/A
Info:
  Memory: total: 8 GiB note: est. available: 7.04 GiB used: 3.04 GiB (43.2%)
  Processes: 362 Uptime: 35m Shell: fish inxi: 3.3.34
mario@mario-Vivobook ~ >

script output:

mario@mario-Vivobook ~ > doas firmware
doas (mario@mario-Vivobook) password: 
linux-firmware-amd-misc
linux-firmware-minimal
linux-firmware-intel-misc
linux-firmware-realtek
linux-firmware-misc
linux-firmware-amd-graphics
mario@mario-Vivobook ~ > 

installing the packages:

(Lese Datenbank ... 247093 Dateien und Verzeichnisse sind derzeit installiert.)
Entfernen von linux-firmware (20250901.git993ff19b-0ubuntu1.11) ...
Vormals nicht ausgewähltes Paket linux-firmware-amd-graphics wird gewählt.
(Lese Datenbank ... 240759 Dateien und Verzeichnisse sind derzeit installiert.)
Vorbereitung zum Entpacken von .../linux-firmware-amd-graphics_20240318.git3b128b60-0ubuntu3.2_all.deb ...
Entpacken von linux-firmware-amd-graphics (20240318.git3b128b60-0ubuntu3.2) ...
Vormals nicht ausgewähltes Paket linux-firmware-amd-misc wird gewählt.
Vorbereitung zum Entpacken von .../linux-firmware-amd-misc_20240318.git3b128b60-0ubuntu3.1_all.deb ...
Entpacken von linux-firmware-amd-misc (20240318.git3b128b60-0ubuntu3.1) ...
Vormals nicht ausgewähltes Paket linux-firmware-intel-misc wird gewählt.
Vorbereitung zum Entpacken von .../linux-firmware-intel-misc_20240318.git3b128b60-0ubuntu3.1_all.deb ...
Entpacken von linux-firmware-intel-misc (20240318.git3b128b60-0ubuntu3.1) ...
Vormals nicht ausgewähltes Paket linux-firmware-misc wird gewählt.
Vorbereitung zum Entpacken von .../linux-firmware-misc_20240318.git3b128b60-0ubuntu3.1_all.deb ...
Entpacken von linux-firmware-misc (20240318.git3b128b60-0ubuntu3.1) ...
Vormals nicht ausgewähltes Paket linux-firmware-realtek wird gewählt.
Vorbereitung zum Entpacken von .../linux-firmware-realtek_20240318.git3b128b60-0ubuntu3.1_all.deb ...
Entpacken von linux-firmware-realtek (20240318.git3b128b60-0ubuntu3.1) ...
linux-firmware-amd-graphics (20240318.git3b128b60-0ubuntu3.2) wird eingerichtet ...
linux-firmware-amd-misc (20240318.git3b128b60-0ubuntu3.1) wird eingerichtet ...
linux-firmware-intel-misc (20240318.git3b128b60-0ubuntu3.1) wird eingerichtet ...
linux-firmware-realtek (20240318.git3b128b60-0ubuntu3.1) wird eingerichtet ...
linux-firmware-misc (20240318.git3b128b60-0ubuntu3.1) wird eingerichtet ...
Trigger fĂĽr dracut (060+5-1ubuntu3.3) werden verarbeitet ...
dracut: Generating /boot/initrd.img-6.18.50-x64v3-xanmod1
dracut: Generating /boot/efi/EFI/Linux/linux-6.18.50-x64v3-xanmod1.efi
dracut: Generating /boot/efi/EFI/Linux/linux-6.18.50-x64v3-xanmod1-rescue.efi
Registering UEFI executable as boot entry...
Boot entry already exists
dracut: Generating /boot/initrd.img-7.2.4-x64v3-xanmod1
dracut: Generating /boot/efi/EFI/Linux/linux-7.2.4-x64v3-xanmod1.efi
dracut: Generating /boot/efi/EFI/Linux/linux-7.2.4-x64v3-xanmod1-rescue.efi
Registering UEFI executable as boot entry...
Boot entry already exists
PrĂĽfe Prozesse...                                                                                
Scanning processor microcode...                                                                   
PrĂĽfe Linux-Kernel...                                                                            

Pending kernel upgrade!
Running kernel version:
  7.2.4-x64v3-xanmod1
Diagnostics:
  FĂĽr den laufende Kernel ist ein ABI-kompatibles Upgrade ausstehend.

Restarting the system to load the new kernel will not be handled automatically, so you should
consider rebooting.

Der Prozessor Mikrocode ist aktuell.

Es mĂĽssen keine Dienste neugestartet werden.

Es mĂĽssen keine Container neu gestartet werden.

Es gibt keine Nutzer-Sitzungen mit veralteten Prozessen.

No VM guests are running outdated hypervisor (qemu) binaries on this host.

and reboot.

Well, back again and all is working.

mario@mario-Vivobook ~ > apt list -ii 'linux-firmware-*'
linux-firmware-amd-graphics/noble-updates,noble-updates,now 20240318.git3b128b60-0ubuntu3.2 all  [installiert]
linux-firmware-amd-misc/noble-updates,noble-updates,now 20240318.git3b128b60-0ubuntu3.1 all  [installiert]
linux-firmware-intel-misc/noble-updates,noble-updates,now 20240318.git3b128b60-0ubuntu3.1 all  [installiert]
linux-firmware-misc/noble-updates,noble-updates,now 20240318.git3b128b60-0ubuntu3.1 all  [installiert]
linux-firmware-realtek/noble-updates,noble-updates,now 20240318.git3b128b60-0ubuntu3.1 all  [installiert]
mario@mario-Vivobook ~ > doas dmesg | grep 'firmware: failed to load'
mario@mario-Vivobook ~ > 

Thanks for splitting the firmware also for Noble.