Acerca de Firmware

Em alguns PCs recentes, pode ser necessário, ou desejável, carregar firmware para fazer com que trabalhem no melhor deles. Existe um diretório, /lib/firmware, onde o núcleo ou os controladores de núcleo procuram por imagens de firmware.

Atualmente, a maioria do "firmware" pode ser encontrada em um repositório git: https://git.kernel.org/cgit/linux/kernel/git/firmware/linux-firmware.git/tree/. Por conveniência, o Projeto LFS criou um espelho, atualizado diariamente, onde esses arquivos de "firmware" podem ser acessados via wget ou via um navegador da "web" em https://anduin.linuxfromscratch.org/BLFS/linux-firmware/.

Para obter o firmware, ou aponte um navegador para um dos repositórios acima e, então, transfira o(s) item(s) que você precisar; ou instale o git-2.39.2 e clone aquele repositório.

Para algum outro firmware, particularmente para microcódigo da Intel e certos dispositivos wifi, o firmware necessário não está disponível no repositório acima. Algo disso será endereçado abaixo, porém uma busca da Internet pelo firmware necessário de vez em quando é necessária.

Os arquivos de firmware convencionalmente são referenciados como blobs, pois você não consegue determinar o que eles farão. Observe que o firmware é distribuído sob diferentes licenças que não permitem desmontagem ou engenharia reversa.

Firmware para PCs caem em quatro categorias:

[Nota]

Nota

Apesar de não necessárias para carregar um blob de firmware, as seguintes ferramentas possivelmente sejam úteis para determinar, obter ou preparar o firmware necessário para a finalidade de carregá-lo no sistema: cpio-2.13; git-2.39.2; pciutils-3.9.0; e Wget-1.21.3

Observações de Usuário(a): https://wiki.linuxfromscratch.org/blfs/wiki/aboutfirmware

Atualizações de microcódigo para CPUs

Em geral, microcódigo pode ser carregado pelo BIOS ou pela UEFI e poderia ser atualizado atualizando-se para uma versão mais recente daqueles. No Linux, você também pode carregar o microcódigo a partir do núcleo se estiver usando um processador AMD família 10h ou posterior (introduzido primeiramente no final de 2007); ou um processador Intel a partir de 1998 e posterior (Pentium4, Core, etc), se microcódigo atualizado tiver sido lançado. Essas atualizações duram somente até que a máquina seja desligada, de forma que elas precisam ser aplicadas a cada inicialização.

A "Intel" fornece atualizações do microcódigo dela para os processadores "Skylake" e posteriores conforme vulnerabilidades novas surjam e forneceu no passado atualizações para processadores a partir do "SandyBridge" em diante, apesar daqueles não mais serem suportados para correções novas. Versões novas do "firmware" "AMD" são raras e geralmente somente se aplicam a uns poucos modelos, apesar dos(as) fabricantes de placas mãe obterem atualizações "AMD Generic Encapsulated Software Architecture" ("AGESA") para mudar os valores do "BIOS", por exemplo, para suportar mais variantes de memória, correções novas de vulnerabilidades ou "CPUs" mais recentes.

Existiam duas maneiras de carregar o microcódigo, descritas como "antecipada" e "atrasada". O carregamento antecipado ocorre antes que o espaço de usuário(a) tenha sido iniciado; o carregamento atrasado ocorre depois que o espaço de usuário(a) iniciou. No entanto, o carregamento atrasado é conhecido por ser problemático e não mais é suportado (veja-se o "commit" do núcleo x86/microcode: Taint and warn on late loading). Na verdade, o carregamento antecipado é necessário para contornar uma errata específica nos primeiros processadores "Intel" "Haswell" que tinham "TSX" habilitado. (Veja-se Intel Disables TSX Instructions: Erratum Found in Haswell, Haswell-E/EP, Broadwell-Y). Sem essa atualização, a "glibc" pode fazer a coisa errada em situações incomuns.

