【DTB/DTBO 分区介绍】

article/2025/10/25 0:57:02

如果你的 DTB/DTBO 位于专属的分区(例如 dtb 和 dtbo 分区)中,请使用以下表格结构和头文件格式:

dtb/dtbo 分区布局示例

数据结构

dt_table_header 仅适用于 dtb/dtbo 分区;您不能在kernel( image.gz) 末尾处附加此格式。如果您有一个 DTB/DTBO,则仍必须使用此格式(并且,dt_table_header 中的 dt_entry_count 为 1)。

#define DT_TABLE_MAGIC 0xd7b7ab1e
#define DT_TABLE_DEFAULT_PAGE_SIZE 2048
#define DT_TABLE_DEFAULT_VERSION 0
struct dt_table_header {  //0x20=32字节uint32_t magic;             // DT_TABLE_MAGICuint32_t total_size;        // includes dt_table_header + all dt_table_entry // and all dtb/dtbo        整个文件的大小uint32_t header_size;       // sizeof(dt_table_header) 固定的大小 0x20uint32_t dt_entry_size;     // sizeof(dt_table_entry)  固定的大小 0x20uint32_t dt_entry_count;    // number of dt_table_entry  dt条目的个数uint32_t dt_entries_offset; // offset to the first dt_table_entry   固定的偏移量 0x20// from head of dt_table_header // 从 dt_table_header 的头部到第一个 dt_table_entry 的偏移量uint32_t page_size;         // flash page size we assumeuint32_t version;       // DTBO image version, the current version is 0.// The version will be incremented when the// dt_table_header struct is updated.
};struct dt_table_entry {  //0x20=32字节uint32_t dt_size;uint32_t dt_offset;         // offset from head of dt_table_headeruint32_t id;                // optional, must be zero if unuseduint32_t rev;               // optional, must be zero if unuseduint32_t custom[4];         // optional, must be zero if unused
};

使用经过压缩的叠加层

Android 9 增加了以下支持:在使用第 1 版设备树表格头文件时,在 DTBO 映像中使用经过压缩的叠加层。 使用 DTBO 头文件 v1 时,dt_table_entry 中标记字段的四个最低有效位会指明 DT 条目的压缩格式。

struct dt_table_entry_v1 {  //0x20=32字节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 bitsof 'flags' will be used to indicate the compressionformat of the DT entry as per the enum 'dt_compression_info' */uint32_t custom[3];  /* optional, must be zero if unused */
};

目前,系统支持 zlib 和 gzip 压缩。

enum dt_compression_info {NO_COMPRESSION,ZLIB_COMPRESSION,GZIP_COMPRESSION
};

Android 9 增加了以下支持:在 VtsFirmwareDtboVerification 测试中测试经过压缩的叠加层,以帮助您验证叠加应用的正确性。

代码

