Auf dieser Seite werden Optimierungen erläutert, die Sie an der Implementierung Ihrer Device Tree Overlay (DTO) vornehmen können. beschreibt Einschränkungen gegen die Überlagerung des Stammknotens und beschreibt, wie Komprimierte Overlays im DTBO-Image konfigurieren Sie enthält auch Beispiele für Implementierungsanleitung und Code.
Kernel-Befehlszeile
Die ursprüngliche Kernel-Befehlszeile in der Gerätestruktur befindet sich im
chosen/bootargs
Knoten. Der Bootloader muss dies verketten.
Speicherort mit anderen Quellen der Kernel-Befehlszeile:
/dts-v1/; / { chosen: chosen { bootargs = "..."; }; };
DTO kann nicht Werte aus Haupt-DT und Overlay-DT verketten.
müssen Sie die Kernel-Befehlszeile des Haupt-DT
chosen/bootargs
und die Kernel-Befehlszeile des Overlay-DT in
chosen/bootargs_ext
. Bootloader kann diese
und das Ergebnis an den Kernel übergeben.
Main.dts | Overlay.dts |
---|---|
/dts-v1/; / { chosen: chosen { bootargs = "..."; }; }; |
/dts-v1/; /plugin/; &chosen { bootargs_ext = "..."; }; |
Libufdt
Obwohl die neuesten
libfdt
unterstützt DTO; wird empfohlen, libufdt
zur Implementierung von DTO zu verwenden
(AOSP-Quelle bei
platform/system/libufdt
.
libufdt
erstellt eine echte Baumstruktur (nicht abgeflachte Gerätestruktur,
oder ufdt) aus der FDT (Flattened Device Tree), damit die
Zusammenführung zweier .dtb
-Dateien von O(N2) zu O(N), wobei N für die
Anzahl der Knoten in der Baumstruktur.
Leistungstests
Bei internen Tests von Google mit libufdt
auf 2405
.dtb
und 283 .dtbo
-DT-Knoten führen zu Dateigrößen von
70.618 und 8.566 Byte nach der Kompilierung. Im Vergleich zu einem
DTO
Implementierung von FreeBSD (124 ms Laufzeit), libufdt
Die DTO-Laufzeit beträgt 10 ms.
Leistungstests für Pixel-Geräte im Vergleich zum libufdt
und
libfdt
. Der Effekt für die Anzahl der Basisknoten ist ähnlich, beinhaltet jedoch
die folgenden Unterschiede:
- 500 Overlay-Vorgänge (Anhängen oder Überschreiben) haben eine 6- bis 8-fache Zeit Differenz
- 1.000 Overlay-Vorgänge (Anhängen oder Überschreiben) haben eine 8- bis 10-fache Zeit Differenz
Beispiel, bei dem die Anzahl der Anhänge auf X festgelegt ist:
Abbildung 1: Die Anzahl der angehängten Elemente beträgt X.
Beispiel mit der Anzahl der Überschreibungen auf X:
Abbildung 2: Die Anzahl der überschriebenen Elemente ist X.
libufdt
wird mit einigen libfdt
-APIs und -Daten entwickelt
Strukturen. Bei der Verwendung von libufdt
müssen Sie Folgendes angeben und verknüpfen:
libfdt
(Sie können in Ihrem Code jedoch die libfdt
API für den Betrieb von DTB oder DTBO).
libufdt-DTO-API
Die Haupt-API für den DTO in libufdt
lautet so:
struct fdt_header *ufdt_apply_overlay( struct fdt_header *main_fdt_header, size_t main_fdt_size, void *overlay_fdt, size_t overlay_size);
Der Parameter main_fdt_header
ist der Haupt-DT und
overlay_fdt
ist der Zwischenspeicher mit dem Inhalt eines
.dtbo
-Datei. Der Rückgabewert ist ein neuer Puffer, der den Wert
zusammengeführter DT (oder null
im Falle eines Fehlers). Die zusammengeführte DT ist
in FDT, die Sie beim Starten des Kernels an den Kernel übergeben können.
Der neue Zwischenspeicher aus dem Rückgabewert wird von dto_malloc()
erstellt,
die du beim Portieren von libufdt
in den Bootloader implementieren solltest.
Referenzimplementierungen findest du unter
sysdeps/libufdt_sysdeps_*.c
Einschränkungen für Root-Knoten
Sie können keinen neuen Knoten oder eine neue Eigenschaft in den Stammknoten des Haupt-DT überlagern da Overlay-Vorgänge auf Labels basieren. Da der Haupt-DT eine und der Overlay-DT den Knoten zuweist, die mit Beschriftungen kann kein Label für den Stammknoten vergeben (und kann daher den Stammknoten nicht überlagern) Knoten).
SoC-Anbieter müssen die Überlagerungsfunktionen der Haupt-DT definieren. ODM/OEMs können
Knoten mit Labels, die vom SoC-Anbieter definiert wurden, anfügen oder überschreiben. Als
Sie können das Problem umgehen, indem Sie einen odm
-Knoten im
Stammknoten in Basis-DT, sodass alle ODM-Knoten in Overlay-DT neue Knoten hinzufügen können.
Alternativ könnten Sie alle SoC-bezogenen Knoten in der Basis-DT
soc
-Knoten unter dem Root-Knoten, wie unten beschrieben:
Main.dts | Overlay.dts |
---|---|
/dts-v1/; / { compatible = "corp,bar"; ... chosen: chosen { bootargs = "..."; }; /* nodes for all soc nodes */ soc { ... soc_device@0: soc_device@0 { compatible = "corp,bar"; ... }; ... }; odm: odm { /* reserved for overlay by odm */ }; }; |
/dts-v1/; /plugin/; / { }; &chosen { bootargs_ex = "..."; }; &odm { odm_device@0 { ... }; ... }; |
Komprimierte Overlays verwenden
Android 9 unterstützt jetzt komprimierte Overlays im DTBO-Image, wenn Version 1 der DT-Tabellenüberschrift verwendet wird. Bei Verwendung des DTBO-Headers v1 werden die vier niedrigstwertigen Bits des Flags-Felds verwendet. in dt_table_entry geben das Komprimierungsformat des DT-Eintrags an.
struct dt_table_entry_v1 { uint32_t dt_size; uint32_t dt_offset; /* offset from head of dt_table_header */ uint32_t id; /* optional, must be zero if unused */ uint32_t rev; /* optional, must be zero if unused */ uint32_t flags; /* For version 1 of dt_table_header, the 4 least significant bits of 'flags' are used to indicate the compression format of the DT entry as per the enum 'dt_compression_info' */ uint32_t custom[3]; /* optional, must be zero if unused */ };
Derzeit werden zlib
- und gzip
-Komprimierungen unterstützt.
enum dt_compression_info { NO_COMPRESSION, ZLIB_COMPRESSION, GZIP_COMPRESSION };
Android 9 unterstützt jetzt das Testen komprimierter Dateien
Overlays zum VtsFirmwareDtboVerification
-Test, um Ihnen zu helfen,
Korrektheit der Overlay-App überprüfen
Beispiel für DTO-Implementierung
Die folgende Anleitung führt Sie durch eine Beispielimplementierung eines DTO
mit libufdt
(Beispielcode unten).
Beispiel für DTO-Anweisungen
- Bibliotheken einschließen. Um
libufdt
zu verwenden, fügen Sielibfdt
für Datenstrukturen und APIs:#include <libfdt.h> #include <ufdt_overlay.h>
- Lädt Haupt-DT und Overlay-DT.
.dtb
und.dtbo
laden vom Speicher zum Arbeitsspeicher wechseln (die genauen Schritte hängen von Ihrem Design ab). An dieser Stelle sollten Sie den Puffer und die Größe.dtb
/.dtbo
haben:main_size = my_load_main_dtb(main_buf, main_buf_size)
overlay_size = my_load_overlay_dtb(overlay_buf, overlay_buf_size);
- DTs überlagern:
<ph type="x-smartling-placeholder">
- </ph>
- Verwenden Sie
ufdt_install_blob()
, um den FDT-Header für Haupt-DT abzurufen:main_fdt_header = ufdt_install_blob(main_buf, main_size); main_fdt_size = main_size;
ufdt_apply_overlay()
beim DTO anrufen, um eine zusammengeführte DT in FDT zu erhalten Format:merged_fdt = ufdt_apply_overlay(main_fdt_header, main_fdt_size, overlay_buf, overlay_size);
- Verwenden Sie
merged_fdt
, um die Größedtc_totalsize()
:merged_fdt_size = dtc_totalsize(merged_fdt);
- Übergeben Sie den zusammengeführten DT, um den Kernel zu starten:
my_kernel_entry(0, machine_type, merged_fdt);
- Verwenden Sie
Beispiel für DTO-Code
#include <libfdt.h> #include <ufdt_overlay.h> … { struct fdt_header *main_fdt_header; struct fdt_header *merged_fdt; /* load main dtb into memory and get the size */ main_size = my_load_main_dtb(main_buf, main_buf_size); /* load overlay dtb into memory and get the size */ overlay_size = my_load_overlay_dtb(overlay_buf, overlay_buf_size); /* overlay */ main_fdt_header = ufdt_install_blob(main_buf, main_size); main_fdt_size = main_size; merged_fdt = ufdt_apply_overlay(main_fdt_header, main_fdt_size, overlay_buf, overlay_size); merged_fdt_size = dtc_totalsize(merged_fdt); /* pass to kernel */ my_kernel_entry(0, machine_type, merged_fdt); }