luckfox-pico-sdk/sysdrv/source/mcu/rt-thread/components/ota/ota_file.c
luckfox-eng29 8f34c2760d project:build.sh: Added fastboot support; custom modifications to U-Boot and kernel implemented using patches.
project:cfg:BoardConfig_IPC: Added fastboot BoardConfig file and firmware post-scripts, distinguishing between
the BoardConfigs for Luckfox Pico Pro and Luckfox Pico Max. project:app: Added fastboot_client and rk_smart_door
for quick boot applications; updated rkipc app to adapt to the latest media library. media:samples: Added more
usage examples. media:rockit: Fixed bugs; removed support for retrieving data frames from VPSS. media:isp:
Updated rkaiq library and related tools to support connection to RKISP_Tuner. sysdrv:Makefile: Added support for
compiling drv_ko on Luckfox Pico Ultra W using Ubuntu; added support for custom root filesystem.
sysdrv:tools:board: Updated Buildroot optional mirror sources, updated some software versions, and stored device
tree files and configuration files that undergo multiple modifications for U-Boot and kernel separately.
sysdrv:source:mcu: Used RISC-V MCU SDK with RT-Thread system, mainly for initializing camera AE during quick
boot. sysdrv:source:uboot: Added support for fastboot; added high baud rate DDR bin for serial firmware upgrades.
sysdrv:source:kernel: Upgraded to version 5.10.160; increased NPU frequency for RV1106G3; added support for
fastboot.

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>
2024-10-14 09:47:04 +08:00

490 lines
11 KiB
C

