4. BL2到BL31镜像哈希校验实现

任务说明

在Bootloader中实现固件版本检查:解析待升级固件的头部信息,提取版本号,与Bootloader当前运行的版本号比较,根据比较结果决定是否执行升级流程。本案例聚焦版本比较逻辑本身,不涉及具体通信协议或存储驱动。

固件头部格式定义


偏移量  字段        大小    说明
0x00    magic      4字节   固定为0xAA55AA55,用于校验固件有效性
0x04    version    4字节   版本号,高2字节为主版本,低2字节为次版本
0x08    length     4字节   固件数据总长度(含头部)
0x0C    crc32      4字节   固件数据CRC32校验值(不含头部)
0x10    payload    N字节   实际固件数据

关键完整代码

#include <stdint.h>
#include <stdbool.h>
#include <string.h>

#define FW_HEADER_MAGIC      0xAA55AA55u
#define FW_HEADER_SIZE       16u
#define FW_VERSION_MAJOR(v)  (((v) >> 16) & 0xFFFF)
#define FW_VERSION_MINOR(v)  ((v) & 0xFFFF)

typedef struct {
    uint32_t magic;
    uint32_t version;
    uint32_t length;
    uint32_t crc32;
} fw_header_t;

/* 当前Bootloader版本号 */
#define BOOTLOADER_VERSION  0x00010002u  /* v1.2 */

/* 模拟从存储介质读取固件头部(实际工程中替换为Flash/通信读取) */
static bool read_fw_header(const uint8_t *fw_addr, fw_header_t *hdr)
{
    if (fw_addr == NULL || hdr == NULL) {
        return false;
    }
    memcpy(hdr, fw_addr, sizeof(fw_header_t));
    return true;
}

/* 版本比较:返回true表示新固件版本高于当前版本 */
static bool is_newer_version(uint32_t new_ver, uint32_t cur_ver)
{
    uint32_t new_major = FW_VERSION_MAJOR(new_ver);
    uint32_t new_minor = FW_VERSION_MINOR(new_ver);
    uint32_t cur_major = FW_VERSION_MAJOR(cur_ver);
    uint32_t cur_minor = FW_VERSION_MINOR(cur_ver);

    if (new_major != cur_major) {
        return new_major > cur_major;
    }
    return new_minor > cur_minor;
}

/* 固件版本检查主函数 */
int check_firmware_version(const uint8_t *fw_addr)
{
    fw_header_t hdr;

    if (fw_addr == NULL) {
        return -1;  /* 参数错误 */
    }

    if (!read_fw_header(fw_addr, &hdr)) {
        return -2;  /* 头部读取失败 */
    }

    if (hdr.magic != FW_HEADER_MAGIC) {
        return -3;  /* 固件magic错误,非法固件 */
    }

    if (hdr.length < FW_HEADER_SIZE) {
        return -4;  /* 固件长度字段非法 */
    }

    if (is_newer_version(hdr.version, BOOTLOADER_VERSION)) {
        return 1;   /* 新固件版本更高,允许升级 */
    } else if (hdr.version == BOOTLOADER_VERSION) {
        return 0;   /* 版本相同,无需升级 */
    } else {
        return -5;  /* 新固件版本更低,拒绝降级 */
    }
}

/* 测试用例 */
#include <stdio.h>

int main(void)
{
    /* 构造测试固件:v2.0,高于当前v1.2 */
    uint8_t fw_new[] = {
        0x55, 0xAA, 0x55, 0xAA,  /* magic */
        0x00, 0x02, 0x00, 0x00,  /* version = 0x00020000 (v2.0) */
        0x10, 0x00, 0x00, 0x00,  /* length = 16 */
        0x00, 0x00, 0x00, 0x00   /* crc32占位 */
    };

    /* 构造测试固件:v1.0,低于当前v1.2 */
    uint8_t fw_old[] = {
        0x55, 0xAA, 0x55, 0xAA,  /* magic */
        0x00, 0x01, 0x00, 0x00,  /* version = 0x00010000 (v1.0) */
        0x10, 0x00, 0x00, 0x00,  /* length = 16 */
        0x00, 0x00, 0x00, 0x00   /* crc32占位 */
    };

    /* 构造测试固件:v1.2,与当前相同 */
    uint8_t fw_same[] = {
        0x55, 0xAA, 0x55, 0xAA,  /* magic */
        0x00, 0x01, 0x00, 0x02,  /* version = 0x00010002 (v1.2) */
        0x10, 0x00, 0x00, 0x00,  /* length = 16 */
        0x00, 0x00, 0x00, 0x00   /* crc32占位 */
    };

    printf("测试v2.0 (高于当前): %d (预期1)\n", check_firmware_version(fw_new));
    printf("测试v1.0 (低于当前): %d (预期-5)\n", check_firmware_version(fw_old));
    printf("测试v1.2 (等于当前): %d (预期0)\n", check_firmware_version(fw_same));

    return 0;
}

编译与运行

gcc -o fw_check fw_version_check.c
./fw_check

验证方法

程序输出以下三行即表示逻辑正确:


测试v2.0 (高于当前): 1 (预期1)
测试v1.0 (低于当前): -5 (预期-5)
测试v1.2 (等于当前): 0 (预期0)

返回码含义:1允许升级,0版本相同无需升级,-5拒绝降级,-1~-4为参数或头部校验错误。

集成说明

在实际Bootloader工程中,fw_addr指向接收缓冲区或Flash映射地址,read_fw_header替换为对应存储介质的读取函数。版本比较通过后,再执行CRC32校验和固件搬运,本案例不涉及这些后续步骤。