You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

227 lines
5.9 KiB

/*
* Copyright (c) Hisilicon Technologies Co., Ltd. 2020-2021. All rights reserved.
* Description: API implementation of loader.
* Author: Hisilicon
* Created: 2020-04-01
*/
#include <command.h>
#include "uapi_otp.h"
#include "soc_log.h"
#include "loader_debug.h"
#include "loader.h"
#include "loader_errno.h"
#include "loader_internal.h"
#include "loader_config.h"
#include "common.h"
#include "download.h"
#include "burn.h"
#include "protocol.h"
#include "ui.h"
#include "verify.h"
#include "usb_if.h"
#define TMP_BUF_SIZE_1 (64 * 1024) /* 64k */
#define TMP_BUF_SIZE_2 (8 * 1024 *1024) /* 8M */
#define MAX_PROGRESS_BYTE (MAX_U32 / 100)
#define CONFIG_LOADER_WITHOUT_REBOOT
loader_chip_related g_chip_info = {
.name_id = 0,
.revision = CHIP_REVISION_MAX,
.fill_size = 0xffffffff,
.fmt = EXT_GFX_COLOR_FORMAT_MAX,
.burn_flag = LOADER_USB_BURN_MAX,
.mem_type = CHIP_MEM_MAX
};
static td_s32 loader_reboot(td_void)
{
#ifdef CONFIG_LOADER_WITHOUT_REBOOT
while (1) {}; /* wait for power off */
#else
do_reset(NULL, 0, 0, NULL);
#endif
/* never run the fallowing */
return TD_SUCCESS;
}
static td_void progress(loader_progress_type type, td_u64 offset, td_u64 total)
{
static td_u32 last_percent[PROGRESS_MAX] = {0};
td_u32 percent;
if (type >= PROGRESS_MAX || type < 0) {
soc_log_fatal("type %d error!\n", type);
return;
}
if (total == 0 || offset > total) {
soc_log_fatal("progress bad parameter! offset:%lld, total:%lld error!\n\n", offset, total);
return;
}
/* Avoid 64-bit division */
while (total > MAX_PROGRESS_BYTE || offset > MAX_PROGRESS_BYTE) {
offset >>= 1;
total >>= 1;
}
percent = (td_u32)offset * 100 / (td_u32)total; /* 100 : 100% */
if (percent != last_percent[type]) {
last_percent[type] = percent;
check_func(loader_ui_progress(last_percent[PROGRESS_DOWNLOAD], last_percent[PROGRESS_BURN]));
soc_log_alert("download: %d%%, burn: %d%%\n", last_percent[PROGRESS_DOWNLOAD], last_percent[PROGRESS_BURN]);
}
return;
}
static td_void exit_tip(td_s32 err_code)
{
ui_string title;
ui_string content;
if (err_code == TD_SUCCESS) {
title = UI_STR_INFO;
} else {
title = UI_STR_WARNING;
}
if (err_code == TD_SUCCESS) {
content = UI_STR_PT_SUCC;
} else if (err_code == SOC_ERR_LOADER_NOT_FOUND_USB_FILE) {
content = UI_STR_NOT_FIND_USB_FILE;
} else if (err_code == SOC_ERR_LOADER_INVALID_DATA) {
content = UI_STR_FAIL_DATA;
} else {
content = UI_STR_FAIL_DATA;
}
check_func(loader_ui_end_tip(title, content));
loader_delay(3000); /* delay 3000 */
}
static td_s32 verify_upgrade_file(td_void)
{
td_s32 ret;
td_bool lock = TD_FALSE;
if_err(uapi_otp_init(), return TD_FAILURE);
if_err(ret = uapi_otp_get_scs_stat(&lock), goto out);
soc_log_alert("success. get scs stat is %d\n", lock);
if (lock == TD_TRUE) {
if_err(ret = loader_verify_upgrade_file(), goto out);
}
out:
(td_void)uapi_otp_deinit();
return ret;
}
static td_void loader_chip_related_init(loader_burn_type type)
{
ext_chip_name_id name_id = 0;
ext_chip_revision chip_revision = CHIP_REVISION_MAX;
if (ext_drv_sys_get_chip_name_id(&name_id) != TD_SUCCESS) {
soc_log_err("Failed to ext_drv_sys_get_chip_name_id func.\n");
return;
}
if (ext_drv_sys_get_chip_revision(&chip_revision) != TD_SUCCESS) {
soc_log_err("Failed to ext_drv_sys_get_chip_revision func.\n");
return;
}
g_chip_info.name_id = name_id;
g_chip_info.revision = chip_revision;
if (type == LOADER_BARE_BURN) {
g_chip_info.burn_flag = LOADER_USB_BARE_BURN;
g_chip_info.fmt = EXT_GFX_COLOR_FORMAT_YUV42221;
g_chip_info.mem_type = CHIP_MEM_LARGE;
g_chip_info.fill_size = TMP_BUF_SIZE_2;
} else if (type == LOADER_EMPTY_BURN) {
g_chip_info.burn_flag = LOADER_USB_EMPTY_BURN;
g_chip_info.fmt = EXT_GFX_COLOR_FORMAT_8888; /* the default support reserved5 */
g_chip_info.mem_type = CHIP_MEM_SMALL;
g_chip_info.fill_size = TMP_BUF_SIZE_1;
} else {
g_chip_info.burn_flag = LOADER_USB_BURN_MAX;
}
soc_log_dbg("chip_info.fmt = %d\n", g_chip_info.fmt);
soc_log_dbg("chip_info.burn_flag = %d\n", g_chip_info.burn_flag);
soc_log_dbg("chip_info.mem_type = %d\n", g_chip_info.mem_type);
soc_log_dbg("chip_info.fill_size = 0x%x\n", g_chip_info.fill_size);
soc_log_dbg("chip_info.name_id = 0x%x\n", g_chip_info.name_id);
soc_log_dbg("chip_info.revision = 0x%x\n", g_chip_info.revision);
return;
}
loader_chip_related *loader_get_chip_related(td_void)
{
return &g_chip_info;
}
td_s32 loader_base_init(loader_burn_type type)
{
td_s32 ret;
soc_log_alert("upgrade start!\n");
loader_chip_related_init(type);
check_func(loader_ui_init());
if_err(ret = loader_dl_init(LOADER_CFG_USB_UPGRADE_FILE), goto out_ui);
return TD_SUCCESS;
out_ui:
check_func(loader_base_deinit(ret));
return ret;
}
td_s32 loader_mandatory_upgrade(td_void)
{
td_s32 ret;
#ifdef SOCT_BOOT_LOG_SUPPORT
soc_log_init();
#endif
soc_dbg_func_enter();
if_err(ret = loader_burn_init(), goto out_dl);
if_err(ret = loader_prot_init(progress), goto out_burn);
if_err(ret = verify_upgrade_file(), goto out_burn);
if_err(ret = loader_prot_upgrade(), goto out_burn);
ret = TD_SUCCESS;
check_func(loader_prot_deinit());
out_burn:
check_func(loader_burn_deinit());
out_dl:
check_func(loader_dl_deinit());
soc_dbg_func_exit();
return ret;
}
td_s32 loader_base_deinit(td_s32 upgrade_status)
{
if (upgrade_status == TD_SUCCESS) {
soc_log_alert("\nupgrade success ! please reboot the machine!\n\n");
} else {
soc_log_alert("\nupgrade failed!\n\n");
}
exit_tip(upgrade_status);
check_func(loader_ui_deinit());
check_func(loader_reboot());
return TD_SUCCESS;
}