Nas versões anteriores deste livro, era recomendado o carregamento atrasado do microcódigo para verificar se ele seria aplicado, seguido pelo uso de um "initrd" para forçar o carregamento antecipado. Mas agora que o conteúdo do "tarball" do microcódigo "Intel" está documentado e o microcódigo "AMD" pode ser lido por um script "Python" para determinar quais máquinas ele cobre, não existe razão real para usar o carregamento atrasado.

Ainda pode ser possível forçar manualmente o carregamento atrasado do microcódigo. Mas isso possivelmente cause mau funcionamento do núcleo e você mesmo(a) deveria correr o risco. Você precisará reconfigurar seu núcleo para qualquer um dos métodos. As instruções aqui te mostrarão como criar um "initrd" para carregamento antecipado. Também é possível construir o mesmo arquivo binário de microcódigo interno ao núcleo, o que permite o carregamento antecipado, mas exige que o núcleo seja recompilado para atualizar o microcódigo.

Para confirmar qual(is) processador(es) você tem (se mais que um, eles serão idênticos) olhe em "/proc/cpuinfo". Determine os valores decimais da família da "CPU"; do modelo; e da revisão executando o seguinte comando (também informará a versão atual do microcódigo):

head -n7 /proc/cpuinfo

Converta a família da "CPU", o modelo e a revisão em pares de dígitos hexadecimais e lembre-se do valor do campo microcode. Agora você pode verificar se existe algum microcódigo disponível.

Se você estiver criando um "initrd" para atualizar "firmware" para máquinas diferentes, como uma distribuição faria, [então] vá para baixo até 'Carregamento antecipado do microcódigo' e concatene todos os "blobs" "Intel" para "GenuineIntel.bin"; ou concatene todos os "blobs" "AMD" para "AuthenticAMD.bin". Isso cria um "initrd" mais largo - para todas as máquinas "Intel" na atualização 20200609, o tamanho era de três (3,0) MB comparado a tipicamente vinte e quatro (24) KB para uma máquina.

Microcódigo Intel para a CPU

O primeiro passo é o de obter a versão mais recente do microcódigo "Intel". Isso precisa ser feito navegando-se até https://github.com/intel/Intel-Linux-Processor-Microcode-Data-Files/releases/ e baixando-se o arquivo mais recente lá. Ao tempo da escrita deste texto, a versão mais segura do microcódigo era microcode-20230214. Extraia esse arquivo da maneira normal; o microcódigo está no diretório intel-ucode, contendo vários "blobs" com nomes na forma "XX-YY-ZZ". Existem também vários outros arquivos e uma observação de lançamento.

No passado, a "Intel" não fornecia quaisquer detalhes relativos a quais "blobs" tinham versões mudadas, mas agora a nota de lançamento detalha isso. Você consegue comparar a versão do microcódigo em /proc/cpuinfo com a versão do seu modelo de "CPU" na nota de lançamento para saber se existe uma atualização.

O firmware recente para processadores mais antigos é fornecido para lidar com vulnerabilidades que agora tenham sido tornadas públicas e, para algumas dessas, tais como Microarchitectural Data Sampling (MDS), você poderia desejar aumentar a proteção desabilitando hyperthreading; ou, alternativamente, desabilitar a mitigação padrão do núcleo, por causa do impacto dela sobre os tempos de compilação. Por favor, leia a documentação online em https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/index.html.

Para um dispositivo móvel "Icelake" (descrito como "CPU" "Intel(R) Core(TM) i7-1065G7"), os valores relevantes são "cpu family 6", "model 126", "stepping 5", de modo que, nesse caso, a identificação necessária é "06-7e-05". A nota de lançamento diz que o microcódigo mais recente tem a versão "0xb8". Se o valor do campo microcode em /proc/cpuinfo for "0xb8" ou superior, [então] indica que a atualização do microcódigo já foi aplicada pelo "BIOS". Caso contrário, configure o núcleo para suportar o carregamento do microcódigo "Intel" e prossiga para “Carregamento antecipado do microcódigo”:

General Setup --->
  [*] Initial RAM filesystem and RAM disk (initramfs/initrd) support [CONFIG_BLK_DEV_INITRD]
