Fragen? Antworten! Siehe auch: Alternativlos
So hatte ich vor einer Weile das Problem, dass auf meinem Notebook mein WLAN nicht mehr funktionierte. Das lag daran, dass der Intel-WLAN-Treiber anfing, eine Firmware hochzuladen, und dafür das Hotplug-Interface zu benutzen. Hotplug, das ist eine archaische Shellskript-Sammlung von Greg Kroah-Hartmann, in einem Shellskript /sbin/hotplug gipfelnd, das dann andere Shellskripte aus /etc/hotplug/* aufruft, und dort die eigentlichen Daten über magische Environment-Variablen übergibt. Nach einer Weile rumdebuggen habe ich damals rausgefunden, dass das Hotplug sich aus den magischen Environment-Variablen (der ganze Prozess ist m.W. nicht brauchbar dokumentiert) einen Pfad zusammenpopelt, und dann am Ende cp aufruft, um /lib/firmware/radeon/RV770_me.bin nach /sys/devices/platform/r600_cp.0/data zu kopieren. Welches cp das am Ende wird, das hängt von $PATH ab. Ich habe ein /usr/bin/cp, ein /bin/cp und ein /opt/diet/bin/cp, alle unterschiedlich. Mein /usr/bin/cp ist von GNU coreutils, und das meinte der Autor von hotplug wohl. /bin/cp ist ein Notfall-cp aus einer alten Version von embutils, falls ich /usr nicht mounten kann oder mir die glibc zerschossen habe. /usr/bin ist vor /bin im Pfad, daher betrifft das nie jemanden. /opt/diet/bin/cp ist das aktuelle cp aus embutils, das ist für meinen User noch vor /usr/bin im Pfad. Hotplug wird aber direkt vom Kernel aufgerufen und erbt daher das Environment von init. Und das hat das Default-Environment, das der Kernel setzt beim Aufruf von init, nämlich
PATH=/sbin:/bin:/usr/sbin:/usr/binAm Ende hat hotplug also das alte Notfall-cp aufgerufen, das in Blöcken zu 1024 Bytes kopiert. Versteht mich nicht falsch: alle dieser cp Binaries sind willens und in der Lage, eine Datei zu kopieren, und hotplug benutzt auch keine komischen GNU-only Flags. Aber das Firmware-Interface des Kernels hat damals Dinge angenommen, die nur GNU cp so gemacht hat. Ich habe die genauen Details vergessen, aber das Notfall-cp hat 1024-Bytes geschrieben, und der Kernel nahm an, dass die Firmware in nur einem Chunk geschrieben wird, und daher schlug das fehl.
Nachdem ich meine Fassungslosigkeit überwunden habe, habe ich damals /etc/hotplug/firmware.agent angefasst, damit er händisch /usr/bin/cp aufruft und nicht bloß cp über $PATH, und damit war das Problem gelöst.
Gestern habe ich jetzt anlässlich dieser Meldung hier den Kernel 2.6.32-rc6 auf meinem Desktop probiert. Mein Desktop hat kein WLAN und lädt an sich keine Firmware. Auf meinem Desktop ist auch seit irgendwann mal vorbeugend /bin/cp ein Symlink auf /usr/bin/cp. Um so größer war meine Überraschung, als mit dem neuen Kernel plötzlich X nur noch ohne Grafik-Beschleunigung hochkam. Nach einer Packung debuggen stellte sich raus, dass er die Firmware nicht laden konnte. Nachtigall, ick hör dir trapsen, dachte ich mir, und prüfte, ob /bin/cp das richtige ist. War es. Mhh, nanu. Ich habe also geprüft, ob hotplug das richtige cp aufruft. Tat er, /usr/bin/cp. Komisch. Weiter debugged. Mal ein strace auf /usr/bin/cp gemacht. Und, was soll ich sagen, /usr/bin/cp kopiert bei mir in 32k-Blöcken. Mein embutils-cp benutzt hingegen mmap und kopiert in 4 MB Blöcken. Also habe ich /etc/hotplug/firmware.agent angefasst, damit er /opt/diet/bin/cp aufruft, und was soll ich euch sagen, jetzt ist mein X wieder beschleunigt.
Nur damit ihr mal seht, auf was für einem Treibsand-Fundament dieses Linux gebaut ist.
Wobei wahrscheinlich ich über drei Ecken Schuld bin. Mein coreutils ist Version 7.6, das ist AFAIK aktuell, aber meine hotplug-Shellskripte sind von 2006. Vielleicht gibt es da ein Update inzwischen.
Aber die Ironie, dass dieses Firmware-Interface so verstrahlt ist, dass es erst mit dem Fefe-cp nicht tat, und jetzt mit dem GNU-cp nicht tut, und ich es fixen kann, indem ich das Fefe-cp benutze, das ist schon grotesk. Freut euch alle, dass ihr solche Details nicht sehen könnt bei euren Distributionen. Und, falls das hier jemand liest, der für das Firmware-Laden-Interface im Kernel verantwortlich ist: SCHANDE! SCHANDE! SCHANDE!!
Update: hotplug ist seit Jahren obsolet und sollte ja eh nicht mehr installiert sein, weil es durch udev abgelöst wurde, was ich ja auch installiert habe. Nur leider hat das Vorhandensein von udev bei mir nie dazu geführt, dass der Kernel nicht trotzdem hotplug aufruft. Jetzt habe ich einige Zuschriften gekriegt, die mir erklärt haben, dass man beim Booten
echo > /sys/kernel/uevent_helpermachen muss. Nun starte ich ja beim Booten den udevd, und hätte mir gedacht, hey, wenn ich den da schon starte, dann ist der bestimmt auch so smart, obiges zu tun. Ist er aber nicht.