IVT、Boot Data structures、DCD是I.MX6启动时的重要数据和配置。IVT中包含Boot Data structures、DCD地址定位的信息。
BOOT ROM 根据这些地址定位找到DCD的存储位置,使用DCD中的配置参数,来初始化DDR,配置时钟,以及其他启动时必要的硬件设置。
Boot Data structures中包含数据拷贝的目标地址和长度, BOOT ROM会在必要的检查和上述的初始化之后,将启动设备中的数据拷贝
到该目标地址中(通常是DDR),然后跳转到IVT中的entry执行程序镜像。
以下的分析中,我们忽略CSF的使用,CSF只用在High Assurance Boot中,有兴趣可参见I.MX6参考手册中的相关描述。
1. I.MX6 BOOT ROM启动流程中IVT、DCD等相关数据操作
当我们选择从SPI FLASH启动时,BOOT ROM会拷贝启动设备SPI FLASH中的前4K bytes数据到片内RAM(OCRAM)。
这初始的4K数据中必须包含IVT(Image vector table)、DCD(Device configuration data)和Boot Data structures,
但由于使用SPI FLASH启动时,IVT的偏移为1K,所以,可以说剩余的3K数据中必须包含IVT、DCD和Boot Data structures。
另外DCD最大长度限制为1768 bytes。
BOOT ROM拷贝SPI FLASH 4K的数据到内部RAM(OCRAM)中去,这4K的空间包含1K的空余头(通常内含分区表)和内含IVT、DCD的数据块。
接着BOOT ROM检查OCRAM 4K数据中包含的IVT头标志0xD1,然后执行DCD检查。这些检查无误通过后,从boot data structure 中解析出
下一步拷贝的目的地址和长度(记为length),然后从SPI FLASH地址0,拷贝长度length的数据到上面解析出的目的地址处。
这里有一个如何在OCRAM中定位boot data structure地址的问题。我们编译生成的u-boot.imx,它的boot data内容即为boot data structure
的地址,而该地址是一个绝对地址,实际为DDR地址,而OCRAM中此时的地址还是原始数据中的该地址。由于此时DDR还未准备好,还未执行
u-boot.imx到DDR的拷贝,BOOT ROM不能使用boot data中的绝对(DDR地址)地址来定位boot data structure。而只能使用偏移地址在
OCRAM中定位boot data structure。   
注意IVT中还有一个self表项,它指向它自身,即IVT的首地址。比如hexdump出u-boot.imx的self的值为0x177ff400,boot_data的值为
0x177ff420,那么boot data structure的地址偏移为
boot data structure  offset = boot_data - self(IVT首地址) = 0x20,
加载到OCRAM中后,boot data structure的有效地址为:OCRAM IVT 加载首地址 + boot data structure  offset,
DCD数据的地址也是如此计算的。
上述过程用C语言伪码描述为:
#define  BOOT_ROM_COPY_DATA_LEN 0x1000  /×4 K bytes */
#define  IVT_OFFSET  0x400
typedefstruct{uint8_t tag;uint16_t length;uint8_t version;
}ivt_header_t;
typedefstruct{ivt_header_t header;uint32_tentry;uint32_treserved1;uint32_tdcd_ptr;uint32_tboot_data_ptr;uint32_tself;uint32_tcsf;uint32_treserved2;
} ivt_t;
typedefstruct{uint32_tstart;uint32_tsize;uint32_tplugin;
}boot_data_t;uint32_t *ocram_load_ptr;
ivt_header_t*ivt_h;
ivt_t  *ivt;
boot_data_t   *boot_data_ptr;
ocram_load_ptr=malloc(OCRAM,BOOT_ROM_COPY_DATA_LEN);
copy_to_ocram(spi_flash_addr0,BOOT_ROM_COPY_DATA_LEN, ocram_load_ptr);
ivt_h  =(ivt_header_t *)(ocram_load_ptr+ IVT_OFFSET);
ivt   =(ivt_t*)(ocram_load_ptr+ IVT_OFFSET);
if(ivt_h->tag!=0xD1){trace"invalid ivt head tag";return-1;
}/*DCD有效性检查*/
......
/*调用DCD中的命令,对DDR、时钟等进行配置*/
......
/*DDR已可用*/boot_data_ptr =(boot_data_t *)(ocram_load_ptr +(ivt->dcd_ptr-ivt->self));
copy_to_ddr(boot_data_ptr->start,boot_data_ptr->size,spi_flash_addr0);
jump_to ivt->entry;
执行完boot_data_ptr中地址和长度的数据拷贝后,我们假定u-boot的加载地址为0x17800000,SPI Flash和DDR RAM的内存镜像图如下:
2. 构建系统生成包含IVT、boot Data、DCD等头部的镜像文件u-boot.imx
2.1 u-boot-2009.8版本
在u-boot-2009.8中,IVT、boot Data、DCD在汇编文件flash_header.S实现:
ivt_header: .word 0x402000D1 /* Tag=0xD1, Len=0x0020, Ver=0x40 */
app_code_jump_v: .word _start
reserv1: .word 0x0
dcd_ptr: .word dcd_hdr
boot_data_ptr: .word boot_data
self_ptr: .word ivt_header
#ifdef CONFIG_SECURE_BOOT
app_code_csf: .word __hab_data
#else
app_code_csf: .word 0x0
#endif
reserv2: .word 0x0boot_data: .word TEXT_BASE
#ifdef CONFIG_SECURE_BOOT
image_len: .word __hab_data_end - TEXT_BASE + CONFIG_FLASH_HEADER_OFFSET
#else
image_len: .word _end_of_copy - TEXT_BASE + CONFIG_FLASH_HEADER_OFFSET
#endif
plugin: .word 0x0dcd_hdr: .word 0x40E001D2 /* DDR cfg Tag=0xD2, Len=59*8 + 4 + 4, Ver=0x40 */write_dcd_cmd: .word 0x048402CC /* Tag=0xCC, Len=80*8 + 4, Param=0x04 */
/* DCD *//* DDR3 initialization based on the MX6Solo Auto Reference Design (ARD) */
/* DDR IO TYPE */
MXC_DCD_ITEM(1, IOMUXC_BASE_ADDR + 0x774, 0x000c0000)
MXC_DCD_ITEM(2, IOMUXC_BASE_ADDR + 0x754, 0x00000000)/* CLOCK */
MXC_DCD_ITEM(3, IOMUXC_BASE_ADDR + 0x4ac, 0x00000030)
MXC_DCD_ITEM(4, IOMUXC_BASE_ADDR + 0x4b0, 0x00000030)
......
上述代码中,部分包含地址的变量和其目标地址的关系图如下:
u-boot构建系统会将此文件编译后,连同u-boot.bin文件链接生成最终的u-boot.imx。
另外,我们看到,上面的ivt_header和dcd_hdr,均是以0x40开头的tag,而i.mx6的用户参考手册reference manual中
该值应为0x41,对此,论坛上有如下解释:
https://community.nxp.com/message/408223
Really i.MX6 is one of HAB 4.1, the mentions about ver. 4.0 are derivative
from i.MX53 and do not influence on HAB functionality. One of main differences
between the ver. 4.1 and ver. 4.0 is ability for the rev. 4.1 to support Encrypted
Boot by ROM.
由于u-boot-2009.8版本已为过时的版本,在此不再多做分析。
2.1 u-boot-2015.07版本
u-boot-2015.07及以后的版本中,更改了u-boot.imx的产生方式,不再使用上述的flash_header.S,
而是使用mkimage工具直接生成。此处使用的mkimage包含的目标文件类型-T参数中新增了imximage选项,
mkimage会调用格式类型imximage的解释器来生成针对i.mx(5系6系)系列芯片的 IVT、boot Data、DCD的格式头。具体的代码
实现在tools/imximage.c中。
我们以boundary的nitrogen6q开发板为例,当构建系统执行:
./tools/mkimage -n board/boundary/nitrogen6x/nitrogen6q.cfg.cfgtmp -T imximage -e 0x17800000 -d u-boot.bin u-boot.imx
其中-n指明输入文件为nitrogen6q.cfg.cfgtmp,-T指明解释器为imximage,-e为镜像程序入口点。
mkimage调用选项-T的imximage 解释器解析输入文件nitrogen6q.cfg.cfgtmp,而文件nitrogen6q.cfg.cfgtmp为nitrogen6q.cfg编译时
预处理(使用gcc -E选项)后产生的临时文件。nitrogen6q.cfg的内容如下:
/* image version */
IMAGE_VERSION 2/** Boot Device : one of* spi, sd (the board has no nand neither onenand)*/
BOOT_FROM      spi#define __ASSEMBLY__
#include <config.h>
#include "asm/arch/mx6-ddr.h"
#include "asm/arch/iomux.h"
#include "asm/arch/crm_regs.h"#include "ddr-setup.cfg"
#include "1066mhz_4x128mx16.cfg"
#include "clocks.cfg"
注意,其中包含的IMAGE_VERSION 2和BOOT_FROM      spi,它们将在下面会被使用。
该文件预处理后会将ddr-setup.cfg、1066mhz_4x128mx16.cfg、clocks.cfg的内容复制到nitrogen6q.cfg.cfgtmp中,而
前三个文件即为DCD配置文件,如ddr-setup.cfg的内容为:
DATA 4, MX6_IOM_DRAM_SDQS0, 0x00000030
DATA 4, MX6_IOM_DRAM_SDQS1, 0x00000030
DATA 4, MX6_IOM_DRAM_SDQS2, 0x00000030
DATA 4, MX6_IOM_DRAM_SDQS3, 0x00000030
如MX6_IOM_DRAM_SDQS0 又在文件arch/arm/include/asm/arch/mx6q-ddr.h中定义:
#define MX6_IOM_DRAM_SDQS0    0x020e05a8
预处理后为(删除了空行和注解):
IMAGE_VERSION 2
BOOT_FROM spi
DATA4,0x020e05a8,0x00000030
DATA4,0x020e05b0,0x00000030
DATA4,0x020e0524,0x00000030
DATA4,0x020e051c,0x00000030
接下来我们分析imximage.c代码中相关处理:
函数的调用流程为:parse_cfg_file-->parse_cfg_fld-->parse_cfg_cmd-->设置imximage_ivt_offset。
下面我们主要分析配置解析函数parse_cfg_cmd:
statictable_entry_t imximage_boot_offset[]={{FLASH_OFFSET_ONENAND,  "onenand",  "OneNAND Flash",},{FLASH_OFFSET_NAND, "nand",     "NAND Flash",   },{FLASH_OFFSET_NOR,  "nor",      "NOR Flash",    },{FLASH_OFFSET_SATA, "sata",     "SATA Disk",    },{FLASH_OFFSET_SD,   "sd",       "SD Card",  },{FLASH_OFFSET_SPI,  "spi",      "SPI Flash",    },{FLASH_OFFSET_QSPI, "qspi",     "QSPI NOR Flash",},{-1,            "",     "Invalid",  },
};staticvoidparse_cfg_cmd(structimx_header*imxhdr,int32_t cmd,char*token,char*name,intlineno,intfld,intdcd_len)
{intvalue;staticintcmd_ver_first=~0;switch(cmd){caseCMD_IMAGE_VERSION:imximage_version=get_cfg_value(token,name,lineno);......set_hdr_func();break;caseCMD_BOOT_FROM:imximage_ivt_offset=get_table_entry_id(imximage_boot_offset,......break;caseCMD_BOOT_OFFSET:imximage_ivt_offset=get_cfg_value(token,name,lineno);......break;......}
}
函数parse_cfg_cmd使用前导函数从输入文件nitrogen6q.cfg.cfgtmp取出的参数,当参数是CMD_IMAGE_VERSION,它对应
nitrogen6q.cfg.cfgtmp文件中的MAGE_VERSION 2,然后调用get_cfg_value得到版本号为2。imximage的头格式分版本号1和2。
同理CMD_BOOT_FROM,对应于nitrogen6q.cfg.cfgtmp文件中的BOOT_FROM   spi,调用get_table_entry_id在
表imximage_boot_offset找到spi对应的偏移量FLASH_OFFSET_SPI(它在文件imximage.h中定义为0x400,这里反映了不同
的启动设备其IVT偏移量的不同)。后续的操作以此为参数,然后联合其他的解析结果,生成总的结构体imx_header_v2_t,
最后mkimage将这个结构体插入文件u-boot.bin的头部,生成u-boot.imx文件。
另外,我们可以在文件imximage.c中的函数print_hdr_v2结尾处增加如下代码,在终端中输出产生的头部信息:
    printf("\n--------------------------------------\n");printf("tag:        0x%04x\n", (uint8_t)fhdr_v2->header.tag);printf("length:     0x%04x\n", (uint16_t)fhdr_v2->header.length);printf("version:    0x%04x\n", (uint8_t)fhdr_v2->header.version);printf("\n");printf("entry:         0x%08x\n", (uint32_t)fhdr_v2->entry);printf("reserved1:     0x%08x\n", (uint32_t)fhdr_v2->reserved1);printf("dcd_ptr:       0x%08x\n", (uint32_t)fhdr_v2->dcd_ptr);printf("boot_data_ptr: 0x%08x\n", (uint32_t)fhdr_v2->boot_data_ptr);printf("self:          0x%08x\n", (uint32_t)fhdr_v2->self);printf("csf:           0x%08x\n", (uint32_t)fhdr_v2->csf);printf("reserved2:     0x%08x\n", (uint32_t)fhdr_v2->reserved2);printf("\n");printf("db start:      0x%08x\n", (uint32_t)db->start);printf("db size:       0x%08x\n", (uint32_t)db->size);printf("db plugin:     0x%08x\n", (uint32_t)db->plugin);printf("--------------------------------------\n\n");
在u-boot源码中重新编译主机程序mkimage:
u-boot$make tools-only
然后单独执行mkimage命令:
u-boot$./tools/mkimage -n board/boundary/nitrogen6x/nitrogen6q.cfg.cfgtmp -T imximage -e 0x17800000 -d u-boot.bin u-boot.imx
相应的输出结果大致如下:
tag:        0x00d1
length:     0x2000   the overall length of the IVT in bytes, including the header. (the length is fixed and must have a value of 32 bytes),8K????
version:    0x0040entry:          0x17800000
reserved1:      0x00000000
dcd_ptr:        0x177ff42c
boot_data_ptr:  0x177ff420
self:           0x177ff400
csf:            0x00000000
reserved2:      0x00000000db start:       0x177ff000
db size:        0x00075000
db plugin:      0x00000000

I.MX6 u-boot.imx中IVT、DCD等头部数据的生成相关推荐

  1. excel中如何et vb根据数据自动生成表格_如何实现excel与PPT互联互通(动态生成PPT)...

    因为经常要做周报.月报PPT,每次重复的的操作效率很低,这里整理了一套可以自动生成PPT的办法. 首先,大概思路是这样的.周报.月报这类经营分析类PPT一般都是由表格.图表以及分析文字组成的,整体结构 ...

  2. Mysql 向表中插入50万条数据(生成随机字符串和 插入的时间间隔是60s)。

    /*rand_string: 生成一个长度为n的随机字符. 注意这个n必须小于'abcdefghijklmnopqrstuvwxyz0123456789' 的长度*/ DROP FUNCTION IF ...

  3. ArcGIS中的TIN与DEM数据的生成

    1.TIN与DEM 的生成 1.1由高程点等高线生成TIN 向软件添加四个图层 勾选3D Analyst 打开工具栏上的自定义-自定义模式,在命令搜索里面搜索从要素创建TIN,将其图标拖到工具栏上,再 ...

  4. ARM(IMX6U)裸机之I.MX6ULL启动头文件详解(内部BOOT ROM、IVT + Boot data + DCD + led.bin)

    参考:Linux之ARM(IMX6U)裸机之I.MX6ULL镜像烧写以及启动头文件的详解 作者:一只青木呀 发布时间: 2020-08-09 17:10:00 网址:https://blog.csdn ...

  5. Guava Cache本地缓存在 Spring Boot应用中的实践

    概述 在如今高并发的互联网应用中,缓存的地位举足轻重,对提升程序性能帮助不小.而 3.x开始的 Spring也引入了对 Cache的支持,那对于如今发展得如火如荼的 Spring Boot来说自然也是 ...

  6. spring boot 项目源码_Spring Boot2 系列教程(三)理解 Spring Boot 项目中的 parent

    前面和大伙聊了 Spring Boot 项目的三种创建方式,这三种创建方式,无论是哪一种,创建成功后,pom.xml 坐标文件中都有如下一段引用: <parent><groupId& ...

  7. Spring Boot 配置中的敏感信息如何保护?

    在之前的系列教程中,我们已经介绍了非常多关于Spring Boot配置文件中的各种细节用法,比如:参数间的引用.随机数的应用.命令行参数的使用.多环境的配置管理等等. 这些配置相关的知识都是Sprin ...

  8. 在Spring Boot项目中使用Spock框架

    转载:https://www.jianshu.com/p/f1e354d382cd Spock框架是基于Groovy语言的测试框架,Groovy与Java具备良好的互操作性,因此可以在Spring B ...

  9. scheduled每天下午1点执行一次_在Spring Boot项目中使用@Scheduled注解实现定时任务...

    在java开发中定时任务的实现有多种方式,jdk有自己的定时任务实现方式,很多框架也有定时任务的实现方式.这里,我介绍一种很简单的实现方式,在Spring Boot项目中使用两个注解即可实现. 在sp ...

最新文章

  1. Android SQLite数据库之事务的学习
  2. Vcastr 2.2 flv 网络播放器 参数设置
  3. 装上后这 14 个插件后,PyCharm 真的是无敌的存在
  4. python 遍历字典
  5. 如何造出逼真图像?南洋理工Zheng博士论文《基于深度生成学习的逼真图像合成》197页pdf阐述视觉合成工作...
  6. TCP,IP,HTTP,SOCKET区别和联系
  7. Java实现找出数组中重复次数最多的元素以及个数
  8. fastText中常见问题汇总
  9. ElementUI中el-table设置指定列固定不动,不受滚动条影响
  10. 《Python Cookbook 3rd》笔记(2.18):字符串令牌解析
  11. Linux系统编程 / triggerhappy 源码分析(3.select 的应用)
  12. 第八章:软件包的安装与管理
  13. [NOI2014] 动物园
  14. [物理学与PDEs]第2章第4节 激波 4.2 熵条件
  15. 网易校招——魔法币问题
  16. 最新最全 快递公司编码 更新时间2020.07.31
  17. php怎么求最小公倍数,最小公倍数算法
  18. opencv中step[i],step1(i),elemsize,elemsize1
  19. 全面提高你的搜索技巧
  20. 【踩坑记录】priority_queue 第三个模板参数和sort 的第三个形参的区别;仿函数、自定义排序函数、lambda 函数分别传入;传入类型和对象的区别;

热门文章

  1. 梦幻之旅游戏开发--辅助知识的了解
  2. 使用开源安装包制作工具Inno Setup制作软件安装包
  3. 25个典型的下一代互联网公司
  4. win10防火墙怎么关闭端口?
  5. Linux下gcc编译c程序生成可执行文件的过程
  6. vue template html属性,详解template标签用法(含vue中的用法总结)
  7. 悲剧!中小企业惨痛的外训经历!
  8. Java 封装基础知识
  9. C++学习(八十四)explicit和implicit
  10. text shadow 兼容ie