gpt4 book ai didi

linux-kernel - Linux 内核如何知道在哪里寻找驱动程序固件?

转载 作者:行者123 更新时间:2023-12-02 23:50:27 27 4
gpt4 key购买 nike

我正在 Ubuntu 下编译自定义内核,但遇到了我的内核似乎不知道在哪里寻找固件的问题。在 Ubuntu 8.04 下,固件与内核版本相关联,就像驱动程序模块一样。例如,内核 2.6.24-24-generic 将其内核模块存储在:

/lib/modules/2.6.24-24-generic

及其固件:

/lib/firmware/2.6.24-24-generic

当我根据“Alternate Build Method: The Old-Fashioned Debian Way”编译 2.6.24-24-generic Ubuntu 内核时,我得到了适当的模块目录,并且我的所有设备都可以工作,除了那些需要固件的设备,例如我的英特尔无线卡(ipw2200 模块)。

内核日志显示,例如,当 ipw2200 尝试加载固件时,控制固件加载的内核子系统无法找到它:

ipw2200: Detected Intel PRO/Wireless 2200BG Network Connection
ipw2200: ipw2200-bss.fw request_firmware failed: Reason -2

errno-base.h 将其定义为:

#define ENOENT       2  /* No such file or directory */

(返回 ENOENT 的函数在其前面添加一个减号。)

我尝试在/lib/firmware 中创建一个符号链接(symbolic link),其中我的内核名称指向 2.6.24-24-generic 目录,但这导致了相同的错误。该固件是非 GPL,由 Intel 提供并由 Ubuntu 打包。我不认为它与特定内核版本有任何实际联系。 cmp显示各个目录中的版本是相同的。

那么内核如何知道在哪里寻找固件呢?

更新

我找到了this solution对于我遇到的确切问题,但是它不再起作用,因为 Ubuntu 已经消除了 /etc/hotplug.d 并且不再将其固件存储在 /usr/lib/hotplug/firmware.

更新2

更多的研究得出了更多的答案。在 udev 版本 92 之前,程序 firmware_helper是固件加载的方式。据我所知,从 udev 93 开始,该程序被替换为名为firmware.sh 的脚本,提供相同的功能。这两个都将固件路径硬编码到 /lib/firmware。 Ubuntu 似乎仍在使用 /lib/udev/firmware_helper 二进制文件。

固件文件的名称传递给环境变量 $FIRMWARE 中的 firmware_helper,该变量与路径 /lib/firmware 连接并用于加载固件。

加载固件的实际请求是由驱动程序(在我的例子中是 ipw2200)通过系统调用发出的:

request_firmware(..., "ipw2200-bss.fw", ...);

现在,在驱动程序调用 request_firmwarefirmware_helper 查看 $FIRMWARE 环境变量之间,内核包名称被添加到前面固件名称。

那么是谁干的呢?

最佳答案

从内核角度看/usr/src/linux/Documentation/firmware_class/README :

 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.

The kernel doesn't actually load any firmware at all. It simply informs userspace, "I want a firmware by the name of xxx", and waits for userspace to pipe the firmware image back to the kernel.

Now, on Ubuntu 8.04,

$ grep firmware /etc/udev/rules.d/80-program.rules# Load firmware on demandSUBSYSTEM=="firmware", ACTION=="add", RUN+="firmware_helper"

so as you've discovered, udev is configured to run firmware_helper when the kernel asks for firmware.

$ apt-get source udevReading package lists... DoneBuilding dependency treeReading state information... DoneNeed 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 17063E6Dgpg: Can't check signature: public key not founddpkg-source: extracting udev in udev-117dpkg-source: unpacking udev_117.orig.tar.gzdpkg-source: applying ./udev_117-8ubuntu0.2.diff.gz$ cd udev-117/$ cat debian/patches/80-extras-firmware.patch

If you read the source, you'll find that Ubuntu wrote a firmware_helper which is hard-coded to first look for /lib/modules/$(uname -r)/$FIRMWARE, then /lib/modules/$FIRMWARE, and no other locations. Translating it to sh, it does approximately this:

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) 中查找的自定义内容。该策略正在用户空间中处理。

关于linux-kernel - Linux 内核如何知道在哪里寻找驱动程序固件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/950107/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com