Просмотр исходного кода

add: 设备启动时fota检查OTA数据,能解析出压缩数据了,还需要进一步规划如何写到脚本区

Wendal Chen 1 год назад
Родитель
Сommit
3b9b8039ee
2 измененных файлов с 118 добавлено и 0 удалено
  1. 117 0
      app/port/luat_fota_air101.c
  2. 1 0
      xmake.lua

+ 117 - 0
app/port/luat_fota_air101.c

@@ -40,6 +40,7 @@ static uint32_t fota_head_check;
 
 static int check_image_head(IMAGE_HEADER_PARAM_ST* imghead, const char* tag);
 static uint32_t img_checksum(const char* ptr, size_t len);
+static void check_ota_zone(void);
 
 int luat_fota_init(uint32_t start_address, uint32_t len, luat_spi_device_t* spi_device, const char *path, uint32_t pathlen) {
     fota_state = FOTA_ONGO;
@@ -222,4 +223,120 @@ void luat_fota_boot_check(void) {
     LLOGD("ota zone : 0x%08X %dkb", upgrade_img_addr, ota_zone_size/1024);
     // 当前运行区镜像的大小
     LLOGD("run image size: 0x%08X %dkb", runimg->img_len, runimg->img_len/1024);
+
+    // 检查OTA区域的数据, 如果存在更新包, 需要解析出脚本区, 然后清除数据
+    check_ota_zone();
+}
+
+#include "miniz.h"
+int my_tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
+{
+    int result = 0;
+    tinfl_decompressor* decomp = luat_heap_malloc(sizeof(tinfl_decompressor));
+    if (!decomp) {
+        LLOGE("分配tinfl_decompressor失败");
+        return TINFL_STATUS_FAILED;
+    }
+    mz_uint8 *pDict = (mz_uint8 *)luat_heap_malloc(TINFL_LZ_DICT_SIZE);
+    size_t in_buf_ofs = 0, dict_ofs = 0;
+    if (!pDict) {
+        LLOGE("分配pDict失败");
+        luat_heap_free(decomp);
+        return TINFL_STATUS_FAILED;
+    }
+    memset(pDict,0,TINFL_LZ_DICT_SIZE);
+    tinfl_init(decomp);
+    for (;;)
+    {
+        size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs;
+        tinfl_status status = tinfl_decompress(decomp, (const mz_uint8 *)pIn_buf + in_buf_ofs, &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size,
+                                               (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)));
+        in_buf_ofs += in_buf_size;
+        if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user)))
+            break;
+        if (status != TINFL_STATUS_HAS_MORE_OUTPUT)
+        {
+            result = (status == TINFL_STATUS_DONE);
+            break;
+        }
+        dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1);
+    }
+    luat_heap_free(pDict);
+    luat_heap_free(decomp);
+    *pIn_buf_size = in_buf_ofs;
+    return result;
+}
+
+static IMAGE_HEADER_PARAM_ST tmphead;
+static uint32_t head_fill_count = 0;
+static uint32_t image_skip_remain = 0;
+
+static int ota_gzcb(const void *pBuf, int len, void *pUser) {
+    const char* tmp = pBuf;
+    LLOGD("得到解压数据 %p %d", tmp, len);
+next:
+    if (len == 0) {
+        return 1;
+    }
+    if (image_skip_remain > 0) {
+        if (len >= image_skip_remain) {
+            tmp += image_skip_remain;
+            len -= image_skip_remain;
+            image_skip_remain = 0;
+            head_fill_count = 0;
+        }
+        else {
+            image_skip_remain -= len;
+            return 1;
+        }
+    }
+    if (head_fill_count < sizeof(IMAGE_HEADER_PARAM_ST)) {
+        // 填充头部信息
+        if (head_fill_count + len >= sizeof(IMAGE_HEADER_PARAM_ST)) {
+            memcpy((char*)&tmphead + head_fill_count, tmp, sizeof(IMAGE_HEADER_PARAM_ST) - head_fill_count);
+            tmp += sizeof(IMAGE_HEADER_PARAM_ST) - head_fill_count;
+            len -= sizeof(IMAGE_HEADER_PARAM_ST) - head_fill_count;
+            head_fill_count = sizeof(IMAGE_HEADER_PARAM_ST);
+            image_skip_remain = tmphead.img_len;
+            LLOGD("找到一个IMG数据段 长度 %d", tmphead.img_len);
+            goto next;
+        }
+        else {
+            // 继续等数据
+            memcpy((char*)&tmphead + head_fill_count, tmp, len);
+            head_fill_count += len;
+            return 1;
+        }
+    }
+    return 1;
+}
+
+static void check_ota_zone(void) {
+    // 首先, 检查是不是OTA数据
+    IMAGE_HEADER_PARAM_ST* imghead = (IMAGE_HEADER_PARAM_ST*)upgrade_img_addr;
+    if (imghead->magic_no != MAGIC_NO) {
+        LLOGD("OTA区域没有数据, 因为magic no不对 %08X", imghead->magic_no);
+        return;
+    }
+    // 检查头部校验和
+    // 计算一下header的checksum
+    uint32_t cm = img_checksum((const char*)imghead, sizeof(IMAGE_HEADER_PARAM_ST) - 4);
+    if (cm != imghead->hd_checksum) {
+        LLOGD("foto包的头部校验和不正确 expect %08X but %08X", imghead->hd_checksum, cm);
+        return;
+    }
+    cm = img_checksum((const char*)upgrade_img_addr + sizeof(IMAGE_HEADER_PARAM_ST), imghead->img_len);
+    if (cm != imghead->org_checksum) {
+        LLOGD("foto包的头部校验和不正确 expect %08X but %08X", imghead->org_checksum, cm);
+        return;
+    }
+    // 当前肯定是压缩的, 需要引入miniz的API进行解压分析
+    LLOGD("发现OTA数据, 继续进行脚本区更新");
+    size_t inSize = imghead->img_len;
+    uint8_t *ptr = (uint8_t *)upgrade_img_addr + sizeof(IMAGE_HEADER_PARAM_ST) + 10; // 跳过GZ的前10个字节
+
+    int ret = my_tinfl_decompress_mem_to_callback(ptr, &inSize, ota_gzcb, NULL, 0);
+    // LLOGD("OTA数据的前8个字节 %02X%02X%02X%02X%02X%02X%02X%02X", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7]);
+    LLOGD("OTA解压函数的返回值 %d", ret);
 }
+

+ 1 - 0
xmake.lua

@@ -585,6 +585,7 @@ target("air10x")
     add_includedirs(luatos.."components/lvgl/gen",{public = true})
     add_includedirs(luatos.."components/lvgl/src",{public = true})
     add_includedirs(luatos.."components/lvgl/font",{public = true})
+    add_includedirs(luatos.."components/miniz", {public = true})
 
     add_includedirs(luatos.."components/iconv")
     add_includedirs(luatos.."components/lfs")