在某些较新的 PC 上,可能需要或希望加载固件以使其发挥最佳性能。内核或内核驱动程序在 /lib/firmware 中查找固件映像。但在 LFS 中,/lib 是指向 usr/lib
的符号链接,因此实际包含固件文件的目录是 /usr/lib/firmware。
目前,大多数固件可以在 git
仓库中找到,可通过 URL
https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/plain
在浏览器中查看。为了方便,LFS 项目创建了一个每日更新的镜像,这些固件文件可以通过 wget 或 Web 浏览器在 https://anduin.linuxfromscratch.org/BLFS/linux-firmware/
访问。
要获取固件,请将浏览器指向上述仓库之一,然后下载您需要的项目。如果您想要所有这些固件文件(例如,您要将系统分发到多个硬件系统上),可以安装
git-2.55.0 并克隆
https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git,或者在浏览器中打开此
URL,并下载 Tag 表中列出的最新快照。
请注意,某些所需的固件文件(和目录)实际上是指向其他文件(或目录)的符号链接。这些符号链接并不存储在 Git 仓库中,而是在
WHENCE 文件中予以说明。每行以 Link:
开头的行描述一个符号链接。如果您正在下载所需项目,且它是一个这样的符号链接(或位于这样的符号链接目录中),您需要手动创建符号链接并下载目标。另一方面,如果您想要所有固件文件,请使用
./copy-firmware.sh
/usr/lib/firmware 命令,该命令将复制固件文件并创建 WHENCE 文件中的所有符号链接,而不是使用像 cp -r * /usr/lib/firmware/
这样的普通复制命令。
对于某些其他固件,特别是 Intel 微码和某些 Wi-Fi 设备,所需的固件不在上述仓库中。下面将讨论其中一些,但有时需要在互联网上搜索所需固件。
固件文件通常被称为 blob,因为您无法确定它们会做什么。请注意,固件是在各种不同许可证下分发的,这些许可证不允许反编译或逆向工程。
PC 的固件分为四类:
用于解决勘误表的 CPU 更新,通常称为微码(microcode)。
视频控制器的固件。在 x86 机器上,ATI 设备(Radeon 和 AMDGPU 芯片)需要此固件,对于 Intel(Skylake 及更新)和 NVIDIA(Kepler 及更新)GPU 也可能有用。
ATI Radeon 和 AMDGPU 设备都需要固件才能使用 KMS(内核模式设置——首选选项)以及 Xorg。
从 Skylake 开始的 Intel 集成 GPU 可以使用 GuC(图形微控制器)的固件,以及 HuC(HEVC/H265 微控制器,将任务卸载到 GPU)和 DMC(显示微控制器)的固件,以提供额外的低功耗状态。GuC 和 HuC 在内核中的历史有些曲折,根据您的内核版本,更新的固件可能默认被禁用。更多详细信息可在 01.org 和 Arch Linux 找到。
从 Kepler 开始的 NVIDIA GPU 需要签名的固件,否则 nouveau 驱动程序无法提供硬件加速。NVIDIA 现已将最高至 Ada Lovelace(GeForce 40 系列)的固件发布到 linux-firmware。
有线网络端口的固件更新。即使没有更新,大多数也能工作,但更新后可能会工作得更好。对于某些现代笔记本电脑,有线以太网(例如 rtl_nic)和蓝牙设备(例如 qca)的固件在使用有线网络之前是 必需 的。
其他设备的固件,例如无线网卡。这些设备不是 PC 启动所必需的,但在这些设备可用之前需要固件。
虽然加载固件 blob 本身不需要,但以下工具可能有助于确定、获取或准备所需固件,以便将其加载到系统中: cpio-2.15(或 libarchive-3.8.8)、 git-2.55.0、 pciutils-3.15.0 和 Wget-1.25.0
通常,微码可以由 BIOS 或 UEFI 加载,并且可以通过升级到这些的新版本进行更新。在 Linux 上,如果您使用的是 AMD 10h 或更高版本的处理器(于 2007 年末首次推出),或者使用的是 1998 年及以后的 Intel 处理器(Pentium4、Core 等),并且已发布更新的微码,则您也可以从内核加载微码。这些更新仅在机器断电前有效,因此需要在每次启动时应用。
在极少数情况下,来自内核的微码更新可能无效。例如,尽管 intel-microcode-20241029 包含旨在修复臭名昭著的过度电压问题的 Raptor Lake 微码修订版 0x12b(该问题会导致稳定性问题甚至永久性 CPU 损坏),但当内核启动时,微码已经 为时已晚,无法修复该问题。解决此问题的唯一方法是更新 BIOS。
随着新漏洞的出现,Intel 为其 Skylake 及更新处理器提供微码更新,并且过去也为 SandyBridge 及更新处理器提供更新,尽管这些处理器不再支持新的修复。新版本的 AMD 固件很少见,通常仅适用于少数型号,尽管主板制造商会获得 AGESA(AMD 通用封装软件架构)更新以更改 BIOS 值,例如支持更多内存变体、新的漏洞修复或更新的 CPU。
加载微码有两种方式,称为“早期”和“晚期”。早期加载在用户空间启动之前进行,晚期加载在用户空间启动之后进行。然而,晚期加载已知存在问题且不再受支持(参见内核提交 x86/microcode: Taint and warn on late loading)。事实上,早期加载是为了解决早期 Intel Haswell 处理器中一个特定的勘误表(该处理器启用了 TSX)所必需的(参见 Intel Disables TSX Instructions: Erratum Found in Haswell, Haswell-E/EP, Broadwell-Y)。如果没有此更新,glibc 在异常情况下可能会执行错误操作。
在本书的先前版本中,建议晚期加载微码以查看其是否被应用,然后使用 initrd 强制早期加载。但现在 Intel 微码压缩包的内容已有文档记录,并且 AMD 微码可以通过 Python 脚本读取以确定其适用的机器,因此没有真正的理由使用晚期加载。
仍有可能手动强制晚期加载微码。但这可能导致内核故障,您应自行承担风险。您需要重新配置内核以支持晚期加载,但早期加载始终受 x86(无论 32 位还是 64 位)系统上的 Linux 内核 6.6 或更高版本支持。此处的说明将向您展示如何为早期加载创建 initrd。也可以将相同的微码 bin 文件构建到内核中,这允许早期加载,但需要重新编译内核才能更新微码。
要确认您拥有的处理器(如果不止一个,它们将相同),请查看 /proc/cpuinfo。通过运行以下命令确定 cpu family、model 和 stepping 的十进制值(它还将报告当前的微码版本):
head -n7 /proc/cpuinfo
将 cpu family、model 和 stepping 转换为十六进制数字对,并记住 “microcode” 字段的值。现在您可以检查是否有任何可用的微码。
如果您正在为不同机器创建 initrd 以更新固件(如发行版所做的那样),请转到“微码的早期加载”并将所有 Intel blob 连接到 GenuineIntel.bin,或将所有 AMD blob 连接到 AuthenticAMD.bin。这会创建更大的 initrd——对于 20200609 更新中的所有 Intel 机器,大小为 3.0 MB,而单台机器通常为 24 KB。
第一步是获取最新版本的 Intel 微码。这必须通过导航到
https://github.com/intel/Intel-Linux-Processor-Microcode-Data-Files/releases/
并下载其中的最新文件来完成。在撰写本文时,最安全的微码版本是 microcode-20260227。以正常方式解压此文件,微码位于
intel-ucode 目录中,包含各种形式为 XX-YY-ZZ 的
blob。还有其他各种文件和一个发行说明。
过去,Intel 没有提供哪些 blob 更改了版本的详细信息,但现在发行说明详细说明了这一点。您可以将 /proc/cpuinfo 中的微码版本与发行说明中您的 CPU
型号的版本进行比较,以了解是否有更新。
为较旧处理器提供的最新固件用于处理现已公开的漏洞,对于其中一些漏洞,例如微架构数据采样(MDS),您可能希望通过禁用超线程来增强保护,或者由于其对编译时间的影响而禁用内核的默认缓解措施。请阅读 https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/index.html 上的在线文档。
对于 Meteor Lake 移动版(描述为 Intel(R) Core(TM) Ultra 5 125H CPU),相关值为
cpu family 6、model 140、stepping 4,因此在这种情况下所需的标识为
06-aa-04。发行说明称其最新微码版本为 0x25。如果 /proc/cpuinfo 中 “microcode” 字段的值为 0x25
或更大,则表示 BIOS 已应用微码更新。否则,请继续执行 “微码的早期加载”一节。
首先从 https://anduin.linuxfromscratch.org/BLFS/linux-firmware/amd-ucode/ 下载适用于您 CPU 系列的固件容器。系列始终以十六进制指定。10h 至 14h(16 至 20)系列位于 microcode_amd.bin 中。15h、16h、17h(Zen、Zen+、Zen2)和 19h(Zen3)系列有自己的容器,但很少有机器能获得更新的微码。相反,AMD 向主板制造商提供更新的 AGESA,制造商可能会据此提供更新的 BIOS。在 https://github.com/AMDESE/amd_ucode_info/blob/master/amd_ucode_info.py 有一个 Python3 脚本。下载该脚本并针对 bin 文件运行,以检查哪些处理器有更新。
对于这些示例中非常老的 Athlon(tm) II X2,其值为 cpu family 16、model 5、stepping 3,标识为 Family=0x10 Model=0x05 Stepping=0x03。amd_ucode_info.py 脚本输出的一行描述了其微码版本:
Family=0x10 Model=0x05 Stepping=0x03: Patch=0x010000c8 Length=960 bytes
如果 /proc/cpuinfo 中 “microcode” 字段的值为
0x10000c8 或更大,则表示 BIOS 已应用微码更新。否则,请继续执行 “微码的早期加载”一节。
如果您已确定您的系统有可用的更新微码,那么是时候准备进行早期加载了。这需要额外的包 cpio-2.15(或 libarchive-3.8.8)并创建 initrd,然后需要将其添加到 grub.cfg 中。
在何处准备 initrd 无关紧要,一旦它正常工作,您可以将相同的 initrd 应用于此机器上的后续 LFS 系统或更新内核,至少在发布任何更新的微码之前。使用以下命令:
mkdir -p initrd/kernel/x86/microcode cd initrd
对于 AMD 机器,使用以下命令(将 <MYCONTAINER> 替换为您的 CPU 系列容器的名称):
cp -v ../<MYCONTAINER> kernel/x86/microcode/AuthenticAMD.bin
或者对于 Intel 机器,使用以下命令复制适当的 blob:
cp -v ../intel-ucode/<XX-YY-ZZ> kernel/x86/microcode/GenuineIntel.bin
现在准备 initrd(您也可以使用 libarchive-3.8.8 中的 bsdcpio 代替 cpio):
find * | cpio -o -H newc > /boot/microcode.img
现在您需要在 /boot/grub/grub.cfg 中添加一个新条目,并且应该在节内的 linux 行之后添加一行新行。如果 /boot 是一个单独挂载点:
initrd /microcode.img
如果不是,则:
initrd /boot/microcode.img
如果您已经使用 initrd 启动(参见 “关于 initramfs”一节),则应将适当的 blob 或容器放入
/usr/lib/firmware 后,再次运行
mkinitramfs。更准确地说,在运行
mkinitramfs 之前,将
Intel blob 放入 /usr/lib/firmware/intel-ucode 目录,或将 AMD 容器放入
/usr/lib/firmware/amd-ucode
目录。或者,您可以将两个 initrd 放在同一行,如 initrd /microcode.img
/other-initrd.img(如果 /boot 不是单独挂载点,请按上述方式调整)。
现在您可以使用添加的 initrd 重新启动,然后使用以下命令检查早期加载是否成功:
dmesg | grep -e 'microcode' -e 'Linux version' -e 'Command line'
如果您更新以解决漏洞,可以查看 lscpu 命令的输出,以了解现在报告的内容。
在 AMD 和 Intel 机器上,早期加载发生的位置和时间有很大不同。首先,一个 Intel(Meteor Lake 移动版)早期加载的示例:
[ 0.000000] Linux version 6.17.6 (xry111@stargazer) (gcc (GCC) 15.2.0, GNU ld (GNU Binutils) 2.45) #1 SMP PREEMPT_DYNAMIC Sun Nov 9 21:03:48 CST 2025
[ 0.000000] Command line: BOOT_IMAGE=/boot/vmlinuz-6.17.6 root=/dev/nvme0n1p6 ro
[ 1.459687] microcode: Current revision: 0x00000025
[ 1.459699] microcode: Updated early from: 0x00000024
一个历史悠久的 AMD 示例:
[ 0.000000] Linux version 4.15.3 (ken@testserver) (gcc version 7.3.0 (GCC))
#2 SMP Sun Feb 18 02:32:03 GMT 2018
[ 0.000000] Command line: BOOT_IMAGE=/vmlinuz-4.15.3-sda5 root=/dev/sda5 ro
[ 0.307619] microcode: microcode updated early to new patch_level=0x010000c8
[ 0.307678] microcode: CPU0: patch_level=0x010000c8
[ 0.307723] microcode: CPU1: patch_level=0x010000c8
[ 0.307795] microcode: Microcode Update Driver: v2.2.
早期的 radeon 设备仅需要一个 2 KB 的固件 blob。较新的设备需要几个不同的 blob,其中一些更大。radeon 固件目录的总大小超过 500 KB——在大型现代系统上,您可能可以腾出空间,但每次构建系统时安装所有未使用的文件仍然是一种冗余。
更好的方法是安装 pciutils-3.15.0,然后使用 lspci 识别安装的 VGA 控制器。
有了这些信息,请查看 Xorg 维基的 RadeonFeature 页面,了解 Decoder ring for engineering vs marketing names 以识别系列(您可能需要了解此信息以用于 BLFS 中的 Xorg 驱动程序——Southern Islands 和 Sea Islands 使用 radeonsi 驱动程序)和具体型号。
既然您知道使用的控制器,请查阅 Gentoo 维基的 Radeon 页面,其中有一个表格列出了各种芯片组所需的固件 blob。请注意,Southern Islands 和 Sea Islands 芯片在 3.17 及更新内核上使用的固件与旧内核不同。识别并下载所需的 blob,然后安装它们:
mkdir -pv /usr/lib/firmware/radeon cp -v <YOUR_BLOBS> /usr/lib/firmware/radeon
建议将内核 amdgpu 驱动程序构建为模块,因为固件文件在加载时需要可访问。如果出于任何原因将其构建为内核映像的一部分,您需要将固件文件包含在 initramfs 中(详细信息请阅读 “关于 initramfs”一节),或将它们包含在内核映像本身中(详细信息请阅读 “在内核映像中包含固件 Blob”一节)。
所有使用 amdgpu 内核驱动程序的视频控制器都需要固件,无论您将使用 xorg amdgpu 驱动程序、xserver 的 modesetting 驱动程序,还是仅使用内核模式设置来获得大于 80x25 的控制台帧缓冲。
安装 pciutils-3.15.0 并使用它检查型号名称(查找“VGA compatible controller:”)。如果您有 APU(加速处理单元,即 CPU 和视频在同一芯片上),那可能会告诉您名称。如果您有单独的 amdgpu 视频卡,则需要搜索以确定它使用的名称(例如,描述为 Advanced Micro Devices, Inc. [AMD/ATI] Baffin [Radeon RX 550 640SP / RX 560/560X] 的卡需要 Polaris11 固件)。在 Gentoo 维基的 AMDGPU 页面末尾的内核部分有一个“Family, Chipset name, Product name and Firmware”表。
一旦确定了固件名称,请安装其所有相关文件。例如,上面提到的 Baffin 卡有 21 个不同的 polaris11* 文件,诸如 renoir 和 picasso 之类的 APU 至少有 12 个文件,并且在未来的更新中可能会增加更多(例如,raven APU 现在有第 13 个文件 raven_ta.bin)。
mkdir -pv /usr/lib/firmware/amdgpu cp -v <YOUR_BLOBS> /usr/lib/firmware/amdgpu
如果磁盘空间不是问题,您可以安装所有当前的 amdgpu 固件文件,而不必担心具体安装的是哪个芯片组。
建议将内核 amdgpu 驱动程序构建为模块,因为固件文件在加载时需要可访问。如果出于任何原因将其构建为内核映像的一部分,您需要将固件文件包含在 initramfs 中(详细信息请阅读 “关于 initramfs”一节),或将它们包含在内核映像本身中(详细信息请阅读 “在内核映像中包含固件 Blob”一节)。
从 Kepler 开始的一些 NVIDIA GPU(包括所有 NVIDIA GeForce RTX GPU 和 GTX 9xx
系列及更新)需要 NVIDIA 签名的固件才能工作。对于 Nouveau 驱动程序,NVIDIA 已在
linux-firmware 的 nvidia/
目录中发布了签名的固件文件。阅读 Nouveau 维基的
CodeNames 页面 以找出您的 NVIDIA GPU 的代号(例如,GeForce RTX 5080 的代号为
GB203)。您需要的固件文件目录名称是将代号转换为小写的结果(例如 gb203)。该目录(或其某些内容)可能实际上是指向另一个目录(或另一个目录中的某些文件)的符号链接,然后您需要自己
创建符号链接并下载其目标(例如,gb207
是指向 gb202 的符号链接)。
如果您在 linux-firmware 树或 WHENCE
文件(作为符号链接)中都找不到 GPU 的目录,则意味着您的 GPU 不需要任何固件,或者它比 Blackwell(RTX
50xx 系列)更新,并且其固件尚未发布(截至 2025 年中)。
对于从 Tesla 到 Kepler 的 NVIDIA GPU,Nouveau 驱动程序需要一些额外的固件来支持视频解码加速。这些固件文件未由 NVIDIA 发布,但可以从 NVIDIA 二进制驱动程序中提取。关于哪些芯片需要提取的固件,更准确的信息请参见 Nouveau 维基的 VideoAcceleration。要提取并安装这些固件文件,请执行:
wget https://anduin.linuxfromscratch.org/BLFS/nvidia-firmware/extract_firmware.py wget https://us.download.nvidia.com/XFree86/Linux-x86/340.32/NVIDIA-Linux-x86-340.32.run sh NVIDIA-Linux-x86-340.32.run --extract-only python3 extract_firmware.py mkdir -p /usr/lib/firmware/nouveau cp -d nv* vuc-* /usr/lib/firmware/nouveau/
内核喜欢为某些网络驱动程序加载固件,尤其是 Realtek 的驱动程序(/usr/lib/linux-firmware/rtl_nic/
目录),但它们通常在没有固件的情况下也能工作。因此,您可以启动内核,检查 dmesg
中有关此缺失固件的消息,如有必要,下载固件并将其放在 /usr/lib/firmware
中的指定目录中,以便在后续启动时找到它。请注意,对于当前内核,无论驱动程序是编译进内核还是构建为模块,这都有效,无需将此固件构建到内核中。以下是一个示例,其中
R8169 驱动程序已编译进内核,但固件未提供。一旦提供了固件,后续启动中就不会再提到它。
dmesg | grep firmware | grep r8169
[ 7.018028] r8169 0000:01:00.0: Direct firmware load for rtl_nic/rtl8168g-2.fw failed with error -2
[ 7.018036] r8169 0000:01:00.0 eth0: unable to load firmware patch rtl_nic/rtl8168g-2.fw (-2)
不同国家对无线设备的无线电频谱使用有不同的规定。您可以安装固件,使无线设备遵守当地的频谱法规,这样您就不会被当地机构询问,也不会发现您的无线网卡干扰其他设备(例如遥控器)的频率。监管数据库固件可以从
https://kernel.org/pub/software/network/wireless-regdb/
下载。要安装它,只需从压缩包中提取 regulatory.db 和
regulatory.db.p7s 到 /usr/lib/firmware。请注意,cfg80211 驱动程序需要被选为模块,才能加载 regulatory.* 文件,或者这些文件需要作为固件包含在内核中,如上文 “显卡的固件”一节 所述。
接入点(AP)会向您的无线网卡发送国家代码,wpa_supplicant-2.11 会告诉内核从 regulatory.db 加载该国家的法规并强制执行。请注意,有些 AP
不发送此国家代码,因此您可能被限制在相当受限的使用范围内(特别是如果您想将接口用作 AP)。
某些系统(尤其是配备最新 Intel CPU 的笔记本电脑)利用 CPU 附带的 DSP 与音频编解码器连接。必须将 Sound
Open Firmware 加载到 DSP 上才能使其正常工作。这些固件文件可以从 https://github.com/thesofproject/sof-bin/releases
下载。解压压缩包并进入解压后的目录,然后以 root
用户身份安装固件:
install -vdm755 /usr/lib/firmware/intel && cp -rv sof* /usr/lib/firmware/intel/
alsa-lib-1.2.16.1 还需要使用 Sound Open Firmware 的系统的 Use Case Manager 配置文件。请阅读 alsa-lib-1.2.16.1 页面以获取安装说明。一旦固件被加载(您可能需要重新启动以便内核加载它们)并且 UCM 配置文件安装完毕,按照 “Configuring ALSA Utilities”一节 为 ALSA 正确设置您的声卡。
识别正确的固件通常需要您安装 pciutils-3.15.0,然后使用 lspci
识别设备。然后您应该在线搜索以检查它使用哪个模块、哪个固件以及从哪里获取固件——并非所有固件都在 linux-firmware 中。
如果可能,您应该在首次启动 LFS 系统时使用有线连接。要使用无线连接,您需要使用网络工具,例如 iw-6.17、Wireless Tools-29 或 wpa_supplicant-2.11。
其他设备(例如某些 SCSI 控制器、蓝牙适配器或电视录像机)也可能需要固件。同样的原则适用。
某些驱动程序,尤其是 ATI 或 AMD GPU
的驱动程序,要求固件文件在加载时可访问。处理这些驱动程序的最简单方法是将其构建为内核模块。另一种方法是创建包含固件文件的
initramfs(详细信息请阅读 “关于
initramfs”一节)。如果您不想使用这两种方法,可以将固件文件包含在内核映像本身中。首先将所需的固件文件安装到
/usr/lib/firmware
中,然后设置以下内核配置并重新构建内核:
Device Drivers ---> Generic Driver Options ---> Firmware loader ---> (xx/aa.bin xx/bb.bin) Build named firmware blobs into the kernel binary ... [EXTRA_FIRMWARE] # This is the default, you can change it to "/usr/lib/firmware" # if you want: (/lib/firmware) Firmware blobs root directory [EXTRA_FIRMWARE_DIR]
将 xx/aa.bin xx/bb.bin
替换为所需固件文件相对于 /usr/lib/firmware
的路径列表,以空格分隔。一种比手动输入列表(可能很长)更容易的方法是运行以下命令:
echo CONFIG_EXTRA_FIRMWARE='"'$({ cd /usr/lib/firmware; echo amdgpu/* })'"' >> .config
make oldconfig
将 amdgpu/* 替换为匹配所需固件文件的
shell 模式。
请勿将包含固件的内核映像分发给他⼈,否则可能违反 GPL。