rslemos Asked: 2020-07-25 06:45:14 +0800 CST2020-07-25 06:45:14 +0800 CST 2020-07-25 06:45:14 +0800 CST 知道我的 linux 内核自启动以来加载了哪些固件 772 在例行更新我的 Debian 系统时,我从来没有花时间选择我真正需要的固件包。基本上我都安装了它们,并且总是最新的。 我一直想知道如何才能选择我真正需要的那些。我正在考虑使用我系统中的所有设备(即使是我很少使用的设备,如蓝牙、以太网、相机、触摸板、多媒体键等),并查看加载的固件列表。 有没有一种简单的方法可以找出当前加载的固件,或者自上次内核启动以来加载的固件? linux firmware 2 个回答 Voted Best Answer James Luke 2020-11-28T17:48:26+08:002020-11-28T17:48:26+08:00 如果您的内核是使用动态调试支持 (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 启动后,运行dmesg | grep firmware_class. 特别感兴趣的是带有 的行firmware_class:fw_get_filesystem_firmware,它应该夹在对 和 的调用__allocate_fw_priv之间__free_fw_priv。 在您重新启动或禁用动态调试之前,将记录所有固件加载。 背景资料: 您不能查询“当前加载的”固件,因为固件不一定保留在系统内存中。它通常被上传到系统外部某些设备中的某个芯片上。驱动程序通常将固件文件加载到内核缓冲区中,使用该缓冲区对设备进行编程,然后丢弃缓冲区而不保留文件的任何记录。并且标准内核固件 API 默认不保留日志。一些驱动程序确实将其固件加载记录到内核日志中,但它不是通用的。 我的第一个想法是“进入”内核和负责抓取固件文件的任何用户空间程序,以便我可以添加一些调试消息。但事实证明这并不总是可能的:内核本身能够直接从文件系统获取固件,不涉及用户空间机制。(事实上,内核更喜欢在可能的情况下直接从 /lib/firmware/ 直接加载。) 我的下一个想法是使用 kprobe 或其他一些跟踪系统来跟踪固件加载中涉及的内核函数调用。但事实证明我不必走那么远:固件加载器方便地包含一些调试消息——一旦启用——足以查看所有正在加载的文件。以上dyndbg利用了这些。 其他信息: 内核的固件加载 API 通常通过调用 request_firmware() 或 request_firmware_nowait() 来访问。驱动程序使用它想要的固件文件的名称调用这些函数之一,内核尝试使用以下过程加载它: 检查内核映像中的固件,如果找到则从那里加载。 检查文件系统上的固件,如果找到则从那里加载。 [如果为它配置了内核] 使用 sysfs "fallback": create /sys/firmware/<xxx>/loading,等待某个程序向其写入固件。 [如果为它配置了内核] 创建一个 uevent 来通知 udev 或任何正在监听的人“如果你能写入这个文件,那就太好了”。 如果时间过长(特别是 /sys/firmware/timeout 中的时间长度),请放弃错误。 Geeky Masters 2020-07-25T08:12:54+08:002020-07-25T08:12:54+08:00 有多个命令,取决于你需要什么。 从它开始lspci -vvvvv将向您显示设备正在使用哪个模块/驱动程序。(查找值Kernel module和Kernel driver)要获取当前使用/加载的模块列表,您可以使用lsmod. 要获得更多详细信息,请查看Wiki Lspci,其中列出了其他命令,但您可能需要安装额外的软件包。 这些将为您提供有关硬件本身的信息: dmidecode和hwinfo或lshw 编辑: 要找出启动期间加载的驱动程序,您通常会搜索(取决于 sys-vinit/systemd): /var/log/bootlog /var/log/syslog /var/log/kern.log 或命令dmesg找出 systemd 中加载的内容journalctl -k kernel或journalctl -b当前/上次启动的内容。请查阅每个命令的手册页。
如果您的内核是使用动态调试支持 (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
启动后,运行
dmesg | grep firmware_class
. 特别感兴趣的是带有 的行firmware_class:fw_get_filesystem_firmware
,它应该夹在对 和 的调用__allocate_fw_priv
之间__free_fw_priv
。在您重新启动或禁用动态调试之前,将记录所有固件加载。
背景资料:
您不能查询“当前加载的”固件,因为固件不一定保留在系统内存中。它通常被上传到系统外部某些设备中的某个芯片上。驱动程序通常将固件文件加载到内核缓冲区中,使用该缓冲区对设备进行编程,然后丢弃缓冲区而不保留文件的任何记录。并且标准内核固件 API 默认不保留日志。一些驱动程序确实将其固件加载记录到内核日志中,但它不是通用的。
我的第一个想法是“进入”内核和负责抓取固件文件的任何用户空间程序,以便我可以添加一些调试消息。但事实证明这并不总是可能的:内核本身能够直接从文件系统获取固件,不涉及用户空间机制。(事实上,内核更喜欢在可能的情况下直接从 /lib/firmware/ 直接加载。)
我的下一个想法是使用 kprobe 或其他一些跟踪系统来跟踪固件加载中涉及的内核函数调用。但事实证明我不必走那么远:固件加载器方便地包含一些调试消息——一旦启用——足以查看所有正在加载的文件。以上
dyndbg
利用了这些。其他信息:
内核的固件加载 API 通常通过调用 request_firmware() 或 request_firmware_nowait() 来访问。驱动程序使用它想要的固件文件的名称调用这些函数之一,内核尝试使用以下过程加载它:
/sys/firmware/<xxx>/loading
,等待某个程序向其写入固件。有多个命令,取决于你需要什么。
从它开始
lspci -vvvvv
将向您显示设备正在使用哪个模块/驱动程序。(查找值Kernel module
和Kernel driver
)要获取当前使用/加载的模块列表,您可以使用lsmod
.要获得更多详细信息,请查看Wiki Lspci,其中列出了其他命令,但您可能需要安装额外的软件包。
这些将为您提供有关硬件本身的信息:
dmidecode
和hwinfo
或lshw
编辑:
要找出启动期间加载的驱动程序,您通常会搜索(取决于 sys-vinit/systemd):
或命令
dmesg
找出 systemd 中加载的内容journalctl -k kernel
或journalctl -b
当前/上次启动的内容。请查阅每个命令的手册页。