So kompilieren Sie zusätzliche Dateien in das Stammverzeichnis eines Android-ROM

8

Ich erstelle einen benutzerdefinierten Android-Kernel, der auf dem Kernel-Quellcode des Cyanogenmod-ROM basiert. Ich möchte Ordner und Dateien zum Stammordner des Betriebssystems ( /) hinzufügen . Nachdem ich beispielsweise meinen Kernel kompiliert habe, möchte ich, dass ein zusätzlicher Ordner mit dem Namen toto(absoluter Pfad = /toto) erstellt wird.

Ich habe wirklich keine Ahnung, welche Dateien bearbeitet werden müssen und wie die Arbeit gemacht werden soll.


Hinweis: Wenn Sie ein Android - Benutzer (kein ROM - Entwickler) sind , die Dateien auf Ihren hinzufügen möchte rootfs, sehen Sie bitte den entsprechenden Android.SE Frage statt.

taub
quelle
3
Android ist ein Linux-System, aber da die Frage spezifisch für Android ist, nicht für alle Unixe. Besser Platz dafür ist auf android.stackexchange.com
enedil
@enedil Im Allgemeinen sind Android-Fragen hier nicht zum Thema, da Android kein Linux im üblichen Sinne ist (es wird lediglich ein Linux-Kernel verwendet). Die gleiche Frage würde jedoch auch für andere eingebettete Linux-Systeme gelten, daher denke ich, dass dies hier in Ordnung ist.
Gilles 'SO - hör auf böse zu sein'
@Graeme Tatsächlich wird das Root-Dateisystem in jeden Kernel kompiliert . Normalerweise ist es leer und wir entpacken ein cpio-Archiv hinein - unser initramfs-Image. Sie können jedoch zur Kompilierungszeit alles einfügen, was Sie möchten.
Mikeserv
@enedil In diesem Fall glaube ich, dass diese Frage vollständig zum Thema gehört. Android unterscheidet sich am meisten von anderen Unixen in, userspace,aber von anderen Linuxes in-kernelbeträgt der Unterschied nur eine Handvoll Patches. Tatsächlich ist die Popularität von Android seit einigen Jahren eine wichtige Triebkraft für die Kernel-Entwicklung. Schauen Sie sich die Änderungsprotokolle von kernel.org an und entscheiden Sie selbst, wie relevant viele für mobile Systeme sind - insbesondere für Android.
Mikeserv
Eine ähnliche Frage auf Android.SE: Wie entpacke und bearbeiteboot.img ich für die ROM-Portierung? : Antworten dort erklären, wie die boot.imgDatei abgerufen und bearbeitet wird, sodass der Inhalt des Stammverzeichnisses des Geräts dauerhaft geändert werden kann.
WhiteWinterWolf

Antworten:

7

Auf Android, wie auf vielen Linux-basierten Systemen, steigt der Kernel zunächst eine initramfs auf /. Das initramfs wird im RAM gespeichert; Es wird aus einem CPIO-Archiv geladen, das zusammen mit dem Kernel selbst gespeichert wird (oder an einem anderen Ort, an dem der Bootloader es finden kann).

Die meisten Desktop-Linux-Systeme verfügen über ein kleines initramfs, das gerade genug Programme und Konfigurationsdateien enthält, um das echte Root-Dateisystem bereitzustellen, auf dem dann /das initramfs ersetzt wird. Android hält, wie einige eingebettete Linux-Systeme, die initramfs für immer bereit. Android initramfs enthält nur /init, adbdund einige Konfigurationsdateien.

Für Cyanogenmod finden Sie Bauanweisungen in der Portierungsanleitung . Sie möchten weitere Dateien auf die Ramdisk kopieren (das initramfs-Image in der Android-Terminologie), daher müssen Sie sie der PRODUCT_COPY_FILESListe im device_*.mkMakefile für Ihr Gerät hinzufügen .

