ucode15 ucode open know iwlwifi instalar check b43 linux-kernel linux-device-driver firmware

ucode - ¿Cómo sabe Linux Kernel dónde buscar el firmware del controlador?



instalar firmware debian 9 (4)

Estoy compilando un kernel personalizado bajo Ubuntu y estoy encontrando el problema de que mi kernel no parece saber dónde buscar el firmware. En Ubuntu 8.04, el firmware está vinculado a la versión del kernel de la misma manera que los módulos de controladores. Por ejemplo, kernel 2.6.24-24-generic almacena sus módulos de kernel en:

/lib/modules/2.6.24-24-generic

y su firmware en:

/lib/firmware/2.6.24-24-generic

Cuando compilo el kernel 2.6.24-24-genérico de Ubuntu de acuerdo con el " Método de compilación alternativo: la antigua forma de Debian ", obtengo el directorio de módulos apropiado y todos mis dispositivos funcionan excepto los que requieren firmware, como mi tarjeta inalámbrica Intel (ipw2200 módulo).

El registro del kernel muestra, por ejemplo, que cuando ipw2200 intenta cargar el firmware, el subsistema del kernel que controla la carga del firmware no puede ubicarlo:

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

errno-base.h define esto como:

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

(La función que devuelve ENOENT pone un signo menos delante.)

Intenté crear un enlace simbólico en / lib / firmware donde el nombre de mi kernel apuntaba al directorio 2.6.24-24-generic, sin embargo, esto resultó en el mismo error. Este firmware no es GPL, proporcionado por Intel y empaquetado por Ubuntu. No creo que tenga ningún vínculo real con una versión particular del kernel. cmp muestra que las versiones en los distintos directorios son idénticas.

Entonces, ¿cómo sabe el núcleo dónde buscar el firmware?

Actualizar

Encontré esta solución al problema exacto que tengo, sin embargo, ya no funciona, ya que Ubuntu eliminó /etc/hotplug.d y ya no almacena su firmware en /usr/lib/hotplug/firmware .

Actualización2

Un poco más de investigación encontró más respuestas. Hasta la versión 92 de udev , el programa firmware_helper era la forma en que se cargaba el firmware. A partir de udev 93, este programa fue reemplazado por un script llamado firmware.sh que proporciona una funcionalidad idéntica por lo que puedo decir. Ambos codifican la ruta del firmware a /lib/firmware . Ubuntu todavía parece estar utilizando el binario /lib/udev/firmware_helper .

El nombre del archivo de firmware se pasa a firmware_helper en la variable de entorno $FIRMWARE que se concatena a la ruta /lib/firmware y se usa para cargar el firmware.

La solicitud real para cargar el firmware la realiza el controlador (ipw2200 en mi caso) a través de la llamada al sistema:

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

Ahora en algún lugar entre el controlador que llama request_firmware y firmware_helper mirando la variable de entorno $FIRMWARE , el nombre del paquete del kernel se está prefijando al nombre del firmware.

Entonces, ¿quién lo está haciendo?


Desde la perspectiva del kernel, vea /usr/src/linux/Documentation/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.

El kernel en realidad no carga ningún firmware. Simplemente informa al espacio de usuario, "Quiero un firmware con el nombre de xxx ", y espera que el espacio de usuario vuelva a colocar la imagen del firmware en el núcleo.

Ahora, en Ubuntu 8.04,

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

por lo que ha descubierto, udev está configurado para ejecutar firmware_helper cuando el núcleo solicita 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

Si lee la fuente, encontrará que Ubuntu escribió un firmware_helper que está codificado para buscar primero /lib/modules/$(uname -r)/$FIRMWARE , luego /lib/modules/$FIRMWARE , y no otros lugares. Traduciéndolo a sh , hace aproximadamente esto:

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 es exactamente el formato que espera el kernel.

Para udev : el paquete udev de Ubuntu tiene personalizaciones que siempre buscan primero en /lib/firmware/$(uname -r) . Esta política se está manejando en el espacio de usuario.


En los sistemas Linux actuales, esto se maneja a través de udev y el firmware.agent .


Linux 3.5.7 Gentoo, tengo el mismo problema. Resuelto:

emerge ipw2200-firmware

Luego ve a / usr / src / linux

make menucofig

en el controlador del dispositivo, elimine todos los controladores inalámbricos que no sean necesarios, configure el Intell 2200 como módulo y vuelva a compilarlo.

make make modules_install cp arch/x86/boot/bzImage /boot/kernel-yourdefault


Wow, esta es una información muy útil y me llevó a la solución para mi problema al crear un módulo de kernel USB personalizado para un dispositivo que requiera firmware.

Básicamente, cada Ubuntu trae una nueva repetición de hal, sysfs, devfs, udev, etc., y las cosas simplemente cambian. De hecho, leí que dejaron de usar hal.

Así que vamos a aplicar ingeniería inversa de nuevo para que sea pertinente a los últimos sistemas [Ubuntu].

En Ubuntu Lucid (lo último al momento de escribir), se usa /lib/udev/rules.d/50-firmware.rules . Este archivo llama al binario /lib/udev/firmware , donde ocurre la magia.

Listado: /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}"

La magia debería ser algo así (fuente: Controladores de dispositivos de Linux, 3ª edición, Capítulo 14: El modelo de dispositivo de Linux ):

  • echo 1 a la loading
  • copiar firmware a los data
  • en caso de fallo, echo -1 para loading y detener el proceso de carga de firmware
  • echo 0 a la loading (señal del kernel)
  • Entonces, un módulo específico del kernel recibe los datos y los envía al dispositivo.

Si observa la página de origen de Lucid para udev, en udev-151/extras/firmware/firmware.c , la fuente de ese binario de firmware / lib / udev / firmware, eso es exactamente lo que sucede.

Extracto: fuente lúcida, 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");

Además, muchos dispositivos utilizan un formato Intel HEX (archivos textuales que contienen suma de comprobación y otras cosas) (wiki no tengo reputación ni capacidad de vincular). El programa del kernel ihex2fw (llamado desde Makefile en kernel_source / lib / firmware en archivos .HEX) convierte estos archivos HEX a un formato binario de diseño arbitrario que el kernel de Linux recoge con request_ihex_firmware , porque pensaban que leer archivos de texto en el kernel era tonto (ralentizaría las cosas).