/** * @file flash_loader_implement.c * @brief The flash loader framework API. * @copyright Copyright (c) 2022 Semidrive Semiconductor. * All rights reserved. */ #include #include #include #include #include #include #include #include #include #include #include #ifdef CONFIG_BPT_UPDATE #include #endif /** external data **/ extern void __iar_data_init3(void); extern void device_init(void); static flash_wrapper_t *flash_wrapper; static flash_addr_t written_size = 0; static flash_addr_t erase_size = 0; static struct spi_nor *flash_loader; static uint32_t img_size; static void *img_flash_base; static uint32_t img_link_base; static uint8_t core; static uint8_t flash_init_flag = 0; static bool img_flash_base_fg; static bool use_flash_base_in_bpt = 0; static bpt_v2_t *p_bpt = NULL; static int32_t base_offset = 0; static volatile int program_hyperflash_fuse_flag = 0; #ifdef CONFIG_BPT_UPDATE static bool bpt_update_fg; #endif #if CONFIG_CHECK_FLASH_LOAD static uint8_t check_buffer[CONFIG_FLASHLOADER_BUFFER_SIZE]; #endif /** public functions **/ #if USE_ARGC_ARGV uint32_t FlashInit(void *base_of_flash, uint32_t image_size, uint32_t link_address, uint32_t flags, int argc, char const *argv[]) { __iar_data_init3(); device_init(); board_init(); ssdk_printf(SSDK_NOTICE, "\r\n------ CMD FlashInit ------\r\nADDR:0x%x " "\r\nLINK_ADDR:0x%x \r\nSIZE:0x%x \r\nFLAGS:0x%x\r\n", (uint32_t)base_of_flash, link_address, image_size, flags); img_size = image_size; img_link_base = link_address; flash_init_flag = flags; use_flash_base_in_bpt = 0; uint32_t image_base = 0; #ifdef CONFIG_BPT_UPDATE if (argc > 1) { core = atoi(argv[0]); bpt_update_fg = atoi(argv[1]); ssdk_printf(SSDK_NOTICE, "ARGV0: core = %d \r\nARGV1: bpt_update_fg = 0x%x \r\n", core, bpt_update_fg); } if (argc > 2) { img_link_base = strtoul(argv[2], NULL, 16); ssdk_printf(SSDK_NOTICE, "ARGV2: img_link_base = 0x%x \r\n", img_link_base); } if (argc > 3) { use_flash_base_in_bpt = atoi(argv[0]); ; ssdk_printf(SSDK_NOTICE, "ARGV3: use_flash_base_in_bpt = 0x%x \r\n", use_flash_base_in_bpt); } #endif board_norflash_init(); flashloader_init(&flash_loader); read_back_buffer_flag = 1; flash_wrapper = flash_wrapper_init(flash_loader); if (flash_wrapper == NULL) { ssdk_printf(SSDK_ERR, "Flash wrapper init fail\r\n"); return RESULT_ERROR; } if (read_sfs(flash_wrapper)) { ssdk_printf(SSDK_NOTICE, "read sfs error\r\n"); } if (use_flash_base_in_bpt && sfs && sfs->normal_img_base) { flash_wrapper_read(flash_wrapper, (flash_addr_t)sfs->normal_img_base, bpt_buffer, FL_BPT_HEDAER_LEN); p_bpt = (bpt_v2_t *)bpt_buffer; if (p_bpt->crc == sfs_crc32(0, (uint8_t *)p_bpt, FL_BPT_CRC_CHECKSUM_OFFSET)) { image_base = BptGetIIBImgbase(p_bpt, core); if (image_base && !img_flash_base_fg) { img_flash_base = (void *)(image_base + XSPI1_BASE + sfs->normal_img_base); img_flash_base_fg = true; base_offset = (uint32_t)img_flash_base - (uint32_t)base_of_flash; ssdk_printf(SSDK_NOTICE, "***base_of_flash change from 0x%x to " "img_flash_base 0x%x***\r\n", base_of_flash, img_flash_base); } else ssdk_printf(SSDK_NOTICE, "can not get core %d image_base(0x%x), " "img_flash_base_fg = %d\r\n", core, image_base, img_flash_base_fg); } else { ssdk_printf(SSDK_ERR, "can not read bpt from flash addr 0x%x\r\n", (flash_addr_t)sfs->normal_img_base); return RESULT_ERROR; } } if (use_flash_base_in_bpt && img_flash_base_fg) { ssdk_printf(SSDK_NOTICE, "FlashInit start, base:0x%x, link base:0x%x, size:0x%x, " "flags:0x%x\r\n\r\n", base_of_flash, img_link_base, img_size, flags); } else { ssdk_printf(SSDK_NOTICE, "FlashInit start, base:0x%x, link base:0x%x, size:0x%x, " "flags:0x%x\r\n\r\n", (uint32_t)img_flash_base, img_link_base, img_size, flags); } ssdk_printf(SSDK_NOTICE, "FlashInit Success\r\n"); return RESULT_OK; } #else uint32_t FlashInit(void *base_of_flash, uint32_t image_size, uint32_t link_address, uint32_t flags) { return RESULT_ERROR; } #endif uint32_t FlashWrite(void *block_start, uint32_t offset_into_block, uint32_t count, char const *buffer) { int ret; uint32_t block_start_addr = (uint32_t)block_start; uint32_t block_end_addr; int32_t written_size_by_addr; ssdk_printf(SSDK_NOTICE, "------ CMD FlashWrite ------\r\nADDR:0x%x \r\nOFFSET:0x%x " "\r\nSIZE:0x%x\r\n", (uint32_t)block_start, offset_into_block, count); if (!use_flash_base_in_bpt) block_start_addr = (uint32_t)block_start; else if (img_flash_base_fg) block_start_addr = (uint32_t)block_start + (uint32_t)base_offset; block_end_addr = block_start_addr + offset_into_block + count; if (!img_flash_base_fg) { img_flash_base = (void *)block_start_addr; img_flash_base_fg = true; } flash_addr_t rx_addr = FLASH_ADDR_MASK((uint32_t)block_start_addr) + offset_into_block; arch_invalidate_cache_range((addr_t)buffer, count); ssdk_printf( SSDK_NOTICE, "FlashWrite addr:0x%x, offset:0x%x, count:0x%x, buffer:0x%x\r\n", (uint32_t)block_start_addr, offset_into_block, count, buffer); if((0 == rx_addr) && is_msfs_data(buffer)) { if(0 != get_matched_sfs(&(flash_loader->info.flash_id[0]), (void **)&buffer, &count)) { ssdk_printf(SSDK_ERR, "FlashWrite msfs error\r\n"); return RESULT_ERROR; } } ret = flash_wrapper_write(flash_wrapper, rx_addr, (const uint8_t *)buffer, (flash_size_t)count); if (ret < 0) { ssdk_printf(SSDK_ERR, "FlashWrite fail\r\n"); return RESULT_ERROR; } written_size += (flash_size_t)count; #if CONFIG_CHECK_FLASH_LOAD uint32_t check_count; uint8_t *buffer_ptr = (uint8_t *)buffer; while (count > 0) { check_count = MIN(count, CONFIG_FLASHLOADER_BUFFER_SIZE); flash_wrapper_read(flash_wrapper, rx_addr, (uint8_t *)check_buffer, (flash_size_t)check_count); for (uint32_t i = 0; i < check_count; i++) { if (buffer_ptr[i] != check_buffer[i]) { ssdk_printf(SSDK_NOTICE, "Error@0x%x: write 0x%x, read 0x%x\r\n", (unsigned int)(rx_addr + i), buffer_ptr[i], check_buffer[i]); } } rx_addr += check_count; buffer_ptr += check_count; count -= check_count; } #endif written_size_by_addr = (block_end_addr - (uint32_t)img_flash_base); ssdk_printf(SSDK_NOTICE, "written_size = 0x%x, written_size_by_addr = 0x%x\r\n", (uint32_t)written_size, (uint32_t)written_size_by_addr); // if the whole image has been written, add the footer or update bpt if (((written_size >= img_size) || (written_size_by_addr >= (int)img_size)) && ret == 0) { ssdk_printf( SSDK_DEBUG, "Last copy done, total written size: 0x%x, image size: 0x%x\r\n", (unsigned int)written_size, img_size); #ifdef CONFIG_BPT_UPDATE if (bpt_update_fg) { ret = BptUpdate(flash_wrapper, img_flash_base, img_link_base, img_size, core); if (ret < 0) { ssdk_printf(SSDK_ERR, "BptUpdate fail\r\n"); return RESULT_ERROR; } } #endif #if (CONFIG_HYPERBUS_MODE == 1) && (CONFIG_IAR_HYPERFLASH_FUSE == 1) if (program_hyperflash_fuse_flag == 0) { ret = program_hyperflash_fuse(); if (ret < 0) { ssdk_printf(SSDK_ERR, "Fuse hyperflash fail\r\n"); return RESULT_ERROR; } program_hyperflash_fuse_flag = 1; } #endif ssdk_printf(SSDK_NOTICE, "Flashload finished, ret:%d (0 is OK)\r\n", ret); } if (ret < 0) { ssdk_printf(SSDK_ERR, "FlashWrite fail\r\n"); return RESULT_ERROR; } return RESULT_OK; } uint32_t FlashErase(void *block_start, uint32_t block_size) { int ret; uint32_t block_start_addr = (uint32_t)block_start; ssdk_printf(SSDK_NOTICE, "------ CMD FlashErase ------ \r\nADDR:0x%x \r\nSIZE:0x%x\r\n", (uint32_t)block_start, block_size); if (!use_flash_base_in_bpt) block_start_addr = (uint32_t)block_start; else if (img_flash_base_fg) block_start_addr = (uint32_t)block_start + (uint32_t)base_offset; if (!img_flash_base_fg) { img_flash_base = (void *)block_start_addr; img_flash_base_fg = true; } if (((erase_size + block_size) > img_size) && img_size) { block_size = img_size - erase_size; } block_size = ALIGN(block_size, flash_wrapper->page_size); erase_size += block_size; if ((core == 255) && (flash_init_flag & FLAG_ERASE_ONLY) && (sfs != NULL)) { if (sfs->normal_img_base) { flash_wrapper_erase(flash_wrapper, sfs->normal_img_base, flash_wrapper->sector_size); ssdk_printf(SSDK_NOTICE, "FlashErase bpt addr:0x%x, count:0x%x\r\n", (uint32_t)sfs->normal_img_base, flash_wrapper->sector_size); } if (sfs->backup_img_base) { flash_wrapper_erase(flash_wrapper, sfs->backup_img_base, flash_wrapper->sector_size); ssdk_printf(SSDK_NOTICE, "FlashErase bpt addr:0x%x, count:0x%x\r\n", (uint32_t)sfs->backup_img_base, flash_wrapper->sector_size); } if (sfs->third_img_base) flash_wrapper_erase(flash_wrapper, sfs->third_img_base, flash_wrapper->sector_size); ssdk_printf(SSDK_NOTICE, "FlashErase bpt addr:0x%x, count:0x%x\r\n", (uint32_t)sfs->third_img_base, flash_wrapper->sector_size); } ssdk_printf(SSDK_NOTICE, "FlashErase addr:0x%x, count:0x%x\r\n", (uint32_t)block_start_addr, block_size); ret = flash_wrapper_erase(flash_wrapper, FLASH_ADDR_MASK((uint32_t)block_start_addr), (flash_size_t)block_size); if (ret < 0) { ssdk_printf(SSDK_ERR, "FlashErase fail\r\n"); return RESULT_ERROR; } return RESULT_OK; }