2. 固件镜像CRC校验

任务说明

在OTA升级流程中,固件镜像在传输或存储过程中可能发生比特翻转,导致设备运行异常。本案例实现标准CRC32(IEEE 802.3,多项式0xEDB88320)校验算法,对固件镜像文件计算校验值,并在模拟升级前验证镜像完整性。

实现方案

采用查表法提升计算效率,预生成256项CRC表,对镜像文件按字节流式处理。核心代码包含:CRC表生成、CRC计算函数、文件读取与校验主流程。该实现不依赖第三方库,可直接在Linux主机或嵌入式Linux环境编译运行。

关键完整代码

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

static uint32_t crc_table[256];

/* 生成CRC32查表(多项式0xEDB88320) */
static void crc32_init(void) {
    for (uint32_t i = 0; i < 256; i++) {
        uint32_t c = i;
        for (int k = 0; k < 8; k++) {
            c = (c & 1) ? (0xEDB88320 ^ (c >> 1)) : (c >> 1);
        }
        crc_table[i] = c;
    }
}

/* 计算缓冲区CRC32值 */
static uint32_t crc32_compute(const uint8_t *data, size_t len, uint32_t crc) {
    crc = ~crc;
    for (size_t i = 0; i < len; i++) {
        crc = crc_table[(crc ^ data[i]) & 0xFF] ^ (crc >> 8);
    }
    return ~crc;
}

/* 计算整个文件的CRC32 */
static int file_crc32(const char *path, uint32_t *out_crc) {
    FILE *fp = fopen(path, "rb");
    if (!fp) return -1;

    uint8_t buf[4096];
    size_t n;
    uint32_t crc = 0xFFFFFFFF;  /* 初始值 */

    while ((n = fread(buf, 1, sizeof(buf), fp)) > 0) {
        crc = crc32_compute(buf, n, crc);
    }
    fclose(fp);

    if (ferror(fp)) return -1;
    *out_crc = crc;
    return 0;
}

int main(int argc, char *argv[]) {
    if (argc != 2) {
        fprintf(stderr, "用法: %s <固件镜像文件>\n", argv[0]);
        return 1;
    }

    crc32_init();

    uint32_t crc;
    if (file_crc32(argv[1], &crc) != 0) {
        fprintf(stderr, "错误: 无法读取文件 %s\n", argv[1]);
        return 1;
    }

    printf("CRC32: 0x%08X\n", crc);
    return 0;
}

编译与运行

# 编译
gcc -O2 -o crc32_check crc32_check.c

# 生成测试镜像(1KB随机数据)
head -c 1024 /dev/urandom > firmware.bin

# 计算校验值
./crc32_check firmware.bin

验证方法

  1. 一致性验证:连续运行两次./crc32_check firmware.bin,两次输出CRC32值必须完全相同。
  2. 完整性验证:使用cksum命令对比结果——cksum firmware.bin输出的第一个数字(十进制)转换为十六进制后,应与本程序输出一致(注意字节序,cksum输出为十进制无符号数)。
  3. 错误检测验证:修改镜像任意一个字节(例如printf 'A' | dd of=firmware.bin bs=1 seek=500 count=1 conv=notrunc),重新计算CRC32,校验值必须发生变化。

通过以上三项测试,即可确认CRC32算法实现正确且能有效检测固件镜像的完整性破坏。