在定期更新我的 Debian 系统时,我从来没有花时间去选择我真正需要的固件包;基本上我已经安装了它们全部,并且始终是最新的。
我一直在想如何挑选我真正需要的固件。我考虑使用系统中的所有设备(即使是我很少使用的设备,如蓝牙、以太网、摄像头、触摸板、多媒体键等),并查看已加载固件的列表。
有没有一种简单的方法可以找出当前已加载的固件,或者自上次内核启动以来已加载的固件?
答案1
如果您的内核是使用动态调试支持 (CONFIG_DYNAMIC_DEBUG) 构建的,则可以使用启动参数来为固件加载程序启用调试消息。它应该捕获所有固件加载,除非某个驱动程序做了一些奇怪的事情并且由于某种原因不使用内核的固件加载 API。
将以下内容添加到您的启动参数中:
对于内核 2.6 - 4.16:dyndbg="file drivers/base/firmware_class.c +fmp"
对于内核 4.17 及更高版本:dyndbg="file drivers/base/firmware_loader/main.c +fmp"
(作为参考,file blah/foo.c +fmp
意思是“对于内核源代码中的所有调试调用文件 blah/foo.c
,启用动态调试页打印,并使消息显示Filename 和米模块名称”。请参阅内核文档了解更多详情。
启动后,运行dmesg | grep firmware_class
。特别值得注意的是带有 的行firmware_class:fw_get_filesystem_firmware
,它们应该夹在__allocate_fw_priv
和 的调用之间__free_fw_priv
。
所有固件加载都将被记录,直到您重新启动或禁用动态调试。
背景信息:
您无法查询“当前已加载”的固件,因为固件不一定保留在系统内存中。它通常被上传到系统外部某个设备的某个芯片中。大多数驱动程序会将固件文件加载到内核缓冲区中,使用该缓冲区对设备进行编程,然后丢弃该缓冲区而不保留任何文件记录。一些驱动程序确实会将其固件加载记录到内核日志中,但这是编写驱动程序的人的选择;它不是通用的。
当我试图弄清楚如何记录固件加载时,我的第一个想法是“介入”内核和负责获取固件文件的用户空间程序。我可以添加一些调试消息,问题就解决了。但事实证明这并不总是可行的:内核本身能够直接从文件系统获取固件,而无需用户空间机制。(事实上,内核偏好在可能的情况下直接从 /lib/firmware/ 直接加载。
我接下来的想法是使用 kprobe 或其他跟踪系统来跟踪固件加载中涉及的内核函数调用。但事实证明我不需要走那么远:固件加载器已经包含一些调试消息,一旦启用,就足以查看正在加载哪些文件。上面的代码dyndbg
利用了这些。
其他信息:
内核的固件加载 API 通常通过调用 request_firmware() 或 request_firmware_nowait() 来访问。驱动程序使用所需固件文件的名称调用其中一个函数,然后内核尝试使用此过程加载它:
- 检查内核映像中的固件,如果找到则从那里加载。
- 检查文件系统上的固件,如果找到则从那里加载。
- [如果内核为其配置了] 使用 sysfs“fallback”:创建
/sys/firmware/<xxx>/loading
,等待某些程序将固件写入其中。- [如果内核为其配置了它] 创建一个 uevent 来通知 udev 或任何正在监听的人“如果您可以写入此文件那就太好了”。
- 如果时间过长(具体来说是 /sys/firmware/timeout 中的时间长度),则放弃并出现错误。
答案2
有多个命令,取决于您的需要。
首先lspci -vvvvv
它将向您显示设备正在使用哪个模块/驱动程序。(查找值Kernel module
和Kernel driver
)要获取当前使用的模块/加载的列表,您可以使用lsmod
。
要获取更多详细信息,请查看维基百科其中列出了其他命令,但您可能需要安装额外的软件包。
这些将为您提供有关 HW 本身的信息:
dmidecode
和hwinfo
或lshw
编辑:
要找出启动期间加载的驱动程序,您通常会搜索(取决于 sys-vinit/systemd):
/var/log/bootlog
/var/log/syslog
/var/log/kern.log
或命令dmesg
来找出 systemd 中正在加载的内容journalctl -k kernel
或journalctl -b
当前/上次启动的内容。查阅每个命令的手册页。