Pergunta

Estou compilando um kernel personalizado no Ubuntu e estou enfrentando o problema que meu kernel parece não saber onde procurar firmware. No Ubuntu 8.04, o firmware está vinculado à versão do kernel da mesma maneira que os módulos de driver. Por exemplo, o kernel 2.6.24-24-genérico armazena seus módulos de kernel em:

/lib/modules/2.6.24-24-generic

e seu firmware em:

/lib/firmware/2.6.24-24-generic

Quando compilar o kernel do Ubuntu 2.6.24-24-genérico de acordo com o "Método de construção alternativa: a maneira antiga do Debian"Eu recebo o diretório de módulos apropriado e todos os meus dispositivos funcionam, exceto aqueles que exigem firmware como meu cartão sem fio Intel (módulo IPW2200).

O log do kernel mostra, por exemplo, que quando o IPW2200 tenta carregar o firmware, o subsistema do kernel que controla o carregamento do firmware não consegue localizá -lo:

ipw2200: Detected Intel PRO/Wireless 2200BG Network Connection
ipw2200: ipw2200-bss.fw request_firmware failed: Reason -2

errno-Base.h define isso como:

#define ENOENT       2  /* No such file or directory */

(A função que retorna a Enoent coloca um menos na frente dela.)

Tentei criar um link simbólico em /lib /firmware, onde o nome do meu kernel apontou para o diretório genérico 2.6.24-24, no entanto, isso resultou no mesmo erro. Este firmware não é GPL, fornecido pela Intel e embalado pelo Ubuntu. Não acredito que tenha algum vínculo real com uma versão específica do kernel. cmp mostra que as versões nos vários diretórios são idênticas.

Então, como o kernel sabe onde procurar firmware?

Atualizar

eu encontrei esta solução Para o problema exato que estou tendo, no entanto, não funciona mais, pois o Ubuntu eliminou /etc/hotplug.d e não armazena mais seu firmware em /usr/lib/hotplug/firmware.

Atualização2

Algumas pesquisas revelaram mais algumas respostas. Até a versão 92 de udev, o programa firmware_helper Foi a maneira como o firmware foi carregado. Começando com udev 93 Este programa foi substituído por um script chamado Firmware.sh, fornecendo funcionalidade idêntica, tanto quanto eu sei. Ambos os codificam o caminho do firmware para /lib/firmware. Ubuntu ainda parece estar usando o /lib/udev/firmware_helper binário.

O nome do arquivo de firmware é passado para firmware_helper na variável do ambiente $FIRMWARE que é concatenado para o caminho /lib/firmware e usado para carregar o firmware.

A solicitação real para carregar o firmware é feita pelo driver (IPW2200 no meu caso) através da chamada do sistema:

request_firmware(..., "ipw2200-bss.fw", ...);

Agora em algum lugar entre o motorista chamando request_firmware e firmware_helper Olhando para o $FIRMWARE Variável de ambiente, o nome do pacote do kernel está sendo preso ao nome do firmware.

Então, quem está fazendo isso?

Foi útil?

Solução

Da perspectiva do kernel, veja /usr/src/linux/documentação/firmware_class/readme:

 kernel(driver): calls request_firmware(&fw_entry, $FIRMWARE, device)

 userspace:
        - /sys/class/firmware/xxx/{loading,data} appear.
        - hotplug gets called with a firmware identifier in $FIRMWARE
          and the usual hotplug environment.
                - hotplug: echo 1 > /sys/class/firmware/xxx/loading

 kernel: Discard any previous partial load.

 userspace:
                - hotplug: cat appropriate_firmware_image > \
                                        /sys/class/firmware/xxx/data

 kernel: grows a buffer in PAGE_SIZE increments to hold the image as it
         comes in.

 userspace:
                - hotplug: echo 0 > /sys/class/firmware/xxx/loading

 kernel: request_firmware() returns and the driver has the firmware
         image in fw_entry->{data,size}. If something went wrong
         request_firmware() returns non-zero and fw_entry is set to
         NULL.

 kernel(driver): Driver code calls release_firmware(fw_entry) releasing
                 the firmware image and any related resource.

O kernel não carrega nenhum firmware. Simplesmente informa o espaço do usuário: "Eu quero um firmware pelo nome de xxx", e aguarda o espaço para os usuários colocar a imagem do firmware de volta ao kernel.

Agora, no Ubuntu 8.04,

$ grep firmware /etc/udev/rules.d/80-program.rules
# Load firmware on demand
SUBSYSTEM=="firmware", ACTION=="add", RUN+="firmware_helper"

Então, como você descobriu, udev está configurado para correr firmware_helper Quando o kernel pede firmware.

