51 votes

Comment le noyau Linux sait-il où chercher le microprogramme du pilote?

Je suis à la compilation d'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 pour le firmware. Sous Ubuntu 8.04, le firmware est lié à la version du noyau de la même façon les modules de 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:

/lib/firmware/2.6.24-24-generic

Quand je compile le 2.6.24-24-generic Ubuntu kernel selon le "Suppléant Construire la Méthode: à L'Ancienne, Façon Debian" je obtenir les modules de répertoire et de tous mes appareils fonctionnent à l'exception de ceux nécessitant le firmware comme ma carte wifi Intel (module ipw2200).

Le noyau historique montre par exemple que, lorsque ipw2200 essaie de charger le firmware, le sous-système du noyau en contrôlant le chargement du firmware est incapable de la localiser:

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

errno-base.h se définit comme:

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

(La fonction de retour ENOENT met un moins devant de lui.)

J'ai essayé de créer un lien symbolique dans /lib/firmware où mon noyau du nom souligné le 2.6.24-24-generic directory, cependant cela a abouti à la même erreur. Ce firmware est non-GPL, fourni par Intel et emballé par Ubuntu. Je ne crois pas qu'elle ait une réelle égalité à une version du noyau. cmp montre que les versions dans les différents répertoires sont identiques.

Alors, comment fonctionne le noyau de savoir où chercher pour le firmware?

Mise à jour

J'ai trouvé cette solution pour le problème exact, je vais avoir, mais il ne fonctionne plus comme Ubuntu a éliminé /etc/hotplug.d et ne stocke plus de son firmware en /usr/lib/hotplug/firmware.

Update2

Un peu plus de recherche sont plus de réponses. Jusqu'à la version de 92 udev, le programme firmware_helper a été la façon dont le firmware a obtenu chargé. En commençant par udev 93 ce programme a été remplacé par un script nommé firmware.sh fournir des fonctionnalités identiques à ce que j'en dis. Ces deux coder en dur le firmware chemin de /lib/firmware. Ubuntu semble toujours être à l'aide de l' /lib/udev/firmware_helper binaire.

Le nom du fichier du micrologiciel est passé de firmware_helper dans la variable d'environnement $FIRMWARE qui est concaténé à la path /lib/firmware et utilisé pour charger le firmware.

La demande réelle pour charger le firmware est effectué 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 à la recherche à l' $FIRMWARE variable d'environnement, le noyau nom du package est l'obtention de préfixer le nom du micrologiciel.

Alors, qui de le faire?

41voto

ephemient Points 87003

À partir du noyau de la perspective, consultez /usr/src/linux/Documentation/firmware_class/README:

 noyau(pilote): les appels request_firmware(&fw_entry, $FIRMWARE, l'appareil)

utilisateur:
 - /sys/class/firmware/xxx/{chargement,les données} apparaissent.
 - hotplug est appelée avec un firmware identificateur $FIRMWARE
 et l'habitude de branchement à chaud de l'environnement.
 - hotplug: echo 1 > /sys/class/firmware/xxx/chargement

 noyau: Jetez tout précédent en charge partielle.

utilisateur:
 - hotplug: chat appropriate_firmware_image > \
/sys/class/firmware/xxx/données

 noyau: il pousse un tampon dans PAGE_SIZE incréments de tenir l'image
 vient dans.

utilisateur:
 - hotplug: echo 0 > /sys/class/firmware/xxx/chargement

 noyau: request_firmware() renvoie et que le conducteur a le firmware
 image dans fw_entry->{données,la taille de l'}. Si quelque chose s'est mal passé
 request_firmware() renvoie zéro et fw_entry est fixé à
La valeur NULL.

 noyau(pilote): code de Pilote appelle release_firmware(fw_entry) la libération
 l'image du microprogramme et des ressources.

Le noyau n'a pas fait de charger un firmware à tous. Il informe simplement de l'espace utilisateur, "je veux un firmware par le nom de xxx", et attend de l'espace utilisateur pour tuyau de l'image du microprogramme vers le noyau.

Maintenant, sur Ubuntu 8.04,

$ grep firmware /etc/udev/rules.d/80-programme.les règles
# Charger un firmware sur demande
SUBSYSTEM=="firmware", ACTION=="add", RUN+="firmware_helper"

donc, comme vous l'avez découvert, udev est configuré pour s'exécuter en firmware_helper lorsque le noyau demande pour le firmware.

$ apt-get source udev
Lecture des listes de paquets... Fait
La construction de l'arbre des dépendances
Lecture des informations d'état... Fait
Besoin d'obtenir 312kB de source archives.
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.7 kB]
Récupérée 312kB en 1s (223kB/s)
gpg: Signature faite Mar 14 Avr 2009 05:31:34 H (HAE) à l'aide de clés DSA ID 17063E6D
gpg: impossible de vérifier la signature: public touche pas trouvé
dpkg-source: extraction de udev dans udev-117
dpkg-source: le déballage udev_117.orig.tar.gz
dpkg-source: application ./udev_117-8ubuntu0.2.diff.gz
$ cd udev-117/
$ cat debian/patches/80-extras-firmware.patch

Si vous avez lu la source, vous verrez que Ubuntu a écrit un firmware_helper qui est codé en dur à regarder d'abord pour /lib/modules/$(uname -r)/$FIRMWARE, alors /lib/modules/$FIRMWARE, et pas d'autres sites. De le traduire en sh, il n'est à peu près ce:

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 le noyau attend.


Pour rendre une longue histoire courte: Ubuntu udev paquet a personnalisations qui ont toujours l'air en /lib/firmware/$(uname -r) première. Cette politique est en cours de traitement dans l'espace utilisateur.

12voto

Andy Matteson Points 73

Wow cette information est très utile et il m'a conduit à la solution à mon problème lors d'une prise USB module du noyau 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 changent. En fait j'ai lu, ils ont arrêté à l'aide de hal.

Donc, nous allons désosser cette fois encore il est donc pertinent au plus tard le [Ubuntu] systèmes.

Sur Ubuntu Lucid (les plus récentes 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.

Cotation: /lib/udev/rules.d/50-firmware.les règles

# 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: Linux Pilotes de Périphérique, 3e Ed., Ch. 14: Le Linux Le Modèle De L'Appareil):

  • echo 1 loading
  • copie firmware data
  • en cas d'échec, l'écho de la valeur -1 loading et de stopper le processus de chargement du firmware
  • echo 0 loading (signal du noyau)
  • ensuite, un module de noyau reçoit les données et il pousse à l'appareil

Si vous regardez Lucide source de la page pour udev, en udev-151/extras/firmware/firmware.c, la source de ce firmware /lib/udev/firmware binaire, c'est exactement ce qui se passe.

Extrait: Lucide 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");

En outre, de nombreux appareils utilisent un processeur Intel HEX format (textish fichiers contenant la somme de contrôle et d'autres trucs) (wiki, j'ai pas de réputation et aucune possibilité de lien). Le noyau du programme ihex2fw (appelée à partir de Makefile dans kernel_source/lib/firmware .Fichiers HEX) permet de convertir ces fichiers HEX arbitraire-conçu format binaire que le noyau Linux puis reprend avec request_ihex_firmware, parce qu'ils pensaient que la lecture des fichiers texte dans le noyau était stupide (il serait de ralentir les choses).

1voto

David Schmitt Points 29384

Sur les systèmes Linux actuels, cela est géré via udev et les firmware.agent .

1voto

MaxV Points 121

Linux 3.5.7 Gentoo, j'ai le même problème. Résolu:

 emerge ipw2200-firmware
 

Ensuite, allez à / 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
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X