首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Linux内核如何知道在哪里查找驱动程序固件?

Linux内核如何知道在哪里查找驱动程序固件?
EN

Stack Overflow用户
提问于 2009-06-04 12:04:35
回答 3查看 77.1K关注 0票数 56

我正在Ubuntu下编译一个自定义内核,遇到的问题是,我的内核似乎不知道在哪里查找固件。在Ubuntu8.04下,固件与内核版本的绑定方式与驱动模块相同。例如,内核2.6.24-24-泛型将其内核模块存储在:

代码语言:javascript
运行
复制
/lib/modules/2.6.24-24-generic

及其固件如下:

代码语言:javascript
运行
复制
/lib/firmware/2.6.24-24-generic

当我根据"交替构建方法:老式的Debian方法“编译2.6.24-24通用的Ubuntu内核时,我会得到适当的模块目录,除了需要固件的设备(如我的英特尔无线网卡(ipw2200模块))之外,我的所有设备都能工作。

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

代码语言:javascript
运行
复制
ipw2200: Detected Intel PRO/Wireless 2200BG Network Connection
ipw2200: ipw2200-bss.fw request_firmware failed: Reason -2

H将其定义为:

代码语言:javascript
运行
复制
#define ENOENT       2  /* No such file or directory */

(返回ENOENT的函数在它前面放一个减号。)

我尝试在/lib/固件中创建一个符号链接,其中内核的名称指向2.6.24-24-泛型目录,但是这导致了同样的错误。这个固件是非GPL,由英特尔提供,由Ubuntu打包.我不相信它与特定的内核版本有任何实际的联系。cmp显示各个目录中的版本是相同的。

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

更新

我发现了这个解决方案的确切问题,但是它不再起作用了,因为Ubuntu已经淘汰了/etc/hotplug.d,并且不再将固件存储在/usr/lib/hotplug/firmware中。

Update2

更多的研究发现了更多的答案。直到92版的udev,程序firmware_helper是固件加载的方式。从udev 93开始,这个程序被一个名为firmware.sh的脚本所取代,据我所知,它提供了相同的功能。这两种方法都硬编码到/lib/firmware的固件路径。Ubuntu似乎仍然在使用/lib/udev/firmware_helper二进制文件。

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

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

代码语言:javascript
运行
复制
request_firmware(..., "ipw2200-bss.fw", ...);

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

那是谁干的?

EN

回答 3

Stack Overflow用户

发布于 2010-06-10 07:04:55

哇,这是非常有用的信息,它引导我解决我的问题时,为一个需要固件的设备定制USB内核模块。

基本上,每个Ubuntu都带来了一个新的hal,sysfs,devfs,udev的重哈希,所以on...and的事情就会改变。事实上,我读到他们不再使用哈尔。

因此,让我们再一次进行逆向工程,以便它与最新的Ubuntu系统相关。

在Ubuntu (撰写本文时的最新版本)上,使用了/lib/udev/rules.d/50-firmware.rules。该文件调用二进制/lib/udev/firmware,其中发生了魔术。

清单:/lib/udev/rules.d es.d/50-固件。

代码语言:javascript
运行
复制
# firmware-class requests, copies files into the kernel
SUBSYSTEM=="firmware", ACTION=="add", RUN+="firmware --firmware=$env{FIRMWARE} --devpath=$env{DEVPATH}"

魔法应该是这样的(源:http://lwn.net/Kernel/LDD3/):

  • 回波1转loading
  • 将固件复制到data
  • 失败时,回显1到loading并停止固件加载过程。
  • 回波0到loading (向内核发送信号)
  • 然后,一个特定的内核模块接收数据并将其推送到设备上。

如果您查看udev的udev-151/extras/firmware/firmware.c源页面,即该固件/lib/udev/固件二进制文件的源代码,这正是所发生的事情。

摘录:清晰来源,UDEV-151/extras/固件/固件.c

代码语言:javascript
运行
复制
    util_strscpyl(datapath, sizeof(datapath), udev_get_sys_path(udev), devpath, "/data", NULL);
    if (!copy_firmware(udev, fwpath, datapath, statbuf.st_size)) {
            err(udev, "error sending firmware '%s' to device\n", firmware);
            set_loading(udev, loadpath, "-1");
            rc = 4;
            goto exit;
    };

    set_loading(udev, loadpath, "0");

此外,许多设备使用Intel HEX格式(包含校验和和等内容的文本文件) (wiki it I‘t’s‘t’t‘s’t‘s’t‘s(我没有声誉,也没有链接能力)。内核程序ihex2fw (从内核_ .HEX /lib/.HEX文件中的Makefile调用)将这些HEX文件转换成任意设计的二进制格式,然后由Linux内核使用request_ihex_firmware来获取,因为他们认为在内核中读取文本文件是愚蠢的(这会减慢速度)。

票数 14
EN

Stack Overflow用户

发布于 2009-06-04 12:12:18

在当前的Linux系统上,这是通过udevfirmware.agent来处理的。

票数 1
EN

Stack Overflow用户

发布于 2013-02-26 09:59:13

Linux3.5.7 Gentoo,我也有同样的问题。已解决:

代码语言:javascript
运行
复制
emerge ipw2200-firmware

然后转到/usr/src/linux

代码语言:javascript
运行
复制
make menucofig

在设备驱动程序上,删除所有不需要的无线型驱动程序,将intel2200设置为模块并重新编译。

代码语言:javascript
运行
复制
make
make modules_install
cp arch/x86/boot/bzImage /boot/kernel-yourdefault
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/950107

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档