Include firmware blob in nixOS

The package linux-firmware contains the file /lib/firmware/imx/sdma/sdma-imx7d.bin.zst, which I need in the fs under /lib/firmware/imx/sdma/sdma-imx7d.bin.

Could anyone please give me a hint on how to get that file on the nixos sd-image I am building?

Is there a firmware option or something?

Or do I need to unpack the file in populateRootCommands?

You’re probably missing the pkgs.linux-firmware package.

1 Like

Good call. The package is existant in the sdImage, I can see and unpack the binary file. Is there a mechanism to get the file unpacked automatically?

Or is the linux-firmware package somehow supposed to install itself onto the file system?

I can see the compressed driver file on the target system, it’s just that the kernel doesn’t seem to load it. So probably, I need to point the kernel to it somehow or it needs to be unpacked to another place in the fs under /lib/firmware....

So maybe there is an option for that or something…

What does ls $(cat /sys/module/firmware_class/parameters/path) show?

1 Like

I think I found out what the problem is. When you asked if there was a mechanism for extracting firmware and putting it in the right place, it made me wonder how it worked on my machine given that just installing pkgs.linux-firmware wouldn’t do anything because it would lie dormant in the nix store.

Turns out, it is liked to /sys/module/firmware_class/parameters/path and that is done by enabling either hardware.enableRedistributableFirmware or hardware.enableAllFirmware.

As long as you set either of the above two options to true, your firmware situation should be resolved.

4 Likes

I tried enableRedistributableFirmware and enableAllFirmware, but without any improvement.

Where would the firmware files land in the fs? My /lib folder only contains ld-linux-aarch64.so.1, and I cannot find sdma-imx7d.bin anywhere on the system. The only thing I can find is /nix/store/1466bb36a1awy8l85r05ni4pr9b8aj65-linux-firmware-20241110-zstd/lib/firmware/imx/sdma/sdma-imx7d.bin.zst, but that is compressed and does not seem to be loaded by the system…

My dmesg is spitting out the following:

[nix-shell:~]$ dmesg | grep firmware
[    0.000000] psci: PSCIv1.1 detected in firmware.
[    0.157099] imx-sdma 30bd0000.dma-controller: Direct firmware load for imx/sdma/sdma-imx7d.bin failed with error -2
[    3.136483] platform regulatory.0: Direct firmware load for regulatory.db failed with error -2
[   15.236384] systemd[1]: Clear Stale Hibernate Storage Info was skipped because of an unmet condition check (ConditionPathExists=/sys/firmware/efi/efivars/HibernateLocation-8cf2644b-4b0b-428f-9387-6d876050dc67).
[   60.425442] imx-sdma 30bd0000.dma-controller: Direct firmware load for imx/sdma/sdma-imx7d.bin failed with error -2
[  121.827964] imx-sdma 30bd0000.dma-controller: external firmware not found, using ROM firmware
[  121.828149] imx-sdma 30e10000.dma-controller: external firmware not found, using ROM firmware
[  138.010758] imx-sdma 30bd0000.dma-controller: sdma or sdma firmware not ready!

Okay, next attempt:

  boot.kernelParams = [
    "console=ttymxc1,115200"
    "console=tty1"
    "root=/dev/mmcblk2p2"
    "firmware_class.path=${pkgs.linux-firmware}/lib/firmware"
  ];

enableRedistributableFirmware causes linux-firmware and others to be added to the hardware.firmware option, which causes /etc/modprobe.d/firmware.conf to have

options firmware_class path=/nix/store/...-firmware/lib/firmware

Where the nix store path is a symlink tree of all the hardware.firmware packages.

So the firmware is probably already being included properly. If something is still not working, it’s probably something else.

2 Likes

Yep, /sys/module/firmware_class/parameters/path indeed points to said folder. The firmware files in there are compresset though. Does the kernel load them automatically?

I don’t remember if it’s modprobe or the kernel that decompresses them, but yes the system will decompress them as they’re loaded.

1 Like

Thanks a lot for your help so far!

The firmware lies under /nix/store/fqprcqr2n8y59nrgzjrfarvq4r1anyg4-firmware/lib/firmware/imx/sdma/sdma-imx7d.bin.zst, and the kernel fails to load it.
When unpacking the firmware to the same folder though, /nix/store/fqprcqr2n8y59nrgzjrfarvq4r1anyg4-firmware/lib/firmware/imx/sdma/sdma-imx7d.bin, all suddenly works!

There seems to be an issue with the decompression, although unzstd works.
Is there something that needs to be enable for decompression to work?

Linux wtc 6.6.23 #1-NixOS SMP PREEMPT Wed Nov 6 10:34:43 UTC 2024 aarch64 GNU/Linux

Oh, the CONFIG_FW_LOADER_COMPRESS_ZSTD option seems to be missing

That seems like the likely culprit. I believe that this should be added in the nixpkgs kernel config.

Edit: But it’s already present and should be enabled (relevant line in nixpkgs). What do you see when you run zgrep FW_LOADER_COMPRESS_ZSTD /proc/config.gz?

2 Likes

We are building our own kernel, and indeed your command yields nothing. So the feature seems to be disabled…

Ah well, in that case, you can provide FW_LOADER_COMPRESS_ZSTD = lib.kernel.yes; to structuredExtraConfig.

2 Likes

In my case, I had to edit the config of the kernel. We missed

CONFIG_FW_LOADER_COMPRESS=y
CONFIG_FW_LOADER_COMPRESS_ZSTD=y

Thanks for your help, it helped a lot!