2009-06-04 9 views
44

Kompiluję niestandardowe jądro pod Ubuntu i mam problem, że moje jądro nie wie, gdzie szukać oprogramowania układowego. Pod Ubuntu 8.04 oprogramowanie układowe jest powiązane z wersją jądra w taki sam sposób jak moduły sterowników. Dla przykładu, jądro 2.6.24-24-generic przechowuje swoje moduły jądra w:W jaki sposób Linux Kernel wie, gdzie szukać oprogramowania układowego sterownika?

/lib/modules/2.6.24-24-generic 

i jego firmware w:

/lib/firmware/2.6.24-24-generic 

Kiedy skompilować jądro 2.6.24-24-generic Ubuntu według "Alternate Build Method: The Old-Fashioned Debian Way" Dostaję odpowiedni katalog modułów i wszystkie moje urządzenia działają oprócz tych, które wymagają oprogramowania układowego, takiego jak moja bezprzewodowa karta Intel (moduł ipw2200).

dziennik jądra pokazuje na przykład, że gdy ipw2200 próbuje załadować firmware podsystem jądra kontrolowania ładowanie firmware jest w stanie go zlokalizować:

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

errno-base.h definiuje to jako:

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

(funkcja powrocie ENOENT stawia minusa przed nim).

próbowałem utworzenie dowiązania symbolicznego w katalogu/lib/firmware gdzie nazwa moim kernelem wskazał do katalogu ogólnego w wersji 2.6.24-24, ale spowodowało to ten sam błąd. To oprogramowanie jest niezgodne z GPL, dostarczane przez firmę Intel i pakowane przez Ubuntu. Nie wierzę, że ma rzeczywisty związek z konkretną wersją jądra. cmp pokazuje, że wersje w różnych katalogach są identyczne.

Skąd jądro wie, gdzie szukać oprogramowania układowego?

Aktualizacja

znalazłem this solution do dokładnego problemu Mam jednak to już nie działa jak Ubuntu wyeliminował /etc/hotplug.d i nie przechowuje swoją firmware w /usr/lib/hotplug/firmware.

Update2

Niektóre dalszych badań okazało się jeszcze kilka odpowiedzi. Do wersji 92 z udev, program firmware_helper był sposobem załadowania oprogramowania układowego. Począwszy od wersji udev 93 ten program został zastąpiony skryptem o nazwie firmware.sh, który zapewnia identyczną funkcjonalność, o ile wiem. Obie te metody kodują ścieżkę oprogramowania układowego do /lib/firmware. Wydaje się, że Ubuntu wciąż używa pliku binarnego /lib/udev/firmware_helper.

Nazwa pliku oprogramowania układowego jest przekazywana do firmware_helper w zmiennej środowiskowej $FIRMWARE, która jest łączona ze ścieżką /lib/firmware i używana do ładowania oprogramowania układowego.

Rzeczywisty wniosek załadować firmware jest wykonany przez kierowcę (ipw2200 w moim przypadku) poprzez wywołanie systemowe:

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

Teraz gdzieś pomiędzy kierowcą wywołującego request_firmware i firmware_helper patrząc na zmiennej $FIRMWARE środowiska , nazwa pakietu jądra jest automatycznie dodawana do nazwy oprogramowania układowego.

Więc kto to robi?

+0

Czy ktoś mógłby dodać komentarz wyjaśniający, dlaczego decyduje się zamknąć to pytanie? Byłbym wdzięczny za opinie. –

+2

To jest głosowanie na zamknięcie, ponieważ "należy do serverfault.com". Ponieważ nie chodzi tu o programowanie, a raczej o administrację, jest to zgodne z deklaracjami misji obu stron. – ephemient

+0

Dzięki za opinię. Rozważałem to pytanie programistyczne, ponieważ napotkano problem podczas próby zbudowania niestandardowego jądra. Chciałbym wiedzieć, dlaczego konkretnie ktoś by pomyślał o tym, nie odnosząc się do programowania, chociaż myślę, że mam kilka dobrych domysłów dlaczego. –

Odpowiedz

38

Z punktu widzenia jądra, patrz /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. 

Jądro nie faktycznie załadować dowolny firmware w ogóle. Po prostu informuje użytkownika, "Chcę oprogramowania o nazwie xxx", i czeka na przestrzeni użytkownika, aby potokować obraz oprogramowania układowego z powrotem do jądra.

Teraz na Ubuntu 8.04,

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

tak jak odkryliśmy, udev jest skonfigurowany do uruchomienia firmware_helper gdy jądro prosi o 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 

Jeśli czytać źródła, przekonasz się, że Ubuntu napisał firmware_helper który jest zakodowany na pierwszy rzut oka dla /lib/modules/$(uname -r)/$FIRMWARE, potem /lib/modules/$FIRMWARE i bez innych lokalizacjach. Przełożenie go sh, robi to w przybliżeniu:

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 

