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!

@thefossguy Hey, I need to seek for your help again.

cat /sys/module/firmware_class/parameters/path
->
/nix/store/h91zdfnz3sj9csqlhbfrwggkl2pxzm4n-firmware/lib/firmware

At the same time,
/nix/store/h91zdfnz3sj9csqlhbfrwggkl2pxzm4n-firmware/lib/firmware/imx/sdma/sdma-imx7d.bin exists.

Yet, journal shows

imx-sdma 30e10000.dma-controller: Direct firmware load for imx/sdma/sdma-imx7d.bin failed with error -2
imx-sdma 30e10000.dma-controller: external firmware not found, using ROM firmware

This happened after the switch from kernel 6.6.23 to 6.6.52.

Any Idea why the loading fails again?

Thanks in any case!

Is the imx-sdma driver built directly into the kernel or is it built as a loadable module?

this problem usually happens when the imx-sdma driver is built directly into the kernel. At the time when the driver is initialized, the root filesystem with the SDMA firmware binary is not yet available.

The best solution is normally to build the i.MX SDMA driver as a kernel module. At the time when the kernel module is loaded, the firmware file is also available. Probably you should load the imx-sdma.ko module early in your boot sequence, so that the SDMA is available at the time other drivers require it.

regards
Christian

Related post on NXP Community: https://community.nxp.com/t5/i-MX-Processors/IMX8MM-EVK-kernel-hang-on-imx-yocto-L5-4-24-2-1-0/m-p/1204627/highlight/true#M166992