Processor type and features  --->
  [*] CPU microcode loading support  [CONFIG_MICROCODE]
  [*]      Intel microcode loading support [CONFIG_MICROCODE_INTEL]

Microcódigo AMD para a CPU

Comece baixando um contêiner do "firmware" para a família da sua "CPU" a partir de https://anduin.linuxfromscratch.org/BLFS/linux-firmware/amd-ucode/. A família sempre é especificada em hexadecimal. As famílias "10h" até "14h" (16 até 20) estão no "microcode_amd.bin". As famílias "15h", "16h", "17h" ("Zen", "Zen+", "Zen2") e "19h" ("Zen3") tem os contêineres próprios delas, mas pouquíssimas máquinas provavelmente receberão microcódigo atualizado. Em vez disso, a "AMD" fornece um "AGESA" atualizado para os(as) fabricantes de placas-mãe, que possivelmente forneçam um "BIOS" atualizado usando-o. Existe um script "Python3" em https://github.com/AMDESE/amd_ucode_info/blob/master/amd_ucode_info.py. Baixe esse script e execute-o em relação ao arquivo "bin" para verificar quais processadores tem atualizações.

Para o muito antigo "Athlon(tm) II X2" nesses exemplos os valores eram "cpu family 16", "model 5", "stepping 3", dando uma identificação de Família=0x10 Modelo=0x05 Passo=0x03. Uma linha da saída gerada do script amd_ucode_info.py descreve a versão do microcódigo para ele:

Family=0x10 Model=0x05 Stepping=0x03: Patch=0x010000c8 Length=960 bytes

Se o valor do campo microcode em /proc/cpuinfo for "0x10000c8" ou superior, [então] indica que o "BIOS" já aplicou a atualização do microcódigo. Caso contrário, configure o núcleo para suportar o carregamento do microcódigo "AMD" e prossiga para “Carregamento antecipado do microcódigo”:

General Setup --->
  [*] Initial RAM filesystem and RAM disk (initramfs/initrd) support [CONFIG_BLK_DEV_INITRD]
Processor type and features  --->
  [*] CPU microcode loading support  [CONFIG_MICROCODE]
  [*]      AMD microcode loading support [CONFIG_MICROCODE_AMD]

Carregamento antecipado do microcódigo

Se você tiver estabelecido que o microcódigo atualizado está disponível para o seu sistema, [então] é hora de prepará-lo para o carregamento antecipado. Isso exige um pacote adicional, o cpio-2.13 e a criação de um initrd que precisará ser adicionado ao grub.cfg.

Não importa onde você prepara o initrd e, tão logo ele esteja funcionando, você pode aplicar o mesmo initrd a sistemas LFS posteriores ou a núcleos mais recentes na mesma máquina, ao menos até que algum microcódigo mais recente seja liberado. Use os seguintes comandos:

mkdir -p initrd/kernel/x86/microcode
cd initrd

Para uma máquina AMD, use o seguinte comando (substitua <MEUCONTEINER> pelo nome do contêiner para a família da sua CPU):

cp -v ../<MEU_CONTẼINER> kernel/x86/microcode/AuthenticAMD.bin

Ou, para uma máquina Intel, copie o blob apropriado usando este comando:

cp -v ../intel-ucode/<XX-YY-ZZ> kernel/x86/microcode/GenuineIntel.bin

Agora, prepare o initrd:

find . | cpio -o -H newc > /boot/microcode.img

Agora você precisa adicionar uma entrada nova a /boot/grub/grub.cfg e aqui você deveria adicionar uma linha nova depois da linha linux dentro da estância. Se /boot for um ponto de montagem separado:

initrd /microcode.img

ou isto, se ele não for:

initrd /boot/microcode.img

