Zróbmy sobie jądro – część I Wstęp

8 minut czytania
Komentarze

Zapraszam do pierwszej części cyklu poradników o przygotowaniu własnych kerneli, czyli jąder, które potem będziecie mogli opublikować czy wykorzystywać. Oczywiście, nie gwarantuję, że wszystko od razu zacznie się udawać, ale zapewniam, że czuje się tę satysfakcję po skończonej pracy, a szczególnie poczuje ją własne urządzenie, któremu poprawi się działanie baterii czy też wydajność.

Przed rozpoczęciem wszystkich działań ostrzeżenie: nie ponoszę odpowiedzialności za niedziałające telefony czy za unieważnienie gwarancji ze strony producenta, które może wyniknąć po wykonaniu poniżej przedstawionych procedur (samo ich wykonanie niczego nie zmienia, jednak wgranie kernela już tak). Nikogo nie namawiam też do wykonywania poniższych instrukcji, choć mogę powiedzieć, że procesy, które zostaną przedstawione, można cofnąć w większości przypadków.

Jeśli jednak zdecydowaliście się podjąć ryzyko, to należy przygotować następujące rzeczy:

  • MacOS lub dystrybucja Linuksa – to podstawowe środowisko, w którym będziemy pracować. Z racji tego, że nie posiadam urządzenia od Apple’a, użyłem popularnego 32-bitowego Ubuntu w wersji 12.04 zainstalowanego w Virtual Boksie. Oczywiście, można się obyć bez ostatniego programu.
  • GNU Toolchains – zestaw narzędzi potrzebnych do stworzenia jądra. Dostępnych jest wiele różnych dystrybucji, jednak ogólna wydajność nie zależy od nich, także większej różnicy nie ma, który będziemy używać. Dla przykładu podam ten udostępniony przez znanego na XDA-developer DooMLoRDa, choć równie dobrze można pobrać ze strony Linarno:
    • git clone git://github.com/DooMLoRD/android_prebuilt_toolchains.git toolchains

W tym przypadku na początku trzeba najpierw przejść do katalogu roboczego ( u mnie cd ~\android), gdyż inaczej folder o nazwie „toolchains” pojawi nam się w głównym.

  • Odpowiednie pakiety – te przydadzą się do wykonywania komend, które są niezbędne do kompilacji. Poniżej te komendę z tymi udostępnionymi na CyanogenMod, którą należy wrzucić w Terminal. Jeśli jakichś nie będzie chciało pobrać, to znaczy, że już są obecne w systemie. Na błędy nie zwracamy uwagi:
    • sudo apt-get install git-core gnupg flex bison gperf libsdl-dev libesd0-dev libwxgtk2.6-dev build-essential zip curl libncurses5-dev zlib1g-dev  – dla 32 bit-owego systemu
    • sudo apt-get install ia32-libs lib32z1-dev lib32ncurses5-dev gcc-multilib g++-multilib ncurses-devel – dla 64 bit-owego systemu
  • Sun Java 6 JDK – nowsza wersja nas nie interesuje, instalacja przy pomocy trzech komend:
    • sudo add-apt-repository ppa:webupd8team/java
    • sudo apt-get update
    • sudo apt-get install oracle-java6-installer
  • Jądro ze strony producenta – w moim przypadku to będzie LG P970 Optimus Black, którego miałem przez pół roku i z racji braku innych kerneli, to stworzyłem własne. Od razu zaznaczę, że nie wszystkie modyfikacje, które dokonam tutaj, zdołacie zrobić w swoim przypadku – każdy producent stosuje własne sposoby programowania, choć w większości przypadków łatwo znaleźć podobieństwa, a szczególnie wtedy, kiedy użyty został ten sam chipset.
  • Cierpliwość – szczególnie wtedy, kiedy pojawiają się błędy, kernel powoduje, że telefon się nie uruchamia itd. Warto się nie poddawać
  • Mała porada dla tych korzystających z VirtualBoksa: jeśli chcecie mieć możliwość ustawienia dowolnej rozdzielczości, a tym samym, by ekran można było swobodnie skalować, to polecam tę komendę: sudo apt-get install virtualbox-ose-guest-utils virtualbox-ose-guest-x11 virtualbox-ose-guest-dkms. Później potrzebny jest restart systemu.

Przed rozpoczęciem zaznaczę, że działania przedstawione poniżej są dla jąder przygotowanych z myślą o ICS i wzwyż. Struktura kerneli stworzonych dla niższych wersji jest inna, przez co inaczej stosuje się modyfikacje.

Zacznijmy jednak od samej konfiguracji – mogę się założyć, że nie wszyscy korzystają z jakiekolwiek dystrybucji Linuksa i pierwsze kroki będą pewnie nieco problematyczne. Ubuntu ma jednak przejrzysty interfejs, z który dość szybko da się oswoić. Po uruchomieniu systemu należy go zaktualizować poprzez Menadżera Aktualizacji (ikonka jest na bocznym pasku), po czym zrestartować i uruchomić Terminal, by wklepać komendy na pakiety i na Javę, choć przed tym uaktualnimy te, które już posiadamy przez sudo apt-get update.

Skoro mamy już wszystko, czego nam do szczęścia potrzeba, to bierzemy się do pracy. Pobrany kernel  rozpakowujemy w takim miejscu i o takiej nazwie, które nie będzie problematyczne do pisania (i tak się namęczymy z wklepywaniem ? ). Po rozpakowaniu za pomocą komendy cd przechodzimy do niego i zajmiemy się na razie najprostszą zmianą, a mianowicie wybierzemy innego domyślnego zarządcę oraz dodamy nasze imię/pseudonim do nazwy jądra.

