On some recent PCs it can be necessary, or desirable, to load
firmware to make them work at their best. There is a directory,
/lib/firmware
, where the kernel or
kernel drivers look for firmware images.
Preparing firmware for multiple different machines, as a distro would do, is outside the scope of this book.
Currently, most firmware can be found at a git
repository:
http://git.kernel.org/cgit/linux/kernel/git/firmware/linux-firmware.git/tree/.
For convenience, the LFS Project has created a mirror, updated daily,
where these firmware files can be accessed via wget
or a web browser at http://anduin.linuxfromscratch.org/BLFS/linux-firmware/.
To get the firmware, either point a browser to one of the above
repositories and then download the item(s) which you need, or install
git
and clone that
repository.
For some other firmware, particularly for Intel microcode and certain wifi devices, the needed firmware is not available in the above repository. Some of this will be addressed below, but a search of the Internet for needed firmware is sometimes necessary.
Firmware files are conventionally referred to as blobs because you cannot determine what they will do. Note that firmware is distributed under various different licenses which do not permit disassembly or reverse-engineering.
Firmware for PCs falls into four categories:
Updates to the CPU to work around errata, usually referred to as microcode.
Firmware for video controllers. On x86 machines this seems to mostly apply to ATI devices : Radeons, the later AMD amdgpu chips, and Nvidia Maxwell cards require firmware to be able to use KMS (kernel modesetting - the preferred option) as well as for Xorg. For earlier radeon chips (before the R600), the firmware is still in the kernel.
Firmware updates for wired network ports. Mostly they work even without the updates, but one must assume that they will work better with the updated firmware.
Firmware for other devices, such as wifi. These devices are not required for the PC to boot, but need the firmware before these devices can be used.
Although not needed to load a firmware blob, the following tools may be useful for determining, obtaining, or preparing the needed firmware in order to load it into the system: cpio-2.12, git-2.14.1, pciutils-3.5.5, and Wget-1.19.1
User Notes: http://wiki.linuxfromscratch.org/blfs/wiki/aboutfirmware
In general, microcode can be loaded by the BIOS or UEFI, and it might be updated by upgrading to a newer version of those. On linux, you can also load the microcode from the kernel if you are using an AMD family 10h or later processor (first introduced late 2007), or an Intel processor from 1998 and later (Pentium4, Core, etc), if updated microcode has been released. These updates only last until the machine is powered off, so they need to be applied on every boot.
Intel provide frequent updates of their microcode. It is not uncommon to find a newer version of microcode for an Intel processor even two years after its release. New versions of AMD firmware are less common.
There used to be two ways of loading the microcode, described as 'early' and 'late'. Early loading happens before userspace has been started, late loading happens after userspace has started. Not surprisingly, early loading was preferred, (see e.g. an explanatory comment in a kernel commit noted at x86/microcode: Early load microcode on LWN.) Indeed, it is needed to work around one particular erratum in early Intel Haswell processors which had TSX enabled. (See Intel Disables TSX Instructions: Erratum Found in Haswell, Haswell-E/EP, Broadwell-Y.) Without this update glibc can do the wrong thing in uncommon situations.
As a result, early loading is now expected, although for the moment
(4.11 kernels) it is still possible to manually force late loading
of microcode for testing. You will need to reconfigure your kernel
for either method. The instructions here will create a kernel
.config
to suite early loading,
before forcing late loading to see if there is any microcode. If
there is, the instructions then show you how to create an initrd
for early loading.
To confirm what processor(s) you have (if more than one, they will be identical) look in /proc/cpuinfo.
The first step is to get the most recent version of the Intel
microcode. This must be done by navigating to
https://downloadcenter.intel.com/download/26400/Linux-Processor-Microcode-Data-File
and following the instructions there. As of this writing the most
recent version of the microcode is microcode-20170511.tgz
. Extract this file in
the normal way to create an intel-ucode
directory, containing various blobs
with names in the form XX-YY-ZZ.
Now you need to determine your processor's identity to see if there is any microcode for it. Determine the decimal values of the cpu family, model and stepping by running the following command (it will also report the current microcode version):
head -n7 /proc/cpuinfo
Convert the cpu family, model and stepping to pairs of hexadecimal digits. For a Haswell i7-4790 (described as Intel(R) Core(TM) i7-4790 CPU) the relevant values are cpu family 6, model 60, stepping 3 so in this case the required identification is 06-3c-03. A look at the blobs will show that there is one for this CPU (although it might have already been applied by the BIOS). If there is a blob for your system then test if it will be applied by copying it (replace <XX-YY-ZZ> by the identifier for your machine) to where the kernel can find it:
mkdir -pv /lib/firmware/intel-ucode cp -v intel-ucode/<XX-YY-ZZ> /lib/firmware/intel-ucode
Now that the Intel microcode has been prepared, use the following options when you configure the kernel to load Intel microcode:
General Setup --->
[y] Initial RAM filesystem and RAM disk (initramfs/initrd) support [CONFIG_BLK_DEV_INITRD]
Processor type and features --->
[y] CPU microcode loading support [CONFIG_MICROCODE]
[y] Intel microcode loading support [CONFIG_MICROCODE_INTEL]
After you have successfully booted the new system, force late loading by using the command:
echo 1 > /sys/devices/system/cpu/microcode/reload
Then use the following command to see if anything was loaded:
dmesg | grep -e 'microcode' -e 'Linux version' -e 'Command line'
This example from the Haswell i7 which was released in Q2 2014 and is not affected by the TSX errata shows it has been updated from revision 0x19 in the BIOS/UEFI to revision 0x22. Unlike in older kernels, the individual CPUs are not separately reported:
[ 0.000000] Linux version 4.11.0 (lfs@plexi) (gcc version 7.1.0 (GCC) )
#1 SMP PREEMPT Sun May 14 16:00:00 BST 2017
[ 0.000000] Command line: BOOT_IMAGE=/vmlinuz-4.11.0-sda6 root=/dev/sda6 ro
[ 0.913685] microcode: sig=0x306c3, pf=0x2, revision=0x22
[ 0.913905] microcode: Microcode Update Driver: v2.2.
[ 148.723932] microcode: updated to revision 0x22, date = 2017-01-27
That may be followed by individual reports for each core.
If the microcode was not updated, there is no new microcode for this system's processor. If it did get updated, you can now proceed to the section called “Early loading of microcode”.
Begin by downloading a container of firmware for your CPU family
from
http://anduin.linuxfromscratch.org/BLFS/linux-firmware/amd-ucode/.
The family is always specified in hex. Families 10h to 14h (16 to
20) are in microcode_amd.bin. Families 15h and 16h have their own
containers. Create the required directory and put the firmware
you downloaded into it as the root
user:
mkdir -pv /lib/firmware/amd-ucode cp -v microcode_amd* /lib/firmware/amd-ucode
When you configure the kernel, use the following options to load AMD microcode:
General Setup --->
[y] Initial RAM filesystem and RAM disk (initramfs/initrd) support [CONFIG_BLK_DEV_INITRD]
Processor type and features --->
[y] CPU microcode loading support [CONFIG_MICROCODE]
[y] AMD microcode loading support [CONFIG_MICROCODE_AMD]
After you have successfully booted the new system, force late loading by using the command:
echo 1 > /sys/devices/system/cpu/microcode/reload
Then use the following command to see if anything was loaded:
dmesg | grep -e 'microcode' -e 'Linux version' -e 'Command line'
This example from an old Athlon(tm) II X2 shows it has been updated. For the moment, all CPUs are still reported in the microcode details on AMD machines:
[ 0.000000] Linux version 4.9.8 (ken@testserver) (gcc version 6.3.0 (GCC) )
#1 SMP Mon Mar 6 22:27:18 GMT 2017
[ 0.000000] Command line: BOOT_IMAGE=/vmlinuz-4.9.8-sdc6 root=/dev/sdc6 ro
[ 0.907752] microcode: CPU0: patch_level=0x010000b6
[ 0.907788] microcode: CPU1: patch_level=0x010000b6
[ 0.907844] microcode: Microcode Update Driver: v2.01 <[email protected]>, Peter Oruba
[ 121.952667] microcode: CPU0: new patch_level=0x010000c8
[ 121.952687] microcode: CPU1: new patch_level=0x010000c8
If the microcode was not updated, there is no new microcode for this system's processor. If it did get updated, you can now proceed to the section called “Early loading of microcode”.
If you have established that updated microcode is available for your system, it is time to prepare it for early loading. This requires an additional package, cpio-2.12 and the creation of an initrd which will need to be added to grub.cfg.
It does not matter where you prepare the initrd, and once it is working you can apply the same initrd to later LFS systems or newer kernels on this same machine, at least until any newer microcode is released. Use the following commands:
mkdir -p initrd/kernel/x86/microcode cd initrd
For an AMD machine, use the following command (replace <MYCONTAINER> with the name of the container for your CPU's family):
cp -v /lib/firmware/amd_ucode/<MYCONTAINER> kernel/x86/microcode/AuthenticAMD.bin
Or for an Intel machine copy the appropriate blob using this command:
cp -v /lib/firmware/intel-ucode/<XX-YY-ZZ> kernel/x86/microcode/GenuineIntel.bin
Now prepare the initrd:
find . | cpio -o -H newc > /boot/microcode.img
You now need to add a new entry to /boot/grub/grub.cfg and here you should add a new line after the linux line within the stanza. If /boot is a separate mountpoint:
initrd /microcode.img
or this if it is not:
initrd /boot/microcode.img
If you are already booting with an initrd (see the section called
“About initramfs”) you must specify the microcode
initrd first, using a line such as initrd /microcode.img
/other-initrd.img
(adapt that as above if /boot
is not a separate mountpoint).
You can now reboot with the added initrd, and then use the same command to check that the early load worked.
dmesg | grep -e 'microcode' -e 'Linux version' -e 'Command line'
The places and times where early loading happens are very different in AMD and Intel machines. First, an Intel example from an updated kernel, showing that the first notification comes before the kernel version is mentioned:
[ 0.000000] microcode: microcode updated early to revision 0x22, date = 2017-01-27
[ 0.000000] Linux version 4.11.0 (lfs@plexi) (gcc version 7.1.0 (GCC) )
#2 SMP PREEMPT Sun May 14 17:58:53 BST 2017
[ 0.000000] Command line: BOOT_IMAGE=/vmlinuz-4.11.0-sda6 root=/dev/sda6 ro
[ 0.928947] microcode: sig=0x306c3, pf=0x2, revision=0x22
[ 0.929160] microcode: Microcode Update Driver: v2.2.
An AMD example for an earlier stable kernel version:
[ 0.000000] Linux version 4.9.14 (ken@testserver) (gcc version 6.3.0 (GCC) )
#2 SMP Mon Mar 13 22:23:44 GMT 2017
[ 0.000000] Command line: BOOT_IMAGE=/vmlinuz-4.9.14-sdc6 root=/dev/sdc6 ro
[ 0.907648] microcode: microcode updated early to new patch_level=0x010000c8
[ 0.907690] microcode: CPU0: patch_level=0x010000c8
[ 0.907733] microcode: CPU1: patch_level=0x010000c8
[ 0.907808] microcode: Microcode Update Driver: v2.01 <[email protected]>, Peter Oruba
These instructions do NOT apply to old radeons before the R600
family. For those, the firmware is in the kernel's /lib/firmware/
directory. Nor do they apply if
you intend to avoid a graphical setup such as Xorg and are
content to use the default 80x25 display rather than a
framebuffer.
Early radeon devices only needed a single 2K blob of firmware. Recent devices need several different blobs, and some of them are much bigger. The total size of the radeon firmware directory is over 500K — on a large modern system you can probably spare the space, but it is still redundant to install all the unused files each time you build a system.
A better approach is to install pciutils-3.5.5 and then use lspci
to identify which VGA
controller is installed.
With that information, check the RadeonFeature page of the Xorg wiki for Decoder ring for engineering vs marketing names to identify the family (you may need to know this for the Xorg driver in BLFS — Southern Islands and Sea Islands use the radeonsi driver) and the specific model.
Now that you know which controller you are using, consult the Radeon page of the Gentoo wiki which has a table listing the required firmware blobs for the various chipsets. Note that Southern Islands and Sea Islands chips use different firmware for kernel 3.17 and later compared to earlier kernels. Identify and download the required blobs then install them:
mkdir -pv /lib/firmware/radeon cp -v <YOUR_BLOBS> /lib/firmware/radeon
There are actually two ways of installing this firmware. BLFS, in the 'Kernel Configuration for additional firmware' section part of the Xorg ATI Driver-7.9.0 section gives an example of compiling the firmware into the kernel - that is slightly faster to load, but uses more kernel memory. Here we will use the alternative method of making the radeon driver a module. In your kernel config set the following:
Device Drivers --->
Graphics support --->
Direct Rendering Manager --->
<*> Direct Rendering Manager (XFree86 ... support) [CONFIG_DRM]
<m> ATI Radeon [CONFIG_DRM_RADEON]
Loading several large blobs from /lib/firmware takes a noticeable time, during which the screen will be blank. If you do not enable the penguin framebuffer logo, or change the console size by using a bigger font, that probably does not matter. If desired, you can slightly reduce the time if you follow the alternate method of specifying 'y' for CONFIG_DRM_RADEON covered in BLFS at the link above — you must specify each needed radeon blob if you do that.
Some Nvidia graphics chips need firmware updates to take advantage of all the card's capability. These are generally the GeForce 8, 9, 9300, and 200-900 series chips. For more exact information, see https://nouveau.freedesktop.org/wiki/VideoAcceleration/#firmware.
First, the kernel Nvidia driver must be activated:
Device Drivers --->
Graphics support --->
Direct Rendering Manager --->
<*> Direct Rendering Manager (XFree86 ... support) [CONFIG_DRM]
<*/m> Nouveau (NVIDIA) cards [CONFIG_DRM_NOUVEAU]
The steps to install the Nvidia firmware are:
wget https://raw.github.com/imirkin/re-vp2/master/extract_firmware.py wget http://us.download.nvidia.com/XFree86/Linux-x86/325.15/NVIDIA-Linux-x86-325.15.run sh NVIDIA-Linux-x86-325.15.run --extract-only python extract_firmware.py mkdir -p /lib/firmware/nouveau cp -d nv* vuc-* /lib/firmware/nouveau/
The kernel likes to load firmware for some network drivers, particularly those from Realtek (the /lib/linux-firmware/rtl_nic/) directory, but they generally appear to work without it. Therefore, you can boot the kernel, check dmesg for messages about this missing firmware, and if necessary download the firmware and put it in the specified directory in /lib/firmware so that it will be found on subsequent boots. Note that with current kernels this works whether or not the driver is compiled in or built as a module, there is no need to build this firmware into the kernel. Here is an example where the R8169 driver has been compiled in but the firmware was not made available. Once the firmware had been provided, there was no mention of it on later boots.
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)
Identifying the correct firmware will typically require you to
install pciutils-3.5.5, and then use lspci
to identify the device. You
should then search online to check which module it uses, which
firmware, and where to obtain the firmware — not all of it is
in linux-firmware.
If possible, you should begin by using a wired connection when you first boot your LFS system. To use a wireless connection you will need to use a network tools such as Wireless Tools-29 and wpa_supplicant-2.6.
Firmware may also be needed for other devices such as some SCSI controllers, bluetooth adaptors, or TV recorders. The same principles apply.
Last updated on 2017-06-01 19:42:51 -0700