Malinowe jajo i moduły

Stwierdzam, że w projekcie Raspbery Pi panuje rozgardiasz. Przykładowo chciałem sobie skompilować moduł jądra, klasyczne „Witaj świecie”, żeby zobaczyć czy wszystko działa. Generalnie koncept jest bardzo prosty:

# rpi-update
# rpi-source
W odpowiednim folderze skompilować moduł...
# make -C /lib/modules/$(uname -r)/build M=$(pwd) modules

I na tym koniec… teoretycznie koniec.

Problem pierwszy.

Wersja GCC. Bieżąca wersja Raspbiana zawiera gcc w wersji 4.6.x. Próba przekompilowania modułu tą wersją kończy się informacją „segmentation fault” podczas operacji ładowania modułu. Można zainstalować i przełączyć gcc na 4.8, ale wersja 4.8, która jest dostępna w smaku „wheezy” jest dość niska i kompilacja źródeł jądra wykłada się z informacją, że nie zaleca się kompilacji jądra tak niską wersją, gdyż poziom bug\’ów jest zbyt duży. No i co? Trzeba przełączyć „apt” na smak „jessie” i stamtąd ściągnąć wyższą wersję gcc. Nie jest to szczególnie trywialne.  Oto sposób:

Plik /etc/apt/sources.list należy zmodyfikować:

deb http://mirrordirector.raspbian.org/raspbian/ wheezy main contrib non-free rpi
deb http://archive.raspbian.org/raspbian wheezy main contrib non-free rpi
# Source repository to add
deb-src http://archive.raspbian.org/raspbian wheezy main contrib non-free rpi
deb http://mirrordirector.raspbian.org/raspbian/ jessie main contrib non-free rpi
deb http://archive.raspbian.org/raspbian jessie main contrib non-free rpi
# Source repository to add
deb-src http://archive.raspbian.org/raspbian jessie main contrib non-free rpi

Plik /etc/apt/preferences należy zmodyfikować:

Package: *
Pin: release n=wheezy
Pin-Priority: 900
Package: *
Pin: release n=jessie
Pin-Priority: 300
Package: *
Pin: release o=Raspbian
Pin-Priority: -10

Ściągamy odpowiednie gcc:

sudo apt-get update
sudo apt-get install -t jessie gcc-4.8 g++-4.8
sudo update-alternatives --remove-all gcc
sudo update-alternatives --remove-all g++
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.6 20
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 50
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.6 20
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 50
sudo gcc --version

Udało się. Moduł się skompilował, jednak podczas ładowania pojawił się nowy problem…

Problem drugi.

Niewłaściwy format modułu. Wynika to (prawdopodobnie) z różnic miedzy nagłówkami, które ściągnąłem a nagłówkami z jakimi zostało skompilowane jądro. Wyjścia są dwa. Skompilować jądro ze źródeł, które się ściągnęło, albo zdobyć odpowiednią binarkę… Skrypt rpi-source ściągnął bieżącą wersję źródeł, 3.18.6, a jądro ściągnięte przez skrypt rpi-update w wersji 3.18.5+. Zerknąłem na head repozytorium z firmware\’em. Jest w nim teoretycznie 3.18.6. WFT? Skrypt nie aktualizuje firmware\’u do bieżącej wersji. Najpierw próbowałem ściągnąć źródła do 3.18.5, ale to nie było zbyt proste, więc „z palca” zaktualizowałem jądro, wszelkie dtb itp.

Po tych mało oczywistych problemach (szczególnie drugim), wynik jest zadowalający:

Feb  8 12:06:19 raspberrypi kernel: [  140.347563] hello: module license \'unspecified\' taints kernel.
Feb  8 12:06:19 raspberrypi kernel: [  140.347605] Disabling lock debugging due to kernel taint
Feb  8 12:06:19 raspberrypi kernel: [  140.350716] Hello World :)
Feb  8 12:06:28 raspberrypi kernel: [  148.711591] Goodbye World!