En esta página, se analizan las optimizaciones que puedes realizar en la implementación de la superposición del árbol de dispositivos (DTO). describe las restricciones contra la superposición del nodo raíz y detalla cómo configurar superposiciones comprimidas en la imagen DTBO. También se proporcionan ejemplos instrucciones de implementación y el código.
Línea de comandos del kernel
La línea de comandos del kernel original en el árbol de dispositivos (DT) se encuentra en
Nodo chosen/bootargs
. El bootloader debe concatenar
ubicación con otras fuentes de la línea de comandos del kernel:
/dts-v1/; / { chosen: chosen { bootargs = "..."; }; };
DTO no puede concatenar valores de la DT principal y la DT de superposición, por lo que
debes colocar la línea de comandos del kernel del DT principal en
chosen/bootargs
y la línea de comandos del kernel de la DT superpuesta en
chosen/bootargs_ext
Bootloader puede concatenar
y pasa el resultado al kernel.
main.dts | superposición.dts |
---|---|
/dts-v1/; / { chosen: chosen { bootargs = "..."; }; }; |
/dts-v1/; /plugin/; &chosen { bootargs_ext = "..."; }; |
libufdt
Si bien la última
libfdt
es compatible con DTO, ¿se recomienda usar libufdt
para implementar DTO?
(Fuente de AOSP en
platform/system/libufdt
).
libufdt
construye una estructura de árbol real (árbol de dispositivos sin compactar,
o ufdt) del árbol de dispositivos acoplado (FDT), por lo que puede mejorar la
combinación de dos archivos .dtb
de O(N2) a O(N), en la que N es la
la cantidad de nodos en el árbol.
Pruebas de rendimiento
En las pruebas internas de Google, con libufdt
en 2405
.dtb
y 283 nodos de DT .dtbo
dan como resultado tamaños de archivo de
70,618 y 8,566 bytes después de la compilación. Comparado con un
DTO
implementación transferida de FreeBSD (124 ms de tiempo de ejecución), libufdt
El tiempo de ejecución de DTO es de 10 ms.
Pruebas de rendimiento para dispositivos Pixel en comparación con 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 un tiempo de 6 a 8 veces más. diferencia
- 1,000 operaciones de superposición (agregar o anular) tienen un tiempo de 8 a 10 veces diferencia
Ejemplo con un recuento de anexos establecido en X:
Figura 1: El recuento de anexos es X.
Ejemplo con el recuento de anulación establecido en X:
Figura 2: El recuento de anulación es X.
libufdt
se desarrolla con algunas APIs y datos de libfdt
.
de las estructuras de datos. Cuando uses libufdt
, debes incluir y vincular
libfdt
(sin embargo, en tu código, puedes usar libfdt
para operar DTB o DTBO).
API de libufdt DTO
La API principal de DTO en libufdt
es la 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 la DT principal y
overlay_fdt
es el búfer que incluye el contenido de una
Archivo .dtbo
. El valor que se muestra es un búfer nuevo que contiene el
DT combinada (o null
en caso de error). La DT combinada tiene formato
en FDT, que puedes pasar al kernel cuando lo inicias.
dto_malloc()
crea el nuevo búfer del valor que se muestra.
que debes implementar cuando portes libufdt
al bootloader.
Para implementaciones de referencia, consulta
sysdeps/libufdt_sysdeps_*.c
Restricciones del nodo raíz
No puedes superponer un nodo o una propiedad nuevos en el nodo raíz de la DT principal porque las operaciones de superposición dependen de las etiquetas. Debido a que la DT principal debe definir un etiqueta y la DT superpuesta asigna los nodos que se superpondrán con etiquetas, no puede asignar una etiqueta al nodo raíz (y, por lo tanto, no puede superponer de Terraform).
Los proveedores de SoC deben definir la capacidad de superposición de la DT principal. Los ODM y OEM solo pueden
agregar o anular nodos con etiquetas definidas por el proveedor del SoC Como
puedes definir un nodo odm
en el
raíz en el DT base, lo que permite que todos los nodos de ODM de la DT superpuesta agreguen nodos nuevos.
De manera alternativa, puedes colocar todos los nodos relacionados con el SoC en el DT base en un
Nodo soc
bajo el nodo raíz, como se describe a continuación:
main.dts | superposición.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 { ... }; ... }; |
Usa superposiciones comprimidas
En Android 9, se agrega compatibilidad para usar superposiciones comprimidas. en la imagen de DTBO cuando se usa la versión 1 del encabezado de la tabla de DT. Cuando se usa el encabezado DTBO v1, los cuatro bits menos significativos del campo de marcas en dt_table_entry indican el formato de compresión de la entrada de 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' 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 */ };
Actualmente, se admiten las compresiones zlib
y gzip
.
enum dt_compression_info { NO_COMPRESSION, ZLIB_COMPRESSION, GZIP_COMPRESSION };
Android 9 agrega compatibilidad para pruebas comprimidas
superposiciones a la prueba de VtsFirmwareDtboVerification
para ayudarte
verificarás que la superposición de apps sea correcta.
Ejemplo de implementación de DTO
Las siguientes instrucciones te guiarán a través de un ejemplo de implementación de DTO
con libufdt
(código de muestra a continuación).
Ejemplo de instrucciones de DTO
- Incluye bibliotecas. Para usar
libufdt
, incluye:libfdt
para estructuras de datos y APIs:#include <libfdt.h> #include <ufdt_overlay.h>
- Carga la DT principal y la DT de superposición. Cargar
.dtb
y.dtbo
del almacenamiento a la memoria (los pasos exactos dependen de tu diseño). En este punto, Deberías tener el búfer 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);
- Superponga las DT:
- Usa
ufdt_install_blob()
para obtener el encabezado de FDT de la DT principal:main_fdt_header = ufdt_install_blob(main_buf, main_size); main_fdt_size = main_size;
- Llama a
ufdt_apply_overlay()
a DTO para obtener una DT combinada en FDT. formato:merged_fdt = ufdt_apply_overlay(main_fdt_header, main_fdt_size, overlay_buf, overlay_size);
- Usa
merged_fdt
para obtener el tamaño dedtc_totalsize()
merged_fdt_size = dtc_totalsize(merged_fdt);
- Pasa la DT combinada para iniciar el kernel:
my_kernel_entry(0, machine_type, merged_fdt);
- Usa
Código de DTO de muestra
#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); }