views:

1955

answers:

3

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?

+1  A: 

On current Linux systems, this is handled via udev and the firmware.agent.

David Schmitt
Apparently Ubuntu 8.04 doesn't have firmware.agent in udev, it has something else called firmware_helper. In any case, how does this tell the kernel where to find firmware?
Robert S. Barnes
Whatever command is called by udev, it is responsible for loading the firmware into the kernel. From my reading of Debian's firmware.agent, it writes the firmware into a special fil in /sys
David Schmitt
+2  A: 
ephemient
Wonderful answer, thanks! I was looking through the udev source pulling my hair out trying to figure out where Ubuntu's `firmware_helper` was coming from. Should have just done a recursive grep for firmware in the udev source tree.
Robert S. Barnes
It's actually probably from the udev-extras tree, some parts of which Ubuntu has decided to modify and bundle with their udev package.
ephemient
`apt-get source` downloads and unpacks the Debian (or Ubuntu) source tree for the package, which includes a `debian` directory with packaging information and distribution-specific setup, which sometimes includes patches which aren't found upstream. This is a case of that.
ephemient
+2  A: 
Andy Matteson
+1 Now you've got some rep and can link. If you found the info in the OP or another person's answer useful, vote them up.
Robert S. Barnes