Gilles 'SO - hör auf böse zu sein'
quelle
Tatsächlich enthält unsere initramfs Image- Datei diese Konfigurationsdateien. Das initramfs Dateisystem wird in jeden Kernel kompiliert.
Mikeserv
1
@mikeserv Ich lade Sie ein, sich mit dem Konzept der Metonymie vertraut zu machen . Technisches Schreiben verwendet es weniger als gewöhnliche Sprache, aber es wird gelegentlich verwendet.
Gilles 'SO - hör auf böse zu sein'
Ich werde es tun, aber zuerst muss ich es im Wörterbuch überprüfen ...
mikeserv
Sie machen einen sehr guten Punkt, und wie ich bereits sagte, der einzige Grund, warum ich daran festhalte, ist, dass es so wenig verstanden zu sein scheint, aber es ist wirklich sehr einfach, also neige ich dazu, dieses Thema nicht zu wählen - wofür ich mich entschuldige . Ich denke nur, es wäre einfacher, anderen zu zeigen, wie einfach es sein kann, ein eigenes System vom Kernel an zu entwickeln, wenn das obige Detail klargestellt wird. Wieder tut es mir leid, Gilles, ich meine überhaupt keine Beleidigung.
Mikeserv
@mikeserv Vielen Dank für Ihre Ratschläge. Ich habe die Datei gefunden, die zum Kopieren von Blobs verwendet wurde (blbs.mk). Ich verstehe immer noch nicht, welche Datei (en) bearbeitet werden müssen, um einen Ordnerordner bei rootfs (/) hinzuzufügen. Ich kann auf die init * .rc-Dateien des Roms zugreifen, aber jetzt nicht, wenn ich diese Dateien bearbeite (indem ich zum Beispiel ein mkdir / titi hinzufüge), kann ich meine Ordner (/ titi) dauerhaft hinzufügen. Danach werde ich in der Datei PRODUCT_COPY_FILES + = / titi / myfile: <localpath> / myfiles hinzufügen. Irgendeine Ahnung ?
Nochmals vielen
1

In den Kerneldokumenten wird erklärt, wie ein Bild in den Kernel selbst gepackt wird. Von kernel.org :

Was ist rootfs?

Rootfsist eine spezielle Instanz von ramfs(oder tmpfs, falls diese aktiviert ist), die in 2.6-Systemen immer vorhanden ist. Sie können die Bereitstellungrootfs aus ungefähr demselben Grund nicht aufheben, aus dem Sie den Init-Prozess nicht beenden können. Anstatt speziellen Code zum Suchen und Behandeln einer leeren Liste zu haben, ist es für den Kernel kleiner und einfacher, nur sicherzustellen, dass bestimmte Listen nicht leer werden können.

Die meisten Systeme mounten einfach ein anderes Dateisystem rootfsund ignorieren es. Der Platz, den eine leere Instanz von Ramfs einnimmt, ist winzig.

Wenn CONFIG_TMPFS aktiviert ist, rootfswird tmpfsanstelle ramfsvon standardmäßig verwendet. Um Kraft ramfs, fügen Sie "rootfstype=ramfs"an die Kernel - Befehlszeile.

Was ist initramfs?

Alle 2.6 Linux-Kernel enthalten ein"cpio"Archiv imkomprimiertenFormat, in das rootfsbeim Booten des Kernels extrahiert wird. Nach dem Extrahieren prüft der Kernel, obrootfseine Datei enthalten ist"init" , und führt sie in diesemFallals PID 1 aus. Wenn sie gefunden wird, ist dieserinitProzess dafür verantwortlich, dass das System den Rest des Weges nach oben bringt, einschließlich des Lokalisierens und Mountens des realen Root-Geräts ( wenn überhaupt). WennrootfsdasinitProgramm nach dem Extrahieren des eingebettetencpioArchivskeinProgrammenthält, wird der Kernel auf den älteren Code zurückgreifen, um eine Root-Partition zu suchen und bereitzustellen, und anschließend eine Variante davon/sbin/initausführen.

