BootLoader与OTA升级
前言
本文使用的工程环境为:CLion、CubeMX、STM32G431
一个量产产品,出厂时必定会关闭调试接口如SWD、JTAG(如提升RDP等级)以避免重要的程序泄露或被注入漏洞,但出厂后在它的全生命周期中仍有升级程序的需要,这就要求做好bootloader与OTA的工作。
- BL:固件的完整性校验(CRC32、SHA256哈希),验权(RSA)、A/B分区切换
- OTA:通过标准通信通道,如UART、BLE、CAN/LIN刷写固件
仓库地址:https://github.com/Dikle-OvO/BootLoaderTest
基础
XIP机制
XIP(eXecute In Place,就地执行),是指CPU可以直接在存储介质如FLASH中取指的技术,这种技术在MCU中比较常见,通用Linux系统(包括内核、BL)几乎不会用到XIP,必须搬运到RAM,除非使用squashfs,XIP模式内核直接挂载读取,否则都要使用ram(Linux的页缓存机制,题外话:写入也有相关的机制,这也是sync命令的作用)
FLASH零等待
指MCU储存访问的理想状态,特指CPU访问储存介质时无需插入等待周期,通过预取指缓冲实现,接近RAM的运行水平,是XIP模式的天花板。
反之,若 Flash XIP 是 1 等待,意味着每读取一次指令要多等 1 个时钟周期,480MHz 主频的实际等效性能会降到 240MHz。
无校验跳转
先从最简单的无校验跳转开始,新建一个led闪烁函数,BL程序函数如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14//1.定义APP地址
uint32_t APP_ADDRESS=0x08008000;
typedef void (*pFunction) (void);
void JumpToApplication(void) {
if (((*(__IO uint32_t*)APP_ADDRESS) & 0x2FFE0000) == 0x20000000) {
//2.将中断向量长重定向到应用程序地址
SCB->VTOR=APP_ADDRESS;
//3.获取应用程序的栈顶地址和复位处理函数地址
pFunction app_reset_handler =(pFunction) (*(__IO uint32_t*)(APP_ADDRESS + 4));
__set_MSP(*(__IO uint32_t*)APP_ADDRESS);
//4.跳转到应用程序
app_reset_handler();
}
}
将BL程序烧录后,修改闪灯频率作为app以表示运行程序的不一样,而后在工程的ld链接文件中,修改Flash的位置为0x08008000(即上述BL配置的APP_ADDRESS),最后修改Keil或者CubeMX Programmer的烧录地址也为APP_ADDRESS即可。
解析
CPU上电后默认从0地址启动,存储器重映射会根据boot选择将特定的地址映射过去,如用户空间0x0800 0000,BL程序只是判断了一下栈顶地址是否有效(在RAM空间中),有效即跳转,这是个非常简陋的校验。
完整性校验
SHA-256
SHA-256是 SHA-2 家族的 256 位密码散列函数,由 NSA 设计、NIST 于 2001 年标准化(FIPS PUB 180-2),用于替代存在安全缺陷的 SHA-1,能将任意长度输入转为 256 位(32 字节,64 个十六进制字符)的消息摘要.
CRC
CRC循环冗余校验是一种基于多项式除法的哈希函数
鉴权
RSA
RSA非对称加密
综合
1 | static uint8_t sign_data[256]; |