który jest dokładnie format jądro oczekuje.


Aby długie opowiadanie: udev pakiet Ubuntu ma dostosowań, które zawsze wyglądają w /lib/firmware/$(uname -r) pierwszy. Ta polityka jest obsługiwana w przestrzeni użytkownika.

+1

Cudowna odpowiedź, dzięki! Przeglądałem źródło udev wyciągając moje włosy, próbując dowiedzieć się, skąd pochodzi Ubuntu 'firmware_helper'. Powinien właśnie zrobić rekursywny grep dla oprogramowania układowego w drzewie źródłowym udev. –

+0

Jest to prawdopodobnie z drzewa udev-extras, którego część Ubuntu postanowiła zmodyfikować i połączyć z pakietem udev. – ephemient

+0

'apt-get source' pobiera i rozpakowuje drzewo źródłowe Debiana (lub Ubuntu) dla pakietu, które zawiera katalog' debian' z informacjami o opakowaniu i konfiguracji specyficznej dla dystrybucji, która czasami zawiera łatki, których nie można odnaleźć. To jest przypadek. – ephemient

1

W obecnych systemach Linux jest to obsługiwane przez udev i firmware.agent.

+0

Podobno Ubuntu 8.04 nie ma firmware.agent w udev, ma coś innego o nazwie firmware_helper. W każdym razie, w jaki sposób informuje to jądro, gdzie znaleźć oprogramowanie układowe? –

+0

Niezależnie od tego, jak polecenie jest wywoływane przez udev, jest ono odpowiedzialne za ładowanie oprogramowania do jądra. Z mojego czytania na firmware .agent Debiana, zapisuje oprogramowanie do specjalnego pliku w/sys –

11

Wow, to bardzo przydatne informacje i doprowadziło mnie do rozwiązania mojego problemu przy tworzeniu niestandardowego modułu jądra USB dla urządzenia wymagającego oprogramowania układowego.

Zasadniczo każdy Ubuntu przynosi nowe odgłosy hal, sysfs, devfs, udev itd. ... i wszystko się zmienia. W rzeczywistości czytałem, że przestali używać hal.

Odtworzyć to jeszcze raz, więc jest to istotne dla najnowszych systemów [Ubuntu].

W systemie Ubuntu Lucid (najnowsze w chwili pisania tego artykułu) używany jest kod /lib/udev/rules.d/50-firmware.rules. Ten plik wywołuje kod binarny /lib/udev/firmware, w którym pojawia się magia.

Listing: /lib/udev/rules.d/50-firmware.Zasady

# firmware-class requests, copies files into the kernel 
SUBSYSTEM=="firmware", ACTION=="add", RUN+="firmware --firmware=$env{FIRMWARE} --devpath=$env{DEVPATH}" 

Magia powinno być coś wzdłuż tych linii (źródło: Linux Device Drivers, 3rd Ed., Ch. 14: The Linux Device Model):

  • echo 1 do loading
  • kopia oprogramowania do data
  • na niepowodzenie, echo -1 loading i zatrzymanie procesu wczytywania oprogramowania układowego
  • echo 0 do loading (sygnalizować jądro)
  • wtedy, specyficzny moduł jądra odbiera dane i pcha go do urządzenia

Jeśli spojrzeć na stronie źródłowej Lucid za udev w udev-151/extras/firmware/firmware.c, źródło dla tego oprogramowania/lib/udev/binarne oprogramowanie układowe, właśnie to się dzieje.

Fragment: Lucid źródło, udev-151/dodatki/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"); 

Dodatkowo wiele urządzeń użyć formatu Intel Hex (pliki textish zawierające kontrolną i inne rzeczy) (wiki go mam brak reputacji i brak możliwości łączenia). Program jądra ihex2fw (wywoływany z Makefile w kernel_source/lib/firmware na plikach .HEX) konwertuje te pliki HEX do arbitralnie zaprojektowanego formatu binarnego, który jądro Linuksa odbiera z request_ihex_firmware, ponieważ myśleli, że czytanie plików tekstowych w jądrze było głupi (spowolniłoby to).

+1

+1 Teraz masz kilka rep i może link. Jeśli informacje w odpowiedzi na PO lub odpowiedź innej osoby są przydatne, zagłosuj na nie. –

1

Linux 3.5.7 Gentoo, mam ten sam problem. rozwiązany:

emerge ipw2200-firmware 

Następnie przejdź do katalogu/usr/src/linux

make menucofig 

na sterowniku urządzenia, usunąć wszystkie Wirless kierowcy nie potrzebna, ustaw Intell 2200 jako moduł i rekompilacji.

make 
make modules_install 
cp arch/x86/boot/bzImage /boot/kernel-yourdefault 
Powiązane problemy