M
MDK2412
Ambitioniertes Mitglied
- 24
Ich möchte hier über meine bisherigen Erfahrungen mit dem Einspielen von neuen Kerneln berichten. Das macht natürlich am ehesten Sinn, wenn man den Kernel selber kompiliert, denn die meisten Kernel aus dem Netz liegen ja in der Regel schon in einem direkt verwendbaren Format vor. Eine mögliche Anwendung läge aber beispielsweise darin, den Stock-LG-Kernel aus einem Firmware-Update separat als Kernel-Update zur Verfügung haben zu wollen.
Vorweg ein wenig notwendige Theorie zum besseren Verständnis, denn es gibt zwei verschiedene Konzepte zum Einspielen von Kernel-Updates, die sich grundlegend voneinander unterscheiden und nicht kompatibel sind. Allerdings lassen sie sich ineinander überführen. Beide haben spezifische Vor- und Nachteile und je nach Anwendungsfall ihre Berechtigung.
Option Nummer 1, ein so genanntes "Boot-Image", das umfasst den Kernel selbst sowie eine Verzeichnisstruktur in Form einer "Ramdisk". Zu erkennen in der Regel an der Dateiendung ".img". Diese Images lassen sich nur mittels der adb-Shell einspielen (analog zu einem Custom Recovery, nur auf die Boot-Partition), nicht aber mit einem Custom Recovery. Entscheidend an diesen Boot-Images ist, dass sie gerätespezifisch sind, da jedes Gerät einen individuellen Offset besitzt (im Falle unseres P500 "0x12800000"), der im Image eingebaut ist. Aus diesem Grund sind Boot-Images von anderen Geräten in aller Regel nicht kompatibel. Sofern Kernel-Module zu dem Kernel gehören, muss man die allerdings nachträglich per Hand ins System-Verzeichnis kopieren. Das sind die wesentlichen Nachteile dieser Option. Allerdings kann man sie auf dem laufenden Telefon einspielen und muss dafür nicht ins Recovery booten, genau genommen braucht man nicht mal überhaupt ein Custom Recovery installiert zu haben. Wenn man - warum auch immer - also nicht in der Lage ist, ein Recovery einzuspielen, ist dies die einzige Chance, den Kernel auszuwechseln
Option 2, ein Update-Zip (basierend auf dem "Any Kernel" Konzept von "koush" Koushik Dutta), das umfasst eine gepackte Verzeichnisstruktur mit dem Kernel und Skripten, um den Kernel einzuspielen, sowie gegebenenfalls den ladbaren Kernel-Modulen (bei unserem P500 der WLAN-Treiber und optional das TUN-Modul). Größter Vorteil hier ist die Kompatibilität, denn diese Kernel-Updates sind unabhängig von dem gerätespezifischen Offset, somit prinzipiell mit verschiedenen ROMs/Geräten lauffähig. Weiterhin gelangen mit dem Einspielen die Module gleich an Ort und Stelle. Zum Einspielen ist aber ein Custom Recovery erforderlich, im laufenden Betrieb ist mit solchen Updates nichts anzufangen.
Soweit so gut, wie erstellt man nun eine der beiden Versionen? Dazu braucht man natürlich erstmal einen kompilierten Kernel. Den kann man selbst kompilieren (Anleitung dazu vielleicht später) oder z.B. aus einem Boot-Image extrahieren. Für alle Basteleien in Sachen Kernel, Custom Recovery etc. benötigt man entweder eine echte oder virtuelle (mit dem kostenlosen Virtual Box) Linux-Installation, vorzugsweise von Ubuntu 9.10 (da LG mit dieser Version arbeitet). Wie man das installiert, sprengt hier den Rahmen und wer schon damit Probleme hat, sollte wohl besser von Spielereien am Android-Kernel etc. die Finger lassen.
Weiterhin braucht man eine funktionierende Ramdisk. Die nimmt man am einfachsten aus dem Stock-LG-Boot-Image.
Zum Extrahieren eines Kernels und der Ramdisk aus einem Boot-Image genügt das Skript "split_bootimg" (z.B. von hier http://dl.dropbox.com/u/23238610/split_bootimg). Das erzeugt aus einem Boot-Image den Kernel als "Name_des_Boot-Images-kernel" sowie die gepackte Ramdisk als "Name_des_Boot-Images-ramdisk.gz" und gibt ferner die "cmdline" des Boot-Images aus, die später noch benötigt wird. Im Falle des P500 lautet die "mem=471M console=ttyMSM2,115200n8 androidboot.hardware=thunderg". Sollte diese anders aussehen, ist das Boot-Image keines für ein P500, und man sollte dann schon wissen, was man tut, d.h. ob der enthaltene Kernel überhaupt fürs P500 passt.
Zum Erstellen des Boot-Images braucht man noch das Programm "mkbootimg" (z.B. von hier http://dl.dropbox.com/u/23238610/mkbootimg). Die Syntax davon, bezogen auf das Beispiel der vorher extrahierten zwei Dateien, lautet dann:
./mkbootimg --kernel Name_des_Boot-Images-kernel --ramdisk Name_des_Boot-Images-ramdisk.gz --cmdline "mem=471M console=ttyMSM2,115200n8 androidboot.hardware=thunderg" --base 0x12800000 -o Ausgabedatei.img
Damit wäre das Boot-Image fertig. Zur Kontrolle empfiehlt es sich, auf das neue Image nochmals split_bootimg anzuwenden. Dabei sollte kein Fehler auftreten und die cmdline korrekt sein.
Um stattdessen ein Update.zip zu erstellen, benötigt man zuerst eine Vorlage, am besten also ein bereits funktionierendes Update.zip. Dieses entpackt man in ein Verzeichnis, dadurch erhält man die Unterverzeichnisse /kernel, /META_INF und /system. Man ersetzt im Unterverzeichnis /kernel die Datei zImage durch den gewünschten Kernel, dabei natürlich den Namen "zImage" beibehalten (auf Groß/Kleinschreibung achten!). Ins Unterverzeichnis /system/lib/modules kommen die entsprechenden neuen Kernel-Module, wobei vorhandene ersetzt werden. Die Kernel-Module sollten natürlich zum neuen Kernel passen. Bei nicht selbst kompiliertem Kernel muss man sich die erstmal beschaffen, denn in einem Boot-Image mit diesem Kernel sind ja bekanntlich keine Module enthalten... Wenn man ein identisches Gerät zur Verfügung hat, wo der Kernel mitsamt Modulen läuft, kann man diese aus /system/lib/modules kopieren.
Das entsprechend angepasste Verzeichnis muss nun mit "zip -r Neues_Update.zip *" wieder eingepackt werden. Prinzipiell wäre man damit schon fertig, allerdings müsste man zum Flashen mittels Recovery das Prüfen auf signierte Updates abschalten, was Probleme machen kann. Daher sollte man das Update noch signieren. Dazu braucht man die entsprechenden Signierwerkzeuge aus dem Android SDK, herunterzuladen z.B. hier PortTools.rar). Das Update.zip wird nun wie folgt signiert (wobei der Pfad zu signapk.jar entsprechend angepasst werden muss, je nachdem, wo man das hinkopiert hat):
java -jar ../SignApp/signapk.jar ../SignApp/testkey.x509.pem ../SignApp/testkey.pk8 Neues_Update.zip Neues_Update_signed.zip
Damit ist das Kernel-Update.zip fertig und man kann es mittels Recovery flashen.
Das neue Wissen um Boot-Images ist übrigens auch nützlich für den Umgang mit Custom Recovery ROMs, denn beide haben im Prinzip dieselbe Struktur Kernel+Ramdisk, nur dass im Recovery in der Ramdisk andere Inhalte drin sind. In analoger Weise wie beim Boot-Image kann man somit z.B. für ein bestehendes Recovery einen anderen Kernel einbauen. Ich habe das genutzt, um für das P500 meiner Frau ein Recovery mit geringerer Größe zu bauen.
Zum Schluss noch einige Links, die mir geholfen haben, die ganze Sache zu verstehen:
Howto: Build a Kernel Port - CyanogenMod Wiki
HOWTO: Unpack, Edit, and Re-Pack Boot Images - Android Wiki
Gratis - Virtuellen PC mit VirtualBox & Ubuntu einrichten - Linux - PC-WELT
HOWTO: Unpack, Edit, and Repack Boot Images - xda-developers
Vorweg ein wenig notwendige Theorie zum besseren Verständnis, denn es gibt zwei verschiedene Konzepte zum Einspielen von Kernel-Updates, die sich grundlegend voneinander unterscheiden und nicht kompatibel sind. Allerdings lassen sie sich ineinander überführen. Beide haben spezifische Vor- und Nachteile und je nach Anwendungsfall ihre Berechtigung.
Option Nummer 1, ein so genanntes "Boot-Image", das umfasst den Kernel selbst sowie eine Verzeichnisstruktur in Form einer "Ramdisk". Zu erkennen in der Regel an der Dateiendung ".img". Diese Images lassen sich nur mittels der adb-Shell einspielen (analog zu einem Custom Recovery, nur auf die Boot-Partition), nicht aber mit einem Custom Recovery. Entscheidend an diesen Boot-Images ist, dass sie gerätespezifisch sind, da jedes Gerät einen individuellen Offset besitzt (im Falle unseres P500 "0x12800000"), der im Image eingebaut ist. Aus diesem Grund sind Boot-Images von anderen Geräten in aller Regel nicht kompatibel. Sofern Kernel-Module zu dem Kernel gehören, muss man die allerdings nachträglich per Hand ins System-Verzeichnis kopieren. Das sind die wesentlichen Nachteile dieser Option. Allerdings kann man sie auf dem laufenden Telefon einspielen und muss dafür nicht ins Recovery booten, genau genommen braucht man nicht mal überhaupt ein Custom Recovery installiert zu haben. Wenn man - warum auch immer - also nicht in der Lage ist, ein Recovery einzuspielen, ist dies die einzige Chance, den Kernel auszuwechseln
Option 2, ein Update-Zip (basierend auf dem "Any Kernel" Konzept von "koush" Koushik Dutta), das umfasst eine gepackte Verzeichnisstruktur mit dem Kernel und Skripten, um den Kernel einzuspielen, sowie gegebenenfalls den ladbaren Kernel-Modulen (bei unserem P500 der WLAN-Treiber und optional das TUN-Modul). Größter Vorteil hier ist die Kompatibilität, denn diese Kernel-Updates sind unabhängig von dem gerätespezifischen Offset, somit prinzipiell mit verschiedenen ROMs/Geräten lauffähig. Weiterhin gelangen mit dem Einspielen die Module gleich an Ort und Stelle. Zum Einspielen ist aber ein Custom Recovery erforderlich, im laufenden Betrieb ist mit solchen Updates nichts anzufangen.
Soweit so gut, wie erstellt man nun eine der beiden Versionen? Dazu braucht man natürlich erstmal einen kompilierten Kernel. Den kann man selbst kompilieren (Anleitung dazu vielleicht später) oder z.B. aus einem Boot-Image extrahieren. Für alle Basteleien in Sachen Kernel, Custom Recovery etc. benötigt man entweder eine echte oder virtuelle (mit dem kostenlosen Virtual Box) Linux-Installation, vorzugsweise von Ubuntu 9.10 (da LG mit dieser Version arbeitet). Wie man das installiert, sprengt hier den Rahmen und wer schon damit Probleme hat, sollte wohl besser von Spielereien am Android-Kernel etc. die Finger lassen.
Weiterhin braucht man eine funktionierende Ramdisk. Die nimmt man am einfachsten aus dem Stock-LG-Boot-Image.
Zum Extrahieren eines Kernels und der Ramdisk aus einem Boot-Image genügt das Skript "split_bootimg" (z.B. von hier http://dl.dropbox.com/u/23238610/split_bootimg). Das erzeugt aus einem Boot-Image den Kernel als "Name_des_Boot-Images-kernel" sowie die gepackte Ramdisk als "Name_des_Boot-Images-ramdisk.gz" und gibt ferner die "cmdline" des Boot-Images aus, die später noch benötigt wird. Im Falle des P500 lautet die "mem=471M console=ttyMSM2,115200n8 androidboot.hardware=thunderg". Sollte diese anders aussehen, ist das Boot-Image keines für ein P500, und man sollte dann schon wissen, was man tut, d.h. ob der enthaltene Kernel überhaupt fürs P500 passt.
Zum Erstellen des Boot-Images braucht man noch das Programm "mkbootimg" (z.B. von hier http://dl.dropbox.com/u/23238610/mkbootimg). Die Syntax davon, bezogen auf das Beispiel der vorher extrahierten zwei Dateien, lautet dann:
./mkbootimg --kernel Name_des_Boot-Images-kernel --ramdisk Name_des_Boot-Images-ramdisk.gz --cmdline "mem=471M console=ttyMSM2,115200n8 androidboot.hardware=thunderg" --base 0x12800000 -o Ausgabedatei.img
Damit wäre das Boot-Image fertig. Zur Kontrolle empfiehlt es sich, auf das neue Image nochmals split_bootimg anzuwenden. Dabei sollte kein Fehler auftreten und die cmdline korrekt sein.
Um stattdessen ein Update.zip zu erstellen, benötigt man zuerst eine Vorlage, am besten also ein bereits funktionierendes Update.zip. Dieses entpackt man in ein Verzeichnis, dadurch erhält man die Unterverzeichnisse /kernel, /META_INF und /system. Man ersetzt im Unterverzeichnis /kernel die Datei zImage durch den gewünschten Kernel, dabei natürlich den Namen "zImage" beibehalten (auf Groß/Kleinschreibung achten!). Ins Unterverzeichnis /system/lib/modules kommen die entsprechenden neuen Kernel-Module, wobei vorhandene ersetzt werden. Die Kernel-Module sollten natürlich zum neuen Kernel passen. Bei nicht selbst kompiliertem Kernel muss man sich die erstmal beschaffen, denn in einem Boot-Image mit diesem Kernel sind ja bekanntlich keine Module enthalten... Wenn man ein identisches Gerät zur Verfügung hat, wo der Kernel mitsamt Modulen läuft, kann man diese aus /system/lib/modules kopieren.
Das entsprechend angepasste Verzeichnis muss nun mit "zip -r Neues_Update.zip *" wieder eingepackt werden. Prinzipiell wäre man damit schon fertig, allerdings müsste man zum Flashen mittels Recovery das Prüfen auf signierte Updates abschalten, was Probleme machen kann. Daher sollte man das Update noch signieren. Dazu braucht man die entsprechenden Signierwerkzeuge aus dem Android SDK, herunterzuladen z.B. hier PortTools.rar). Das Update.zip wird nun wie folgt signiert (wobei der Pfad zu signapk.jar entsprechend angepasst werden muss, je nachdem, wo man das hinkopiert hat):
java -jar ../SignApp/signapk.jar ../SignApp/testkey.x509.pem ../SignApp/testkey.pk8 Neues_Update.zip Neues_Update_signed.zip
Damit ist das Kernel-Update.zip fertig und man kann es mittels Recovery flashen.
Das neue Wissen um Boot-Images ist übrigens auch nützlich für den Umgang mit Custom Recovery ROMs, denn beide haben im Prinzip dieselbe Struktur Kernel+Ramdisk, nur dass im Recovery in der Ramdisk andere Inhalte drin sind. In analoger Weise wie beim Boot-Image kann man somit z.B. für ein bestehendes Recovery einen anderen Kernel einbauen. Ich habe das genutzt, um für das P500 meiner Frau ein Recovery mit geringerer Größe zu bauen.
Zum Schluss noch einige Links, die mir geholfen haben, die ganze Sache zu verstehen:
Howto: Build a Kernel Port - CyanogenMod Wiki
HOWTO: Unpack, Edit, and Re-Pack Boot Images - Android Wiki
Gratis - Virtuellen PC mit VirtualBox & Ubuntu einrichten - Linux - PC-WELT
HOWTO: Unpack, Edit, and Repack Boot Images - xda-developers