Se já estiver inicializando com um "initrd" (veja-se “A respeito do initramfs”), [então] você deveria executar mkinitramfs novamente depois de colocar o "blob" ou contêiner apropriado no /lib/firmware. Mais precisamente, coloque um "blob" "Intel" em um diretório /lib/firmware/intel-ucode ou um contêiner "AMD" em um diretório /lib/firmware/amd-ucode antes de executar mkinitramfs. Alternativamente, você pode ter ambos os "initrd" na mesma linha, tal como initrd /microcode.img /outro-initrd.img (adapte isso conforme acima se "/boot" não for um ponto de montagem separado).

Você agora pode reinicializar com o "initrd" adicionado e, então, usar o seguinte comando para verificar se o carregamento antecipado funcionou:

dmesg | grep -e 'microcode' -e 'Linux version' -e 'Command line'

Se atualizou para endereçar vulnerabilidades, [então] você pode olhar a saída gerada do comando lscpu para ver o que é informado agora.

Os locais e horários onde o carregamento antecipado acontece são muito diferentes em máquinas "AMD" e "Intel". Primeiro, um exemplo de uma "Intel" (dispositivo móvel "Icelake") com carregamento antecipado:

[    0.000000] microcode: microcode updated early to revision 0xb8, date = 2022-08-31
[    0.000000] Linux version 6.1.11 (xry111@stargazer) (gcc (GCC) 12.2.0, GNU ld (GNU Binutils) 2.40) #2 SMP PREEMPT_DYNAMIC Tue Feb 14 23:23:31 CST 2023
[    0.000000] Command line: BOOT_IMAGE=/vmlinuz-6.1.11-lfs-11.3-rc1 root=PARTUUID=<CLASSIFIED> ro
[    0.452924] microcode: sig=0x706e5, pf=0x80, revision=0xb8
[    0.453197] microcode: Microcode Update Driver: v2.2.

Um exemplo histórico 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.

Firmware para Placas de Vídeo

Firmware para chips de vídeo ATI (R600 e posteriores)

Estas instruções NÃO se aplicam aos antigos Radeons antes da família R600. Para aqueles, o firmware está no diretório do núcleo /lib/firmware/. Nem se aplicam se você pretender evitar uma configuração gráfica como o Xorg e estiver contente em usar a exibição padrão de 80x25 em vez de um framebuffer.

Os dispositivos iniciais Radeon precisavam somente de um blob de firmware de 2K. Os dispositivos recentes precisam de vários blobs e alguns deles são muito maiores. O tamanho total do diretório do firmware Radeon é de mais que 500K — em um sistema largo moderno você provavelmente pode poupar o espaço, porém ainda é redundante instalar todos os arquivos não usados a cada vez que construir um sistema.

Uma abordagem melhor é a de instalar o pciutils-3.9.0 e, então, usar o lspci para identificar qual controlador VGA está instalado.

Com essa informação, verifique a página "RadeonFeature" da "wiki" do "Xorg" para Decoder ring for engineering vs marketing names para identificar a família (você possivelmente precise saber disso para o controlador "Xorg" no BLFS — Ilhas do Sul e Ilhas do Mar usam o controlador "radeonsi") e o modelo específico.

Agora que você sabe qual controlador está usando, consulte a página Radeon da wiki do Gentoo a qual tem uma tabela listando os blobs de firmware exigidos para os vários chipsets. Observe que os chips das Ilhas do Sul e os das Ilhas do Mar usam firmware diferente para o núcleo 3.17 e posteriores comparados a núcleos anteriores. Identifique e baixe os blobs exigidos; então instale-os:

mkdir -pv /lib/firmware/radeon
cp -v <YOUR_BLOBS> /lib/firmware/radeon

Atualmente existem duas maneiras de instalar esse firmware. No BLFS, na seção 'Configuração do Núcleo para firmware adicional', parte da seção Controlador ATI do Xorg-19.1.0 dá um exemplo de compilar o firmware no núcleo - isso é ligeiramente mais rápido de carregar, porém usa mais memória do núcleo. Aqui nós usaremos o método alternativo de tornar o controlador Radeon um módulo. No seu config do núcleo, configure o seguinte:

