/* * Copyright (c) Hisilicon Technologies Co., Ltd. 2020-2021. All rights reserved. * Description: API implementation of loader. * Author: Hisilicon * Created: 2020-04-01 */ #include #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; }