title: How does Linux Kernel know where to look for driver firmware?
body: <p>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 its kernel modules in:</p>
  
  <pre><code>/lib/modules/2.6.24-24-generic
  </code></pre>
  
  <p>and its firmware in:</p>
  
  <pre><code>/lib/firmware/2.6.24-24-generic
  </code></pre>
  
  <p>When I compile the 2.6.24-24-generic Ubuntu kernel according the "<a href="https://help.ubuntu.com/community/Kernel/Compile#AltBuildMethod" rel="noreferrer">Alternate Build Method: The Old-Fashioned Debian Way</a>" I get the appropriate modules directory and all my devices work except those requiring firmware such as my Intel wireless card (ipw2200 module).</p>
  
  <p>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:</p>
  
  <pre><code>ipw2200: Detected Intel PRO/Wireless 2200BG Network Connection
  ipw2200: ipw2200-bss.fw request_firmware failed: Reason -2
  </code></pre>
  
  <p>errno-base.h defines this as:</p>
  
  <pre><code>#define ENOENT       2  /* No such file or directory */
  </code></pre>
  
  <p>(The function returning ENOENT puts a minus in front of it.)</p>
  
  <p>I tried creating a symlink in /lib/firmware where my kernel's 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. <code>cmp</code> shows that the versions in the various directories are identical.</p>
  
  <p>So how does the kernel know where to look for firmware?</p>
  
  <p><strong>Update</strong></p>
  
  <p>I found <a href="http://ubuntuforums.org/showthread.php?p=441343" rel="noreferrer">this solution</a> to the exact problem I'm having, however it no longer works as Ubuntu has eliminated <code>/etc/hotplug.d</code> and no longer stores its firmware in <code>/usr/lib/hotplug/firmware</code>.</p>
  
  <p><strong>Update2</strong></p>
  
  <p>Some more research turned up some more answers.  Up until version 92 of <code>udev</code>, the program <a href="http://www.redhat.com/archives/fedora-cvs-commits/2005-July/msg00931.html" rel="noreferrer"><code>firmware_helper</code></a> was the way firmware got loaded.  Starting with <code>udev</code> 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 <code>/lib/firmware</code>.  Ubuntu still seems to be using the <code>/lib/udev/firmware_helper</code> binary.</p>
  
  <p>The name of the firmware file is passed to <code>firmware_helper</code> in the environment variable <code>$FIRMWARE</code> which is concatenated to the path <code>/lib/firmware</code> and used to load the firmware.</p>
  
  <p>The actual request to load the firmware is made by the driver (ipw2200 in my case) via the system call: </p>
  
  <pre><code>request_firmware(..., "ipw2200-bss.fw", ...);
  </code></pre>
  
  <p>Now somewhere in between the driver calling <code>request_firmware</code> and <code>firmware_helper</code> looking at the <code>$FIRMWARE</code> environment variable, the kernel package name is getting prepended to the firmware name. </p>
  
  <p>So who's doing it?</p>