# PatchReadme **Repository Path**: wanghui0571/PatchReadme ## Basic Information - **Project Name**: PatchReadme - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2020-05-09 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # PATCH v1.2.4 ## 约定 1. 小端模式, 低字节在前. ## 分包内容 Part: ``` Len + Flag + Index + OldLen + OldCrc + NewLen + NewCrc + Data + Crc Len: 2字节, 整个Part的字节数 Flag: 1字节, bit0-1: 2:diff, 1:copy, 0:same; bit2:oldCode不完整, bit3:newCode不完整, 一般最后一包可能不完整. Index: 2字节, 分包序号. OldCrc: 2字节, oldCode的CRC16, 验证 odlcode正确, 类型为diff时有此数据 OldLen: 2字节, oldCode不完整时, 表示oldCode长度. 类型为diff, oldCode不完整时,有此数据, 完整时默认为4k NewCrc: 2字节, newCode的CRC16, 用于验证生成的newCode是否正确. 类型为diff, copy时有此数据 NewLen: 2字节, newCode不完整时, 表示newCode长度, 类型为diff, copy时, newCode不完整时,有此数据, 完整时默认为4k Data: n字节, 分包数据, 类型为diff, copy时有此数据 Crc: 2字节, diff的CRC16, 验证part的正确 ``` ## 补丁文件内容 File: ``` FLen + Fcount + Version + OldLen + OldCrc + NewLen + NewCrc + Part0 + Part1 + ... Partx + CRC FLen: 4字节, 文件长度,包含全部字节数 Fcount: 2字节, 分包数 Version:1字节, 库文件版本号 OldLen: 4字节, old App 的长度 OldCrc: 4字节, old App 的Crc32, 用于验证是否与生成补丁文件时的old一致. NewLen: 4字节, new App 的长度 NewCrc: 4字节, new App 的Crc32, 用于验证是生成的new App是否正确. Part: n字节, 分包内容. CRC: 4字节, 补丁文件从FLen到CRC前的Crc32, 用于传输文件时比对. ``` ## 补丁文件使用: ``` 1. App 程序在接收完整的补丁文件后, 对补丁文件验证正确, 验证old是否与生成补丁文件时的old一致. 之后再启动bootloader升级. 2. bootloader 程序链接patch_lib_xxx.a 3. bootloader 程序的heap设置在8k及以上, stack设置在4k及以上. 4. bootloader 程序声明外部函数patchX. 5. bootloader 程序 升级功能如下: 5.1. 读Fcount, 对Part0--Partx进行循环 5.2. 读 Part的 Len + Flag + Index 得到分包序号,长度, 类型. 序号不对不升级 5.3. 再按长度获取Part_i的内容 5.4. 将Len + Flag + Index + OldLen + OldCrc + NewLen + NewCrc + Data + Crc 作为 diff_i 5.5 调用patchX函数, 将old_i, diff_i, 生成 new_i 5.6 patchX 返回1表示new,old一致, 不需要刷mcu; 返回0:表示new, old不一致, 需要刷mcu; 返回<0, 表示失败. 5.6 重复步骤5.2, 5.3, 5.4, 5.5, 5.6直到分包全部处理完毕 ``` 此部分需要由各项目自行处理. ## 宏定义: ``` #define SAME (1) // patchX 返回新旧一致. #define PATCH_OK (0) // patchX 返回新旧不一致, 补丁恢复成功. #define PATCH_ERROR (-1) // 补丁使用错误. #define OLD_LEN_ERROR (-2) // old 长度错误 #define OLD_CRC_ERROR (-3) // old crc 错误 #define NEW_LEN_ERROR (-4) // new 长度错误 #define NEW_CRC_ERROR (-5) // new crc 错误 #define DIFF_LEN_ERROR (-6) // diff长度错误 #define DIFF_CRC_ERROR (-7) // diff crc 错误 #define MALLOC_ERROR (-8) // malloc 分配空间错误 #define VERSION_ERROR (-9) // 库文件版本号错误 #define INDEX_ERROR (-10) // 分包序号错误 ``` ## 一个分包补丁恢复 ``` /** * @brief 4k一包补丁恢复 * @param newData [ O] 输出new的缓存起始指针 * @param pNewLen [IO] 输出new的实际大小, 输入newlen的最大值 * @param oldData [I ] 输入old的起始指针 * @param pOldLen [IO] 输出old的实际大小, 输入oldlen的最大值 * @param diffData [I ] 输入diff的起始指针 * @param diffLen [I ] 输入diff的实际大小 * @return 1:new与old一致, 不需要刷mcu; 0:new与old不一致, 需要刷mcu, <0:失败. */ int8_t patchX(uint8_t *newData, uint16_t *pNewLen, const uint8_t *oldData, uint16_t *pOldLen, const uint8_t *diffData, uint16_t diffLen) ``` ## 所有分包补丁恢复 ``` typedef uint32_t Address_t; /** * @brief 全文件补丁恢复 * @param old old 指针 * @param old_file_len old 大小 * @param diff diff存放位置 * @param diff_file_len diff 大小 * @param diff_get_cb diff获取的回调函数, 可以是读dataflash * @param new new存放位置 * @param new_put_cb new放置的回调函数, 可以时写mcuflash, 也可以是写dataflash等. * @return >=0 new 的长度; <0 错误码 */ int32_t patchAll(char* old, uint32_t old_file_len, char *new, Address_t diff, uint32_t diff_file_len, void(*diff_get_cb)(void*buf, Address_t d, uint32_t num), void(*new_put_cb)(void*dest, void *src, uint32_t num) ); ``` ## crc32 ``` /** * @brief crc32 计算 * @param crc 初始值 * @param buf 数据 * @param size 数据字节数 * @param c 1: 不需要继续计算, 返回值为crc结果. 0: 继续计算, 返回值^0xffffffff 才是crc结果 * @return */ extern uint32_t patch_crc32( uint32_t crc, const uint8_t *buf, uint32_t size, uint8_t c); ``` ## 补丁文件分析例子 ``` 80 47 00 00 // FLen: 18304字节 3c 00 // Fcount: 60 包 01 // version 版本1 1c bd 03 00 // OldLen: 245020 18 cd 4d aa // OldCrc: AA4DCD18 e2 bd 03 00 // NewLen: 245218 74 92 87 a6 // NewCrc: A6979274 ================================================================ 07 01 // Len: 263 02 // Flag: 02, diff 完整 00 // index: 0 dd d2 // oldcrc: d2dd 87 0f // newcrc: 0f87 01 02 01 01 00 a0 00 00 00 81 05 03 c1 01 c1 01 c1 01 80 02 80 02 80 16 80 0e c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 80 02 80 02 80 02 80 02 80 02 80 02 80 02 80 02 80 02 80 02 80 02 80 02 c1 01 80 02 80 02 80 02 c1 01 c1 01 c1 01 80 02 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 38 0d 80 25 4e c8 01 c8 01 c8 01 c8 c8 c8 c8 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 c8 c8 c8 c8 c8 c8 c8 c8 c8 c8 c8 c8 01 c8 c8 c8 c8 01 c8 01 c8 01 c8 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 02 85 a2 // diffcrc: a285 ---------------------------------------------------------------- 06 00 // Len: 6 00 // Flag: 00, same 01 // index: 1 a8 46 // diffcrc: 46a8 ---------------------------------------------------------------- ff 00 // Len: 255 02 // Flag: 02, diff 完整 02 // index: 0 a7 27 // oldcrc 5a e8 // newcrc 01 02 01 01 00 a0 00 00 00 7e 32 03 c1 01 c1 01 c1 01 c1 01 80 02 80 02 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 80 02 c1 01 c1 24 1d c1 01 80 02 c1 01 c1 01 c1 01 80 02 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 80 02 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 80 02 c1 01 80 02 c1 01 80 02 80 02 c1 01 c1 01 c1 01 c1 01 c1 01 c1 21 6d c1 01 c1 21 7d c1 05 c1 01 80 02 c1 24 05 c8 01 c8 01 c8 01 c8 01 c8 c8 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 c8 01 c8 01 c8 01 c8 c8 01 c8 01 c8 01 c8 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 c8 01 c8 c8 01 c8 c8 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 c8 01 36 05 ---------------------------------------------------------------- 7f 00 02 03 72 bb e6 7f 01 02 01 01 00 a0 00 00 00 39 32 1b c1 01 c1 01 c1 01 c1 26 41 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 25 05 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 c1 01 80 02 80 02 c1 01 c1 21 39 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 01 c8 c8 c8 01 c8 01 74 f1 ---------------------------------------------------------------- 64 00 02 04 f0 bd 06 5e 01 02 01 01 00 a0 00 00 00 2d 23 67 c1 01 c1 01 c1 01 80 02 80 02 c1 01 c1 01 80 02 c1 01 c1 01 c1 01 c1 01 80 02 c1 01 c1 01 80 02 c1 01 c1 2a 31 c1 2b 39 c1 25 61 c8 01 c8 01 c8 01 c8 c8 c8 01 c8 01 c8 c8 01 c8 01 c8 01 c8 01 c8 c8 01 c8 01 c8 c8 01 c8 01 c8 01 c8 01 e1 d6 ---------------------------------------------------------------- 15 10 // 4117 06 // flag: old 不完整, diff类型 3b // 59 e2 0d // 3554 old len 00 4d // 4d00 crc 0f f8 // f8f0 crc 00 00 00 00 a0 00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ... ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 02 3f 7f 2b ff ```