Device Drivers --->
  Graphics support --->
      Direct Rendering Manager --->
        [*] Direct Rendering Manager (XFree86 ... support)  [CONFIG_DRM]
      [M] ATI Radeon                                        [CONFIG_DRM_RADEON]

O carregamento de vários blobs largos a partir de /lib/firmware toma um tempo notável, durante o qual a tela estará sem escrito. Se você não habilitar o logotipo pinguim do framebuffer ou mudar o tamanho do console usando uma fonte maior, [então] provavelmente isso não importa. Se desejado, você pode reduzir ligeiramente o tempo se seguir o método alternativo de especificar 'y' para CONFIG_DRM_RADEON coberto no BLFS no link acima — você precisa especificar cada blob Radeon necessário se fizer isso.

"Firmware" para chips de vídeo "amdgpu" "AMD"/"ATI"

Todos os controladores de vídeo que usam o controlador "amdgpu" do núcleo exigem "firmware", se você estará usando o controlador "amdgpu" do "Xorg", o controlador "modesetting" do "xserver" ou apenas o "modesetting" do núcleo para obter um "framebuffer" do console maior que "80x25".

Instale pciutils-3.9.0 e use-o para verificar o nome do modelo (procure por "VGA compatible controller:"). Se você tiver uma "Unidade de Processamento Acelerado" ("APU"), ou seja, "CPU" e vídeo no mesmo chip), provavelmente te dirá o nome. Se você tiver uma placa de vídeo "amdgpu" separada, [então] precisará pesquisar para determinar qual nome ela usa (por exemplo, uma placa descrita como "Advanced Micro Devices, Inc." ["AMD"/"ATI"] "Baffin" ["Radeon RX 550 640SP / RX 560/560X"] precisa de "firmware" "Polaris11". Existe uma tabela de "Família, nome do "Chipset", nome do Produto e Firmware" no final das seções "Kernel" na página AMDGPU do "wiki" do "Gentoo".

Depois que você tiver identificado o nome do "firmware", instale todos os arquivos relevantes para ele. Por exemplo, a placa "Baffin" mencionada acima tem vinte e um (21) arquivos "polaris11*", "APUs" como "renoir" e "picasso" tem pelo menos doze (12) arquivos e podem ganhar mais em atualizações futuras (por exemplo, a "APU" "raven" agora tem um décimo terceiro (13º) arquivo, "raven_ta.bin").

mkdir -pv /lib/firmware/amdgpu
cp -v <TEUS_BLOBS> /lib/firmware/amdgpu

Se espaço em disco não for um problema, [então] você poderá instalar todos os arquivos atuais de "firmware" "amdgpu" e não se preocupar exatamente com qual "chipset" está instalado.

É recomendado construir o controlador "amdgpu" do núcleo como um módulo. Em seu ".config" do núcleo configure pelo menos as seguintes opções e revise as outras opções "AMDGPU" de acordo com teu "hardware" alvo, por exemplo "Configuração ACP (Coprocessador de Áudio)":

Device Drivers --->
  Graphics support --->
      Direct Rendering Manager --->
        [*] Direct Rendering Manager (XFree86 ... support)  [CONFIG_DRM]
        [M] AMD GPU                                        [CONFIG_DRM_AMDGPU]
        Display Engine Configuration --->
          [*] AMD DC - Enable new display engine (NEW)      [CONFIG_DRM_AMD_DC]

Conforme escrito acima no final da seção sobre "Firmware para chips de vídeo ATI", carregar grandes "blobs" a partir de "/lib/firmware" pode levar um tempo perceptível durante o qual a tela ficará em branco. Em uma máquina lenta, você pode desejar consultar a parte "Configuração do Núcleo para "firmware" adicional" de Controlador AMDGPU do Xorg-23.0.0 e compilar todos os módulos exigidos internos ao núcleo para reduzir esse tempo, ao custo de usar mais memória do núcleo.

Firmware para chips de vídeo Nvidia

A "Nvidia" lançou "firmware" básico assinado para chips gráficos recentes, mas significativamente depois que os chips e os próprios controladores binários deles foram disponibilizados pela primeira vez. Para outros chips tem sido necessário extrair o "firmware" a partir do controlador binário.

Para informações mais exatas relativas a quais chips precisam de "firmware" extraído, veja-se https://nouveau.freedesktop.org/wiki/VideoAcceleration/#firmware.

Primeiro, o controlador de núcleo Nvidia precisa ser ativado:

Device Drivers --->
  Graphics support --->
      Direct Rendering Manager --->
        <*> Direct Rendering Manager (XFree86 ... support)  [CONFIG_DRM]
      <*/M> Nouveau (NVIDIA) cards                          [CONFIG_DRM_NOUVEAU]

Se o "firmware" necessário estiver disponível no diretório nvidia/ de "linux-firmware", [então] copie-o /lib/firmware/nouveau.

Se o "firmware" não tiver sido disponibilizado em "linux-firmware", para os chips antigos mencionados no link "nouveau" do "wiki" acima, [então] certifique-se de ter instalado Python-2.7.18 e execute os seguintes comandos:

wget https://raw.github.com/imirkin/re-vp2/master/extract_firmware.py
wget https://us.download.nvidia.com/XFree86/Linux-x86/325.15/NVIDIA-Linux-x86-325.15.run
sh NVIDIA-Linux-x86-325.15.run --extract-only
python2 extract_firmware.py
mkdir -p /lib/firmware/nouveau
cp -d nv* vuc-* /lib/firmware/nouveau/

Firmware para Interfaces de Rede de Comunicação

O núcleo gosta de carregar firmware para alguns controladores de rede de comunicação, particularmente aqueles originários do diretório da Realtek (o /lib/linux-firmware/rtl_nic/), porém geralmente eles aparentam funcionar sem isso. Sendo assim, você pode inicializar o núcleo; verificar dmesg para mensagens acerca desse firmware ausente; e, se necessário, baixar o firmware e colocá-lo no diretório especificado no /lib/firmware, de forma que ele será encontrado nas inicializações subsequentes. Observe que, com os núcleos atuais, isso funciona se ou não o controlador for compilado internamente ou construído como um módulo; não existe necessidade de construir esse firmware internamente ao núcleo. Aqui está um exemplo onde o controlador R8169 foi compilado internamente, porém o firmware não foi tornado disponível. Tão logo o firmware tenha sido fornecido, não existiu menção dele nas inicializações posteriores.

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)

