ota-burnboot介绍
2 ota-burnboot 介绍
2.1 文档说明
此文档主要介绍如何在OTA 时升级boot0/uboot。
升级工具包含两个方面内容:
OTA 命令升级boot0 和uboot。
OTA 升级boot0 和uboot 的C/C++ APIs。
2.2 概念说明
概念 | 说明 |
---|---|
boot0 | 较为简单, 主要作用是初始化dram 并加载运行uboot。一般不需修改。 |
uboot | 功能较丰富, 支持烧写, 启动内核, 烧key 及其他一些定制化的功能。 |
sys_config | 全志特有的配置文件, 对于使用linxu3.4/uboot2011 的平台, 在打包之 后sys_config 会跟uboot 拼接到一起。对于使用 linux3.10/uboot2014 及更高版本的平台,sys_config 会在打包阶段, 跟设备树的配置合并, 生成最终的dtb。linux5.4 开始不再合并到 dtb。 |
dtb | 设备树, 由dts 配置和sys_config 配置综合得到。 |
u-boot.fex | 使用linxu3.4/uboot2011 的平台最终用到的uboot, 其实是 uboot+sys_config。 |
boot_package.fex | 使用linux3.10/uboot2014 及更高版本的平台最终用到的uboot, 其 实包含的文件由配置文件boot_package.cfg 决定, 一般至少包含了 uboot 和dtb, 安全方案会包含一些安全所需文件文件, 可能还有 bootlogo 等文件。 |
toc0.fex | 安全方案使用的boot0。 |
toc1.fex | 安全方案使用的uboot, 类似boot_package.fex 说明, 其中实际也包 含了dts 等多个文件。 |
即, 本文介绍的升级uboot, 其实是升级uboot+dtb 这样的一个整体文件。后文不再区分更新uboot, 更新sys_config, 更新dtb。这几个打包完毕是合成一个文件的,
暂不支持单独更新其中一个, 需整体更新。
2.3 用于更新的bin 文件
获取用于OTA 的boot0 与uboot 的bin 文件, 用于加入OTA 包中。
2.3.1 编译boot0 uboot
如果原本的固件生成流程已经包含编译uboot, 则正常编译固件即可。
否则可按照如下步骤编译生成uboot
$ source build/envsetup.sh
=> 设置环境变量。
$ lunch
=> 选择方案。
$ muboot
=> 编译uboot。
$ mboot0
=> 编译boot0 (注意,此命令在大多数平台无效,因为boot0不开源,SDK中提供了编译好的bin文件)。
编译后会自行拷贝bin 文件到该平台的目录下, 即:
对于tina3.5.0 及之前版本,路径为:
对于tina3.5.1 及之后版本,路径为:
编译出的boot0/uboot 还不能直接用于OTA, 请继续编译和打包固件, 如执行:
$ make -j <N>
=> 编译命令,若只修改boot0/uboot/sys_config 无需重新编译,可跳过。
=> 若修改了dts 则需要执行,重新编译。
$ pack [-d]。
=> 非安全方案的打包命令。
$ pack -s [-d]
=> 安全方案的打包命令。
2.3.2 关于更新boot0
大多数平台,代码环境中并不包含boot0 相关代码, 因此无法编译boot0。
一般情况下并不需要修改boot0, 而是直接使用提供的boot0 的bin 文件即可。少部分平台提供了可编译的boot0 代码,可使用mboot0 编译。
2.3.3 Bin 文件路径
2.3.3.1 使用uboot2011 的非安全方案
以R16 的astar-parrot 方案为例。
根据对应存储介质选择bin。
boot0:
out/astar-parrot/image/boot0_nand.fex :nand 方案使用的boot0。
out/astar-parrot/image/boot0_sdcard.fex :mmc 方案使用的boot0。
out/astar-parrot/image/boot0_spinor.fex :nor 方案使用的boot0。
uboot:
out/astar-parrot/image/u-boot.fex :nand/mmc 方案使用的uboot。
out/astar-parrot/image/u-boot-spinor.fex :nor 方案使用的uboot。
2.3.3.2 使用uboot2014 及更高版本的非安全方案
以R6 的sitar-evb 方案为例。
根据对应存储介质选择bin。
boot0:
out/sitar-evb/image/boot0_nand.fex :nand 方案使用的boot0。
out/sitar-evb/image/boot0_sdcard.fex :mmc 方案使用的boot0。
out/sitar-evb/image/boot0_spinor.fex :nor 方案使用的boot0。
uboot:
out/sitar-evb/image/boot_package.fex :nand/mmc 方案使用的uboot。
out/sitar-evb/image/boot_package_nor.fex :nor 方案使用的uboot。
2.3.3.3 安全方案
以R18 的tulip-noma 方案为例。
boot0:
uboot:
2.4 OTA 升级命令
2.4.1 支持OTA 升级命令
升级boot0 与uboot 分别使用ota-burnboot0 与ota-burnuboot 命令。
两个命令都是OTA 升级boot0 和uboot 的C/C++ APIs 的封装。
要支持本功能, 需要选中ota-burnboot 的包, 即:
2.4.2 ota-burnboot0
2.4.2.1 命令说明
升级boot0, 其中boot0-image 是镜像的路径。
请注意, 安全和非安全方案所使用的boot0-image 是不同的, 具体见“用于更新的bin 文件” 章节。
2.4.2.2 使用示例
2.4.3 ota-burnuboot
2.4.3.1 命令说明
升级uboot, 其中uboot-image 是镜像的路径。请注意, 安全和非安全方案, 不同的uboot 版本,所使用的uboot-image 是不同的,具体见第二章。
2.4.3.2 使用示例
2.5 OTA 升级C/C++ APIs
包含头文件OTA_BurnBoot.h,使用库libota-burnboot.so
2.5.1 int OTA_burnboot0(const char *img_path)
函数原型 | int OTA_burnboot0(const char *img_path); |
---|---|
参数说明 | img_path:boot0 镜像路径 |
返回说明 | 0:成功; 非零:失败 |
功能描述 | 烧写boot0 |
2.5.2 int OTA_burnuboot(const char *img_path)
函数原型 | int OTA_burnuboot(const char *img_path); |
---|---|
参数说明 | img_path:uboot 镜像路径 |
返回说明 | 0:成功; 非零:失败 |
功能描述 | 烧写uboot |
2.6 底层实现
2.6.1 如何保证安全更新boot0/uboot
前提条件是,flash 中存有不止一份boot0/uboot。在这个基础上, 启动流程需支持校验并选择完整的boot0/uboot 进行启动, 更新流程需保证任意时刻掉电,flash 上
总存在至少一份可用的boot0/uboot。
2.6.2 Nand Flash NFTL 方案实现
在nand nftl 方案中,boot0 和uboot 是由nand 驱动管理, 保存在物理地址中, 逻辑分区不可见。
Nand 驱动会保存多份boot0 和uboot, 启动时, 从第一份开始依次尝试, 直到找到一份完整的boot0/uboot 进行使用。
更新boot0/uboot 时, 上层调用nand 驱动提供的接口, 驱动中会从第一份开始依次更新, 多份全部更新完毕后返回。因此可保证在OTA 过程中任意时刻掉电,flash
中均有至少一份完整的boot0/uboot 可用。再次启动后, 只需重新调用更新接口进行更新, 直到调用成功返回即可。
目前nand 中的多份boot0/uboot 是由nand 驱动管理的, 只能整体更新, 暂不支持单独更新其中的一份。
2.6.3 Nand Flash UBI 方案实现
在nand ubi 方案中, boot0 一般存放于mtd0 中,uboot 存放于mtd1 中。
与nftl 方案一样,底层实际是保存多份boot0 和uboot。启动时, 从第一份开始依次尝试, 直到找到一份完整的boot0/uboot 进行使用。对上提供多份统一的更新接
口,软件包会通过对mtd的iotcl 接口发起更新。
注:用户空间直接读写/dev/mtdx 节点,需要内核使能CONFIG_MTD_CHAR=y。
2.6.4 MMC Flash 实现
在mmc 方案中, boot0 和uboot 各有两份, 存在mmc 上的指定偏移处, 逻辑分区不可见。需要读写可直接操作/dev/mmcblk0 节点的指定偏移。
具体位置:
1 sector = 512 bytes = 0.5k。
boot0/toc0 保存了两份,offset1: 16 sector, offset2: 256 sector。
uboot/toc1 保存了两份,offset1: 32800 sector, offset2: 24576 sector。
启动时会先读取offset1,如果完整性校验失败,则读取offset2。
更新时, 默认只更新offset1, 而offset2 是保持在出厂状态的。只要offset1 正常更新了, 则启动时会优先使用。如果在更新offset1 的过程中掉电导致数据损坏, 则自
动使用offset2 进行启动。
如需定制策略,例如改成每次offset1 和offset2 均更新,可自行修改ota-burnboot 代码。
2.6.5 NOR Flash 实现
nor 方案中, 只保存一份boot0 和uboot, 更新过程中掉电可能导致无法启动, 只能进行刷机。故目前未实现ota 更新, 需后续扩展。