赞
踩
下图引自:https://source.android.com/devices/architecture/dto/partitions
本文中所述工具和源码详见Google代码仓:
git clone https://android.googlesource.com/platform/system/libufdt
dt或者dto镜像在这里Google把它笼统地称作dtbo镜像,他们的格式是一样的,都是把多个dtc编译出来的dtb二进制或者dto二进制打包到一个image,在image的结尾加一个avb的校验签名或者各个厂商自定义的镜像签名。
多个硬件设备可能配置都不一样,寄存器或者内存大小的配置等。每个硬件设备对应一个dtb和dto,把多个dtb或者dto按照图示的格式打包成对应的dt.img和dto.img,这样软件可以做到共镜像,方便了厂商对产品的维护工作。
每个硬件设备怎么识别到对应自己的dtb和dto呢?这里就需要依赖dt_table_entry中的id、rev、custom这几个字段了,它作用是硬件标识。这样bootloader就可以根据硬件设备获取的标识加载匹配的dtb和dto了。
例如:单板配置一和二
jun@ubuntu:~/dtbo/libufdt/utils/tests/data$ cat board1v1.dts /dts-v1/; /plugin/; / { compatible = "board_manufacturer,board_model"; board_id = <0x00010000>; board_rev = <0x00010000>; /* optional, the soc used by the board */ soc_id = <0x00020000>; deviceB:deviceB { }; }; &deviceB { value = <0x1>; status = "okay"; }; jun@ubuntu:~/dtbo/libufdt/utils/tests/data$ cat board2v1.dts /dts-v1/; /plugin/; / { compatible = "board_manufacturer,board_model"; board_id = <0x00020000>; board_rev = <0x00010000>; /* optional, the soc used by the board */ soc_id = <0x00010000>; deviceA: deviceA { }; }; &deviceA { value = <0x1>; status = "okay"; };
安装dts编译器:
sudo apt install device-tree-compiler
jun@ubuntu:~/dtbo/libufdt/utils/tests/data$ dtc --version
Version: DTC 1.4.5
编译dts到dtb二进制格式:
dtc -O dtb board1v1.dts -o board1v1.dtb
dtc -O dtb board2v1.dts -o board2v1.dtb
使用mkdtboimg.py工具制作生成dt.img
注意:
version参数没有或者是0,代表打包前不对dtb进行压缩处理,如果version参数为1,并且配合flags参数可设置dtb压缩格式。
flags为0,不压缩dtb
flags为1,zlib压缩dtb
flags为2,gzip压缩dtb
jun@ubuntu:~/dtbo/libufdt/utils/tests/data$ ../../src/mkdtboimg.py create dt.img --page_size=4096 --flags=2 --version=1 board1v1.dtb --id=0x10000 board2v1.dtb --id=0x20000 jun@ubuntu:~/dtbo/libufdt/utils/tests/data$ ../../src/mkdtboimg.py dump dt.img dt_table_header: magic = d7b7ab1e total_size = 429 header_size = 32 dt_entry_size = 32 dt_entry_count = 2 dt_entries_offset = 32 page_size = 4096 version = 1 dt_table_entry[0]: dt_size = 166 dt_offset = 96 id = 00010000 rev = 00000000 custom[0] = 00000002 custom[1] = 00000000 custom[2] = 00000000 custom[3] = 00000000 dt_table_entry[1]: dt_size = 167 dt_offset = 262 id = 00020000 rev = 00000000 custom[0] = 00000002 custom[1] = 00000000 custom[2] = 00000000 custom[3] = 00000000
dtbo镜像详细的数据结构定义:
#define DT_TABLE_MAGIC 0xd7b7ab1e #define DT_TABLE_DEFAULT_PAGE_SIZE 2048 #define DT_TABLE_DEFAULT_VERSION 0 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. The value will be equal to header_size if no padding is appended */ uint32_t page_size; /* flash page size we assume */ uint32_t version; /* DTBO image version, the current version is 0. The version will be incremented when the dt_table_header struct is updated. */ }; // 下面定义的是dtb或dto支持的压缩格式,mkdtboimg.py命令行version必须为1,flags可设0~2 enum dt_compression_info { NO_COMPRESSION, // mkdtboimg.py --version=1 --flags=0 ZLIB_COMPRESSION, // mkdtboimg.py --version=1 --flags=1 GZIP_COMPRESSION // mkdtboimg.py --version=1 --flags=2 }; // 下面这个结构体对应的是mkdtboimg.py脚本命令行参数version是0或默认的情况 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 */ }; // 下面这个结构体对应的是mkdtboimg.py脚本命令行参数version是1的情况 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 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 */ };
bootloader中查找硬件设备对于的dtb或者dto示例代码:
#include <stdlib.h> #include <stdio.h> #include "../../src/dt_table.h" #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include <endian.h> void *read_dtbo(char *ptn) { int ret; char *dtbo; struct stat buf = {0}; ret = stat(ptn, &buf); if (ret != 0) { printf("stat err\n"); return NULL; } dtbo = (char *)malloc(buf.st_size); ret = open(ptn, O_RDONLY); if (ret < 0) { printf("open fail\n"); return NULL; } ret = read(ret, dtbo, buf.st_size); if (ret != buf.st_size) { printf("read err\n"); return NULL; } return dtbo; } unsigned int get_board_id(void) { return 0x20000; } void *load_dtbo(void) { char *dtbo; struct dt_table_header *dtbo_head; unsigned int board_id; struct dt_table_entry_v1 *dtbo_entry; dtbo = read_dtbo("dt.img"); if (!dtbo) { printf("read_dtbo err!\n"); return NULL; } dtbo_head = (struct dt_table_header *)dtbo; printf("magic %x\n", be32toh(dtbo_head->magic)); if (be32toh(dtbo_head->magic) != DT_TABLE_MAGIC) { printf("Magic not match!\n"); return NULL; } board_id = get_board_id(); for (dtbo_entry = (struct dt_table_entry_v1 *)(dtbo + be32toh(dtbo_head->dt_entries_offset)); (char *)dtbo_entry < dtbo + be32toh(dtbo_head->dt_entries_offset) + be32toh(dtbo_head->dt_entry_size) * be32toh(dtbo_head->dt_entry_count); ++dtbo_entry) { if (be32toh(dtbo_entry->id) == board_id) { printf("dtbo_entry info dt_size %x\n", be32toh(dtbo_entry->dt_size)); printf("dtbo_entry info dt_offset %x\n", be32toh(dtbo_entry->dt_offset)); printf("dtbo_entry info id %x\n", be32toh(dtbo_entry->id)); printf("dtbo_entry info rev %x\n", be32toh(dtbo_entry->rev)); break; } } return dtbo_entry; } void main() { load_dtbo(); }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。