I'm compiling a custom kernel under Ubuntu and I'm running into the problem that my kernel doesn't seem to know where to look for firmware. Under Ubuntu 8.04, firmware is tied to kernel version the same way driver modules are. For example, kernel 2.6.24-24-generic stores it's kernel modules in:
/lib/modules/2.6.24-24-generic
and it's firmwares in:
/lib/firmware/2.6.24-24-generic
When I compile the 2.6.24-24-generic Ubuntu kernel according the "Alternate Build Method: The Old-Fashioned Debian Way" I get the appropriate modules directory and all my devices work except those requiring firmwares such as my Intel wireless card ( ipw2200 module ).
The kernel log shows for example that when ipw2200 tries to load the firmware the kernel subsystem controlling the loading of firmware is unable to locate it:
ipw2200: Detected Intel PRO/Wireless 2200BG Network Connection
ipw2200: ipw2200-bss.fw request_firmware failed: Reason -2
errno-base.h defines this as:
#define ENOENT 2 /* No such file or directory */
( The function returning ENOENT puts a minus in front of it )
I tried creating a symlink in /lib/firmware where my kernels name pointed to the 2.6.24-24-generic directory, however this resulted in the same error. This firmware is non-GPL, provided by Intel and packed by Ubuntu. I don't believe it has any actual tie to a particular kernel version. cmp shows that the versions in the various directories are identical.
So how does the kernel know where to look for firmwares?
Update
I found this solution to the exact problem I'm having, however it no longer works as Ubuntu has eliminated /etc/hotplug.d
and no longer stores it's firmware in /usr/lib/hotplug/firmware
.
Update2
Some more research turned up some more answers. Up until version 92 of udev the program firmware_helper
was the way firmware got loaded. Starting with udev 93 this program was replaced with a script named firmware.sh providing identical functionality as far as I can tell. Both of these hardcode the firmware path to /lib/firmware
. Ubuntu still seems to be using the /lib/udev/firmware_helper
binary.
The name of the firmware file is passed to firmware_helper in the environment variable $FIRMWARE
which is concatenated to the path /lib/firmware
and used to load the firmware into memory.
The actual request to load the firmware is made by the driver ( ipw2200 in my case ) via the system call:
request_firmware(..., "ipw2200-bss.fw", ...);
.
Now somewhere in between the driver calling request_firmware
and firmware_helper
looking at the $FIRMWARE
env var the kernel package name is getting prepended to the firmware name.
So who's doing it?