Si votre blob d'arborescence d'appareil (DTB) ou blob d'arborescence d'appareil pour superposition (DTBO) se trouve dans une partition unique, par exemple la partition dtb et dtbo, utilisez la structure de tableau et le format d'en-tête suivants:

Figure 1 : Exemple de disposition de partition DTB et DTBO.
Structures de données
dt_table_header est uniquement pour la partition dtb/dtbo. Vous NE POUVEZ PAS ajouter ce format après la fin de image.gz. Si vous disposez d'un seul DTB ou DTBO, vous devez toujours utiliser ce format (et le dt_entry_count dans dt_table_header est 1).
#define DT_TABLE_MAGIC 0xd7b7ab1e
struct dt_table_header {
uint32_t magic; // DT_TABLE_MAGIC
uint32_t total_size; // includes dt_table_header + all dt_table_entry
// and all dtb/dtbo
uint32_t header_size; // sizeof(dt_table_header)
uint32_t dt_entry_size; // sizeof(dt_table_entry)
uint32_t dt_entry_count; // number of dt_table_entry
uint32_t dt_entries_offset; // offset to the first dt_table_entry
// from head of dt_table_header
uint32_t page_size; // flash page size we assume
uint32_t version; // DTBO image version, the current version is 0.
// The version is incremented when the
// dt_table_header struct is updated.
};
struct dt_table_entry {
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 custom[4]; // optional, must be zero if unused
};Pour lire tous les dt_table_entry, utilisez dt_entry_size, dt_entry_count et dt_entries_offset. Exemple :
my_read(entries_buf, header_addr + header->dt_entries_offset, header->dt_entry_size * header->dt_entry_count);
id, rev et custom dans dt_table_entry sont des identifications matérielles facultatives de l'arborescence de l'appareil que le bootloader peut utiliser pour identifier efficacement le DTB ou le DTBO à charger. Si le bootloader nécessite des informations supplémentaires, placez-les dans le DTB ou le DTBO, où le bootloader peut les lire en analysant le DTB ou le DTBO (voir l'exemple de code ci-dessous).
Exemple de code
L'exemple de code suivant vérifie l'identification matérielle dans le bootloader.
- La fonction
check_dtbo()vérifie l'identification matérielle. Il vérifie d'abord les données dans la structuredt_table_entry(id,rev, etc.). Si ces données ne suffisent pas, il charge les donnéesdtbdans la mémoire et vérifie la valeur dansdtb. - Les valeurs des propriétés
my_hw_informationetsoc_idsont analysées dans le nœud racine (exemple dansmy_dtbo_1.dts).[my_dtbo_1.dts] /dts-v1/; /plugin/; / { /* As DTS design, these properties only for loader, won't overlay */ compatible = "board_manufacturer,board_model"; /* These properties are examples */ board_id = <0x00010000>; board_rev = <0x00010001>; another_hw_information = "some_data"; soc_id = <0x68000000>; ... }; &device@0 { value = <0x1>; status = "okay"; }; [my_bootloader.c] int check_dtbo(const dt_table_entry *entry, uint32_t header_addr) { ... if (entry->id != ... || entry->rev != ...) { ... } ... void * fdt_buf = my_load_dtb(header_addr + entry->dt_offset, entry->dt_size); int root_node_off = fdt_path_offset(fdt_buf, "/"); ... const char *my_hw_information = (const char *)fdt_getprop(fdt_buf, root_node_off, "my_hw_information", NULL); if (my_hw_information != NULL && strcmp(my_hw_information, ...) != 0) { ... } const fdt32_t *soc_id = fdt_getprop(fdt_buf, root_node_off, "soc_id", NULL); if (soc_id != NULL && *soc_id != ...) { ... } ... }
mkdtimg
mkdtimg est un outil permettant de créer des images dtb/dtbo (code source à system/libufdt dans AOSP). mkdtimg est compatible avec plusieurs commandes, y compris create, cfg_create et dump.
create
Utilisez la commande create pour créer une image dtb/dtbo:
mkdtimg create <image_filename> (<global-option>...) \
<ftb1_filename> (<entry1_option>...) \
<ftb2_filename> (<entry2_option>...) \
...
ftbX_filename génère un dt_table_entry dans l'image. Les entryX_option sont les valeurs à attribuer à dt_table_entry. Ces valeurs peuvent être l'une des suivantes:
--id=<number|path> --rev=<number|path> --custom0=<number|path> --custom1=<number|path> --custom2=<number|path> --custom3=<number|path>
Les valeurs numériques peuvent être un chiffre de 32 bits (par exemple, 68000) ou un nombre hexadécimal (par exemple, 0x6800). Vous pouvez également spécifier un chemin d'accès au format suivant:
<full_node_path>:<property_name>
(par exemple, /board/:id). mkdtimg lit la valeur à partir du chemin d'accès dans le fichier DTB ou DTBO et attribue la valeur (32 bits) à une propriété relative dans dt_table_entry. Vous pouvez également définir une global_option comme option par défaut pour toutes les entrées. La valeur par défaut de page_size dans dt_table_header est 2 048. Utilisez global_option --page_size=<number> pour attribuer une valeur différente.
Exemple :
[board1.dts]
/dts-v1/;
/plugin/;
/ {
compatible = "board_manufacturer,board_model";
board_id = <0x00010000>;
board_rev = <0x00010001>;
another_hw_information = "some_data";
...
};
&device@0 {
value = <0x1>;
status = "okay";
};
mkdtimg create dtbo.img --id=/:board_id --custom0=0xabc \
board1.dtbo \
board2.dtbo --id=0x6800 \
board3.dtbo --id=0x6801 --custom0=0x123
iddu premierdt_table_entry(board1.dtbo) est0x00010000etcustom[0]est0x00000abc.- Le deuxième
idest0x00006800etcustom[0]est0x00000abc. - Le troisième
idest0x00006801etcustom[0]est0x00000123. - Tous les autres utilisent la valeur par défaut (
0).
cfg_create
La commande cfg_create crée une image avec un fichier de configuration au format suivant:
# global options <global_option> ... # entries <ftb1_filename> # comment <entry1_option> # comment ... <ftb2_filename> <entry2_option> ... ...
Les options global_option et entryX_option doivent commencer par un ou plusieurs caractères d'espace (ces options sont identiques aux options create, sans le préfixe --). Les lignes vides ou celles commençant par # sont ignorées.
Exemple :
[dtboimg.cfg]
# global options
id=/:board_id
rev=/:board_rev
custom0=0xabc
board1.dtbo
board2.dtbo
id=0x6800 # override the value of id in global options
board2.dtbo
id=0x6801 # override the value of id in global options
custom0=0x123 # override the value of custom0 in global options
mkdtimg cfg_create dtbo.img dtboimg.cfg
mkdtimg ne gère pas l'alignement des fichiers .dtb/.dtbo, mais les ajoute à l'image.
Lorsque vous utilisez dtc pour compiler .dts en .dtb/.dtbo, vous devez ajouter l'option -a. Par exemple, l'ajout de l'option -a 4 ajoute une marge intérieure afin que la taille de .dtb/.dtbo s'aligne sur 4 octets.
Plusieurs entrées de table DT peuvent partager un .dtb/.dtbo. Si vous utilisez le même nom de fichier pour différentes entrées, un seul contenu est stocké dans l'image avec les mêmes dt_offset et dt_size. Cela est utile lorsque vous utilisez du matériel différent avec des DT identiques.
vider
Pour les images dtb/dtbo, utilisez la commande dump pour imprimer les informations de l'image. Exemple :
mkdtimg dump dtbo.img
dt_table_header:
magic = d7b7ab1e
total_size = 1300
header_size = 32
dt_entry_size = 32
dt_entry_count = 3
dt_entries_offset = 32
page_size = 2048
version = 0
dt_table_entry[0]:
dt_size = 380
dt_offset = 128
id = 00010000
rev = 00010001
custom[0] = 00000abc
custom[1] = 00000000
custom[2] = 00000000
custom[3] = 00000000
(FDT)size = 380
(FDT)compatible = board_manufacturer,board_model
...