瀏覽代碼

add: 先把已经完成fota代码提交一下

Wendal Chen 2 年之前
父節點
當前提交
4f602a2dd6
共有 1 個文件被更改,包括 153 次插入3 次删除
  1. 153 3
      app/port/luat_fota_air101.c

+ 153 - 3
app/port/luat_fota_air101.c

@@ -13,6 +13,7 @@
 
 #include "luat_base.h"
 #include "luat_crypto.h"
+#include "luat_malloc.h"
 #define LUAT_LOG_TAG "fota"
 #include "luat_log.h"
 
@@ -21,22 +22,171 @@
 
 #include "luat_fota.h"
 
+static const uint32_t MAGIC_NO = 0xA0FFFF9F;
+
+enum {
+    FOTA_IDLE,
+    FOTA_ONGO,
+    FOTA_DONE
+};
+
+static int fota_state;
+static uint32_t fota_write_offset;
+static uint32_t ota_zone_size;
+static uint32_t upgrade_img_addr;
+
+static int check_image_head(IMAGE_HEADER_PARAM_ST* imghead, const char* tag);
+
 int luat_fota_init(uint32_t start_address, uint32_t len, luat_spi_device_t* spi_device, const char *path, uint32_t pathlen) {
-    return -1;
+    fota_state = FOTA_ONGO;
+    fota_write_offset = 0;
+    // 读取update区域位置及大小, 按4k对齐的方式, 清除对应的区域
+    for (size_t i = 0; i < ota_zone_size / 4096; i++)
+    {
+        LLOGD("清除ota区域: %08X", upgrade_img_addr + i * 4096);
+        tls_fls_erase((upgrade_img_addr + i * 4096) / INSIDE_FLS_SECTOR_SIZE);
+    }
+    LLOGI("OTA区域初始化完成");
+    return 0;
 }
 
 int luat_fota_write(uint8_t *data, uint32_t len) {
-    return -1;
+    if (len + fota_write_offset > ota_zone_size) {
+        LLOGE("OTA区域写满, 无法继续写入");
+        return -1;
+    }
+    int ret = tls_fls_write_without_erase(upgrade_img_addr + fota_write_offset, data, len);
+    fota_write_offset += len;
+    return ret;
 }
 
 int luat_fota_done(void) {
-    return -1;
+    if (fota_write_offset == 0) {
+        LLOGE("未写入任何数据, 无法完成OTA");
+        return -1;
+    }
+    if (fota_write_offset < sizeof(IMAGE_HEADER_PARAM_ST)) {
+        LLOGI("写入数据小于最小长度, 还不能判断");
+        return 0;
+    }
+    // 写入长度已经超过最小长度, 判断是否是合法的镜像
+    IMAGE_HEADER_PARAM_ST* imghead = (IMAGE_HEADER_PARAM_ST*)upgrade_img_addr;
+    if (imghead->magic_no != MAGIC_NO) {
+        LLOGE("image magic: %08x", imghead->magic_no);
+        return -2;
+    }
+    if (imghead->img_len + sizeof(IMAGE_HEADER_PARAM_ST) < fota_write_offset) {
+        LLOGI("fota数据还不够, 继续等数据");
+        return 0;
+    }
+    // 写入长度足够, 判断是否是合法的镜像, 开始计算check sum
+    if (check_image_head(imghead, "fota") == 0) {
+        LLOGI("image check sum: %08x", imghead->hd_checksum);
+        fota_state = FOTA_DONE;
+        return 0;
+    }
+
+    return 0;
 }
 
 int luat_fota_end(uint8_t is_ok) {
+    if (fota_state == FOTA_DONE) {
+        return 0;
+    }
+    LLOGD("状态不正确, 要么数据没写完,要么校验没通过");
     return -1;
 }
 
 uint8_t luat_fota_wait_ready(void) {
     return 0;
 }
