kernel(driver): calls request_firmware(&fw_entry, $FIRMWARE, device)
userspace:
- /sys/class/firmware/xxx/{loading,data} appear.
- hotplug gets called with a firmware identifier in $FIRMWARE
and the usual hotplug environment.
- hotplug: echo 1 > /sys/class/firmware/xxx/loading
kernel: Discard any previous partial load.
userspace:
- hotplug: cat appropriate_firmware_image > \
/sys/class/firmware/xxx/data
kernel: grows a buffer in PAGE_SIZE increments to hold the image as it
comes in.
userspace:
- hotplug: echo 0 > /sys/class/firmware/xxx/loading
kernel: request_firmware() returns and the driver has the firmware
image in fw_entry->{data,size}. If something went wrong
request_firmware() returns non-zero and fw_entry is set to
NULL.
kernel(driver): Driver code calls release_firmware(fw_entry) releasing
the firmware image and any related resource.
内核实际上根本不加载任何固件 . 它只是通知用户空间,“我想要一个名为xxx的固件”,并等待用户空间将固件映像传送回内核 .
现在,在Ubuntu 8.04上,
$ grep firmware /etc/udev/rules.d/80-program.rules
# Load firmware on demand
SUBSYSTEM=="firmware", ACTION=="add", RUN+="firmware_helper"
正如您所发现的那样, udev 配置为在内核请求固件时运行 firmware_helper .
$ apt-get source udev
Reading package lists... Done
Building dependency tree
Reading state information... Done
Need to get 312kB of source archives.
Get:1 http://us.archive.ubuntu.com hardy-security/main udev 117-8ubuntu0.2 (dsc) [716B]
Get:2 http://us.archive.ubuntu.com hardy-security/main udev 117-8ubuntu0.2 (tar) [245kB]
Get:3 http://us.archive.ubuntu.com hardy-security/main udev 117-8ubuntu0.2 (diff) [65.7kB]
Fetched 312kB in 1s (223kB/s)
gpg: Signature made Tue 14 Apr 2009 05:31:34 PM EDT using DSA key ID 17063E6D
gpg: Can't check signature: public key not found
dpkg-source: extracting udev in udev-117
dpkg-source: unpacking udev_117.orig.tar.gz
dpkg-source: applying ./udev_117-8ubuntu0.2.diff.gz
$ cd udev-117/
$ cat debian/patches/80-extras-firmware.patch
如果您阅读了源代码,您会发现Ubuntu写了一个 firmware_helper ,它是硬编码的,首先查找 /lib/modules/$(uname -r)/$FIRMWARE ,然后是 /lib/modules/$FIRMWARE ,没有其他位置 . 将其翻译为 sh ,它大致如下:
echo -n 1 > /sys/$DEVPATH/loading
cat /lib/firmware/$(uname -r)/$FIRMWARE > /sys/$DEVPATH/data \
|| cat /lib/firmware/$FIRMWARE > /sys/$DEVPATH/data
if [ $? = 0 ]; then
echo -n 1 > /sys/$DEVPATH/loading
echo -n -1 > /sys/$DEVPATH/loading
fi
这正是内核期望的格式 .
简而言之:Ubuntu的 udev 包具有始终首先在 /lib/firmware/$(uname -r) 中查找的自定义 . 此策略正在用户空间中处理 .