/**
* Copyright (c) 2020 Fuzhou Rockchip Electronics Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <rtdevice.h>
#include <rtthread.h>
#include <dfs_posix.h>
#include <drivers/mtd_nor.h>
#include "hal_base.h"
#ifdef RT_USING_OTA_FROM_LOCAL
#include "fw_analysis.h"
#include "rkpart.h"
#ifdef RT_USING_DSP
#include "dsp_fw/dsp_fw_version.h"
#endif
#include "ota.h"
#include "ota_file.h"
#if OTA_OPT_PROTOCOL_FILE
#define DBG_SECTION_NAME "OTA_FILE"
#include "rkdebug.h"
typedef struct ota_fs_param
{
char *url;
uint32_t imgsize;
int imgfile;
} ota_fs_param_st;
typedef enum
{
UPDATE_NULL,
UPDATE_SYS_START,
UPDATE_SYS_DONE,
UPDATE_DATA_START,
UPDATE_DATA_DONE,
UPDATE_USER_START,
UPDATE_USER_DONE
} ota_file_state;
extern rt_uint32_t g_fw_curr_slot;
extern rt_uint32_t g_user_curr_slot;
extern rt_uint32_t g_os_real_size;
extern rt_uint32_t g_data_real_size;
extern rt_uint32_t g_user_real_size;
static ota_fs_param_st *g_fs_param;
static rt_uint32_t gImgSize;
static int g_ota_file_state;
rt_bool_t ota_is_exist_fw_file(char *path)
{
int fd;
rt_bool_t is_exist = RT_FALSE;
LOGD("%s: Enter", __func__);
LOGD("Check %s", path);
fd = open(path, O_RDONLY, 0);
if (fd < 0)
{
LOGD("ota_is_exist_fw_file: open file for check failed\n");
return is_exist;
}
else
{
close(fd);
is_exist = RT_TRUE;
LOGD("Found %s", path);
}
return is_exist;
}
static ota_status ota_update_file_check(void *url)
{
uint8_t TmpBuf[512];
PFIRMWARE_HEADER pFWHead;
unsigned char magic[8] = {'R', 'E', 'S', 'C', 0, 0, 0, 0};
ota_status ret = OTA_STATUS_ERR;
uint32_t addr = 0;
int fd = -1;
int length = 0;
if (g_fs_param == NULL)
return OTA_STATUS_ERR;
LOGD("%s : Enter", __func__);
fd = open((const char *)url, O_RDONLY, 0);
if (fd < 0)
{
LOGE("check: open file for read failed\n");
return OTA_STATUS_ERR;
}
g_fs_param->imgfile = fd;
LOGD("Current run %d slot fw, will update %d slot fw!", g_fw_curr_slot, 1 - g_fw_curr_slot);
LOGD("fw1 addr 0x%#x, fw2 addr 0x%#x", firmware_addr1, firmware_addr2);
LOGD("Data addr 0x%#x", data_start_addr);
if (g_fw_curr_slot == 0)
addr = firmware_addr2;
else if (g_fw_curr_slot == 1)
addr = firmware_addr1;
else
return OTA_STATUS_ERR;
lseek(fd, addr, SEEK_SET);
length = read(fd, TmpBuf, sizeof(TmpBuf));
if (sizeof(TmpBuf) != length)
{
LOGE("read image file Error!");
return OTA_STATUS_ERR;
}
pFWHead = (PFIRMWARE_HEADER)TmpBuf;
if (0 != rt_memcmp(pFWHead->magic, magic, 8))
{
LOGE("Fw head Error!");
return OTA_STATUS_ERR;
}
g_fs_param->imgsize = pFWHead->data_size + 512 + 4;
gImgSize = pFWHead->data_size + 512 + 4;
g_os_real_size = gImgSize;
LOGD("fw data offset = %u(0x%#x)", pFWHead->data_offset, pFWHead->data_offset);
LOGD("fw data size = %u(0x%#x)", pFWHead->data_size, pFWHead->data_size);
LOGD("fw file size = %u(0x%#x)", gImgSize, gImgSize);
ret = OTA_STATUS_OK;
g_ota_file_state = UPDATE_SYS_START;
/* go back to the fw data position */
lseek(fd, addr, SEEK_SET);
return ret;
}
ota_status ota_update_file_init(void *url)
{
LOGD("%s() Enter", __func__);
/* fw file in emmc device. */
rt_bool_t is_exist = RT_FALSE;
int retry_cnt = 0;
if (g_fs_param == NULL)
{
g_fs_param = rt_malloc(sizeof(ota_fs_param_st));
if (g_fs_param == NULL)
{
LOGE("fs param malloc fail");
return OTA_STATUS_ERR;
}
}
RETRY:
/* Judge whether fw url is exist */
is_exist = ota_is_exist_fw_file((char *)url);
/* exist fw */
if (is_exist)
{
g_fs_param->url = rt_strdup((const char *)url);
if (ota_update_file_check(url) != OTA_STATUS_OK)
return OTA_STATUS_ERR;
}
else
{
LOGD("Not found FW in device, retry %d times !!!", retry_cnt + 1);
rt_thread_delay(1000);
if (++retry_cnt < 5)
goto RETRY;
else
goto END;
}
LOGD("%s() Success", __func__);
return OTA_STATUS_OK;
END:
return OTA_STATUS_ERR;
}
static ota_status ota_update_file_os_proc(void)
{
rt_int32_t ret = -1;
int fd;
fd = g_fs_param->imgfile;
if (g_ota_file_state == UPDATE_SYS_START)
{
g_ota_file_state = UPDATE_SYS_DONE;
//LOGD("Read System %s partiton have End!", g_fw_curr_slot == 0 ? "B" : "A");
//LOGD("ota_file_state is UPDATE_SYS_DONE");
if (data_part_size)
{
//LOGD("will seek to data part pos = 0x%#x", data_start_addr);
ret = lseek(fd, data_start_addr, SEEK_SET);
if (ret < 0)
{
LOGE("ERROR: lseek happen err.The data part not exist ???");
ota_update_file_deinit();
return OTA_STATUS_ERR;
}
/* ready for update data part size */
gImgSize = data_part_size;
/* data partition realsize we don't know. here we use partiton size */
g_data_real_size = gImgSize;
g_ota_file_state = UPDATE_DATA_START;
//LOGD("ota_file_state is UPDATE_DATA_START");
}
else
{
ota_update_file_deinit();
}
}
else if (g_ota_file_state == UPDATE_DATA_START)
{
g_ota_file_state = UPDATE_DATA_DONE;
//LOGD("Read data part have End!");
ota_update_file_deinit();
}
return OTA_STATUS_OK;
}
#ifdef RT_SUPPORT_ROOT_AB
static ota_status ota_update_file_root_proc(void)
{
rt_int32_t ret = -1;
rt_uint32_t user_addr = 0;
int fd;
fd = g_fs_param->imgfile;
if (g_ota_file_state == UPDATE_SYS_START)
{
g_ota_file_state = UPDATE_SYS_DONE;
//LOGD("Read OS FW End!");
}
else if (g_ota_file_state == UPDATE_USER_START)
{
g_ota_file_state = UPDATE_USER_DONE;
//LOGD("Read USER FW End!");
ota_update_file_deinit();
return OTA_STATUS_OK;
}
if (g_user_curr_slot == 0)
{
user_addr = user_start_addr2;
//LOGD("will seek to pos = %d", user_addr);
ret = lseek(fd, user_addr, SEEK_SET);
if (ret < 0)
{
LOGE("ERROR: lseek happen err. The user fw2 not exist ?");
ota_update_file_deinit();
return OTA_STATUS_ERR;
}
/* update user part size */
gImgSize = user_part_size;
g_ota_file_state = UPDATE_USER_START;
//LOGD("user part image 2 size %#d", gImgSize);
}
else if (g_user_curr_slot == 1)
{
user_addr = user_start_addr1;
LOGD("will seek to pos = %d", user_addr);
ret = lseek(fd, user_addr, SEEK_SET);
if (ret < 0)
{
LOGE("ERROR: lseek happen err.The user fw1 not exist ?");
ota_update_file_deinit();
return OTA_STATUS_ERR;
}
/* update user part size */
gImgSize = user_part_size;
g_ota_file_state = UPDATE_USER_START;
//LOGD("user part image 1 size %#d", gImgSize);
}
else
return OTA_STATUS_ERR;
return OTA_STATUS_OK;
}
#endif
ota_status ota_update_file_get(uint8_t *buf, uint32_t buf_size, uint32_t *recv_size, uint8_t *eof_flag)
{
uint32_t len = 0;
int fd;
fd = g_fs_param->imgfile;
if (gImgSize > 0 && gImgSize <= buf_size)
{
buf_size = gImgSize;
}
len = read(fd, buf, buf_size);
//LOGD("len = %u buf_size = %u left = %u",len, buf_size, gImgSize);
if (len != buf_size && gImgSize != len)
{
LOGE("Read FW Error! len = %d buf_size = %d", len, buf_size);
rt_free(g_fs_param->url);
rt_free(g_fs_param);
g_fs_param = NULL;
return OTA_STATUS_ERR;
}
*recv_size = len;
gImgSize -= len;
if (gImgSize == 0)
{
*eof_flag = 1;
if (ota_update_file_os_proc() != OTA_STATUS_OK)
return OTA_STATUS_ERR;
#ifdef RT_SUPPORT_ROOT_AB
if (ota_update_file_root_proc() != OTA_STATUS_OK)
return OTA_STATUS_ERR;
#endif
}
else
*eof_flag = 0;
return OTA_STATUS_OK;
}
ota_status ota_update_file_deinit(void)
{
close(g_fs_param->imgfile);
rt_free(g_fs_param->url);
rt_free(g_fs_param);
g_fs_param = NULL;
g_ota_file_state = UPDATE_NULL;
//LOGD("ota_update_file_deinit done!");
return OTA_STATUS_OK;
}
ota_status ota_data_check(void *url)
{
rt_uint8_t *pBuf = RT_NULL;
ota_status ret = OTA_STATUS_ERR;
uint32_t addr = 0, data_size = 0;
int fd = -1;
int length = 0;
int rst = -1;
rt_uint8_t *dataBuf = RT_NULL;
struct rt_mtd_nor_device *snor_dev = RT_NULL;
LOGD("%s : Enter", __func__);
snor_dev = (struct rt_mtd_nor_device *)rt_device_find("snor");
if (snor_dev == RT_NULL)
{
LOGE("Did not find device: snor....");
return ret;
}
dataBuf = (rt_uint8_t *)rt_malloc(4 * 1024);
if (dataBuf == NULL)
return ret;
pBuf = rt_malloc(OTA_BUF_SIZE);
if (pBuf == RT_NULL)
return ret;
fd = open((const char *)url, O_RDONLY, 0);
if (fd < 0)
{
LOGE("check: open file for read failed");
goto ERROR;
}
rst = lseek(fd, data_start_addr, SEEK_SET);
if (rst < 0)
{
LOGE("ERROR: lseek happen err.The data part not exist ???");
goto ERROR;
}
addr = data_start_addr;
data_size = data_part_size;
while (data_size > 0)
{
uint32_t len;
len = MINIMUM(data_size, OTA_BUF_SIZE);
if (len != rt_mtd_nor_read(snor_dev, addr, (rt_uint8_t *)dataBuf, len))
{
LOGE("rt_mtd_nor_read error");
goto ERROR;
}
length = read(fd, pBuf, len);
if (length != OTA_BUF_SIZE)
{
LOGE("Read FW Error! len = %d", length);
goto ERROR;
}
if (memcmp(pBuf, dataBuf, OTA_BUF_SIZE) != 0)
{
LOGE("Data part check fail, addr = 0x%#x", addr);
break;
}
data_size -= len;
addr += len;
}
if (data_size == 0)
{
ret = OTA_STATUS_OK;
LOGD("Data partition check Pass");
}
ERROR:
if (pBuf)
rt_free(pBuf);
if (dataBuf)
rt_free(dataBuf);
close(fd);
return ret;
}
/* read from dsp version from flash (data partiton start 16 bytes),
compare with dsp_fw_version string.
*/
ota_status ota_dsp_version_cmp(void)
{
#ifdef RT_USING_DSP
ota_status ret = OTA_STATUS_ERR;
uint32_t addr = 0;
int len = 0;
rt_uint8_t dataBuf[32] = {0};
struct rt_mtd_nor_device *snor_dev = RT_NULL;
LOGD("%s : Enter", __func__);
snor_dev = (struct rt_mtd_nor_device *)rt_device_find("snor");
if (snor_dev == RT_NULL)
{
LOGE("Did not find device: snor....");
return ret;
}
addr = data_start_addr;
len = sizeof(dsp_fw_version);
if (len != rt_mtd_nor_read(snor_dev, addr, (rt_uint8_t *)dataBuf, len))
{
LOGE("rt_mtd_nor_read error");
return ret;
}
LOGI("DSP_VERSION flash: %s", dataBuf);
LOGI("DSP_VERSION sram : %s", dsp_fw_version);
if (memcmp(dsp_fw_version, dataBuf, sizeof(dsp_fw_version)) == 0)
{
ret = OTA_STATUS_OK;
LOGD("dsp version check ok !!!");
}
return ret;
#else
return OTA_STATUS_OK;
#endif
}
#endif
#endif