336 lines
10 KiB
C
336 lines
10 KiB
C
/* *
|
|
* Copyright (c) CompanyNameMagicTag 2018-2019. All rights reserved.
|
|
* Description: upg check
|
|
* Author: CompanyName
|
|
* Create: 2018-10-31
|
|
*/
|
|
|
|
#include "boot_upg_check.h"
|
|
|
|
EXT_PRV td_u32 uapi_product_get_type(td_void)
|
|
{
|
|
ext_start_ctrl *start_ctrl = &g_start_ctrl;
|
|
return start_ctrl->product_type;
|
|
}
|
|
|
|
EXT_PRV td_u32 upg_check_chip_maigc(td_u32 chip_magic)
|
|
{
|
|
if (chip_magic != (td_u32)PRODUCT_CFG_CHIP_MAGIC) {
|
|
return EXT_ERR_UPG_HEAD_CHECK_MAGIC_WRONG;
|
|
}
|
|
|
|
return EXT_ERR_SUCCESS;
|
|
}
|
|
|
|
td_u32 upg_check_manufactuer(td_u16 manufactuer_code)
|
|
{
|
|
if (manufactuer_code != PRODUCT_CFG_MANUCODE) {
|
|
return EXT_ERR_UPG_HEAD_CHECK_MANUCODE_WRONG;
|
|
}
|
|
|
|
return EXT_ERR_SUCCESS;
|
|
}
|
|
|
|
EXT_PRV td_u32 upg_check_product_list(const ext_21_upg_head_product *product_info, td_u32 list_count)
|
|
{
|
|
td_u32 i;
|
|
|
|
for (i = 0; i < list_count; i++) {
|
|
const ext_21_upg_head_product *item = &product_info[i];
|
|
|
|
if (uapi_product_get_type() >= item->min_id && uapi_product_get_type() <= item->max_id) {
|
|
return EXT_ERR_SUCCESS;
|
|
}
|
|
}
|
|
|
|
return EXT_ERR_UPG_HEAD_CHECK_PRODUCT_LIST_WRONG;
|
|
}
|
|
|
|
td_u32 upg_check_file_type(td_u8 file_type)
|
|
{
|
|
if (file_type == EXT_21_UPG_TYPE_KERNEL || file_type == EXT_21_UPG_TYPE_BOOT) {
|
|
return EXT_ERR_SUCCESS;
|
|
}
|
|
return EXT_ERR_UPG_HEAD_CHECK_FILE_TYPE_WRONG;
|
|
}
|
|
|
|
EXT_PRV td_u32 upg_check_file_len(td_u32 size) /* size is a little difference */
|
|
{
|
|
if (size > (16 * 1024 * 1024)) { /* size less than 16*1024*1024 */
|
|
return EXT_ERR_UPG_HEAD_CHECK_FILE_LEN_WRONG;
|
|
}
|
|
return EXT_ERR_SUCCESS;
|
|
}
|
|
|
|
td_u32 upg_conver_tail_addr_2_head_addr(td_u32 upg_tail_addr, td_u32 *upg_head_addr)
|
|
{
|
|
td_u32 ret;
|
|
ext_21_upg_tail_new tail = { 0 };
|
|
ext_start_ctrl *start_ctrl = &g_start_ctrl;
|
|
|
|
/* read file tail */
|
|
ret = uapi_flash_read(upg_tail_addr - sizeof(ext_21_upg_tail_new), sizeof(ext_21_upg_tail_new), (td_u8 *)(&tail));
|
|
if (ret != EXT_ERR_SUCCESS) {
|
|
return ret;
|
|
}
|
|
|
|
if (tail.head_end_magic != (td_u32)PRODUCT_CFG_UPG_FILE_END_SIGNATURE) {
|
|
return EXT_ERR_UPG_CHECK_UPG_END_MAGIC_FAIL;
|
|
}
|
|
/* assure the position of upgrade file head */
|
|
if (upg_tail_addr <= tail.head_before_offset) {
|
|
return EXT_ERR_UPG_CHECK_UPG_END_OFFSET_FAIL;
|
|
}
|
|
|
|
if (tail.mode_magic == EXT_UPG_NEW_PROCESS_MAGIC) {
|
|
start_ctrl->new_kernel = TD_TRUE;
|
|
if (tail.upg_magic[2] == EXT_UPG_DO_UPG_MAGIC) { /* index 2 */
|
|
start_ctrl->upg_magics_exist |= 0x4;
|
|
}
|
|
|
|
if (tail.upg_magic[1] == EXT_UPG_DO_UPG_MAGIC) {
|
|
start_ctrl->upg_magics_exist |= 0x2;
|
|
}
|
|
|
|
if (tail.upg_magic[0] == EXT_UPG_DO_UPG_MAGIC) {
|
|
start_ctrl->upg_magics_exist |= 0x1;
|
|
}
|
|
} else {
|
|
start_ctrl->new_kernel = TD_FALSE;
|
|
}
|
|
|
|
*upg_head_addr = upg_tail_addr - tail.head_before_offset;
|
|
return EXT_ERR_SUCCESS;
|
|
}
|
|
|
|
EXT_PRV td_u32 upg_get_head_from_flash(td_bool end_addr, td_u32 flash_addr,
|
|
ext_21_upg_head *upg_head, td_u32 *upg_head_addr)
|
|
{
|
|
td_u32 ret;
|
|
|
|
if (end_addr) {
|
|
/* get the position of upg head */
|
|
ret = upg_conver_tail_addr_2_head_addr(flash_addr, upg_head_addr);
|
|
if (ret != EXT_ERR_SUCCESS) {
|
|
return ret;
|
|
}
|
|
} else {
|
|
*upg_head_addr = flash_addr;
|
|
}
|
|
|
|
/* read upg head */
|
|
return uapi_flash_read(*upg_head_addr, sizeof(ext_21_upg_head), (td_u8 *)upg_head);
|
|
}
|
|
|
|
td_u32 upg_check_head_common_info(const ext_21_upg_head *upg_head, td_u8 *file_type)
|
|
{
|
|
if (upg_check_file_len(upg_head->file_len) != EXT_ERR_SUCCESS) {
|
|
return EXT_ERR_UPG_HEAD_CHECK_FILE_LEN_WRONG;
|
|
}
|
|
|
|
/* verify the chip magic byte and manufacturer magic byte of upgrade file */
|
|
if (upg_check_chip_maigc(upg_head->chip_magic) != EXT_ERR_SUCCESS) {
|
|
return EXT_ERR_UPG_HEAD_CHECK_MAGIC_WRONG;
|
|
}
|
|
|
|
if (upg_check_manufactuer(upg_head->manufactuer_code) != EXT_ERR_SUCCESS) {
|
|
return EXT_ERR_UPG_HEAD_CHECK_MANUCODE_WRONG;
|
|
}
|
|
|
|
*file_type = upg_head->file_type;
|
|
if (upg_check_file_type(upg_head->file_type) != EXT_ERR_SUCCESS) {
|
|
return EXT_ERR_UPG_HEAD_CHECK_FILE_TYPE_WRONG;
|
|
}
|
|
|
|
/* verify product type of upgrade file */
|
|
if (upg_check_product_list(upg_head->product_list, 2) != EXT_ERR_SUCCESS) { /* list count 2 */
|
|
return EXT_ERR_UPG_HEAD_CHECK_PRODUCT_LIST_WRONG;
|
|
}
|
|
|
|
return EXT_ERR_SUCCESS;
|
|
}
|
|
|
|
td_u32 uapi_upg_check_head(const ext_21_upg_head *upg_head)
|
|
{
|
|
td_u32 ret;
|
|
td_u8 file_type = EXT_21_UPG_TYPE_NONE;
|
|
#ifdef EXT_UPG_IN_BOOT_CHECK_PARTITION
|
|
ext_partition_ver ver_ret;
|
|
#endif
|
|
|
|
ret = upg_check_head_common_info(upg_head, &file_type);
|
|
if (ret != EXT_ERR_SUCCESS) {
|
|
return ret;
|
|
}
|
|
#ifdef EXT_UPG_IN_BOOT_CHECK_PARTITION
|
|
ver_ret = uapi_flash_partition_check_ver(&upg_head->partion_ver);
|
|
if (file_type != EXT_21_UPG_TYPE_KERNEL && file_type != EXT_21_UPG_TYPE_BOOT) {
|
|
return EXT_ERR_UPG_HEAD_CHECK_PARTION_NO_GO;
|
|
}
|
|
if (file_type == EXT_21_UPG_TYPE_KERNEL && ver_ret != EXT_PARTITION_VER_THE_SAME) {
|
|
return EXT_ERR_UPG_HEAD_CHECK_PARTION_NOT_SAME;
|
|
}
|
|
#endif
|
|
return EXT_ERR_SUCCESS;
|
|
}
|
|
|
|
EXT_PRV td_u32 boot_upg_check_by_file_type(const ext_21_upg_head *upg_head)
|
|
{
|
|
td_u32 ret;
|
|
ext_start_ctrl *start_ctrl = &g_start_ctrl;
|
|
ext_start_tbl *start_tbl = start_ctrl->start_tbl;
|
|
ext_21_upg_head_section *sections = ext_upg_head_get_sections();
|
|
|
|
start_ctrl->upg_file_type = upg_head->file_type;
|
|
if (upg_head->file_type == EXT_21_UPG_TYPE_KERNEL &&
|
|
((upg_head->ver_magic != start_tbl->ver_magic || start_ctrl->new_kernel) || start_ctrl->tbl_ok == TD_FALSE)) {
|
|
/* upgrding */
|
|
start_ctrl->ver_magic_different = TD_TRUE;
|
|
} else if (upg_head->file_type == EXT_21_UPG_TYPE_BOOT &&
|
|
((upg_head->ver_magic != start_ctrl->boot_ver_magic || start_ctrl->new_kernel))) {
|
|
/* not verify start info list */
|
|
/* BOOT upgrade */
|
|
start_ctrl->ver_magic_different = TD_TRUE;
|
|
}
|
|
|
|
/* read sub section info */
|
|
ret = uapi_flash_read(g_start_ctrl.flash_addr_upg + upg_head->section_list_offset,
|
|
sizeof(ext_21_upg_head_section) * upg_head->section_count, (td_u8 *)sections);
|
|
if (ret != EXT_ERR_SUCCESS) {
|
|
return EXT_ERR_UPG_CHECK_UPG_READ_SECTION_FAIL;
|
|
}
|
|
|
|
return EXT_ERR_SUCCESS;
|
|
}
|
|
|
|
td_u32 boot_upg_clear_upg_magic_one(td_void)
|
|
{
|
|
ext_start_ctrl *start_ctrl = &g_start_ctrl;
|
|
ext_21_upg_tail_new tail = { 0 };
|
|
td_u32 data = 0;
|
|
size_t flash_addr = start_ctrl->flash_addr_tail_upg - sizeof(ext_21_upg_tail_new);
|
|
flash_addr = flash_addr + ext_struct_offset(ext_21_upg_tail_new, upg_magic[0]);
|
|
if (start_ctrl->upg_magics_exist) {
|
|
for (td_u32 i = 0; i < sizeof(tail.upg_magic) / sizeof(tail.upg_magic[0]); i++) {
|
|
if (start_ctrl->upg_magics_exist & (1 << i)) {
|
|
return uapi_flash_write(flash_addr + sizeof(tail.upg_magic[0]) * i, sizeof(tail.upg_magic[0]),
|
|
(td_u8 *)&data, TD_FALSE);
|
|
}
|
|
}
|
|
}
|
|
return EXT_ERR_SUCCESS;
|
|
}
|
|
|
|
td_u32 boot_upg_clear_upg_magic_all(td_void)
|
|
{
|
|
td_u32 ret = EXT_ERR_SUCCESS;
|
|
ext_start_ctrl *start_ctrl = &g_start_ctrl;
|
|
ext_21_upg_tail_new tail = { 0 };
|
|
td_u32 data = 0;
|
|
size_t flash_addr = start_ctrl->flash_addr_tail_upg - sizeof(ext_21_upg_tail_new);
|
|
flash_addr = flash_addr + ext_struct_offset(ext_21_upg_tail_new, upg_magic[0]);
|
|
|
|
if (start_ctrl->upg_magics_exist) {
|
|
for (td_u32 i = 0; i < sizeof(tail.upg_magic) / sizeof(tail.upg_magic[0]); i++) {
|
|
if (start_ctrl->upg_magics_exist & (1 << i)) {
|
|
ret |= uapi_flash_write(flash_addr + sizeof(tail.upg_magic[0]) * i, sizeof(tail.upg_magic[0]),
|
|
(td_u8 *)&data, TD_FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
td_u32 boot_upg_check_upg_phase0(td_void)
|
|
{
|
|
ext_start_ctrl *start_ctrl = &g_start_ctrl;
|
|
ext_21_upg_head *upg_head = start_ctrl->upg_head; /* point to upgrade file head */
|
|
td_u32 ret;
|
|
|
|
if (upg_head == TD_NULL) {
|
|
return EXT_ERR_INVALID_PARAMETER;
|
|
}
|
|
|
|
/* get file head */
|
|
ret = upg_get_head_from_flash(TD_TRUE, start_ctrl->flash_addr_tail_upg, upg_head, &g_start_ctrl.flash_addr_upg);
|
|
if (ret != EXT_ERR_SUCCESS) {
|
|
return ret;
|
|
}
|
|
|
|
start_ctrl->upg_file_phas0_ok = TD_TRUE;
|
|
return EXT_ERR_SUCCESS;
|
|
}
|
|
|
|
td_u32 boot_upg_check_upg_phase1(td_void)
|
|
{
|
|
ext_start_ctrl *start_ctrl = &g_start_ctrl;
|
|
td_u32 ret;
|
|
td_u8 check_sum[32] = { 0 }; /* length 32 */
|
|
ext_21_upg_head *upg_head = start_ctrl->upg_head; /* point to upgrade file head */
|
|
static td_bool s_b_checked = TD_FALSE;
|
|
|
|
if (upg_head == TD_NULL) {
|
|
return EXT_ERR_FAILURE;
|
|
}
|
|
|
|
if (start_ctrl->upg_file_phas0_ok == TD_FALSE) {
|
|
return EXT_ERR_FAILURE;
|
|
}
|
|
|
|
if (s_b_checked) {
|
|
return EXT_ERR_SUCCESS;
|
|
}
|
|
|
|
s_b_checked = TD_TRUE;
|
|
|
|
/* verify upgrade file head */
|
|
ret = uapi_upg_check_head(upg_head);
|
|
if (ret != EXT_ERR_SUCCESS) {
|
|
return ret;
|
|
}
|
|
|
|
/* verify crc of upgrade file */
|
|
ret = upg_hash_block(g_start_ctrl.flash_addr_upg + EXT_UPG_HEAD_CHECK_SUM_START_OFFSET,
|
|
upg_head->file_len - EXT_UPG_HEAD_CHECK_SUM_START_OFFSET, check_sum);
|
|
if (ret != EXT_ERR_SUCCESS || memcmp(upg_head->check_sum, check_sum, EXT_UPG_HEAD_CHECK_SUM_SIZE)) {
|
|
return EXT_ERR_UPG_CHECK_UPG_CRC_WRONG;
|
|
}
|
|
|
|
ret = boot_upg_check_by_file_type(upg_head);
|
|
if (ret != EXT_ERR_SUCCESS) {
|
|
return ret;
|
|
}
|
|
|
|
start_ctrl->upg_file_phas1_ok = TD_TRUE;
|
|
return EXT_ERR_SUCCESS;
|
|
}
|
|
|
|
td_u32 boot_upg_check_upg_phase2(td_void)
|
|
{
|
|
td_u32 ret;
|
|
ext_21_upg_head *upg_head = ext_upg_head_get_head();
|
|
ext_start_ctrl *start_ctrl = &g_start_ctrl;
|
|
|
|
if (!start_ctrl->upg_file_phas1_ok) {
|
|
return EXT_ERR_UPG_FAIL_4;
|
|
}
|
|
|
|
/* check for hupg secure head */
|
|
ret = boot_upg_check_secure_head();
|
|
if (ret != EXT_ERR_SUCCESS) {
|
|
return ret;
|
|
}
|
|
|
|
/* check boot security if the type is boot */
|
|
if (upg_head->file_type == EXT_21_UPG_TYPE_BOOT) {
|
|
ret = boot_upg_check_secure_boot();
|
|
if (ret != EXT_ERR_SUCCESS) {
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
start_ctrl->upg_file_phas2_ok = TD_TRUE;
|
|
return EXT_ERR_SUCCESS;
|
|
}
|