下图引自: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-compilerjun@ubuntu:~/dtbo/libufdt/utils/tests/data$ dtc --versionVersion: DTC 1.4.5

编译dts到dtb二进制格式:

dtc -O dtb board1v1.dts -o board1v1.dtbdtc -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=0x20000jun@ubuntu:~/dtbo/libufdt/utils/tests/data$ ../../src/mkdtboimg.py dump dt.imgdt_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 = 1dt_table_entry[0]:             dt_size = 166           dt_offset = 96                  id = 00010000                 rev = 00000000           custom[0] = 00000002           custom[1] = 00000000           custom[2] = 00000000           custom[3] = 00000000dt_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 0struct 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~2enum 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 #include #include "../../src/dt_table.h"#include #include #include #include #include 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();}

更多相关文章

  1. Android(安卓)动画之属性动画ObjectAnimator
  2. Android(安卓)Studio重写方法时参数显示异常的解决方法
  3. 实习杂记(28):Android不同层次开启硬件加速的方式
  4. Bundle传值与取值
  5. android之 h5调用系统相机和相册并显示
  6. Android启动动画
  7. adb:) adb install
  8. android实现倒计时功能的方法
  9. java android HTTP应用程序设计

随机推荐

  1. Android通知栏的变化
  2. Android(安卓)ThreadLocal 源码分析
  3. 《Android(安卓)Dev Guide》系列教程7:And
  4. Android布局——Linearlayout线性布局
  5. Ubuntu共享WiFi(AP)给Android方法【修正
  6. Android中包含多个Activity的应用退出按
  7. Android(安卓)第二课——命令行基本操作
  8. Android布局文件的属性值解析
  9. [Android] View和ViewGroup事件分发机制
  10. Android:WebService