Musimy wpisać dwie komendy – export ARCH=arm, za pomocą której wybieramy architekturę urządzenia oraz export CROSS_COMPILE=~/android/toolchains/arm-eabi-linaro-4.6.2/bin/arm-eabi- (uwaga: nie zawsze ta wersja działa. Czasami potrzeba 4.7.1, czasami 4.7. Jeśli nie pójdzie, to polecam zmienić na drugi toolchain w folderze, czyli 4.4.3), dzięki czemu wskazujemy miejsce naszego zestawu narzędzi potrzebnych do kompilacji. Teraz załadujemy plik konfiguracyjny dla naszego urządzenia, w moim przypadku LG P970 Optimus Black: make black_open_eur_defconfig, a następnie przechodzimy do menu, gdzie wybierzemy odpowiednie dla nas parametry: make menuconfig.

Ukaże się nam niebieskie okno, w którym widzimy wiele opcji do wyboru. Dla przykładu: wybiorę domyślnego planistę I/O (ang: I/O scheduler) Deadline, zarządcę Powersave oraz zmienę nazwę na Jadro. Na początku udajemy się do Enable the block layer/IO Schedulers i klikamy klawisz „Y”, by wybrać Deadline. Następnie w tym samym menu przechodzimy do Deafult I/O Scheduler i zmieniamy na ten, który chcemy. Cofamy do początkowego ekranu i wchodzimy w General Setup, a następnie wciskamy enter w Local version – append of kernel release i wpisujemy nazwę. Ostatnią sprawą do załatwienia jest zmiana zarządcy, a więc ponownie powracam do głównego menu i tym razem musi wejść w CPU Power Managment/CPU Frequency scaling, gdzie zaznaczamy wszystko, po czym klikamy „Enter” na pozycji Default CPUFreq governor, a następnie wybieramy takiego zarządcę, jaki jest nam potrzebny. Po kilkukrotnym naciśnięciu Exit dostaniemy zapytanie o zapisanie pliku konfiguracyjnego – oczywiście, zgadzamy się. Po wyjściu z menu czas na kompilację – wpisujemy komendę make –j2 (wartość liczbowa zależy od ilości wątków, jakie może obsłużyć procesor, jednak nie polecam zbytniego obciążania. Samo make też wystarczy). Proces ten trwa od kilku do kilkunastu minut w zależności od mocy procesora i zastosowanym systemie (w VirtualBoksie nieznacznie się czas wydłuża). Po skończeniu przechodzimy do folderu kernela, a dalej do arch/arm/boot/zImage, by skopiować nasze jądro oraz do /drivers/net/wireless/, gdzie znajdziemy moduł WiFi (uwaga: nie zawsze jest on kompatybilny ze wszystkimi systemami. Czasami lepiej skopiować ten moduł z romu, który nas interesuje).

Teraz mamy dwie drogi do wyboru: albo flashujemy przez adb zImage (komenda: fastboot flash zimage zImage), albo przy pomocy zewnętrznych skryptów konwertujemy go w boot.img. W drugim przypadku potrzebny byłby już wcześniej skompilowany kernel, w którym zamienilibyśmy zImage na własny. Jest to też nieco dłuższa droga, jednak czasami jedyna, gdyż nie zawsze istnieje możliwość skorzystania z komend fastboot (zablokowany bootloader).

Potrzebne nam będą unpackbootimg oraz mkbootimg, które pobierzmy stąd . Pierwszy służy do rozpakowania, drugi do spakowania kernela. Umieszczamy boot.img w folderze, gdzie znajdują się oba narzędzia. Następnie uruchamiamy Terminal, komendą cd przechodzimy do tego folderu, a następnie wpisujemy sudo ./unpackbootimg -i boot.img.  Rozpakują nam się pliki potrzebne do kompilacji jądra oraz wyświetlą nam się właściwości użytego kernela, które przydadzą się później. Teraz trzeba usunąć boot.img-zImage oraz, opocjalnie, boot.img (podczas kompilacji i tak się zamieni na nasz). Pozostało wpisać komendę (nawiasy pomijamy): sudo ./mkbootimg –kernel zImage –ramdisk boot.img-ramdisk.gz –base (liczba, która się wyświetliła przy KERNEL_BASE) –pagesize (liczba, która nam się wyświetliła przy PAGE_SIZE)  –cmdline (komendy, które wyświetliły się na samym początku, w moim przypadku brak, więc pomijam tę linię) -o boot.img. Tym sposobem otrzymaliśmy kernel w formacie .img, który możemy spakować do .zip, przed tym tworząc odpowiedni skrypt, który wgra też moduł WiFi, i zainstalować przez recovery. Można też skorzystać ze skryptu, który już ktoś wcześniej wykorzystał.

Gdyby coś poszło nie tak, to jest kilka dróg powrotu do pożądanego stanu pełnej sprawności: albo zainstalować sam kernel przez recovery, albo przywrócić go w tymże miejscu, a ostatecznością jest wgranie systemu oferowanego przez samego producenta przy pomocy SmartFlash w LG, Odin w Samsungach, RUU w HTC itd. Nie zmienia to faktu, że dość ciężko jest uzyskać w pełni niesprawny telefon. W wielu telefonach stosuje się zablokowany bootloader i choć jest zmorą dla bardziej zaawansowanych użytkowników, może okazać się ratunkiem dla początkujących, dzięki czemu zaoszczędzą nerwy i czas (urządzenie w serwisie trochę jednak leży).

Tyle w tej części poradnika. W następnym pokażę, jak dodać zarządcę, podkręcić procesor oraz zmniejszyć napięcie na dane taktowanie. W razie wszelkich wątpliwości zapraszam do kontaktu mailowego: [email protected] lub pozostawienia komentarza pod tym artykułem – postaram się odpowiedzieć na Wasze pytania. Udanej kompilacji!

Motyw