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 micrologiciel est lié à la version du noyau de la même manière que les modules de pilotes. 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
Lorsque je compile le noyau Ubuntu générique 2.6.24-24 selon la " méthode de construction alternative: l'ancienne méthode Debian " j'obtiens le répertoire de modules approprié et tous mes périphériques fonctionnent à l'exception de ceux nécessitant un firmware tel que comme ma carte sans fil Intel (module ipw2200).
Le journal du noyau montre par exemple que lorsque ipw2200 essaie 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:
#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 générique 2.6.24-24, mais cela a entraîné la même erreur. Ce firmware n'est pas GPL, fourni par Intel et emballé par Ubuntu. Je ne pense pas qu'il ait un lien réel avec une version particulière du noyau. cmp
montre que les versions des différents répertoires sont identiques.
Alors, comment le noyau sait-il où chercher le firmware?
Mise à jour
J'ai trouvé cette solution au problème exact 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
Quelques recherches supplémentaires ont permis de trouver d'autres réponses. Jusqu'à la version 92 de udev
, le programme firmware_helper
était la façon dont le firmware était chargé. À partir de udev
93 ce programme a été remplacé par un script nommé firmware.sh fournissant des fonctionnalités identiques pour autant que je sache. Ces deux codent en dur le chemin du micrologiciel vers /lib/firmware
. Ubuntu semble toujours utiliser le /lib/udev/firmware_helper
binaire.
Le nom du fichier du firmware est transmis à firmware_helper
dans la variable d'environnement $FIRMWARE
qui est concaténé au chemin /lib/firmware
et utilisé 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 le $FIRMWARE
variable d'environnement, le nom du package du noyau est ajouté au nom du micrologiciel.
Alors qui le fait?
Du point de vue du noyau, voir / usr/src/linux/Documentation/firmware_class/README :
noyau (pilote): appelle request_firmware (& fw_entry, $ FIRMWARE, périphérique) espace utilisateur: -/sys/class/firmware/xxx/{loading, data} apparaissent. - hotplug est appelé avec un identifiant de firmware dans $ FIRMWARE et l'environnement hotplug habituel. - hotplug: echo 1>/sys/class/firmware/xxx /loading[.____. noyau: Jeter toute charge partielle précédente. espace utilisateur: - hotplug: cat appropri_firmware_image>\ /sys/class/firmware/xxx/data noyau: agrandit un tampon par incréments de PAGE_SIZE pour contenir l'image à mesure que entre. espace utilisateur: - hotplug: echo 0> /sys/class/firmware/xxx/loading[.____. noyau: request_firmware () renvoie et le pilote a le firmware image dans fw_entry -> {data, size}. Si quelque chose s'est mal passé Request_firmware () renvoie différent de zéro et fw_entry est défini sur NULL. Noyau (pilote): le code du pilote appelle release_firmware (fw_entry) libérer l'image du micrologiciel et toute ressource connexe.
Le noyau ne charge en fait aucun firmware. Il informe simplement l'espace utilisateur, "Je veux un firmware du nom de xxx ", et attend que l'espace utilisateur redirige l'image du firmware vers le noyau.
Maintenant, sur Ubuntu 8.04,
$ grep firmware /etc/udev/rules.d/80-program.rules[.____.[# Charger le firmware sur demande SUBSYSTEM == "firmware", ACTION == "add" , RUN + = "firmware_helper"
comme vous l'avez découvert, udev
est configuré pour exécuter firmware_helper
lorsque le noyau demande un firmware.
$ apt-get source udev Lecture des listes de packages ... Terminé Construction de l'arborescence des dépendances Lecture des informations d'état ... Terminé Besoin de obtenir 312 Ko d'archives sources. Obtenir: 1 http://us.archive.ubuntu.com hardy-security/main udev 117-8ubuntu0.2 (dsc) [716B] Obtenir: 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] Récupéré 312kB en 1s (223kB/s) gpg: Signature faite le mardi 14 avril 2009 05:31:34 PM EDT utilisant l'ID de clé DSA 17063E6D Gpg: impossible de vérifier la signature: clé publique introuvable Dpkg-source: extraction d'udev dans udev-117 dpkg-source: déballage de udev_117.orig.tar.gz dpkg-source: application ./udev_117-8ubuntu0.2.diff.gz[.____.[$ cd udev-117 /[.____.ram$ cat debian/patches/80-extras-firmware.patch
Si vous lisez la source, vous constaterez qu'Ubuntu a écrit un firmware_helper
Qui est codé en dur pour rechercher d'abord /lib/modules/$(uname -r)/$FIRMWARE
, puis /lib/modules/$FIRMWARE
, Et aucun autre emplacement. Le traduire 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 package udev
d'Ubuntu a des personnalisations qui apparaissent toujours dans /lib/firmware/$(uname -r)
en premier. Cette politique est gérée dans l'espace utilisateur.
Wow, ce sont des informations très utiles 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 une nouvelle refonte de hal, sysfs, devfs, udev, etc. ... et les choses changent simplement. En fait, j'ai lu qu'ils avaient cessé d'utiliser hal.
Donc, inversons encore une fois l'ingénierie afin qu'elle soit pertinente pour les derniers systèmes [Ubuntu].
Sur Ubuntu Lucid (la dernière 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 opère.
Liste: /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 magie devrait être quelque chose dans ce sens (source: Linux Device Drivers, 3rd Ed., Ch. 14: The Linux Device Model ):
loading
data
loading
et arrêt du processus de chargement du firmware loading
(signalez le noyau) 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 Lucid, 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 textuels contenant une somme de contrôle et d'autres choses) (wiki, je n'ai aucune réputation et aucune capacité de lien). Le programme du noyau ihex2fw (appelé depuis Makefile dans kernel_source/lib/firmware sur les fichiers .HEX) convertit ces fichiers HEX en un format binaire de conception arbitraire que le noyau Linux récupère ensuite avec request_ihex_firmware
, car ils pensaient que lire des fichiers texte dans le noyau était idiot (cela ralentirait les choses).
Linux 3.5.7 Gentoo, j'ai le même problème. RESOLU:
emerge ipw2200-firmware
Allez ensuite dans/usr/src/linux
make menucofig
sur le pilote de périphérique, supprimez tous les pilotes sans fil inutiles, définissez Intell 2200 comme module et recompilez.
make
make modules_install
cp Arch/x86/boot/bzImage /boot/kernel-yourdefault
Sur les systèmes Linux actuels, cela est géré via udev
et le firmware.agent
.