All dies unterscheidet sich in mehreren Punkten von der alten Initrd:

  • Die alte initrd war immer eine separate Datei, während das initramfs-Archiv mit dem Linux-Kernel-Image verknüpft ist. (Das Verzeichnis linux - * / usr dient zum Generieren dieses Archivs während des Builds.)

  • Die alte initrd-Datei war ein komprimiertes Dateisystem-Image (in einem Dateiformat wie ext2, für das ein im Kernel integrierter Treiber erforderlich war), während das neue initramfs-Archiv ein komprimiertes cpio-Archiv ist (wie tar nur einfacher, siehe cpio (1)). und Documentation / Early-Userspace / Buffer-Format.txt). Der CPIO-Extraktionscode des Kernels ist nicht nur extrem klein, sondern enthält auch __init Text und Daten, die während des Startvorgangs verworfen werden können.

  • Das vom alten initrd ausgeführte Programm (das / initrd, nicht / init genannt wurde) hat einige Einstellungen vorgenommen und ist dann zum Kernel zurückgekehrt, während das init-Programm von initramfs nicht zum Kernel zurückkehren soll. (Wenn / init die Steuerung übergeben muss, kann es / mit einem neuen Root-Gerät überhängen und ein anderes Init-Programm ausführen. Siehe das Dienstprogramm switch_root unten.)

  • Beim Wechseln eines anderen Root-Geräts würde initrd pivot_root ausführen und dann die Ramdisk umhängen. Aber initramfs ist rootfs: Sie können pivot_root rootfs weder anheben noch aushängen. Löschen Sie stattdessen alles aus rootfs, um Speicherplatz freizugeben (find -xdev / -exec rm '{}' ';'), und überlagern Sie rootfs mit dem neuen root (cd / newmount; mount --move. /; Chroot.). hänge stdin / stdout / stderr an die neue / dev / console an und führe den neuen init aus.

Da dies ein bemerkenswert hartnäckiger Prozess ist (und das Löschen von Befehlen beinhaltet, bevor Sie sie ausführen können), hat das klibc-Paket ein Hilfsprogramm (utils / run_init.c) eingeführt, um all dies für Sie zu erledigen. Die meisten anderen Pakete (z. B. Busybox) haben diesen Befehl "switch_root" genannt.

Initramfs füllen:

Der Kernel-Build-Prozess 2.6 erstellt immer ein initramfs-Archiv im komprimierten cpio-Format und verknüpft es mit der resultierenden Kernel-Binärdatei. Standardmäßig ist dieses Archiv leer (verbraucht 134 Byte auf x86).

Mit der Konfigurationsoption CONFIG_INITRAMFS_SOURCE (im allgemeinen Setup in menuconfig,und im Leben in usr/Kconfig) kann eine Quelle für das initramfsArchiv angegeben werden, die automatisch in die resultierende Binärdatei integriert wird. Diese Option kann auf ein * vorhandenes gzipped cpio* -Archiv , ein Verzeichnis mit zu archivierenden Dateien oder eine Textdateispezifikation wie das folgende Beispiel verweisen :

 dir /dev 755 0 0
 nod /dev/console 644 0 0 c 5 1
 nod /dev/loop0 644 0 0 b 7 0
 dir /bin 755 1000 1000
 slink /bin/sh busybox 777 0 0
 file /bin/busybox initramfs/busybox 755 0 0
 dir /proc 755 0 0
 dir /sys 755 0 0
 dir /mnt 755 0 0
 file /init initramfs/init.sh 755 0 0

Führen Sie " usr/gen_init_cpio" (nach dem Kernel-Build) aus , um eine Verwendungsnachricht zu erhalten, die das obige Dateiformat dokumentiert.

Ein Vorteil der Konfigurationsdatei besteht darin, dass rootkein Zugriff erforderlich ist, um Berechtigungen festzulegen oder Geräteknoten im neuen Archiv zu erstellen.

(Beachten Sie, dass diese beiden Beispieleinträge "Datei" erwarten, dass Dateien mit den Namen " init.sh" und " busybox" in einem Verzeichnis mit dem Namen " initramfs" unter dem linuxVerzeichnis -2.6. * Gefunden werden. Weitere Informationen finden Sie unter Dokumentation / Early-Userspace / README .)

Der Kernel ist nicht von externen cpioTools abhängig . Wenn Sie ein Verzeichnis anstelle einer Konfigurationsdatei angeben, erstellt die Build-Infrastruktur des Kernels eine Konfigurationsdatei aus diesem Verzeichnis ( usr/MakefileAufrufe scripts/gen_initramfs_list.sh) und packt dieses Verzeichnis mithilfe der Konfigurationsdatei (indem Sie es an usr/gen_init_cpiodieusr/gen_init_cpio.c Datei senden , aus der es erstellt wurde ). Der Build-Time- cpioErstellungscode des Kernels ist vollständig in sich geschlossen, und der Boot-Time-Extraktor des Kernels ist (offensichtlich) auch in sich geschlossen.

mikeserv
quelle