/**************************************************************************** Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED. This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT be copied by any method or incorporated into another program without the express written consent of Aerospace C.Power. This Information or any portion thereof remains the property of Aerospace C.Power. The Information contained herein is believed to be accurate and Aerospace C.Power assumes no responsibility or liability for its use in any way and conveys no license or title under any patent or copyright and makes no representation or warranty that this Information is free from patent or copyright infringement. ****************************************************************************/ #include "os_types.h" #include "os_mem.h" #include "os_lock.h" #include "os_task.h" #include "cpu.h" #include "gp_timer.h" #include "flash.h" #include "iot_config.h" #include "iot_module.h" #include "iot_io.h" #include "iot_string.h" #include "iot_system.h" #include "iot_img_hdr.h" #include "iot_board.h" #include "iot_pib.h" #include "iot_dbglog_parser.h" #include "iot_flash_layout.h" #include "iot_pkt_api.h" #include "os_task_api.h" #include "iot_flash_api.h" #include "iot_crc_api.h" #include "iot_utils_api.h" #include "iot_errno_api.h" #include "iot_wdg_api.h" #include "iot_dbglog_api.h" #include "mtd.h" #define MTD_CRC_CALC_LEN (64) #define MTD_COPY_FLASH_SIZE_ONCE (512) typedef struct _mtd_device_t { uint32_t device_id; /* flash device id */ uint32_t pagesize; /* flash page size */ uint32_t sectorsize; /* flash sector size */ uint32_t blocksize; /* flash block size */ uint32_t size; /* flash memory size */ } mtd_device_t; typedef struct _mtd_info_t { /* page erase command enable */ uint8_t page_erase_ena; uint8_t resv[3]; /* pointer of flash chip information struction */ mtd_device_t dev; /* pointer of partition information struction */ part_info_t *part; /* file system information struction */ struct { int fd; uint32_t pos; int used; } file[PART_NUM_MAX]; /* operation functions struction */ struct { uint8_t (*init)(int mode); uint8_t (*read)(void* data, uint32_t addr, int size, uint8_t mode); uint8_t (*write)(const void* data, uint32_t addr, uint32_t size, void *param); uint8_t (*erase)(uint32_t addr, void *param); uint8_t (*get_dev_id)(void *data); uint8_t (*addr_mapping)(uint32_t offset1, uint32_t offset2, uint32_t size); } opt; } mtd_info_t; /* mtd boot parameter information */ static uint8_t g_first_boot = 0; static uint8_t g_start_flag = 0; static uint8_t g_last_flag = 0; static uint8_t g_cnt_flag = 0; bool_t g_upgrade_flag = false; /* Indicates whether this startup is the first after burning. */ uint8_t g_first_run = 0; os_mutex_h mtd_op_mutex = NULL; flash_os_cb_t g_flash_os_cb = {0}; /* mtd partion information */ uint8_t g_dev_flash_size = FLASH_1M; uint8_t g_run_in_psram = 0; uint8_t g_part_num_fw1 = PART_NUM_FW1; uint8_t g_part_num_fw2 = PART_NUM_FW2; /* partition array */ part_info_t g_part_info[PART_NUM_MAX] = {0}; /* mtd information */ mtd_info_t g_mtd_info = {0}; /* flash chip informations */ const mtd_device_t mtd_flash_devices[] = { /* device_id, pagesize, sectorsize, blocksize, size */ {FLASH_VENDOR_ID_GD, 0x100, 0x1000, 0x10000, 0x3FFFFF},/* model: gd25q32c */ {FLASH_VENDOR_ID_PUYA, 0x100, 0x1000, 0x10000, 0x3FFFFF},/* model: p25q80h */ {FLASH_VENDOR_ID_WINBOND, 0x100, 0x1000, 0x10000, 0x3FFFFF},/* model: p25q80h */ {0x0002, 0x100, 0x1000, 0x10000, 0x3FFFFF} }; extern uint32_t g_fw_mode; extern void vTaskSuspendAll(); extern void xTaskResumeAll(); extern uint32_t patch_puya_twicewrite_flag_check(void); int32_t mtd_patch_for_puya(void); /**************************** mtd init functions ******************************/ void mtd_os_cb_enable() { g_flash_os_cb.get_gp_timer_val = gp_timer_get_current_val; g_flash_os_cb.task_suspend_all = vTaskSuspendAll; g_flash_os_cb.task_resume_all = xTaskResumeAll; } void mtd_set_flash_size(uint8_t size) { if (size == 1) g_dev_flash_size = FLASH_1M; else if(size == 2) g_dev_flash_size = FLASH_2M; else if(size >= 3) g_dev_flash_size = FLASH_4M; else /*compatable with old sbl*/ g_dev_flash_size = FLASH_1M; } uint32_t mtd_get_flash_size() { return g_dev_flash_size; } uint8_t mtd_get_psram_state() { return g_run_in_psram; } void mtd_set_psram_state(uint8_t en) { g_run_in_psram = en; } uint32_t mtd_flash_init(int index, int mode) { int i = 0; part_info_t *part_info = g_part_info; iot_layout_init_index(FLASH_LAYOUT_INDEX, g_dev_flash_size, g_run_in_psram); /* init local partition array */ for (i = 0; i < PART_NUM_MAX; i++) { part_info_t part_info_temp; if (iot_layout_get_part_info(i, &part_info_temp) != ERR_OK) { continue; } part_info[i].offset = part_info_temp.offset; part_info[i].size = part_info_temp.size; part_info[i].authority = part_info_temp.authority; } /* set partition variable value */ #if (BUILD_AMP_TYPE == IOT_BUILD_AMP_CUSTOM) g_part_num_fw1 = PART_NUM_CUS_FW1; g_part_num_fw2 = PART_NUM_CUS_FW2; #else g_part_num_fw1 = PART_NUM_FW1; g_part_num_fw2 = PART_NUM_FW2; #endif /* flash firmware need to re-define log partition to the back of run partition */ if (g_dev_flash_size > FLASH_1M && !g_run_in_psram) { uint32_t temp_fw_size, temp_run_offset, temp_run_size, temp_log_size; temp_fw_size = (uint32_t)&_flash_end - (uint32_t)&_start; //fw size // padding 4K byte to avoid overlap temp_fw_size += 0x1000; // 4K aligned temp_fw_size += 0x1000; temp_fw_size &= ~0xFFF; #if (BUILD_AMP_TYPE == IOT_BUILD_AMP_CUSTOM) temp_run_offset = part_info[PART_NUM_CUS_RUN].offset; temp_run_size = part_info[PART_NUM_CUS_RUN].size; #else temp_run_offset = part_info[PART_NUM_RUN].offset; temp_run_size = part_info[PART_NUM_RUN].size; #endif temp_log_size = (temp_run_size - temp_fw_size) >> 1; //divide by 2 part_info[PART_NUM_LOG1].offset = temp_run_offset + temp_fw_size; part_info[PART_NUM_LOG1].size = temp_log_size; part_info[PART_NUM_LOG2].offset = temp_run_offset + temp_fw_size + temp_log_size; part_info[PART_NUM_LOG2].size = temp_log_size; } /* mtd params init */ os_mem_cpy(&g_mtd_info.dev, &mtd_flash_devices[index], sizeof(mtd_device_t)); g_mtd_info.part = part_info; if (mtd_flash_devices[index].device_id == FLASH_VENDOR_ID_PUYA) { g_mtd_info.page_erase_ena = MODE_ERASE_PAGE; } else { g_mtd_info.page_erase_ena = MODE_ERASE_SECTOR; } /* mtd callback functions */ g_mtd_info.opt.init = flash_init; g_mtd_info.opt.read = flash_read; g_mtd_info.opt.write = flash_write; g_mtd_info.opt.erase = flash_erase; g_mtd_info.opt.get_dev_id = flash_get_dev_id; /* init file system */ for (i = 0; i < PART_NUM_MAX; i++) { g_mtd_info.file[i].used = FILE_UNUSE; g_mtd_info.file[i].fd = i; g_mtd_info.file[i].pos = 0; } mtd_os_cb_enable(); g_mtd_info.opt.init(mode); if (mtd_op_mutex == NULL) { mtd_op_mutex = os_create_mutex(IOT_DRIVER_MID); } return HAL_OK; } int mtd_device_probe(void) { /* get current flash device id */ int i = 0; uint32_t id = 0; flash_probe(&id); for (i = 0; IOT_ARRAY_CNT(mtd_flash_devices); i++) { if (mtd_flash_devices[i].device_id == id) { return i; } } /* probe fail */ return -1; } uint32_t mtd_device_init(int mode) { int index; index = mtd_device_probe(); if (index < 0) { return HAL_ERROR; } mtd_flash_init(index, mode); #if FLASH_HIGH_FREQ_ENABLE flash_clk_div_set(0); #else flash_clk_div_set(1); #endif mtd_patch_for_puya(); return HAL_OK; } int mtd_device_get_info(void* buf, uint32_t type) { uint8_t* p = (uint8_t*)buf; (void)type; if (g_mtd_info.opt.get_dev_id) { g_mtd_info.opt.get_dev_id(p); } return 0; } int mtd_get_size_of_erase_once(int fd) { if (fd > PART_NUM_MAX) { return 0; } if (g_mtd_info.page_erase_ena == MODE_ERASE_PAGE) { return PAGE_PROGRAM_SIZE; } else { return SECTOR_ERASE_SIZE; } } /************************* partition basics functions *************************/ uint32_t dev_get_oem_part_num(uint8_t * num) { *num = PART_NUM_OEM; return HAL_OK; } uint32_t dev_get_cal_data_part_num(uint8_t * num) { *num = PART_NUM_CAL_DATA; return HAL_OK; } uint32_t dev_get_boot_fw_part_num(uint8_t *part) { if (g_start_flag == 0) { *part = g_part_num_fw1; } else if (g_start_flag == 1) { *part = g_part_num_fw2; } else { return 1; } return 0; } uint32_t dev_get_boot_pib_part_num(uint8_t *part) { if (g_last_flag == 0) { *part = PART_NUM_PIB1; } else if (g_last_flag == 1) { *part = PART_NUM_PIB2; } else { return 1; } return 0; } uint32_t dev_get_boot_cus_part_num(uint8_t *part) { *part = PART_NUM_INVALID; if (g_part_info[PART_NUM_CUS_FW1].size == 0 || g_part_info[PART_NUM_CUS_FW2].size == 0) { return 1; } if (g_last_flag == 0) { *part = PART_NUM_CUS_FW1; } else if (g_last_flag == 1) { *part = PART_NUM_CUS_FW2; } else { return 1; } return 0; } uint32_t dev_get_upgrade_fw_part_num(uint8_t *part) { uint32_t start_part = 0; /* g_start_flag cann't used at here, because an exception may occur * before it is initialized. */ if (dev_param_get_start_flag(&start_part)) { return 1; } if (start_part == 0) { *part = g_part_num_fw2; } else if (start_part == 1) { *part = g_part_num_fw1; } else { return 1; } return 0; } uint32_t dev_get_upgrade_pib_part_num(uint8_t *part) { if (g_last_flag == 0) { *part = PART_NUM_PIB2; } else if (g_last_flag == 1) { *part = PART_NUM_PIB1; } else { return 1; } return 0; } uint32_t dev_get_upgrade_cus_part_num(uint8_t *part) { *part = PART_NUM_INVALID; if (g_part_info[PART_NUM_CUS_FW1].size == 0 || g_part_info[PART_NUM_CUS_FW2].size == 0) { return 1; } if (g_last_flag == 0) { *part = PART_NUM_CUS_FW2; } else if (g_last_flag == 1) { *part = PART_NUM_CUS_FW1; } else { return 1; } return 0; } uint8_t dev_get_pib_ext_part_num(uint8_t part) { if (part == PART_NUM_PIB1) { return PART_NUM_PIB1_EXT; } else { return PART_NUM_PIB2_EXT; } } uint32_t dev_get_part_size(uint8_t part) { return g_part_info[part].size; } /************************ file system basics functions ************************/ int dev_open(int num, uint32_t flags) { int fd; uint32_t core_id; if (num < PART_NUM_MIN || num >= PART_NUM_MAX) { return -1; } fd = g_mtd_info.file[num].fd; core_id = cpu_get_mhartid(); if (!(MTD_AUTH_RW & GET_CORE_AUTHORITY(g_mtd_info.part[num].authority, core_id))) { return -1; } if ((!os_atomic_check_set(&g_mtd_info.file[num].used, FILE_UNUSE, FILE_INUSE)) && flags == 0) { /* re-open */ return -1; } g_mtd_info.file[num].pos = 0; return fd; } int dev_close(int fd) { if (fd < 0) { /* fd invalid */ return -1; } if (!os_atomic_check_set(&g_mtd_info.file[fd].used, FILE_INUSE, FILE_UNUSE)) { return -1; } g_mtd_info.file[fd].pos = 0; return 0; } int dev_seek(int fd, uint32_t offset, uint8_t fromwhere) { uint32_t pos = 0; uint32_t part_size = 0; if (fd < 0 || g_mtd_info.file[fd].used != FILE_INUSE) { /* fd invalid */ return -1; } pos = g_mtd_info.file[fd].pos; part_size = g_mtd_info.part[fd].size; if (offset >= part_size) { /* over range */ return -1; } switch(fromwhere) { case DEV_SEEK_SET: g_mtd_info.file[fd].pos = offset; break; case DEV_SEEK_CUR: if(pos + offset > part_size){ /* over range */ return -1; } g_mtd_info.file[fd].pos = pos + offset; break; case DEV_SEEK_END: g_mtd_info.file[fd].pos = g_mtd_info.part[fd].size - offset; break; } return g_mtd_info.file[fd].pos; } int dev_read(int fd, void* buf, size_t count) { int ret = 0; uint32_t core_id; uint32_t pos, offset, part_size, addr; uint8_t* p = (uint8_t*)buf; if (fd < 0 || (g_mtd_info.file[fd].used != FILE_INUSE)) { /* fd invalid */ return -1; } core_id = cpu_get_mhartid(); if (!(MTD_AUTH_READ & GET_CORE_AUTHORITY(g_mtd_info.part[fd].authority, core_id))) { return -1; } pos = g_mtd_info.file[fd].pos; offset = g_mtd_info.part[fd].offset; part_size = g_mtd_info.part[fd].size; addr = offset + pos; if(pos + count > part_size) { /* over range */ return -1; } if (FLASH_OS_ENABLE == flash_os_is_enable()) { os_acquire_mutex(mtd_op_mutex); } ret = g_mtd_info.opt.read(p, addr, count, MOD_SFC_READ_QUAD_FAST); if (ret != HAL_OK) { if (FLASH_OS_ENABLE == flash_os_is_enable()) { os_release_mutex(mtd_op_mutex); } return -1; } /* position move */ pos += count; g_mtd_info.file[fd].pos = pos; if (FLASH_OS_ENABLE == flash_os_is_enable()) { os_release_mutex(mtd_op_mutex); } return count; } int dev_write(int fd, void*buf, size_t count) { uint8_t is_erase; if ((fd == g_part_num_fw1) || (fd == g_part_num_fw2)) { /* using this, please make sure the part has been erased */ is_erase = 0; } else { is_erase = 1; } return dev_write_ext(fd, buf, count, is_erase); } int dev_write_ext(int fd, void *buf, size_t count, uint8_t is_erase) { int ret = 0; uint8_t* p = (uint8_t*)buf; uint32_t core_id; uint32_t pos, offset, part_size, addr; flash_write_param_t param = {0}; if (fd < 0) { /* fd invalid */ return -1; } if ((FLASH_OS_ENABLE == flash_os_is_enable()) && (g_mtd_info.file[fd].used != FILE_INUSE)) { return -1; } core_id = cpu_get_mhartid(); if (!(MTD_AUTH_WRITE & GET_CORE_AUTHORITY(g_mtd_info.part[fd].authority, core_id))) { return -1; } pos = g_mtd_info.file[fd].pos; offset = g_mtd_info.part[fd].offset; part_size = g_mtd_info.part[fd].size; addr = offset + pos; if(pos + count > part_size) { /* over range */ return -1; } if (FLASH_OS_ENABLE == flash_os_is_enable()) { os_acquire_mutex(mtd_op_mutex); } param.read_mode = MOD_SFC_READ_QUAD_IO_FAST; param.write_mode = MOD_SFC_PROG_QUAD; param.erase_mode = g_mtd_info.page_erase_ena; if (FLASH_OS_ENABLE == flash_os_is_enable()) { param.sw_mode = flash_get_pe_mode(); if(param.sw_mode == MOD_SW_MODE_ENA){ param.cb = &g_flash_os_cb; } else { param.cb = 0; } } else { param.sw_mode = MOD_SW_MODE_DIS; param.cb = 0; } param.is_erase = !!is_erase; iot_printf("[dev_write] addr: %08x, count: %08x is_erase %d\n", addr, count, param.is_erase); ret = g_mtd_info.opt.write( p, addr, count, ¶m); if (ret != HAL_OK) { goto w_err; } iot_printf("[dev_write] finished, addr:%08x, count:%08x\n", addr, count); /* position move */ pos += count; g_mtd_info.file[fd].pos = pos; if (FLASH_OS_ENABLE == flash_os_is_enable()) { os_release_mutex(mtd_op_mutex); } return count; w_err: if (FLASH_OS_ENABLE == flash_os_is_enable()) { os_release_mutex(mtd_op_mutex); } return -1; } int dev_erase(int fd, uint32_t addr, uint8_t mode) { uint8_t ret = 0; uint32_t offset = 0; uint32_t size = 0; uint32_t pos = 0; uint32_t core_id; flash_write_param_t param = {0}; if (fd < 0) { /* fd invalid */ return -1; } if ((FLASH_OS_ENABLE == flash_os_is_enable()) && (g_mtd_info.file[fd].used != FILE_INUSE)) { return -1; } core_id = cpu_get_mhartid(); if (!(MTD_AUTH_WRITE & GET_CORE_AUTHORITY(g_mtd_info.part[fd].authority, core_id))) { return -1; } if (addr > g_mtd_info.part[fd].size) { return -1; } if (FLASH_OS_ENABLE == flash_os_is_enable()) { os_acquire_mutex(mtd_op_mutex); } offset = g_mtd_info.part[fd].offset; size = g_mtd_info.part[fd].size; if (FLASH_OS_ENABLE == flash_os_is_enable()) { param.sw_mode = flash_get_pe_mode(); if(param.sw_mode == MOD_SW_MODE_ENA){ param.cb = &g_flash_os_cb; } else { param.cb = 0; } } else { param.sw_mode = MOD_SW_MODE_DIS; param.cb = 0; } if (mode == DEV_ERASE_TYPE_FULL_PART) { pos = offset; while(size > 0) { if (size >= BLOCK_ERASE_64K_SIZE) { param.erase_mode = MODE_ERASE_BLOCK64; ret = g_mtd_info.opt.erase(pos, ¶m); if (ret > 0) { goto e_err; } size -= BLOCK_ERASE_64K_SIZE; pos += BLOCK_ERASE_64K_SIZE; } else if (size >= SECTOR_ERASE_SIZE) { param.erase_mode = MODE_ERASE_SECTOR; ret = g_mtd_info.opt.erase(pos, ¶m); if (ret > 0) { goto e_err; } size -= SECTOR_ERASE_SIZE; pos += SECTOR_ERASE_SIZE; } else { goto e_err; } } } else if (mode == DEV_ERASE_TYPE_SECTOR) { param.erase_mode = MODE_ERASE_SECTOR; ret = g_mtd_info.opt.erase(offset + addr, ¶m); if (ret > 0) { goto e_err; } } else if (mode == DEV_ERASE_TYPE_PAGE) { param.erase_mode = MODE_ERASE_PAGE; ret = g_mtd_info.opt.erase(offset + addr, ¶m); if (ret > 0) { goto e_err; } } else { goto e_err; } if (FLASH_OS_ENABLE == flash_os_is_enable()) { os_release_mutex(mtd_op_mutex); } return 0; e_err: if (FLASH_OS_ENABLE == flash_os_is_enable()) { os_release_mutex(mtd_op_mutex); IOT_ASSERT(0); } return -1; } /************************ image header basics functions ***********************/ /** * @brief mtd_get_hdr(): get firmware header information of specified partition. * @param part_num: the specified partition. * @param hdr: pointer to save header information. * @return ERR_FAIL: failed; ERR_OK: succeed. */ static uint32_t mtd_get_hdr(uint8_t part_num, imgHdr *hdr) { int fd; static uint8_t last_part = PART_NUM_INVALID; static uint8_t block[HEADER_TOLTAL_SIZE]; if (part_num >= PART_NUM_MAX) { return ERR_FAIL; } os_mem_set(hdr, 0, sizeof(hdr)); if (part_num != last_part) { os_mem_set(block, 0, sizeof(block)); fd = dev_open(part_num, 0); if (fd > 0) { dev_read(fd, block, HEADER_TOLTAL_SIZE); dev_close(fd); } else { return ERR_FAIL; } } img_header_construct(hdr, (char *)block); if (iot_imghdr_get_guard(hdr) != IMAGE_GUARD) { /* header information is invalid */ last_part = PART_NUM_INVALID; return ERR_FAIL; } last_part = part_num; return ERR_OK; } /** * @brief mtd_get_hdr_img_size(): get image size of specified partition from hdr. * @param part: the specified partition. * @return 0: failed; other: image size. */ uint32_t mtd_get_hdr_img_size(uint8_t part) { imgHdr hdr = {0}; if (mtd_get_hdr(part, &hdr) != ERR_OK) { return 0; } return iot_imghdr_get_imgSize(&hdr); } /** * @brief mtd_get_hdr_fw_size(): get firmware size of specified partition from hdr. * only v0\v0.1 header struction has fw_size member, and sbl\oem\pib fixed 0. * @param part: the specified partition. * @return 0: failed; other: firmware size. */ uint32_t mtd_get_hdr_fw_size(uint8_t part) { imgHdr hdr = {0}; if (mtd_get_hdr(part, &hdr) != ERR_OK) { return 0; } return iot_imghdr_get_fwSize(&hdr); } /** * @brief mtd_get_hdr_img_crc(): get crc of specified partition from hdr. * @param part: the specified partition. * @return 0: failed; other: firmware size. */ uint32_t mtd_get_hdr_img_crc(uint8_t part) { imgHdr hdr = {0}; if (mtd_get_hdr(part, &hdr) != ERR_OK) { return 0; } return iot_imghdr_get_imgCRC(&hdr); } /********************** boot partition basics functions ***********************/ static uint32_t dev_param_gen_list(dev_param_t *param, const char *name, const char *value) { uint32_t len_name, len_value; len_name = iot_strlen(name); len_value = iot_strlen(value); if (len_name >= PARAM_NAME_LEN_MAX || len_value > PARAM_VAL_LEN_MAX) { return 1; } os_mem_cpy(param->name, name, len_name); os_mem_cpy(param->value, value, len_value); param->equal = PARAM_EQUAL_CHAR; param->end = PARAM_END_CHAR; return 0; } static uint32_t dev_param_create_value(const char *name, char *value) { int i = 0; int fd = 0; uint32_t ret = 1; int name_len = 0; int pos = 0; dev_param_t param = {0}; name_len = iot_strlen(name); fd = dev_open(PART_NUM_PARAM, 0); if (fd < 0) { iot_printf("open part %d failed\n", PART_NUM_PARAM); goto out; } for (i = 0; i < PARAM_MAX_LENGTH; i++) { os_mem_set(¶m, 0, sizeof(dev_param_t)); if (dev_read(fd, ¶m, sizeof(dev_param_t)) < 0) { iot_printf("read part parameters failed\n"); goto out; } if (param.end == PARAM_END_CHAR) { if (os_mem_cmp(name, param.name, name_len) == 0) { ret = 0; goto out; } } else { os_mem_set(¶m, 0, sizeof(dev_param_t)); if (dev_param_gen_list(¶m, name, value)) { goto out; } pos += sizeof(dev_param_t) * i; dev_seek(fd, pos, DEV_SEEK_SET); if (dev_write(fd, ¶m,sizeof(dev_param_t)) < 0) { iot_printf("write param[%s=%s] failed\n", name, value); goto out; } ret = 0; goto out; } } out: dev_close(fd); return ret; } uint32_t dev_param_get_value(const char *name, char *value, int *pos) { int i = 0; int fd = 0; uint32_t ret = 1; int name_len = 0; int value_len = 0; dev_param_t param = {0}; if (name == NULL || pos == NULL) {\ goto out; } name_len = iot_strlen(name); fd = dev_open(PART_NUM_PARAM, 0); if (fd < 0) { iot_printf("open part %d failed\n", PART_NUM_PARAM);\ goto out; } for (i = 0; i < PARAM_MAX_LENGTH; i++) { os_mem_set(¶m, 0, sizeof(dev_param_t)); if (dev_read(fd, ¶m, sizeof(dev_param_t)) < 0) { iot_printf("read part parameters failed\n"); goto out; } if (param.end == PARAM_END_CHAR) { if (os_mem_cmp(name, param.name, name_len) == 0) { value_len = iot_strlen(param.value); os_mem_cpy(value, param.value, value_len); *pos = dev_seek(fd, 0, DEV_SEEK_CUR); *pos -= sizeof(dev_param_t); ret = 0; goto out; } } else { iot_printf("part parameters not found\n");\ goto out; } } out: dev_close(fd); return ret; } uint32_t dev_param_save_value(const char *name, char *value) { int fd = 0; int pos = 0; uint32_t ret = 1; dev_param_t param = {0}; char tmp[PARAM_VAL_LEN_MAX] = {0}; int name_len = iot_strlen(name); if (name == NULL && value == NULL) { goto out; } if (dev_param_get_value(name, tmp, &pos)) { if ((os_mem_cmp(name, PARAM_STRING_UPGRADE_STS, name_len) == 0)) { ret = dev_param_create_value(name, value); goto out; } else { goto out; } } if ((iot_strlen(value) == iot_strlen(tmp)) && (os_mem_cmp(tmp, value, iot_strlen(value)) == 0)) { ret = 0; goto out; } if (dev_param_gen_list(¶m, name, value)) { goto out; } fd = dev_open(PART_NUM_PARAM, 0); if (fd < 0) { iot_printf("open part %d failed\n", PART_NUM_PARAM); dev_close(fd); goto out; } dev_seek(fd, pos, DEV_SEEK_SET); if (dev_write(fd, ¶m,sizeof(dev_param_t)) < 0) { iot_printf("write param[%s=%s] failed\n", name, value); dev_close(fd); IOT_ASSERT(0); goto out; } dev_close(fd); ret = 0; out: return ret; } /************************* boot parameter functions ***************************/ uint8_t dev_get_first_boot_val() { return g_first_boot; } uint8_t dev_get_first_run_val() { return g_first_run; } uint8_t dev_get_boot_cnt() { return g_cnt_flag; } bool_t dev_get_upgrade_flag(void) { return g_upgrade_flag; } static uint32_t dev_param_get_flag(const char *name, uint32_t *flag) { int pos = 0; char value[PARAM_VAL_LEN_MAX] = {0}; if (dev_param_get_value(name, value, &pos)) { iot_printf("get %s flag value error\n", name); return 1; } // check valid number, ascii range is '0' - '9' if ((value[0] < 0x30) || (value[0] > 0x39)) { iot_printf("invalid parameter value: %s\n", value); return 1; } *flag = value[0] - 0x30; return 0; } uint32_t dev_param_get_start_flag(uint32_t *flag) { return dev_param_get_flag(PARAM_STRING_START_PART, flag); } uint32_t dev_param_get_uncp_flag(uint32_t *flag) { return dev_param_get_flag(PARAM_STRING_FW_UNCP, flag); } uint32_t dev_param_get_last_flag(uint32_t *flag) { return dev_param_get_flag(PARAM_STRING_LAST_PART, flag); } uint32_t dev_param_get_boot_flag(uint32_t *flag) { return dev_param_get_flag(PARAM_STRING_BOOT_PART, flag); } uint32_t dev_param_get_cnt_flag(uint32_t *flag) { return dev_param_get_flag(PARAM_STRING_BOOT_CNT, flag); } uint32_t dev_param_get_boot_after_burn(uint32_t *p_flag) { if (dev_param_get_flag(PARAM_STRING_FIRST_RUN, p_flag)) { iot_printf("get first run flag value error\n"); return ERR_FAIL; } /* If the startup is the first after burning, save the flag. * do not use the p_flag, because it will be clean up later. */ if (*p_flag) { g_first_run = 1; } return ERR_OK; } uint32_t dev_param_clear_boot_after_burn(void) { uint32_t flag = ERR_OK; /* when FW starts, the "first_run" field is cleared */ if (dev_param_get_boot_after_burn(&flag) != ERR_OK) { return ERR_OK; } if (dev_param_save_value(PARAM_STRING_FIRST_RUN, "0") != ERR_OK) { return ERR_FAIL; } return ERR_OK; } void dev_switch_part_flag(uint8_t cause) { char switch_info; if (g_last_flag == 0) { dev_param_save_value(PARAM_STRING_START_PART, "1"); } else if (g_last_flag == 1) { dev_param_save_value(PARAM_STRING_START_PART, "0"); } /* valid param check */ dev_param_save_value(PARAM_STRING_BOOT_PART, "1"); if (cause != DEV_SWITCH_PART_CAUSE_CRASH) { switch_info = '0' + (cause * 2 + g_last_flag); dev_param_save_value(PARAM_STRING_SWITCH_INFO, &switch_info); } if (cause == DEV_SWITCH_PART_CAUSE_UPGRADE) { iot_printf("upgrade is complete, current part:%d\n", g_last_flag); } } void dev_switch_part() { if (g_cnt_flag == 0) { // if cnt is not cleared, don't run switch part flash_set_os_dis(); dev_switch_part_flag(DEV_SWITCH_PART_CAUSE_CRASH); flash_set_os_ena(); } } void dev_get_switch_part_info(uint8_t *cause, uint8_t *upgrade_flag) { uint32_t switch_info = 0; uint8_t last_pass_part = 0, switch_cause = 0; /* default value */ *cause = DEV_SWITCH_PART_CAUSE_UPGRADE; *upgrade_flag = 1; if (dev_param_get_flag(PARAM_STRING_SWITCH_INFO, &switch_info)) { /* the parameter does not exist(old version) */ return; } switch_cause = switch_info / 2; last_pass_part = switch_info % 2; if (switch_cause >= DEV_SWITCH_PART_CAUSE_MAX) { /* invalid value */ return; } *cause = switch_cause; if (g_start_flag == last_pass_part) { *upgrade_flag = 0; } return; } uint32_t dev_startup_param_value_check(bool_t sync) { uint32_t boot = 0; uint32_t start = 0; uint32_t last = 0; uint32_t cnt = 0; uint32_t ret = HAL_ERROR; uint32_t failed_pos = 0; if (dev_param_get_start_flag(&start)) { failed_pos = 1; goto err_exit; } if (dev_param_get_last_flag(&last)) { failed_pos = 2; goto err_exit; } if (dev_param_get_boot_flag(&boot)) { failed_pos = 3; goto err_exit; } if (dev_param_get_cnt_flag(&cnt)) { // boot_cnt not found, set cnt as default cnt = 0; } g_start_flag = start; g_last_flag = last; g_cnt_flag = cnt; iot_printf("boot: %d, start: %d, last: %d\n", boot, start, last); iot_printf("boot cnt: %d\n", cnt); if (last != start) { g_upgrade_flag = true; if (0 == last) { if (sync) { iot_printf("start=1, then set start=0\n"); dev_param_save_value(PARAM_STRING_START_PART, "0"); g_start_flag = 0; } ret = HAL_OK; } else if (1 == last) { if (sync) { iot_printf("start=0, then set start=1\n"); dev_param_save_value(PARAM_STRING_START_PART, "1"); g_start_flag = 1; } ret = HAL_OK; } else { failed_pos = 4; goto err_exit; } } if (cnt && sync) { iot_printf("boot cnt=%d, then set cnt=0\n", cnt); dev_param_save_value(PARAM_STRING_BOOT_CNT, "0"); g_cnt_flag = 0; } if (boot && sync) { if (g_first_boot == 0) { g_first_boot = 1; } iot_printf("boot=1, then set boot=0\n"); dev_param_save_value(PARAM_STRING_BOOT_PART, "0"); } err_exit: iot_printf("startup param value check, failed_pos %d, ret %d \n", failed_pos, ret); return ret; } /**************************** firmware functions ******************************/ /** * @brief mtd_get_fw_decompressed_crc(): get crc of decompressed firmware. * @param part: fw1 or fw2 partition. * @return 0: failed; other: decompressed firmware crc. */ static uint32_t mtd_get_fw_decompressed_crc(uint8_t part) { imgHdr hdr = {0}; if (mtd_get_hdr(part, &hdr) != ERR_OK) { return 0; } if (hdrVer_10 == iot_imghdr_get_hdrVer(&hdr)) { /* [TODO]: get header info form psram chip */ if (mtd_get_hdr(PART_NUM_RUN, &hdr) != ERR_OK) { return 0; } return iot_imghdr_get_imgCRC(&hdr); } else { return iot_imghdr_get_fwCRC(&hdr); } } /** * @brief mtd_get_fw_decompressed_size(): get size of decompressed firmware. * @param part: fw1 or fw2 partition. * @return 0: failed; other: decompressed firmware size. */ static uint32_t mtd_get_fw_decompressed_size(uint8_t part) { imgHdr hdr = {0}; if (mtd_get_hdr(part, &hdr) != ERR_OK) { return 0; } if (hdrVer_10 == iot_imghdr_get_hdrVer(&hdr)) { /* [TODO]: get header info form psram chip */ if (mtd_get_hdr(PART_NUM_RUN, &hdr) != ERR_OK) { return 0; } return iot_imghdr_get_imgSize(&hdr); } else { return iot_imghdr_get_fwSize(&hdr); } } /** * @brief mtd_calc_part_crc_internal(): calculate firmware crc for specified part. * @param part: the specified partition. * @return 0: failed; other: firmware crc. */ static uint32_t mtd_calc_part_crc_internal(uint8_t part_num) { #define READ_BUFF_SIZE (0x100) iot_pkt_t *pkt = NULL; uint32_t size_crc = 0, crc_cal = 0xffffffff; uint32_t calc_pos = 0, calc_size, end_pos = 0; uint8_t pib_upgrade_part = 0; uint8_t *block = NULL; imgHdr hdr = {0}; int fd; if (dev_get_upgrade_pib_part_num(&pib_upgrade_part)) { iot_printf("get pib upgrade part number failed\n"); return 0; } pkt = iot_pkt_alloc(READ_BUFF_SIZE, IOT_DRIVER_MID); if (pkt == NULL) { iot_printf("memory malloc failed.\n"); return 0; } block = iot_pkt_data(pkt); if (part_num == PART_NUM_RUN) { /* kl1 kl2 run partition not has header information, but kl3 has it */ if (g_start_flag) { size_crc = mtd_get_fw_decompressed_size(g_part_num_fw2); mtd_get_hdr(g_part_num_fw2, &hdr); } else { size_crc = mtd_get_fw_decompressed_size(g_part_num_fw1); mtd_get_hdr(g_part_num_fw1, &hdr); } /* kl3 need IMAGE_LEN_FOR_CRC */ if (hdrVer_10 == iot_imghdr_get_hdrVer(&hdr)) { size_crc = IMAGE_LEN_FOR_CRC(size_crc); } } else { size_crc = mtd_get_hdr_img_size(part_num); size_crc = IMAGE_LEN_FOR_CRC(size_crc); } fd = dev_open(part_num, 0); if (fd < 0) { iot_pkt_free(pkt); return 0; } /* skip header area */ calc_pos = sizeof(imgHdr); dev_seek(fd, calc_pos, DEV_SEEK_SET); end_pos = size_crc + calc_pos; if (part_num == pib_upgrade_part) { /* PIB firmware only needs to verify ro data (first 4KB) */ while (calc_pos < IOT_PIB_W_SECTION_START_ADDR) { calc_size = min(READ_BUFF_SIZE, IOT_PIB_W_SECTION_START_ADDR - calc_pos); dev_read(fd, block, calc_size); crc_cal = iot_getcrc32_update(crc_cal, block, calc_size); calc_pos += calc_size; } os_mem_set(block, 0, READ_BUFF_SIZE); while (calc_pos < end_pos) { calc_size = min(READ_BUFF_SIZE, end_pos - calc_pos); crc_cal = iot_getcrc32_update(crc_cal, block, calc_size); calc_pos += calc_size; } } else { while (calc_pos < end_pos) { calc_size = min(READ_BUFF_SIZE, end_pos - calc_pos); dev_read(fd, block, calc_size); crc_cal = iot_getcrc32_update(crc_cal, block, calc_size); calc_pos += calc_size; } } dev_close(fd); iot_pkt_free(pkt); return (crc_cal ^ 0xffffffff); } uint32_t mtd_calc_decompressed_fw_crc_mp(uint8_t part) { uint8_t *src, *buf, *p; uint32_t size_crc, crc_cal = 0xffffffff; uint32_t left = 0, len = 0; uint8_t first = 1; imgHdr hdr = {0}; #define BLOCK_SIZE 0x4000 src = (uint8_t *)(g_part_info[PART_NUM_RUN].offset + flash_get_dev_base()); buf = os_mem_malloc(IOT_DRIVER_MID, BLOCK_SIZE); if(buf == NULL) { iot_printf("memory malloc failed.\n"); return 0; } size_crc = mtd_get_fw_decompressed_size(part); left = size_crc; p = src + sizeof(imgHdr); if (ERR_OK != mtd_get_hdr(part, &hdr)) { iot_printf("get fw hdr failed\n"); os_mem_free(buf); return 0; } /* kl3 need IMAGE_LEN_FOR_CRC */ if (hdrVer_10 == iot_imghdr_get_hdrVer(&hdr)) { left = IMAGE_LEN_FOR_CRC(size_crc); } os_disable_irq(); while (left > 0) { // read data by block if(first){ len = 13; first = 0; } else { len = BLOCK_SIZE; } len = (len > left) ? left : len; // copy to data buffer; os_mem_cpy(buf, p, len); crc_cal = iot_getcrc32_update(crc_cal, buf, len); left = left - len; p = p + len; } os_enable_irq(); os_mem_free(buf); crc_cal ^= 0xffffffff; return crc_cal; } uint32_t mtd_calc_hdr_img_part_crc(uint8_t part) { return mtd_calc_part_crc_internal(part); } uint8_t mtd_fw_hdr_img_crc_compare() { uint8_t ret = 0; uint32_t ori_hdr_crc = 0; uint32_t calc_hdr_crc = 0; uint32_t ori_fw_crc = 0; uint32_t calc_fw_crc = 0; uint8_t fw_part = 0; dev_get_boot_fw_part_num(&fw_part); ori_hdr_crc = mtd_get_hdr_img_crc(fw_part); calc_hdr_crc = mtd_calc_hdr_img_part_crc(fw_part); if (!g_run_in_psram) { if (fw_part == PART_NUM_FW1 || fw_part == PART_NUM_FW2) { ori_fw_crc = mtd_get_fw_decompressed_crc(fw_part); if(g_fw_mode == FTM_MODE){ calc_fw_crc = mtd_calc_decompressed_fw_crc_mp(fw_part); } else { calc_fw_crc = mtd_calc_part_crc_internal(PART_NUM_RUN); } } } if ((ori_hdr_crc == calc_hdr_crc) && (ori_fw_crc == calc_fw_crc)) { iot_printf("Matched: fw_hdr_crc=%x; fw_crc=%x.\n", \ calc_hdr_crc, calc_fw_crc); } else { ret = 1; iot_printf("Mismatched: fw_hdr_crc ori=%x, calc=%x; fw_crc ori=%x, " "calc=%x.\n", ori_hdr_crc, calc_hdr_crc, ori_fw_crc, calc_fw_crc); } return ret; } uint32_t mtd_copy_part(uint8_t src_part, uint8_t dest_part) { int fd_s = -1, fd_d = -1; int status = 0; uint8_t is_erase = 0, is_exist_cus = 0; uint8_t boot_fw_part, boot_pib_part, boot_cus_part; uint32_t reason = ERR_OK; uint32_t offset = 0, write_len = 0; uint32_t size_img = 0; uint8_t pib_type = 0; iot_pkt_t *cache_pkt; cache_pkt = (iot_pkt_t*)iot_pkt_alloc(MTD_COPY_FLASH_SIZE_ONCE, IOT_DRIVER_MID); if (cache_pkt == NULL) { return ERR_NOMEM; } if (g_part_info[PART_NUM_CUS_FW1].size && g_part_info[PART_NUM_CUS_FW2].size) { is_exist_cus = 1; } if (dev_get_boot_fw_part_num(&boot_fw_part)) { iot_printf("%s firmware boot part open failed\n", __FUNCTION__); } else { if (boot_fw_part == dest_part) { reason = 1; goto err_exit; } } if (dev_get_boot_pib_part_num(&boot_pib_part)) { iot_printf("%s pib boot part open failed\n", __FUNCTION__); } else { if (boot_pib_part == dest_part) { reason = 2; goto err_exit; } } if (is_exist_cus) { if (dev_get_boot_cus_part_num(&boot_cus_part)) { iot_printf("%s cus boot part open failed\n", __FUNCTION__); } else { if (boot_cus_part == dest_part) { reason = 3; goto err_exit; } } } /* kl1, kl2 and kl3 are same; 1m, 2m and 4m are same */ if (src_part == PART_NUM_PIB1) { pib_type = 1; if (dest_part != PART_NUM_PIB2) { reason = 4; } } else if (src_part == PART_NUM_PIB2) { pib_type = 1; if (dest_part != PART_NUM_PIB1) { reason = 5; } } else if (src_part == g_part_num_fw1) { if (dest_part != g_part_num_fw2) { reason = 6; } } else if (src_part == g_part_num_fw2) { if (dest_part != g_part_num_fw1) { reason = 7; } } else if (src_part == PART_NUM_CUS_FW1) { if (dest_part != PART_NUM_CUS_FW2 || !is_exist_cus) { reason = 8; } } else if (src_part == PART_NUM_CUS_FW2) { if (dest_part != PART_NUM_CUS_FW1 || !is_exist_cus) { reason = 9; } } else { reason = 10; } if (reason) { goto err_exit; } size_img = mtd_get_hdr_img_size(src_part); size_img = IMAGE_LEN_FOR_CRC(size_img); if (size_img > 0) { fd_s = dev_open(src_part, 0); if (fd_s < 0) { reason = 12; goto err_exit; } fd_d = dev_open(dest_part, 0); if (fd_d < 0) { reason = 13; goto err_exit; } if (pib_type) { size_img = IOT_PIB_W_SECTION_START_ADDR; is_erase = 1; } else { size_img += sizeof(imgHdr); status = dev_erase(fd_d, 0, DEV_ERASE_TYPE_FULL_PART); } if (status < 0) { reason = 14; goto err_exit; } while (offset < size_img) { iot_wdg_feed_dog(); write_len = min(MTD_COPY_FLASH_SIZE_ONCE, size_img - offset); status = dev_read(fd_s, iot_pkt_data(cache_pkt), write_len); if (status < 0) { reason = 15; goto err_exit; } status = dev_write_ext(fd_d, iot_pkt_data(cache_pkt), write_len, is_erase); if (status < 0) { reason = 16; goto err_exit; } offset += write_len; } } err_exit: if (fd_s >= 0) { dev_close(fd_s); } if (fd_d >= 0) { dev_close(fd_d); } if (cache_pkt != NULL) { iot_pkt_free(cache_pkt); } iot_printf("%s copy part result:%d\n", __FUNCTION__, reason); if (reason) { return ERR_FAIL; } return ERR_OK; } uint32_t mtd_running_fw_get_size(void) { uint32_t curr_run_part = 0; uint32_t size = 0; if (g_last_flag == 0) { curr_run_part = g_part_num_fw1; } else if (g_last_flag == 1) { curr_run_part = g_part_num_fw2; } else { return 0; } size = mtd_get_hdr_img_size(curr_run_part); if (size == 0) { return 0; } size += HEADER_TOLTAL_SIZE; if (size > g_part_info[curr_run_part].size) { size = g_part_info[curr_run_part].size; } return size; } uint32_t mtd_running_fw_read(uint32_t offset, uint8_t *buffer, uint32_t length) { uint8_t ret = ERR_FAIL; static uint32_t image_size = 0; uint32_t read_len = 0; uint32_t curr_run_part = 0; if (buffer == NULL || length == 0) { goto out; } if (image_size == 0) { image_size = mtd_running_fw_get_size(); if (image_size == 0) { goto out; } } if (offset > image_size) { goto out; } if (offset + length > image_size) { length = image_size - offset; } if (g_last_flag == 0) { curr_run_part = g_part_num_fw1; } else if (g_last_flag == 1) { curr_run_part = g_part_num_fw2; } else { goto out; } offset += g_part_info[curr_run_part].offset; if (FLASH_OS_ENABLE == flash_os_is_enable()) { os_acquire_mutex(mtd_op_mutex); } ret = flash_read(buffer, offset, length, MOD_SFC_READ_QUAD_FAST); if (FLASH_OS_ENABLE == flash_os_is_enable()) { os_release_mutex(mtd_op_mutex); } if (ret != HAL_OK) { goto out; } read_len = length; out: return read_len; } /************************* custom partition functions *************************/ uint32_t custom_dev_resize(uint32_t offset, uint32_t size) { if (offset < 0x200000) { return HAL_ERROR; } if (size > 0x5e0000) { return HAL_ERROR; } g_part_info[PART_NUM_CUS_DATA].offset = offset; g_part_info[PART_NUM_CUS_DATA].size = size; return HAL_OK; } uint32_t custom_dev_query_offset() { return g_part_info[PART_NUM_CUS_DATA].offset; } int32_t custom_dev_query_rw_size() { return g_part_info[PART_NUM_CUS_DATA].size; } int32_t custom_dev_open() { int fd = 0; fd = dev_open(PART_NUM_CUS_DATA, 0); if (fd < 0) { iot_printf("open custom part failed\n"); return -1; } return fd; } int32_t custom_dev_close(int32_t fd) { if (fd != PART_NUM_CUS_DATA) { return -1; } return dev_close(fd); } int32_t custom_dev_seek(int32_t fd, uint32_t offset, uint8_t fromwhere) { if (fd != PART_NUM_CUS_DATA) { return -1; } return dev_seek(fd, offset, fromwhere); } int32_t custom_dev_read(int32_t fd, void* buf, size_t count) { if (fd != PART_NUM_CUS_DATA) { return -1; } return dev_read(fd, buf, count); } int32_t custom_dev_write(int32_t fd, void*buf, size_t count) { if (fd != PART_NUM_CUS_DATA) { return -1; } return dev_write(fd, buf, count); } int32_t custom_dev_write_without_erase(int32_t fd, void*buf, size_t count) { if (fd != PART_NUM_CUS_DATA) { return -1; } return dev_write_ext(fd, buf, count, 0); } int32_t custom_dev_erase(int32_t fd, uint32_t offset, size_t count) { uint8_t mode; uint32_t erase_len; if (fd != PART_NUM_CUS_DATA) { return -1; } if ((mtd_get_size_of_erase_once(fd) == PAGE_PROGRAM_SIZE) && ((count & (PAGE_ERASE_SIZE - 1)) == 0)) { mode = MODE_ERASE_PAGE; erase_len = PAGE_ERASE_SIZE; } else { mode = MODE_ERASE_SECTOR; erase_len = SECTOR_ERASE_SIZE; } if (offset & (erase_len - 1) ){ return -1; } if (count & (erase_len - 1) ){ return -1; } while(count > 0){ if (dev_erase(fd, offset, mode) < 0){ return -1; } offset += erase_len; count -= erase_len; } return 0; } int32_t custom_dev_get_size_of_erase_once(int32_t fd) { if (fd != PART_NUM_CUS_DATA) { return -1; } return mtd_get_size_of_erase_once(fd); } /***************************** special functions ******************************/ static uint32_t mtd_part_reinforce(uint32_t offset, uint32_t len) { uint32_t ret = 0; /* feed watchdog */ iot_wdg_feed_dog(); ret = flash_data_reinforce(offset, len); return (ret ? ERR_FAIL : ERR_OK); } /** * @brief mtd_patch_for_puya() - data reinforce for some flash chips of Puya. when we run flash reinforce logic for the first time, we will reinforce all partitions except LOG1\LOG2, PIB1\PIB2(backup each other), PARAM2(not used), SP_FW1\SP_FW2(not used). reinforce the param partition after each restart, and reinforce the run partition after each switch boot area (flash module). * @return ERR_OK - operation successful, ERR_FAIL - operation failed. */ int32_t mtd_patch_for_puya(void) { uint32_t flag_reinforced = 0xff; uint32_t ret = 0; uint32_t offset = 0, size = 0; uint8_t part_num = 0; uint32_t boot = 0, start = 0; int32_t result = ERR_FAIL; uint8_t os_disable = 0; if (patch_puya_twicewrite_flag_check() == 0) { result = ERR_OK; goto out; } ret = dev_param_get_flag(PARAM_STRING_REINFORCE, &flag_reinforced); if (ret == 0 && flag_reinforced == 0) { //reinforced, do nothing } else if (ret == 0 && flag_reinforced == 1) { /* always reinforce param partition after restart */ offset = g_part_info[PART_NUM_PARAM].offset; size = g_part_info[PART_NUM_PARAM].size; if (mtd_part_reinforce(offset, size)) { goto out; } if (dev_param_get_boot_flag(&boot)) { goto out; } if (dev_param_get_start_flag(&start)) { goto out; } /* reinforce the run partition if the startup area is switched */ if (!g_run_in_psram && boot == 1) { offset = g_part_info[PART_NUM_RUN].offset; if (start) { size = mtd_get_fw_decompressed_size(g_part_num_fw2); } else { size = mtd_get_fw_decompressed_size(g_part_num_fw1); } if (mtd_part_reinforce(offset, size)) { goto out; } } } else { /* in 1m, 2m and 4m layout, * SP, SBL, PARAM, PIB and OEM partition information are the same. */ for (part_num = PART_NUM_MIN; part_num < PART_NUM_MAX; part_num++) { /* do not reinforce log and pib partition */ if (part_num == PART_NUM_LOG1 || part_num == PART_NUM_LOG2 || part_num == PART_NUM_PIB1 || part_num == PART_NUM_PIB2) { continue; } offset = g_part_info[part_num].offset; size = g_part_info[part_num].size; /* partition for storing firmware only needs to be reinforced * according to the size of firmware. */ if (part_num == PART_NUM_SP || part_num == PART_NUM_SBL || part_num == PART_NUM_FW1 || part_num == PART_NUM_FW2 || part_num == PART_NUM_CUS_FW1 || part_num == PART_NUM_CUS_FW2 || part_num == PART_NUM_RUN || part_num == PART_NUM_SBL2) { if (part_num == PART_NUM_RUN) { if (start) { size = mtd_get_fw_decompressed_size(g_part_num_fw2); } else { size = mtd_get_fw_decompressed_size(g_part_num_fw1); } } else { size = mtd_get_hdr_img_size(part_num); } } if (mtd_part_reinforce(offset, size)) { goto out; } } /* when running here, the OS has not been started */ if (FLASH_OS_ENABLE == flash_os_is_enable()) { flash_set_os_dis(); os_disable = 1; } ret = dev_param_create_value(PARAM_STRING_REINFORCE, "1"); if (os_disable) { flash_set_os_ena(); } if (ret) { goto out; } } result = ERR_OK; out: return result; }