inwudriver-weibo/boot/flashboot/upg/boot_upg_check.c

336 lines
10 KiB
C
Raw Normal View History

/* *
* 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;
}