Frage

Ich kompile einen benutzerdefinierten Kernel unter Ubuntu und stieß auf das Problem zu, dass mein Kernel nicht weiß, wo ich nach Firmware suchen soll. Unter Ubuntu 8.04 ist die Firmware an die Kernelversion gebunden wie Treibermodule. Zum Beispiel speichert Kernel 2.6.24-24-Generic seine Kernel-Module in:

/lib/modules/2.6.24-24-generic

und seine Firmware in:

/lib/firmware/2.6.24-24-generic

Wenn ich den Ubuntu-Kern der 2,6.24-24-generischen Ubuntu nach dem "zusammenstellen" zusammenstelle "Alternative Build-Methode: Der altmodische Debian-Weg"Ich erhalte das entsprechende Modulverzeichnis und alle meine Geräte funktionieren außer denen, die Firmware wie meine Intel Wireless Card (IPW2200 -Modul) benötigen.

Das Kernel -Protokoll zeigt beispielsweise, dass das Kernel -Subsystem, das das Laden der Firmware steuert, nicht in der Lage ist, die Firmware zu laden, wenn IPW2200 versucht, die Firmware zu laden.

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

errno-base.h definiert dies als:

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

(Die Funktion, die den Enoent zurückgibt, stellt einen Minus vor sich.)

Ich habe versucht, einen Symlink in /lib /firmware zu erstellen, in dem der Name meines Kernels auf das Gener-Verzeichnis 2.6.24-24 hinwies. Dies führte jedoch zu demselben Fehler. Diese Firmware ist nicht GPL, von Intel bereitgestellt und von Ubuntu gepackt. Ich glaube nicht, dass es eine tatsächliche Verbindung zu einer bestimmten Kernelversion hat. cmp zeigt, dass die Versionen in den verschiedenen Verzeichnissen identisch sind.

Woher weiß der Kernel, wo er nach Firmware suchen soll?

Aktualisieren

ich fand diese Lösung Zu dem genauen Problem, das ich habe, funktioniert es jedoch nicht mehr, wie Ubuntu beseitigt hat /etc/hotplug.d und speichert seine Firmware nicht mehr in /usr/lib/hotplug/firmware.

Update2

Einige weitere Forschungen haben weitere Antworten ausgeführt. Bis zu Version 92 von udev, das Programm firmware_helper War die Art und Weise, wie Firmware geladen wurde. Beginnen mit udev 93 Dieses Programm wurde durch ein Skript namens Firmware ersetzt. Beide hardcode den Firmware -Pfad zu /lib/firmware. Ubuntu scheint immer noch die zu verwenden /lib/udev/firmware_helper binär.

Der Name der Firmware -Datei wird an übergeben firmware_helper in der Umgebungsvariablen $FIRMWARE das wird mit dem Weg verkettet /lib/firmware und verwendet, um die Firmware zu laden.

Die tatsächliche Anfrage zum Laden der Firmware wird vom Treiber (in meinem Fall IPW2200) über den Systemanruf erfolgen:

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

Jetzt irgendwo zwischen dem Fahrer anruft request_firmware und firmware_helper Mit Blick auf die $FIRMWARE Umgebungsvariable, der Kernel -Paketname wird auf den Firmware -Namen vorbereitet.

Also, wer macht das?

War es hilfreich?

Lösung

Aus der Sicht des Kernels siehe /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.

Der Kernel lädt keine Firmware. Es informiert UserSpace einfach: "Ich möchte eine Firmware namens der Namen von xxx", und wartet darauf, dass Benutzerspace das Firmware -Image zurück zum Kernel leitet.

Jetzt auf Ubuntu 8.04,

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

Also, wie Sie entdeckt haben, udev ist zum Ausführen konfiguriert firmware_helper Wenn der Kernel nach Firmware fragt.

$ 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

Wenn Sie die Quelle lesen, werden Sie feststellen, dass Ubuntu a geschrieben hat firmware_helper das ist hart codiert, um zuerst zu suchen /lib/modules/$(uname -r)/$FIRMWARE, dann /lib/modules/$FIRMWARE, und keine anderen Orte. Übersetzen in sh, Es macht ungefähr das:

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

Das ist genau das Format, das der Kernel erwartet.


Um eine lange Geschichte kurz zu machen: Ubuntu's udev Paket hat Anpassungen, die immer einsehen /lib/firmware/$(uname -r) Erste. Diese Richtlinie wird im Userspace behandelt.

Andere Tipps

Wow, das sind sehr nützliche Informationen und es führte mich zu der Lösung für mein Problem, wenn ich ein benutzerdefiniertes USB -Kernelmodul für ein Gerät erstellte, das Firmware erfordert.

Grundsätzlich bringt jeder Ubuntu eine neue Wiederholung von Hal, Sysfs, Devfs, Udev usw. und so weiter ... und die Dinge ändern sich einfach. Tatsächlich habe ich gelesen, dass sie aufgehört haben, Hal zu verwenden.

Lassen Sie uns dies also erneut umkehren, damit es für die neuesten [Ubuntu] -Systeme relevant ist.

Auf Ubuntu Lucid (die neueste zum Zeitpunkt des Schreibens), /lib/udev/rules.d/50-firmware.rules wird genutzt. Diese Datei ruft die Binärdatei auf /lib/udev/firmware, wo Magie passiert.

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

Die Magie sollte etwas in dieser Richtung sein (Quelle: Linux -Geräte -Treiber, 3. Aufl., Ch. 14: Das Linux -Gerätemodell):

  • Echo 1 bis loading
  • Kopieren Sie die Firmware an data
  • beim Versagen echo -1 bis loading und den Firmware -Ladeprozess stoppen
  • echo 0 bis loading (Signal des Kernels)
  • Anschließend empfängt ein bestimmtes Kernel -Modul die Daten und drückt sie auf das Gerät

Wenn Sie sich die Quellseite von Lucid für Udev ansehen, in udev-151/extras/firmware/firmware.c, Die Quelle für diese Firmware/Lib/Udev/Firmware Binary ist genau das, was los ist.

Auszug: Lucid 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");

Darüber hinaus verwenden viele Geräte ein Intel -Hex -Format (Textish -Dateien, die Prüfsumme und andere Dinge enthalten) (Wiki Es habe keinen Ruf und keine Verknüpfungsfähigkeit). Das Kernel-Programm IHEX2FW (von Makefile in Kernel_Source/lib/firmware auf .hex-Dateien genannt) konvertiert diese HEX-Dateien in ein beliebig entworfenes binäres Format, mit dem der Linux-Kernel dann aufnimmt request_ihex_firmware, weil sie dachten, dass das Lesen von Textdateien im Kernel albern war (es würde die Dinge verlangsamen).

Auf aktuellen Linux -Systemen wird dies über behandelt udev und die firmware.agent.

Linux 3.5.7 Gentoo, ich habe das gleiche Problem. Gelöst:

emerge ipw2200-firmware

Gehen Sie dann zu/usr/src/Linux

make menucofig

Entfernen Sie auf dem Gerätetreiber alle nicht benötigten drahlosen Treiber, setzen Sie den Intelligenz in 2200 als Modul und kompilieren Sie sie neu.

make
make modules_install
cp arch/x86/boot/bzImage /boot/kernel-yourdefault
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top