+
+static uint32_t img_checksum(const char* ptr, size_t len) {
+    psCrcContext_t	crcContext;
+	unsigned int crcvalue = 0;
+	unsigned int crccallen = 0;
+	unsigned int i = 0;
+
+    crccallen = len;
+
+	tls_crypto_crc_init(&crcContext, 0xFFFFFFFF, CRYPTO_CRC_TYPE_32, 3);
+	for (i = 0; i <  crccallen/4; i++)
+	{
+		MEMCPY((unsigned char *)&crcvalue, (unsigned char *)ptr +i*4, 4); 
+		tls_crypto_crc_update(&crcContext, (unsigned char *)&crcvalue, 4);
+	}
+	crcvalue = 0;
+	tls_crypto_crc_final(&crcContext, &crcvalue);
+
+    return crcvalue;
+}
+
+static int check_image_head(IMAGE_HEADER_PARAM_ST* imghead, const char* tag) {
+    if (imghead == NULL) {
+        return -1;
+    }
+    if (imghead->magic_no != MAGIC_NO) {
+        LLOGE("%s image magic: %08x", tag, imghead->magic_no);
+        return -2;
+    }
+    LLOGD("%s image img_addr: %08X", tag, imghead->img_addr);
+    LLOGD("%s image img_len: %08X", tag, imghead->img_len);
+    LLOGD("%s image img_header_addr: %08X", tag, imghead->img_header_addr);
+    LLOGD("%s image upgrade_img_addr: %08X", tag, imghead->upgrade_img_addr);
+    LLOGD("%s image org_checksum: %08X", tag, imghead->org_checksum);
+    LLOGD("%s image upd_no: %08X", tag, imghead->upd_no);
+    LLOGD("%s image ver: %.16s", tag, imghead->ver);
+    LLOGD("%s image hd_checksum: %08X", tag, imghead->hd_checksum);
+    LLOGD("%s image next: %08X", tag, imghead->next);
+    
+    // image attr
+    LLOGD("%s image attr img_type: %d", tag, imghead->img_attr.b.img_type);
+    LLOGD("%s image attr zip_type: %d", tag, imghead->img_attr.b.zip_type);
+    LLOGD("%s image attr psram_io: %d", tag, imghead->img_attr.b.psram_io);
+    LLOGD("%s image attr erase_block_en: %d", tag, imghead->img_attr.b.erase_block_en);
+    LLOGD("%s image attr erase_always: %d", tag, imghead->img_attr.b.erase_always);
+    
+    // 先判断一下magicno
+    if (imghead->magic_no != MAGIC_NO) {
+        return -2;
+    }
+    // 计算一下header的checksum
+    uint32_t cm = img_checksum((const char*)imghead, sizeof(IMAGE_HEADER_PARAM_ST) - 4);
+    LLOGD("%s head checksum: %08X %08X", tag, cm, imghead->hd_checksum);
+    if (cm != imghead->hd_checksum) {
+        return -3;
+    }
+    cm = img_checksum((const char*)imghead->img_addr, imghead->img_len);
+    LLOGD("%s data checksum: %08X %08X", tag, cm, imghead->org_checksum);
+    if (cm != imghead->org_checksum) {
+        return -4;
+    }
+
+    return 0;
+}
+
+void luat_fota_boot_check(void) {
+    LLOGD("启动fota开机检查");
+    LLOGD("sizeof(IMAGE_HEADER_PARAM_ST) %d %d %d", sizeof(IMAGE_HEADER_PARAM_ST), sizeof(Img_Attr_Type), sizeof(unsigned int));
+    // 读取secboot区域的信息, 大小1kb
+    IMAGE_HEADER_PARAM_ST* secimg = (IMAGE_HEADER_PARAM_ST*)0x8002000;
+    // check_image_head(secimg, "secboot");
+    IMAGE_HEADER_PARAM_ST* upimg = (IMAGE_HEADER_PARAM_ST*)secimg->upgrade_img_addr;
+    IMAGE_HEADER_PARAM_ST* runimg = (secimg->next);
+
+    // check_image_head(upimg, "update");
+    // check_image_head(runimg, "user");
+
+    // 计算出OTA区域大小, 运行区镜像的大小
+    uint32_t ota_size = ((uint32_t)runimg) - ((uint32_t)upimg);
+    LLOGD("ota zone size: 0x%08X %dkb", ota_size, ota_size/1024);
+
+    // 当前运行区镜像的大小
+    LLOGD("run image size: 0x%08X %dkb", runimg->img_len, runimg->img_len/1024);
+
+    // 把相关参数存起来
+    upgrade_img_addr = secimg->upgrade_img_addr;
+    
+    ota_zone_size = ((uint32_t)runimg) - ((uint32_t)upimg);
+    ota_zone_size = (ota_zone_size + 0x3FF) & (~0x3FF);
+}