Firmware para Outros Dispositivos

Identificar o firmware correto tipicamente exigirá que você instale o pciutils-3.9.0 e, então, use o lspci para identificar o dispositivo. Você deveria então procurar online para verificar qual módulo ele usa; qual firmware; e onde obter o firmware — nem todos eles estão no linux-firmware.

Se possível, você deveria iniciar usando uma conexão com fios quando inicializar pela primeira vez o seu sistema LFS. Para usar uma conexão sem fios, você precisará usar ferramentas de rede de comunicação, tais como Wireless Tools-29 e wpa_supplicant-2.10.

Países diferentes tem regulações diferentes acerca do uso do espectro de rádio dos dispositivos sem fios. Você pode instalar um firmware para fazer com que os dispositivos sem fios obedeçam às regulações locais de espectro, de forma que você não seria questionado(a) pela autoridade local ou não encontraria sua NIC sem fios atrapalhando as frequências de outros dispositivos (por exemplo, controles remotos). O firmware da base de dados regulatória pode ser baixado a partir de https://kernel.org/pub/software/network/wireless-regdb/. Para instalá-lo, simplesmente extraia o regulatory.db e o regulatory.db.p7s a partir do tarball no /lib/firmware. O ponto de acesso enviaria um código de país para a sua NIC sem fios e o wpa_supplicant-2.10 diria ao núcleo para carregar a regulação desse país a partir do regulatory.db; e impô-la.

Firmware possivelmente também seja necessário para outros dispositivos, tais como alguns controladores SCSI; adaptadores bluetooth; ou gravadores de TV. Os mesmos princípios se aplicam.