了解我的 Linux 内核自启动以来加载了哪些固件

rsl*_*mos 8 linux firmware

在例行更新我的 Debian 系统时,我从来没有花时间去选择我真正需要的固件包;基本上我已经安装了它们,并且始终是最新的。

我一直在想如何才能挑选出我真正需要的。我正在考虑使用系统中的每个设备(甚至是我很少使用的设备,例如蓝牙、以太网、相机、触摸板、多媒体键等),然后查看加载的固件列表。

有没有一种简单的方法可以找出当前加载的固件或自上次内核启动以来加载的固件?

Jam*_*uke 8

如果您的内核是使用动态调试支持 (CONFIG_DYNAMIC_DEBUG) 构建的,则可以使用引导参数来启用固件加载程序的调试消息。它应该捕获所有固件加载,除非特定驱动程序做了一些奇怪的事情并且由于某种原因不使用内核的固件加载 API。

\n

将以下内容添加到启动参数中:

\n

对于内核 2.6 - 4.16:dyndbg="file drivers/base/firmware_class.c +fmp"

\n

对于内核 4.17 及更高版本:dyndbg="file drivers/base/firmware_loader/main.c +fmp"

\n

(作为参考,file blah/foo.c +fmp意味着“对于内核源文件 blah/foo.c中的所有调试调用,启用动态调试打印,并使消息显示文件名和模块名称”。有关更多详细信息,请参阅内核文档。)

\n

启动后,运行dmesg | grep firmware_class. 特别令人感兴趣的是 with 行firmware_class:fw_get_filesystem_firmware,它应该夹在对__allocate_fw_priv和 的调用之间__free_fw_priv

\n

将记录所有固件加载,直到您重新启动或禁用动态调试。

\n
\n

背景资料:

\n

您无法查询“当前加载的”固件,因为固件不一定保留在系统内存中。它经常被上传到系统外部的某些设备中的某些芯片上。大多数驱动程序会将固件文件加载到内核缓冲区中,使用该缓冲区对设备进行编程,然后丢弃该缓冲区,而不保留文件内容的任何记录。有些驱动程序确实将其固件加载记录到内核日志中,但这是由编写驱动程序的人选择的;它不是通用的。

\n

当我试图弄清楚如何记录固件加载时,我的第一个想法是“介于”内核和任何必须负责获取固件文件的用户空间程序之间。我可以添加一些调试消息,问题就会得到解决。但事实证明这并不总是可能的:内核本身能够直接从文件系统获取固件,而不涉及用户空间机制。(事实上​​,如果可能的话,内核更喜欢直接从 /lib/firmware/ 直接加载。)

\n

我的下一个想法是使用 kprobe 或其他一些跟踪系统来跟踪固件加载中涉及的内核函数调用。但事实证明我不必走那么远:固件加载程序已经包含一些调试消息,一旦启用 \xe2\x80\x94 就足以查看正在加载哪些文件。上面的内容dyndbg就利用了这些。

\n
\n

其他信息:

\n

内核的固件加载 API 通常通过调用 request_firmware() 或 request_firmware_nowait() 来访问。驱动程序使用它想要的固件文件的名称调用这些函数之一,并且内核尝试使用此过程加载它:

\n
    \n
  • 检查内核映像中的固件,如果找到则从那里加载。
  • \n
  • 检查文件系统上的固件,如果找到则从那里加载。
  • \n
  • [如果为它配置了内核]使用 sysfs“后备”:创建/sys/firmware/<xxx>/loading,等待某个程序向其写入固件。\n
      \n
    • [如果为它配置了内核]创建一个 uevent 来通知 udev 或正在侦听的任何人“如果您可以写入此文件,那就太好了”。
    • \n
    • 如果时间过长(特别是 /sys/firmware/timeout 中的时间长度),则放弃并出现错误。
    • \n
    \n
  • \n
\n