Comment le noyau Linux sait où chercher firmware du pilote?
-
09-09-2019 - |
Question
Je compile un noyau personnalisé sous Ubuntu et je suis en cours d'exécution dans le problème que mon noyau ne semble pas savoir où chercher firmware. Sous Ubuntu 8.04, le firmware est lié à la version du noyau les mêmes modules de pilotes sont ainsi. Par exemple, le noyau 2.6.24-24-générique 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 générique selon Autre construction du « Debian » je reçois le répertoire des modules appropriés et travailler tous mes appareils sauf ceux qui ont besoin du firmware tels que ma carte sans fil Intel (module ipw2200)
.Le journal du noyau montre par exemple que lorsque ipw2200 tente de charger le firmware du 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 comme:
#define ENOENT 2 /* No such file or directory */
(La fonction de retour ENOENT met un signe moins en face d'elle.)
J'ai essayé de créer un lien symbolique dans / lib / firmware où le nom de mon noyau a dans le répertoire 2.6.24-24-générique, mais cela a donné lieu à la même erreur. Ce firmware est non-GPL, fourni par Intel et emballé par Ubuntu. Je ne crois pas qu'il y ait aucun lien réel à une version particulière du noyau. cmp
montre que les versions dans les différents répertoires sont identiques.
Alors, comment le noyau sait où chercher firmware?
Mise à jour
J'ai trouvé cette solution au problème exact que je vais avoir, mais il ne fonctionne plus comme Ubuntu a éliminé /etc/hotplug.d
et ne stocke son firmware dans /usr/lib/hotplug/firmware
.
Update2
Un peu plus recherche a révélé de plus de réponses. Jusqu'à la version 92 de udev
, le programme firmware_helper
était le firmware de manière obtenu chargé. A partir de 93 udev
ce programme a été remplacé par un script nommé firmware.sh fournissant des fonctionnalités identiques pour autant que je peux dire. Ces deux hardcode le chemin du firmware pour /lib/firmware
. Ubuntu semble encore être en utilisant le binaire /lib/udev/firmware_helper
.
Le nom du fichier du firmware est passé à firmware_helper
dans l'environnement $FIRMWARE
variable qui est concaténer le chemin /lib/firmware
et utilisé pour charger le firmware.
La demande réelle pour charger le firmware est fait par le conducteur (ipw2200 dans mon cas) via l'appel système:
request_firmware(..., "ipw2200-bss.fw", ...);
quelque part entre le conducteur appelant request_firmware
et firmware_helper
regardant la variable d'environnement $FIRMWARE
, le nom du package du noyau est obtenir le nom ajouté au début du firmware.
Alors qui le fait?
La solution
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 fait charger tout firmware du tout. Il informe simplement l'espace utilisateur, « Je veux un firmware par le nom de xxx », et attend l'espace utilisateur à la conduite de 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"
afin que vous avez découvert, udev
est configuré pour exécuter firmware_helper
lorsque le noyau 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 verrez que 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 qu'aucun autre endroit. Traduire à sh
, il fait à peu près 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
ce qui est exactement le format que le noyau attend.
Pour faire une histoire courte: paquet de udev
Ubuntu a personnalisations qui semblent toujours /lib/firmware/$(uname -r)
d'abord. Cette politique est en cours de traitement dans l'espace utilisateur.
Autres conseils
Wow ce qui est très utile et des informations m'a conduit à la solution à mon problème lors d'un module noyau USB personnalisé pour un appareil nécessitant le firmware.
Fondamentalement, chaque Ubuntu apporte une nouvelle mouture de hal, sysfs, devfs, udev, et ainsi de suite ... et les choses changer. En fait, je lis, ils ont cessé d'utiliser hal.
Alors l'ingénieur Inversez cette fois encore il est pertinent aux derniers [Ubuntu] systèmes.
Ubuntu Lucid (la dernière au moment de la rédaction), /lib/udev/rules.d/50-firmware.rules
est utilisé. Ce fichier appelle le /lib/udev/firmware
binaire, où la magie se produit.
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 doit être quelque chose le long de ces lignes (source:. Pilotes de périphériques Linux, 3ème Ed, Ch . 14: Le modèle de périphérique Linux ):
- echo 1 à
loading
- firmware de copie à
data
- en cas d'échec, l'écho de -1 à
loading
et le processus de chargement du micrologiciel d'arrêt - echo 0 à
loading
(signaler le noyau) - puis, un module noyau spécifique reçoit les données et le pousse à l'appareil
Si vous regardez la page source de Lucid pour udev, dans udev-151/extras/firmware/firmware.c
, la source de ce firmware / lib / udev / binaire du firmware, qui 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");
En outre, de nombreux appareils utilisent un format Intel HEX (fichiers contenant textish somme de contrôle et d'autres choses) (wiki Je n'ai pas la réputation et pas la possibilité de créer un lien). Le programme du noyau ihex2fw (appelé de Makefile dans kernel_source / lib / firmware sur les fichiers HEX) convertit ces fichiers HEX à un format binaire arbitraire conçu que le noyau Linux prend alors avec request_ihex_firmware
, parce qu'ils pensaient que la lecture de fichiers texte dans le noyau était idiot (il ralentirait les choses).
Sur les systèmes Linux actuels, cela est géré par udev
et firmware.agent
.
Linux 3.5.7 Gentoo, j'ai le même problème. RESOLU:
emerge ipw2200-firmware
Ensuite, allez dans / usr / src / linux
make menucofig
sur pilote de périphérique, supprimer tous les pilotes wirless ne sont pas nécessaires, réglez Intelli 2200 en tant que module et recompiler.
make
make modules_install
cp arch/x86/boot/bzImage /boot/kernel-yourdefault