inwudriver-weibo/boot/flashboot/partition_table/boot_partition_table.c

352 lines
14 KiB
C
Raw Normal View History

/* *
* Copyright (c) CompanyNameMagicTag 2018-2019. All rights reserved.
* Description: boot partition
* Author: CompanyName
* Create: 2018-10-31
*/
#include "boot_partition_table.h"
static ext_flash_partition_table g_partition_table;
#define ext_flash_partition_refresh_make_address() \
do { \
src_addr = old_table->table[current_index].addr_blk * BLOCK_SIZE; \
dst_addr = new_table->table[current_index].addr_blk * BLOCK_SIZE; \
src_end_addr = old_table->table[current_index].addr_blk * BLOCK_SIZE + \
old_table->table[current_index].size_blk * BLOCK_SIZE; \
dst_end_addr = new_table->table[current_index].addr_blk * BLOCK_SIZE + \
new_table->table[current_index].size_blk * BLOCK_SIZE; \
} while (0)
/* move the highest address first. address grows down to lower address */
#define ext_flash_partition_refresh_proc1() \
do { \
size_per_time = 0 - BLOCK_SIZE; \
size_finished = (td_s32)(0 - abs_size_finished); \
src_addr = src_end_addr - BLOCK_SIZE; \
dst_addr = dst_end_addr - BLOCK_SIZE; \
} while (0)
#define ext_flash_partition_refresh_proc2() \
do { \
if ((inter_ctrl->table[i].top1_or_bottom0 == EXT_PARTITION_TB_TOP) || \
((dst_addr > src_addr) && (inter_ctrl->table[i].top1_or_bottom0 == EXT_PARTITION_TB_AUTO))) { \
ext_flash_partition_refresh_proc1(); \
} else { \
size_per_time = BLOCK_SIZE; \
size_finished = (td_s32)abs_size_finished; \
} \
} while (0)
#define ext_flash_partition_refresh_proc3() \
do { \
src_addr = (td_u32)((td_s32)src_addr + size_per_time); \
dst_addr = (td_u32)((td_s32)dst_addr + size_per_time); \
len += BLOCK_SIZE; \
inter_ctrl->table[current_index].finished_block = len / BLOCK_SIZE; \
ret = uapi_common_nv_read(EXT_NV_FTM_FLASH_PARTIRION_CHANGE_ID, inter_ctrl, \
sizeof(ext_pt_change_log), save_type); \
} while (0)
ext_flash_partition_table *uapi_get_partition_table(td_void)
{
return &g_partition_table;
}
static td_void uapi_flash_partition_refresh_free_memery(EXT_CONST ext_pt_change_log *inter_ctrl,
EXT_CONST ext_flash_partition_table *new_table,
EXT_CONST td_u8 *buffer)
{
uapi_free(EXT_MOD_ID_PARTITION, (td_pvoid)buffer);
uapi_free(EXT_MOD_ID_PARTITION, (td_pvoid)new_table);
uapi_free(EXT_MOD_ID_PARTITION, (td_pvoid)inter_ctrl);
}
/* inner interface */
static td_u32 flash_partition_get_ver(ext_partition_ver_info *ver)
{
td_u32 ret;
ext_flash_partition_table *ptable;
/* inner interface does not verify the legality of input parameter */
ptable = boot_malloc(sizeof(ext_flash_partition_table));
ret = uapi_common_nv_read(EXT_NV_FTM_FLASH_PARTIRION_TABLE_ID, ptable, sizeof(ext_flash_partition_table),
EXT_TYPE_FACTORY_NV);
if (ret == EXT_ERR_SUCCESS) {
*ver = ptable->ver;
}
boot_free(ptable);
return ret;
}
td_u32 uapi_flash_partition_get_ver(ext_partition_ver_info *ver)
{
if (ver == TD_NULL) {
return EXT_ERR_INVALID_PARAMETER;
}
return flash_partition_get_ver(ver);
}
/* inner interface */
EXT_PRV ext_partition_ver flash_partition_check_ver(const ext_partition_ver_info *ver)
{
ext_partition_ver_info local_ver;
td_u32 ret;
if (ver->boot_support == 0) {
return EXT_PARTITION_VER_ERR;
}
ret = flash_partition_get_ver(&local_ver);
if (ret != EXT_ERR_SUCCESS) {
return EXT_PARTITION_VER_ERR;
}
if (local_ver.ver_num == 0) {
return EXT_PARTITION_VER_ERR;
}
if ((local_ver.map & ver->map) == 0) {
return EXT_PARTITION_VER_ERR;
}
if (local_ver.ver_num > ver->ver_num) {
return EXT_PARTITION_VER_ERR;
} else if (local_ver.ver_num == ver->ver_num) {
return EXT_PARTITION_VER_THE_SAME;
} else {
return EXT_PARTITION_VER_NEW;
}
}
ext_partition_ver uapi_flash_partition_check_ver(const ext_partition_ver_info *ver)
{
if (ver == TD_NULL) {
return EXT_PARTITION_VER_ERR;
}
return flash_partition_check_ver(ver);
}
EXT_PRV td_u32 flash_partition_reset(td_void)
{
ext_flash_partition_table *table = TD_NULL;
table = uapi_get_partition_table();
return uapi_common_nv_read(EXT_NV_FTM_FLASH_PARTIRION_TABLE_ID, table, sizeof(ext_flash_partition_table),
EXT_TYPE_FACTORY_NV);
}
EXT_PRV td_u32 uapi_flash_self_check(ext_pt_change_log *inter_ctrl, ext_flash_partition_table *new_table,
const ext_flash_partition_table *old_table, ext_nv_type *save_type)
{
td_u32 ret;
ext_nv_type type;
ret = uapi_common_nv_read(EXT_NV_FTM_FLASH_PARTIRION_CHANGE_ID, inter_ctrl, sizeof(ext_pt_change_log),
EXT_TYPE_FACTORY_NV);
if (ret != EXT_ERR_SUCCESS) {
return ret;
}
if (inter_ctrl->ctrl.status != REFRESH_BUSY) {
ret = EXT_ERR_SUCCESS;
return ret;
}
ret = uapi_common_nv_read(EXT_NV_FTM_FLASH_PARTIRION_TABLE_B_ID, (td_pvoid)new_table,
sizeof(ext_flash_partition_table), EXT_TYPE_FACTORY_NV);
if (ret != EXT_ERR_SUCCESS) {
return ret;
}
if (inter_ctrl->ctrl.temp_area_blk != 0) {
type = EXT_TYPE_TEMP;
/* refresh the data */
ret = uapi_temp_nv_init(inter_ctrl->ctrl.temp_area_blk * BLOCK_SIZE,
old_table->table[EXT_FLASH_PARTITON_FACTORY_NV].addr_blk * BLOCK_SIZE);
if (ret != EXT_ERR_SUCCESS) {
return ret;
}
ret = uapi_common_nv_read(EXT_NV_FTM_FLASH_PARTIRION_CHANGE_ID, inter_ctrl, sizeof(ext_pt_change_log), type);
if (ret != EXT_ERR_SUCCESS) {
return ret;
}
} else {
type = EXT_TYPE_FACTORY_NV;
}
*save_type = type;
return ret;
}
EXT_PRV td_u32 uapi_flash_after_move(ext_pt_change_log *inter_ctrl, EXT_CONST ext_flash_partition_table *new_table)
{
td_u32 ret;
do {
ret = uapi_common_nv_write(EXT_NV_FTM_FLASH_PARTIRION_TABLE_ID,
(td_pvoid)new_table,
sizeof(ext_flash_partition_table),
EXT_TYPE_FACTORY_NV);
if (ret != EXT_ERR_SUCCESS) {
break;
}
inter_ctrl->ctrl.status = REFRESH_IDLE;
ret = uapi_common_nv_write(EXT_NV_FTM_FLASH_PARTIRION_CHANGE_ID, inter_ctrl, sizeof(ext_pt_change_log),
EXT_TYPE_FACTORY_NV); /* write nv partiton list one more time */
if (ret != EXT_ERR_SUCCESS) {
break;
}
ret = flash_partition_reset();
if (ret != EXT_ERR_SUCCESS) {
break;
}
} while (0);
return ret;
}
EXT_PRV td_bool uapi_flash_partition_refresh_malloc(ext_pt_change_log **inter_ctrl,
ext_flash_partition_table **new_table, td_u8 **buffer)
{
if (inter_ctrl == TD_NULL || new_table == TD_NULL || buffer == TD_NULL) {
return TD_FALSE;
}
*inter_ctrl = (ext_pt_change_log *)uapi_malloc(EXT_MOD_ID_PARTITION, sizeof(ext_pt_change_log));
if (*inter_ctrl == TD_NULL) {
return TD_FALSE;
}
*new_table = (ext_flash_partition_table *)uapi_malloc(EXT_MOD_ID_PARTITION, sizeof(ext_flash_partition_table));
if (*new_table == TD_NULL) {
uapi_free(EXT_MOD_ID_PARTITION, *inter_ctrl);
return TD_FALSE;
}
*buffer = (td_u8 *)uapi_malloc(EXT_MOD_ID_PARTITION, BLOCK_SIZE);
if (*buffer == TD_NULL) {
uapi_free(EXT_MOD_ID_PARTITION, *new_table);
uapi_free(EXT_MOD_ID_PARTITION, *inter_ctrl);
return TD_FALSE;
}
return TD_TRUE;
}
#define ext_flash_partition_refresh_proc44() \
do { \
ext_flash_partition_refresh_proc2(); \
src_addr = (td_u32)((td_s32)src_addr + size_finished); /* not consider the process of error */ \
dst_addr = (td_u32)((td_s32)dst_addr + size_finished); \
} while (0)
#define ext_flash_partition_refresh_proc45() \
do { \
inter_ctrl->table[i].move = TD_FALSE; \
ret = uapi_common_nv_write(EXT_NV_FTM_FLASH_PARTIRION_CHANGE_ID, inter_ctrl, sizeof(ext_pt_change_log), \
save_type); \
} while (0)
#define ext_flash_partition_refresh_proc52() \
do { \
} while (0)
EXT_PRV td_u32 uapi_flash_partition_refresh_proc55(ext_pt_change_log *inter_ctrl,
ext_flash_partition_table *new_table, td_u8 *buffer, ext_nv_type save_type)
{
ext_flash_partition_table *old_table = uapi_get_partition_table();
td_u32 src_addr, dst_addr;
td_s32 size_finished, size_per_time;
td_u32 ret = EXT_ERR_SUCCESS;
for (td_u8 i = 0; i < inter_ctrl->ctrl.total_num; i++) {
td_u32 src_end_addr, dst_end_addr;
td_u32 current_index = array_index(inter_ctrl->table[i].id);
if ((inter_ctrl->table[i].move == TD_FALSE) ||
(current_index >= EXT_FLASH_PARTITON_MAX)) {
continue;
}
ext_flash_partition_refresh_make_address();
/* not consider the change of version direction */
if (((new_table->table[current_index].dir == 0) && (src_addr == dst_addr)) ||
((new_table->table[current_index].dir != 0) && (src_end_addr == dst_end_addr))) {
continue;
}
/* select the smaller size to move */
td_u32 total_size = (old_table->table[current_index].size_blk <= new_table->table[current_index].size_blk) ?
(old_table->table[current_index].size_blk * BLOCK_SIZE) :
(new_table->table[current_index].size_blk * BLOCK_SIZE);
td_u32 abs_size_finished = (inter_ctrl->table[current_index].finished_block) * BLOCK_SIZE;
ext_flash_partition_refresh_proc44();
for (td_u32 len = abs_size_finished; len < total_size;) {
ret = uapi_flash_read(src_addr, BLOCK_SIZE, buffer);
if (ret != EXT_ERR_SUCCESS) {
uapi_flash_partition_refresh_free_memery(inter_ctrl, new_table, buffer);
return ret;
}
boot_msg2("addr ", src_addr, dst_addr);
ret = uapi_flash_erase(dst_addr, BLOCK_SIZE);
ret |= uapi_flash_write(dst_addr, BLOCK_SIZE, buffer, TD_FALSE);
if (ret != EXT_ERR_SUCCESS) {
uapi_flash_partition_refresh_free_memery(inter_ctrl, new_table, buffer);
return ret;
}
ext_flash_partition_refresh_proc3();
if (ret != EXT_ERR_SUCCESS) {
uapi_flash_partition_refresh_free_memery(inter_ctrl, new_table, buffer);
return ret;
}
}
ext_flash_partition_refresh_proc45();
if (ret != EXT_ERR_SUCCESS) {
uapi_flash_partition_refresh_free_memery(inter_ctrl, new_table, buffer);
return ret;
}
}
return ret;
}
td_u32 uapi_flash_partition_refresh(td_void)
{
td_u32 ret;
ext_flash_partition_table *old_table = uapi_get_partition_table();
ext_nv_type save_type;
ext_pt_change_log *inter_ctrl = TD_NULL;
ext_flash_partition_table *new_table = TD_NULL;
td_u8 *buffer = TD_NULL;
if (uapi_flash_partition_refresh_malloc(&inter_ctrl, &new_table, &buffer) != TD_TRUE) {
return EXT_ERR_MALLOC_FAILUE;
}
do {
/* start self check */
ret = uapi_flash_self_check(inter_ctrl, new_table, old_table, &save_type);
if ((ret != EXT_ERR_SUCCESS) || (inter_ctrl->ctrl.status != REFRESH_BUSY)) {
break;
}
ret = uapi_flash_partition_refresh_proc55(inter_ctrl, new_table, buffer, save_type);
if ((ret != EXT_ERR_SUCCESS)) {
break;
}
ret = uapi_flash_after_move(inter_ctrl, new_table);
} while (0);
uapi_flash_partition_refresh_free_memery(inter_ctrl, new_table, buffer);
return ret;
}
td_u32 uapi_flash_partition_init(td_void)
{
td_u32 ret;
ext_flash_partition_table *table = TD_NULL;
(td_void)uapi_factory_nv_init(FACTORY_NV_ADDR);
table = uapi_get_partition_table();
ret = uapi_factory_nv_read(EXT_NV_FTM_FLASH_PARTIRION_TABLE_ID, table, sizeof(ext_flash_partition_table));
if (ret != EXT_ERR_SUCCESS) {
return ret;
}
ret = uapi_flash_partition_refresh();
return ret;
}