Files
E3_boot/middleware/flashloader/flash_loader_implement.c
2025-11-07 10:05:24 +08:00

353 lines
12 KiB
C

/**
* @file flash_loader_implement.c
* @brief The flash loader framework API.
* @copyright Copyright (c) 2022 Semidrive Semiconductor.
* All rights reserved.
*/
#include <armv7-r/cache.h>
#include <debug.h>
#include <flash_loader.h>
#include <flash_loader_extra.h>
#include <flash_wrapper.h>
#include <param.h>
#include <regs_base.h>
#include <sd_boot_img/sd_boot_img.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef CONFIG_BPT_UPDATE
#include <bpt_v2.h>
#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;
}