/system/libufdt/utils/src/
dt_table.h:
enum DT_TYPE { DTB, ACPI };
void dt_table_header_init(struct dt_table_header *header, enum DT_TYPE dt_type);dt_table.c:
void dt_table_header_init(struct dt_table_header *header, enum DT_TYPE dt_type) {const uint32_t header_size = sizeof(struct dt_table_header);const uint32_t entry_size = sizeof(struct dt_table_entry);dto_memset(header, 0, header_size); //清零void *dto_memset(void *s, int c, size_t n) { return memset(s, c, n); }if (dt_type == ACPI)header->magic = cpu_to_fdt32(ACPI_TABLE_MAGIC); // dtb/dtbo的存储格式是大端字节序elseheader->magic = cpu_to_fdt32(DT_TABLE_MAGIC);header->total_size = cpu_to_fdt32(header_size);header->header_size = cpu_to_fdt32(header_size);header->dt_entry_size = cpu_to_fdt32(entry_size);header->dt_entries_offset = cpu_to_fdt32(header_size);header->page_size = cpu_to_fdt32(DT_TABLE_DEFAULT_PAGE_SIZE);header->version = cpu_to_fdt32(DT_TABLE_DEFAULT_VERSION);
}
//system/libufdt/utils/src/mkdtimg_core.c
output_img_header(writer->img_fp, //输出文件的文件指针writer->entry_count,  //dtb文件的个数,动态变化,见该结构体struct dt_image_writer {}的解释writer->dt_offset,  //dt文件的偏移量,动态变化,见该结构体struct dt_image_writer {}的解释&writer->global_options)  //全局选项
static int output_img_header(FILE *img_fp,uint32_t entry_count, uint32_t total_size,struct dt_global_options *options) {struct dt_table_header header;dt_table_header_init(&header, options->dt_type);header.dt_entry_count = cpu_to_fdt32(entry_count);header.total_size = cpu_to_fdt32(total_size);header.page_size = cpu_to_fdt32(options->page_size);header.version = cpu_to_fdt32(options->version);fseek(img_fp, 0, SEEK_SET);fwrite(&header, sizeof(header), 1, img_fp);return 0;
}

mkdtimg工具链接:
https://android-review.googlesource.com/c/platform/system/libufdt/+/347649
https://cs.android.com/android/platform/superproject/+/master:system/libufdt/utils/src/Android.bp

mkdtimg有哪些功能?

struct command_info {const char *command;void (*usage)(FILE *out_fp, const char *prog_name);  //输出命令的帮助信息int (*handler)(int argc, char *argv[], int arg_start);  //命令的处理
};static const struct command_info command_infos[] = {  //总共有4个子功能{ "help", handle_usage_help, handle_command_help },   //mkdtimg help all打印所有帮助信息{ "dump", handle_usage_dump, handle_command_dump },{ "create", handle_usage_create, handle_command_create },{ "cfg_create", handle_usage_cfg_create, handle_command_cfg_create },{ NULL, NULL, NULL }
};
  • 功能1:create 功能

./mkdtimg create <image_file> (<global_option>…) (<dtb_file>> (<entry_option>…) …)

global_options:--dt_type=<type>         Device Tree type (dtb|acpi). Default: dtb--page_size=<number>     Output page size. Default: 2048--version=<version>      DTBO version. Default: 0--id=<number|path>       The default value to set property id in dt_table_entry. Default: 0--rev=<number|path>--custom0=<number|path>--custom1=<number|path>--custom2=<number|path>--custom3=<number|path>The value could be a number or a DT node path.<number> could be a 32-bits digit or hex value, ex. 68000, 0x6800.<path> format is <full_node_path>:<property_name>, ex. /board/:id,will read the value in given FTB file with the path.
struct dt_options {#define OPTION_VALUE_SIZE_MAX 512char id[OPTION_VALUE_SIZE_MAX];  char rev[OPTION_VALUE_SIZE_MAX];char custom[4][OPTION_VALUE_SIZE_MAX];
};struct dt_global_options {   //对应上面帮助信息的global_optionsstruct dt_options default_options;enum DT_TYPE dt_type;uint32_t page_size;uint32_t version;
};struct dt_image_writer_fdt_info {char filename[1024];uint32_t dt_offset;
};struct dt_image_writer {FILE *img_fp;  //制作的镜像的文件指针struct dt_global_options global_options;  // create相关的global选项信息struct dt_options entry_options; // create相关的dt条目选项char entry_filename[1024];uint32_t entry_count; //dto的条目个数uint32_t entry_offset; //dto的条目偏移量= 开始为sizeof(struct dt_table_header),后面每次处理一个dt文件,递增sizeof(struct dt_table_entry)uint32_t dt_offset; //dt的偏移量= 开始为writer->entry_offset + sizeof(struct dt_table_entry) * entry_count;后面每次处理一个dt文件,递增 该dt文件的大小struct dt_image_writer_fdt_info *fdt_infos; // fdt信息=malloc(sizeof(struct dt_image_writer_fdt_info) * entry_count);uint32_t fdt_info_count; //fdt信息个数,开始为0,后面每次处理一个dt文件,递增1
};
// mkdtimg create <image_file> (<global_option>...) (<dtb_file>> (<entry_option>...) ...)的实际处理程序
int handle_command_create(int argc, char *argv[], int arg_start) { //arg_start = 2int ret = -1;FILE *img_fp = NULL;if (argc - arg_start < 1) {handle_usage_create(stderr, argv[0]);goto end;}const char *img_filename = argv[arg_start];  //argv[2] = "<image_file>"printf("create image file: %s...\n", img_filename);img_fp = fopen(img_filename, "wb");if (img_fp == NULL) {fprintf(stderr, "Can not create file: %s\n", img_filename);goto end;}ret = output_img_with_args(img_fp, argc, argv, arg_start + 1);  //实际的处理程序if (ret < 0) fprintf(stderr, "Can not output image with args\n");end:if (img_fp) {fclose(img_fp);if (ret < 0) unlink(img_filename);}return ret;
}
//output_img_with_args(img_fp, argc, argv, arg_start + 1);
//参数1是输出的文件,
//参数4是从(<global_option>...) (<dtb_file>> (<entry_option>...) ...)中的<global_option>...开始的
static int output_img_with_args(FILE *img_fp, int argc, char *argv[], int arg_start) { //arg_start = 3int entry_count = calculate_args_entry_count(argc, argv, arg_start); //计算参数有多少个dtb条目(非选项参数个数)struct dt_image_writer *writer = dt_image_writer_start(img_fp, entry_count);//根据dtb条目的个数来创建一个(struct dt_image_writer{ ... })结构体变量并初始化,int is_entry = 0;int i;for (i = arg_start; i < argc; i++) {char *arg = argv[i]; //循环的参数char *option, *value;if (parse_arg(&option, &value, arg) != 0) {  //解析参数,返回0为解析ok,返回-1解析失败fprintf(stderr, "Wrong syntax: %s\n", arg);return -1;}if (option == NULL) {  //解析的返回值option为NULL,说明这是一个文件名/* This is a file name */if (dt_image_writer_add_entry(writer, arg) != 0) { //循环处理dt文件://1. 将该dt文件写到img_fp文件里面,由于开始writer->entry_filename赋值为"\0",所以直接return 0,不写dt文件到img_fp文件//2. 将dt文件名保存在writer->entry_filename//3. 将writer->global_options.default_options的选项赋值到writer->entry_optionsreturn -1;}is_entry = 1;continue;} //否则,解析的返回值option不为NULL,说明这是一个选项,接下来做选项处理int ret = is_entry ? //根据is_entry(是一个条目)这个变量判断来设置条目选项还是全局选项set_entry_options(writer, option, value) :set_global_options(writer, option, value);if (ret != 0) {fprintf(stderr, "Unknown option: %s\n", option);return -1;}} /* for all argv */if (dt_image_writer_end(writer) != 0) { //写最后一个dt文件到镜像,写镜像头到镜像return -1;}return 0;
}
  • 功能2:cfg_create 功能

与create功能相同,均是create dtb/dtbo镜像,区别在于create是从命令行读取参数,cfg_create是从配置文件中读取相关参数
$ mkdtimg cfg_create
mkdtimg cfg_create <image_file> <config_file> (…)

options:-d, --dtb-dir            The path to load dtb files.Default is load from the current path.
  • 功能3:dump 功能

$ mkdtimg dump
mkdtimg dump <image_file> (…)

options:-o, --output <filename>  Output file name.Default is output to stdout.-b, --dtb <filename>     Dump dtb/dtbo files from image.Will output to <filename>.0, <filename>.1, etc.
  • 功能4:help 功能

$ mkdtimg help
mkdtimg help all mkdtimg help

commands:help, dump, create, cfg_create

http://chatgpt.dhexx.cn/article/9OGrMLmf.shtml

相关文章

2.2设备树的规范(dts和dtb)——DTB格式

本节讲述设备树的dtb格式。 上节讲述了dts格式。回顾上节&#xff0c;在dts文件和dtsi文件中&#xff0c;可以使用C语言的define和include&#xff0c;使用方法和作用也同C语言相同。 编写dts文件后&#xff0c;需要使用dtc工具将dts文件编译成dtb文件。dtc工具可以检查dts文…

「设备树」dtb给内核的两种工作模式

一&#xff0c;传递dtb给内核 对于传统bootloader提供两种工作模式&#xff1a;一是启动加载模式&#xff08;start loading&#xff09;&#xff0c;一是下载模式&#xff08;downloading&#xff09; 工作在启动加载模式时&#xff0c;bootloader会自动执行bootcmd命令&#…

设备树_dtb文件分析

前言&#xff1a;我之前的原计划是没有打算写设备树dtb文件分析&#xff0c;但是情势所迫啊&#xff01;&#xff0c;学习还是要一步一步来的。 在前面的章节提到过.dts文件以文本方式对系统设备树进行描述&#xff0c;经过Device Tree Compiler(dtc)将dts文件转换成二进制文件…

Linux设备树学习2 - DTB文件格式

一. DTB文件简介 DTB文件是由DTS文件通过dtc命令编译生成的二进制文件。DTS文件不能直接被内核解析&#xff0c;需要编译成DTB文件才可以直接被内核识别并解析使用的。 二. DTB文件内容布局 从上图可以看出&#xff0c;DTB由四个部分组成&#xff0c;分别是struct fdt_header&a…

setUserVisibleHint-- fragment真正的onResume和onPause方法

这个情况仅适合与多个fragment之间切换时统计&#xff0c;而非activity和fragment同时交互&#xff0c;因当时项目为首页4个fargment时长统计&#xff0c;因此适合&#xff0c;经下面网友评论指出&#xff0c;特在这里写出此问题&#xff0c;因最近项目较忙&#xff0c;具体情况…

onCreate与onStart区别,onStart与onResume区别

http://www.cnblogs.com/kofi1122/archive/2011/04/10/2011772.html Activity生命周期之我见 关于Activity生命周期的文章很多&#xff0c;而且大部分也说得很详细&#xff0c;所以作为关于这方面的内容我本来不想多说&#xff0c;但是大家可能跟我之前一样&#xff0c;在看这方…

Flutter BaseWidget 实现onResume、onPause()

熟读唐诗三百首&#xff0c;不会作诗也会吟。——孙洙 最近用Flutter开发的项目算是完成了开发到上线第一阶段了。任何一个项目开始了&#xff0c;若想追求的是更好&#xff0c;那么就需要下功夫对项目用户体验和代码效率深入的研究了。作为用户和产品经理、老板、UI、不懂技术…

Activity生命周期中onStart()和onResume()的区别

Activity生命周期中onStart()和onResume()的区别 在讲onStart()和onResume()的区别之前&#xff0c;必须清楚Activity的四种状态&#xff1a; 1.Running状态&#xff1a;一个新的Activity的启动入栈后&#xff0c;它在屏幕最前端&#xff0c;处于栈的最顶端&#xff0c;此时它…

android Activity的onPause()与onResume()

官方文档地址&#xff1a;http://www.android-doc.com/training/basics/activity-lifecycle/pausing.html#Resume Pause和Resume一个Activity 在一般的app使用中&#xff0c;前台的activity一般是会被视觉组件所遮住的&#xff0c;这就会导致activity的pause。举个例子&#x…

android中onResume、onPause等方法

程序正常启动&#xff1a;onCreate()->onStart()->onResume(); 正常退出&#xff1a;onPause()->onStop()->onDestory() 程序按back 退出&#xff1a; onPause()->onStop()->onDestory(),再进入&#xff1a;onCreate()->onStart()->onResume(); 程序按…

OnStart()方法和OnResume()方法的区别

文章目录 一、Activity的生命周期简述在讲onStart()和onResume()的区别之前&#xff0c;必须清楚Activity的四种状态&#xff1a; 二、OnStart()和OnResume()方法的区别区别&#xff1a; 总结 一、Activity的生命周期简述 在讲onStart()和onResume()的区别之前&#xff0c;必须…

简单介绍几种Java后台开发常用框架组合

01 前言 Java框架一直以来都是面试必备的知识点&#xff0c;而掌握Java框架&#xff0c;不管在成熟的大公司&#xff0c;快速发展的公司&#xff0c;还是创业阶段的公司&#xff0c;都能对当前正在开发中的系统有整体的认知&#xff0c;从而更好的熟悉和学习技术&#xff0c;这…

用IDEA进行Java后台开发(一)

想尝试着进行java后台开发&#xff0c;发现能找到的完整工程教程很多都是用eclipse开发的&#xff0c;于是照着搭了一套开发环境&#xff0c;也简单的写了一个测试代码&#xff0c;由于好几年没有使用eclipse了&#xff0c;快捷键实在用的费劲&#xff0c;遂找到了IDEA这个开发…

Java后台学习路线

2021.01.31.更新 2018.11.10更新&#xff0c;请看文章末尾惊喜 或者点击 https://blog.csdn.net/qq_40374604/article/details/83932163 本文摘自---https://blog.csdn.net/u014624241/article/details/52946378---感谢作者的分享 ①一段摘自知乎的文档 Java就业方向目前主…

Java后台开发一:环境搭建

很久之前就想做Java后台开发了&#xff0c;苦于一直没有找到合适的后台开发教程&#xff0c;某日发现一篇很不错的Java后台开发配置文章&#xff0c;记录如下&#xff1a; jdkeclipsesvnmavenmysqltomcat7.0sublime安装包和jar插件 配置管理工具-SVN http://download.csdn.net/…

Java后台开发知识一览

Java后台开发知识一览 1、后端 WEB服务器&#xff1a;Weblogic、Tomcat、WebSphere、JBoss、Jetty 核心框架&#xff1a;Spring Framework 分布式服务框架 Dubbo&#xff08;感谢浅浅浅丿忧伤指正&#xff09; 安全框架&#xff1a;Apache Shiro 视图框架&#xff1a;Spr…

Java后台开发常见官方网站汇总

Java后台开发常见官方网站汇总 写在前面开发工具篇JDKJavaSE开发文档Oracle数据库&#xff08;收费&#xff09;MySQL数据库&#xff08;免费&#xff09;RedisMongoDBJDBCDruid连接池ElasticsearchKibana——Elasticsearch的客户端RabbitMQMavenGitSpring Framework&#xff0…

【Java后台开发规范】--- 日志的输出

文章目录 前言其他类型的规范 日志输出过多日志重复打印批量打印日志中带方法讲故事日志跟踪其他基本要求 前言 做Java开发的&#xff0c;大多数可能都有看过阿里的Java后台开发手册&#xff0c;里面有关于Java后台开发规范的一些内容&#xff0c;基本覆盖了一些通用、普适的规…

用IDEA进行Java后台开发(二)

这篇博客接上一篇&#xff0c;用IDEA进行Java后台开发&#xff08;一&#xff09; 上一篇我们已经将工程创建完成了&#xff0c;下面我们将创建一个Servlet&#xff0c;然后本地启动tomcat后调用接口&#xff0c;返回helloWorld&#xff0c;过程如下&#xff1a; 1.在src目录…

Java后台开发入门

转载自: 梦回河口&#xff1a;http://blog.csdn.net/zxc514257857/article/details/71152003 1&#xff0c;什么是Web应用程序 Web应用程序是可以通过Web进行访问的应用程序&#xff0c;最大的好处是访问非常容易。比如淘宝、新浪、网易等门户网站   软件开发领域的三大方向…