$ apt-get source udev
Reading package lists... Done
Building dependency tree
Reading state information... Done
Need to get 312kB of source archives.
Get:1 http://us.archive.ubuntu.com hardy-security/main udev 117-8ubuntu0.2 (dsc) [716B]
Get:2 http://us.archive.ubuntu.com hardy-security/main udev 117-8ubuntu0.2 (tar) [245kB]
Get:3 http://us.archive.ubuntu.com hardy-security/main udev 117-8ubuntu0.2 (diff) [65.7kB]
Fetched 312kB in 1s (223kB/s)
gpg: Signature made Tue 14 Apr 2009 05:31:34 PM EDT using DSA key ID 17063E6D
gpg: Can't check signature: public key not found
dpkg-source: extracting udev in udev-117
dpkg-source: unpacking udev_117.orig.tar.gz
dpkg-source: applying ./udev_117-8ubuntu0.2.diff.gz
$ cd udev-117/
$ cat debian/patches/80-extras-firmware.patch

Se você ler a fonte, você descobrirá que o Ubuntu escreveu um firmware_helper que é codificado para primeiro procurar /lib/modules/$(uname -r)/$FIRMWARE, então /lib/modules/$FIRMWARE, e nenhum outro local. Traduzindo para sh, faz aproximadamente isso:

echo -n 1 > /sys/$DEVPATH/loading
cat /lib/firmware/$(uname -r)/$FIRMWARE > /sys/$DEVPATH/data \
    || cat /lib/firmware/$FIRMWARE      > /sys/$DEVPATH/data
if [ $? = 0 ]; then
    echo -n  1 > /sys/$DEVPATH/loading
    echo -n -1 > /sys/$DEVPATH/loading
fi

que é exatamente o formato que o kernel espera.


Para encurtar uma longa história: Ubuntu's udev o pacote tem personalizações que sempre olham /lib/firmware/$(uname -r) primeiro. Esta política está sendo tratada no espaço do usuário.

Outras dicas

Uau, isso é uma informação muito útil e me levou à solução para o meu problema ao fazer um módulo de kernel USB personalizado para um dispositivo que requer firmware.

Basicamente, todo Ubuntu traz uma nova rehash de hal, sysfs, devfs, udev e assim por diante ... e as coisas simplesmente mudam. Na verdade, eu li que eles pararam de usar o HAL.

Então, vamos engenharia reversa mais uma vez, para que seja pertinente aos mais recentes sistemas [Ubuntu].

No Ubuntu Lucid (o mais recente no momento da redação), /lib/udev/rules.d/50-firmware.rules é usado. Este arquivo chama o binário /lib/udev/firmware, onde a magia acontece.

Listagem: /lib/udev/rules.d/50-firmware.rules

# firmware-class requests, copies files into the kernel
SUBSYSTEM=="firmware", ACTION=="add", RUN+="firmware --firmware=$env{FIRMWARE} --devpath=$env{DEVPATH}"

A magia deve ser algo nesse sentido (fonte: Drivers de dispositivo Linux, 3ª ed., Ch. 14: O modelo de dispositivo Linux):

  • eco 1 para loading
  • Copie o firmware para data
  • no fracasso, eco -1 para loading e interromper o processo de carregamento de firmware
  • eco 0 para loading (sinalize o kernel)
  • Em seguida, um módulo de kernel específico recebe os dados e o empurra para o dispositivo

Se você olhar para a página de origem de Lucid para Udev, em udev-151/extras/firmware/firmware.c, a fonte para esse binário de firmware/lib/udev/firmware, é exatamente o que acontece.

Trecho: Lucid Source, UDEV-151/Extras/Firmware/Firmware.c

    util_strscpyl(datapath, sizeof(datapath), udev_get_sys_path(udev), devpath, "/data", NULL);
    if (!copy_firmware(udev, fwpath, datapath, statbuf.st_size)) {
            err(udev, "error sending firmware '%s' to device\n", firmware);
            set_loading(udev, loadpath, "-1");
            rc = 4;
            goto exit;
    };

    set_loading(udev, loadpath, "0");

Além disso, muitos dispositivos usam um formato Intel Hex (arquivos textish contendo soma de verificação e outras coisas) (Wiki It Não tenho reputação e nenhuma capacidade de vincular). O Programa Kernel IHEX2FW (chamado From Makefile em Kernel_source/lib/firmware em arquivos .hex) converte esses arquivos hexadecimais em um formato binário projetado por arbitrário que o kernel Linux então pega com com request_ihex_firmware, porque eles pensavam que ler arquivos de texto no kernel era bobo (diminuiria as coisas).

On current Linux systems, this is handled via udev and the firmware.agent.

Linux 3.5.7 Gentoo, I have the same issue. SOLVED:

emerge ipw2200-firmware

Then go to /usr/src/linux

make menucofig

on device driver, remove all wirless drivers don't needed, set Intell 2200 as module and recompile.

make
make modules_install
cp arch/x86/boot/bzImage /boot/kernel-yourdefault
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top