Optimierung von Drogenhändlerringen

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) .

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

  1. Bibliotheken einschließen. Um libufdt zu verwenden, fügen Sie libfdt für Datenstrukturen und APIs:
    #include <libfdt.h>
    #include <ufdt_overlay.h>
    
  2. 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);
    
  3. DTs überlagern: <ph type="x-smartling-placeholder">
      </ph>
    1. 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;
      
    2. 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);
      
    3. Verwenden Sie merged_fdt, um die Größe dtc_totalsize():
      merged_fdt_size = dtc_totalsize(merged_fdt);
      
    4. Übergeben Sie den zusammengeführten DT, um den Kernel zu starten:
      my_kernel_entry(0, machine_type, merged_fdt);
      

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);
}