Domanda

Sto compilando un kernel personalizzato sotto Ubuntu e sto correndo nel problema che il mio kernel sembra non sapere dove cercare per il firmware. In Ubuntu 8.04, il firmware è legata alla versione del kernel gli stessi moduli driver modo sono. Ad esempio, il kernel 2.6.24-24-generic negozi i suoi moduli del kernel in:

/lib/modules/2.6.24-24-generic

e il suo firmware:

/lib/firmware/2.6.24-24-generic

Quando compilo il kernel di Ubuntu 2.6.24-24-generic secondo la " Corporatura alternativo metodo: il Debian vecchia maniera " ho la directory dei moduli appropriata e tutti i miei dispositivi di lavoro ad eccezione di quelli che richiedono il firmware come la mia scheda wireless Intel (ipw2200 modulo)

.

Il registro del kernel mostra per esempio che quando ipw2200 cerca di caricare il firmware del sottosistema kernel controlla il caricamento del firmware è in grado di individuarlo:

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

errno-base.h definisce come:

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

(La funzione che restituisce ENOENT mette un meno di fronte ad essa.)

Ho cercato di creare un link simbolico in / lib / firmware in cui il nome di mio kernel indicò la directory 2.6.24-24-generic, tuttavia questo ha provocato lo stesso errore. Questo firmware è non-GPL, fornito da Intel e imballato da Ubuntu. Non credo che abbia qualche legame effettivo ad una particolare versione del kernel. cmp dimostra che le versioni nelle varie directory sono identici.

Quindi, come fa il kernel sa dove cercare il firmware?

Aggiorna

questa soluzione per l'esatto problema che sto avendo, tuttavia, non funziona più come Ubuntu ha eliminato /etc/hotplug.d e non più memorizza il firmware in /usr/lib/hotplug/firmware.

Update2

Alcuni ulteriori ricerche alzato alcuni più risposte. Fino fino alla versione 92 del udev, il programma firmware_helper è stato il modo in cui ha ottenuto il firmware caricato. A partire da 93 udev questo programma è stato sostituito con uno script chiamato firmware.sh fornendo funzionalità identiche per quanto posso dire. Entrambi questi hardcode percorso firmware per /lib/firmware. Ubuntu sembra essere ancora utilizzando il binario /lib/udev/firmware_helper.

Il nome del file del firmware viene passato al firmware_helper nel $FIRMWARE variabile d'ambiente che viene concatenato alla /lib/firmware percorso e utilizzato per caricare il firmware.

La richiesta effettiva per caricare il firmware è fatta dal conducente (ipw2200 nel mio caso) tramite la chiamata di sistema:

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

Ora da qualche parte tra il driver chiamando request_firmware e firmware_helper guardando la variabile d'ambiente $FIRMWARE, il nome del pacchetto del kernel è sempre anteposto al nome del firmware.

Quindi, chi lo sta facendo?

È stato utile?

Soluzione

Dal punto di vista del kernel, vedere / 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.

Il kernel in realtà non caricare qualsiasi firmware a tutti. Si informa semplicemente userspace, "Voglio un firmware con il nome di xxx ", e attende userspace al tubo l'immagine del firmware di nuovo al kernel.

Ora, su Ubuntu 8.04,

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

in modo che hai scoperto, udev è configurato per eseguire firmware_helper quando il kernel richiede il 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

Se avete letto la fonte, ci si accorge che Ubuntu ha scritto un firmware_helper che è hard-coded al primo sguardo per /lib/modules/$(uname -r)/$FIRMWARE, poi /lib/modules/$FIRMWARE, e non altri luoghi. Tradurre per sh, lo fa circa questa:

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

che è esattamente il formato del kernel si aspetta.


Per fare una lunga storia breve: il pacchetto udev di Ubuntu ha personalizzazioni che sembrano sempre in /lib/firmware/$(uname -r) prima. Questa politica viene gestita in userspace.

Altri suggerimenti

Wow questo è informazioni molto utili e mi ha portato alla soluzione per il mio problema quando si effettua un modulo del kernel USB personalizzata per un firmware che richiede dispositivo.

In sostanza, ogni Ubuntu porta un nuovo rimaneggiamento di HAL, sysfs, devfs, udev, e così via ... e le cose basta cambiare. In realtà ho letto hanno smesso di utilizzare Hal.

Quindi cerchiamo di decodificare questo, ancora una volta in modo che sia pertinente per gli ultimi [Ubuntu] sistemi.

Su Ubuntu Lucid (l'ultima al momento della scrittura), viene utilizzato /lib/udev/rules.d/50-firmware.rules. Questo file chiama il /lib/udev/firmware binario, dove la magia accade.

Quotazione: /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 magia dovrebbe essere qualcosa in questo senso (fonte:. Linux driver di periferica, 3a ed, Ch . 14: il modello del dispositivo Linux ):

  • echo 1 a loading
  • firmware copia data
  • sul fallimento, echo -1 a loading e processo firmware arresto loading
  • echo 0 a loading (segnalare il kernel)
  • poi, un modulo kernel specifico riceve i dati e spinge al dispositivo

Se si guarda alla pagina di origine di Lucid per udev, in udev-151/extras/firmware/firmware.c, la fonte per questo firmware / lib / udev / binario del firmware, che è esattamente quello che succede.

Estratto: fonte 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");

Inoltre, molti dispositivi utilizzano un formato Intel HEX (file textish contengono checksum e altre cose) (Wiki non ho la reputazione e nessuna capacità di collegamento). Il programma di ihex2fw kernel (chiamato da Makefile in kernel_source / lib / firmware su file .HEX) converte i file HEX in un formato binario arbitrario-progettato che il kernel di Linux, allora prende con request_ihex_firmware, perché pensavano leggere i file di testo nel kernel era sciocco (sarebbe rallentare le cose).

Su sistemi Linux attuali, questo viene gestito tramite udev e il firmware.agent.

Linux 3.5.7 Gentoo, io ho lo stesso problema. Risolto:

emerge ipw2200-firmware

Poi vai a / usr / src / linux

make menucofig

il driver di periferica, rimuovere tutti i driver wirless non necessari, impostare Intell 2200 come modulo e ricompilare.

make
make modules_install
cp arch/x86/boot/bzImage /boot/kernel-yourdefault
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top