Comment le noyau Linux sait-Il où chercher le firmware du pilote?
Je compile un noyau personnalisé sous Ubuntu et je rencontre le problème que mon noyau ne semble pas savoir où chercher le firmware. Sous Ubuntu 8.04, le firmware est lié à la version du noyau de la même manière que les modules du pilote. Par exemple, le noyau 2.6.24-24-generic stocke ses modules du noyau dans:
/lib/modules/2.6.24-24-generic
Et son firmware dans:
/lib/firmware/2.6.24-24-generic
Quand je compile le noyau Ubuntu 2.6.24-24-generic selon la " méthode de construction alternative: L'ancienne Debian Way " j'obtiens le répertoire de modules approprié et tous mes appareils fonctionnent sauf ceux nécessitant un firmware tel que ma carte sans fil Intel (module ipw2200).
Le Journal du noyau montre par exemple que lorsque ipw2200 tente de charger le firmware, le sous-système du noyau contrôlant le chargement du firmware est incapable de le localiser:
ipw2200: Detected Intel PRO/Wireless 2200BG Network Connection
ipw2200: ipw2200-bss.fw request_firmware failed: Reason -2
Errno-base.h définit ceci comme suit:
#define ENOENT 2 /* No such file or directory */
(la fonction renvoyant ENOENT met un moins devant elle.)
J'ai essayé de créer un lien symbolique dans / lib / firmware où le nom de mon noyau pointait vers le répertoire 2.6.24-24-generic, cependant cela a entraîné la même erreur. Ce firmware est non-GPL, fourni par Intel et emballé par Ubuntu. Je ne crois pas qu'il ait un lien réel avec une version particulière du noyau. cmp
montre que les versions dans les différents répertoires sont identiques.
Alors, comment le noyau sait - il où chercher le firmware?
Mise à Jour
, j'ai trouvé cette solution exacte problème que j'ai, mais cela ne fonctionne plus car Ubuntu a éliminé /etc/hotplug.d
et ne stocke plus son firmware dans /usr/lib/hotplug/firmware
.
Update2
D'autres recherches ont trouvé d'autres réponses. Jusqu'à la version 92 de udev
, le programme firmware_helper
a la manière du micrologiciel suis chargé. Commençant par udev
93 ce programme a été remplacé par un script nommé firmware.sh fournir des fonctionnalités identiques pour autant que je sache. Ces deux codent en dur le chemin du firmware vers /lib/firmware
. Ubuntu semble toujours utiliser le binaire /lib/udev/firmware_helper
.
Le nom du fichier firmware est passé à firmware_helper
dans la variable d'environnement $FIRMWARE
qui est concaténée au chemin /lib/firmware
et utilisée pour charger le firmware.
La demande réelle de chargement du firmware est faite par le pilote (ipw2200 dans mon cas) via l'appel système:
request_firmware(..., "ipw2200-bss.fw", ...);
Maintenant, quelque part entre le pilote appelant request_firmware
et firmware_helper
en regardant la variable d'environnement $FIRMWARE
, le nom du paquet du noyau est obtenir ajouté au nom du firmware.
Alors qui le fait?
4 réponses
Du point de vue du noyau, voir /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.
Le noyau ne Charge aucun firmware. Il informe simplement userspace ," je veux un firmware du nom de xxx ", et attend que userspace redirige l'image du firmware vers le noyau.
Maintenant, sur Ubuntu 8.04,
$ grep firmware /etc/udev/rules.d/80-program.rules # Load firmware on demand SUBSYSTEM=="firmware", ACTION=="add", RUN+="firmware_helper"
Donc, comme vous l'avez découvert, {[4] } est configuré pour exécuter firmware_helper
lorsque le noyau le demande 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 vous lisez la source, vous constaterez Qu'Ubuntu a écrit un {[5] } qui est codé en dur pour rechercher d'abord /lib/modules/$(uname -r)/$FIRMWARE
, puis /lib/modules/$FIRMWARE
, et aucun autre emplacement. En le traduisant en sh
, Il fait approximativement ceci:
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
Qui est exactement le format attendu par le noyau.
Pour faire court: le paquet udev
D'Ubuntu a des personnalisations qui regardent toujours /lib/firmware/$(uname -r)
en premier. Cette stratégie est gérée dans l'espace utilisateur.
Wow c'est une information très utile et cela m'a conduit à la solution de mon problème lors de la création d'un module de noyau USB personnalisé pour un périphérique nécessitant un firmware.
Fondamentalement, chaque Ubuntu apporte un nouveau ressaisissement de hal, sysfs, devfs,udev, et ainsi de suite...et les choses changent. En fait, j'ai lu qu'ils ont cessé d'utiliser hal.
Alors, faisons de l'ingénierie inverse encore une fois, donc c'est pertinent pour les derniers systèmes [Ubuntu].
Sur Ubuntu Lucid (le dernier au moment de la rédaction), /lib/udev/rules.d/50-firmware.rules
est utilisé. Ce fichier appelle le binaire /lib/udev/firmware
, où la magie se produit.
Liste:/lib/udev / règles.d / 50-firmware.règles
# firmware-class requests, copies files into the kernel
SUBSYSTEM=="firmware", ACTION=="add", RUN+="firmware --firmware=$env{FIRMWARE} --devpath=$env{DEVPATH}"
La magie devrait être quelque chose dans ce sens (source: pilotes de périphériques Linux, 3e éd., Ch. 14: Le Modèle De Périphérique Linux):
- echo 1 à
loading
- copier le micrologiciel vers
data
- en cas d'échec, echo -1 à
loading
et arrêter le processus de chargement du firmware - echo 0 à
loading
(signaler le noyau) - alors, un module de noyau spécifique reçoit les données et les pousse vers le périphérique
Si vous regardez la page source de Lucid pour udev, dans udev-151/extras/firmware/firmware.c
, la source de ce binaire firmware /lib/udev/firmware, c'est exactement ce qui se passe.
Extrait: Source lucide, 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");
De plus, de nombreux appareils utilisent un format Intel HEX (fichiers textish contenant la somme de contrôle et d'autres choses) (wiki Je n'ai aucune réputation et aucune capacité à lier). Le programme du noyau ihex2fw (appelé à partir de Makefile dans kernel_source/lib / firmware sur .Fichiers hexadécimaux) convertit ces fichiers hexadécimaux en un format binaire de conception arbitraire que le noyau Linux récupère ensuite avec request_ihex_firmware
, car ils pensaient que la lecture de fichiers texte dans le noyau était stupide (cela ralentirait les choses).
Sur les systèmes Linux actuels, ceci est géré via udev
et le firmware.agent
.
Linux 3.5.7 Gentoo, j'ai le même problème. Résolu:
emerge ipw2200-firmware
Ensuite, allez dans /usr/src / linux
make menucofig
Sur le pilote de périphérique, supprimez tous les pilotes wirless qui ne sont pas nécessaires, définissez Intell 2200 comme module et recompilez.
make
make modules_install
cp arch/x86/boot/bzImage /boot/kernel-yourdefault