Google se compromete a impulsar la igualdad racial para las comunidades afrodescendientes. Obtén información al respecto.

Optimización de DTO

Esta página analiza las optimizaciones que puede realizar en su implementación de DTO, describe las restricciones contra la superposición del nodo raíz y detalla cómo configurar superposiciones comprimidas en la imagen de DTBO. También proporciona instrucciones y código de implementación de muestra.

Línea de comando del kernel

La línea de comandos del kernel original en árbol de dispositivos se encuentra en el chosen/bootargs nodo. El cargador de arranque debe concatenar esta ubicación con otras fuentes de la línea de comandos del kernel:

/dts-v1/;

/ {
  chosen: chosen {
    bootargs = "...";
  };
};

DTO no puede concatenar los valores de la principal DT y DT de superposición, por lo que debe poner la línea de comandos del núcleo principal de DT chosen/bootargs y la línea de comandos del núcleo de la superposición de DT chosen/bootargs_ext . El cargador de arranque puede concatenar estas ubicaciones y pasar el resultado al kernel.

main.dts overlay.dts
/dts-v1/;

/ {
  chosen: chosen {
    bootargs = "...";
  };
};
/dts-v1/;
/plugin/;

&chosen {
  bootargs_ext = "...";
};

libufdt

Mientras que la última libfdt apoya DTO, ¿es recomendable utilizar libufdt para implementar DTO (fuente PSE al platform/system/libufdt ). libufdt construye una estructura de árbol real (árbol de dispositivos un-aplanada, o ufdt) del árbol de dispositivos aplanado (FDT), por lo que puede mejorar la fusión de dos .dtb archivos de O (N 2) a O (N), donde N es el número de nodos del árbol.

Pruebas de rendimiento

En pruebas internas de Google, utilizando libufdt en 2405 .dtb y 283 .dtbo resultados DT nodos en tamaños de archivo de 70,618 y 8,566 bytes después de la compilación. En comparación con una aplicación DTO portado desde FreeBSD (124 ms tiempo de ejecución), libufdt DTO de tiempo de ejecución es de 10 ms.

Las pruebas de rendimiento para los dispositivos de píxeles en comparación libufdt y libfdt . El efecto del número de nodos base es similar, pero incluye las siguientes diferencias:

  • 500 operaciones de superposición (agregar o anular) tienen una diferencia de tiempo de 6x a 8x
  • 1000 operaciones de superposición (agregar o anular) tienen una diferencia de tiempo de 8x a 10x

Ejemplo con un recuento agregado establecido en X:

Figura 1. Anexión de recuento es X

Ejemplo con el recuento de anulación establecido en X:

Figura 2. Anulación de recuento es X

libufdt se desarrolla con algunas libfdt API y estructuras de datos. Al utilizar libufdt , debe incluir y enlace libfdt (sin embargo, en su código puede utilizar el libfdt API para operar DTB o DTBO).

API libufdt DTO

La principal API para DTO en libufdt es el siguiente:

struct fdt_header *ufdt_apply_overlay(
        struct fdt_header *main_fdt_header,
        size_t main_fdt_size,
        void *overlay_fdt,
        size_t overlay_size);

El parámetro main_fdt_header es el principal DT y overlay_fdt es el tampón que contiene el contenido de un .dtbo archivo. El valor de retorno es un tampón nuevo que contiene el DT fusionada (o null en caso de error). El DT combinado está formateado en FDT, que puede pasar al kernel al iniciar el kernel.

El nuevo buffer del valor de retorno es creada por dto_malloc() , que se debe aplicar al portar libufdt en gestor de arranque. Para implementaciones de referencia, consulte sysdeps/libufdt_sysdeps_*.c .

Restricciones del nodo raíz

No puede superponer un nuevo nodo o propiedad en el nodo raíz del DT principal porque las operaciones de superposición se basan en etiquetas. Debido a que el DT principal debe definir una etiqueta y el DT de superposición asigna los nodos para que se superpongan con etiquetas, no puede dar una etiqueta para el nodo raíz (y, por lo tanto, no puede superponer el nodo raíz).

Los proveedores de SoC deben definir la capacidad de superposición del DT principal; Los ODM / OEM solo pueden agregar o anular nodos con etiquetas definidas por el proveedor de SoC. Como solución alternativa, se puede definir un odm nodo bajo el nodo raíz de la base de DT, lo que permite que todos los nodos del ODM en superposición DT añadir nuevos nodos. Alternativamente, se puede poner todos los nodos relacionados con SoC en la base de DT en una soc nodo bajo el nodo raíz como se describe a continuación:

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 {
        ...
    };
    ...
};

Usar superposiciones comprimidas

Android 9 agrega soporte para usar superposiciones comprimidas en la imagen DTBO cuando se usa la versión 1 del encabezado de la tabla del árbol de dispositivos. Al utilizar DTBO v1 cabecera, los cuatro bits menos significativos del campo de banderas en dt_table_entry indican el formato de compresión de la entrada DT.

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' will be 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 */
};

Actualmente, zlib y gzip compresiones son compatibles.

enum dt_compression_info {
    NO_COMPRESSION,
    ZLIB_COMPRESSION,
    GZIP_COMPRESSION
};

Android 9 añade soporte para las pruebas de superposiciones comprimido a la VtsFirmwareDtboVerification prueba para ayudarle a verificar la exactitud de la aplicación de superposición.

Ejemplo de implementación de DTO

Las siguientes instrucciones le guiarán a través de una implementación de ejemplo de DTO con libufdt (código de ejemplo a continuación).

Ejemplo de instrucciones DTO

  1. Incluya bibliotecas. Para uso libufdt , incluir libfdt para estructuras de datos y APIs:
    #include <libfdt.h>
    #include <ufdt_overlay.h>
    
  2. Cargue el DT principal y el DT de superposición. Cargar .dtb y .dtbo de almacenamiento en la memoria (pasos exactos dependen de su diseño). En este punto, usted debe tener la memoria intermedia y el tamaño de .dtb / .dtbo :
    main_size = my_load_main_dtb(main_buf, main_buf_size)
    
    overlay_size = my_load_overlay_dtb(overlay_buf, overlay_buf_size);
    
  3. Superponga los DT:
    1. Utilice ufdt_install_blob() para obtener el encabezado FDT para DT principal:
      main_fdt_header = ufdt_install_blob(main_buf, main_size);
      main_fdt_size = main_size;
      
    2. Llamar ufdt_apply_overlay() a DTO para obtener una fusionaron en formato DT FDT:
      merged_fdt = ufdt_apply_overlay(main_fdt_header, main_fdt_size,
                                      overlay_buf, overlay_size);
      
    3. Uso merged_fdt para obtener el tamaño de dtc_totalsize() :
      merged_fdt_size = dtc_totalsize(merged_fdt);
      
    4. Pasar el DT se fusionaron para iniciar el kernel:
      my_kernel_entry(0, machine_type, merged_fdt);
      

Ejemplo de código DTO

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