/******************************************************************************
* Copyright (c) 2018-2018 TP-Link Technologies CO.,LTD.
*
* Filename: fw_upgrade.c
* Version: 1.0
* Description: Check and Upgrade firmware, including kernel, romfs, isp_config
* Author: yexuelin<yexuelin@tp-link.com.cn>
* Date: 2018-12-15
******************************************************************************/
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/reboot.h>
#include <sys/shm.h>
#include <errno.h>
#include "common.h"
#include "nsd_common.h"
#include "slp_model.h"
#include "flashio.h"
#include "libds.h"
////#include "libctaocrypt/md5.h"
////#include "libctaocrypt/rsa.h"
////#include "libctaocrypt/coding.h"
////#include "libctaocrypt/sha.h"
#include "sslApi.h"
#include "idle_worker.h"
#include "lock_text.h"
#ifdef FACTORY_BOOT_SDCARD_RECOVERY
#include "sd_backup.h"
#endif
#include "rsaVerify.h"
#define UP_HEADER_ELE(ele) ((rsaSignatureProtocol == 2) ? ((UPGRADE_HEADER_RSA2048*)buf_start)->ele : ((UPGRADE_HEAD*)buf_start)->ele)
#define HEAD_SIZE ((rsaSignatureProtocol == 2) ? (sizeof(UPGRADE_HEADER_RSA2048)) : (sizeof(UPGRADE_HEAD)))
static uint32_t uhTagLength = 0;
#define VERIFY_STAT_SUCCESS 1
#define VERIFY_STAT_FAIL 2
#define DOWNLOAD_FW_SUCCESS 2
/* 注意 p 是网络字节序 */
#define BIT_VAL(p, index) ((*(p + (index >> 3)) >> (7 - (index & 0x7))) & 0x1)
#define WORD_ALIGN(p) (((U32)(p) + 3) & ~3)
#define FW_KEY_PATH "/www/cert/firmware/firmware-pub-key.pem"
#define FW_KEY_PATH_2048 "/www/cert/firmware/firmware-pub-key.rsa2048key"
#define UG_RSA_KEY_PEM_LEN 2048
#define UG_RSA_KEY_DER_LEN 1024
#define ASN1_LEN sizeof(g_asn1_weird_stuff)
#define SHA1_HASH_LEN 20
#ifdef SYSUPGRADE_CHECK_RSA
LOCAL BOOL g_fw_rsa_checking = TRUE;
#else
LOCAL BOOL g_fw_rsa_checking = FALSE;
#endif
LOCAL char* g_upgrade_mmap_addr = NULL;
LOCAL S32 g_upgrade_file_size = 0;
LOCAL int g_upgrade_file_fd = -1;
LOCAL EXE_UPGRADE_PARAM g_upgrade_param = {0};
static int rsaSignatureProtocol = 1;
static int align_size = 0;
static int ubootNoUpgrade = 0;
typedef struct _upgrade_method
{
EXECUTE_UPGRADE_TYPE upgrade_type;
S32 (*method)(UPGRADE_MSG *msg);
}UPGRADE_METHOD;
LOCAL const U8 g_asn1_weird_stuff[] =
{
0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B,
0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14,
};
LOCAL const U8 g_blk_hdr_magic_num[] = {0x12, 0x34, 0x56, 0x78};
/* Global variable for firmware upgrade */
LOCAL U8 kern_and_romfs_changed = 0;
LOCAL U8 boot_changed = 0;
LOCAL U8 fdt_changed = 0; //fdt
LOCAL unsigned char upgrade_header_magic[MAGIC_LEN] =
{
0x55, 0xAA, 0x4C, 0x5E, 0x83, 0x1F, 0x53, 0x4B, 0xA1, 0xF8,
0xF7, 0xC9, 0x18, 0xDF, 0x8F, 0xBF, 0x7D, 0xA1, 0xAA, 0x55
};
/* calculate md5 with data and size, put result to *md5_value */
LOCAL S32 calc_md5(U8 *data, S32 size, U8 *md5_value) //用data和size计算md5,将结果代入*md5_value
{
if (NULL == data || NULL == md5_value || size <= 0)
{
UPGRADE_ERROR("Invalid MD5 argument.");
return ERROR;
}
Md5 md5;
tpssl_InitMd5(&md5);
tpssl_Md5Update(&md5, data, size);
tpssl_Md5Final(&md5, md5_value);
return OK;
}
#if 0
LOCAL void print_arr_hex(char *text, int len, U8 arr[])
{
char buf[64];
int i;
char *p = buf;
for (i = 0; i < len; i++)
p += sprintf(p, "%x,", arr[i]);
UPGRADE_ERROR("%s: %s", text, buf);
}
#endif
/* ------------------------------------------------本地 Firmware 信息获取--------------------------------------------*/
/* 本地 Firmware 信息的初始化,读取本地 tp_header 和 factory info
*
* @context: origin_info, 保存本地 firmware 信息的结构体
fac_info, 从 flash 的 factory info 区域读取的信息字符串
*
* Return: OK/ERROR, 初始化成功/失败
*/
S32 origin_info_init(ORIGIN_FW_INFO *origin_info) //读取本地固件信息到origin_info
{
TP_HEAD_INFO origin_tp_head;
FACTORY_INFO_DATA fac_info;
U32 size;
S32 ret;
#ifdef CONFIG_LTE_MODULE_IN_UP_BIN
MODULE_SPEC module_spec;
LTE_PARAM_MODULE_INFO lte_module_info;
#endif
if (NULL == origin_info)
{
goto INIT_ERROR;
}
memset(origin_info, 0, sizeof(ORIGIN_FW_INFO));
memset(&origin_tp_head, 0, sizeof(TP_HEAD_INFO));
memset(&fac_info, 0, sizeof(FACTORY_INFO_DATA));
#ifdef CONFIG_LTE_MODULE_IN_UP_BIN
memset(&module_spec, 0, sizeof(MODULE_SPEC));
memset(<e_module_info, 0, sizeof(LTE_PARAM_MODULE_INFO));
#endif
/* 读取 TP HEAD */
size = ds_read(TP_HEADER_PATH, &origin_tp_head, sizeof(TP_HEAD_INFO));
if (size < sizeof(TP_HEAD_INFO))
{
UPGRADE_ERROR("Reading TP_HEAD failed.");
goto INIT_ERROR;
}
/* 读取 fac_info */
size = ds_read(FACTORY_INFO_DATA_PATH, &fac_info, sizeof(FACTORY_INFO_DATA));
if (size < sizeof(FACTORY_INFO_DATA))
{
UPGRADE_ERROR("Reading FACTORY_INFO_DATA failed.");
goto INIT_ERROR;
}
/* init local partition offsets and lens */
origin_info->tphead_len = ntohl(origin_tp_head.tphead_len);
#ifdef FDT_UPGRADE_SUPPORT
origin_info->fdt_offset = ntohl(origin_tp_head.fdt_offset); //fdt
origin_info->fdt_len = ntohl(origin_tp_head.fdt_len);
#else
origin_info->fdt_offset = 0; //fdt
origin_info->fdt_len = 0;
#endif
origin_info->uboot_offset = ntohl(origin_tp_head.uboot_offset);
origin_info->uboot_len = ntohl(origin_tp_head.uboot_len);
origin_info->tphead_offset = ntohl(origin_tp_head.tphead_offset);
origin_info->kernel_offset = ntohl(origin_tp_head.kernel_offset);
origin_info->vendor_id = ntohs(origin_tp_head.vendor_id);
origin_info->zone_code = ntohs(origin_tp_head.zone_code);
/* init local partition CRCs */
#ifdef FDT_UPGRADE_SUPPORT
memcpy(origin_info->fdt_crc, origin_tp_head.fdt_crc, CRC_LEN); //fdt
#endif
memcpy(origin_info->factory_info_crc, origin_tp_head.factory_info_crc, CRC_LEN);
memcpy(origin_info->radio_crc, origin_tp_head.radio_crc, CRC_LEN);
memcpy(origin_info->bootloader_crc, origin_tp_head.uboot_crc, CRC_LEN);
memcpy(origin_info->kernel_and_romfs_crc, origin_tp_head.firmware_crc, CRC_LEN);
memcpy(origin_info->fw_id, origin_tp_head.fw_id, FW_ID_LEN);
/* get BL FwID number and init BL */
origin_info->bl_num = ntohl(origin_tp_head.fw_id_bl_num);
memcpy(origin_info->bl_id, origin_tp_head.fw_id_bl, FW_ID_LEN * origin_info->bl_num);
/* init hwid */
ret = hex_str_to_bytes(origin_info->hw_id, (char*)fac_info.hw_id, HW_ID_LEN);
if (0 != ret)
{
goto INIT_ERROR;
}
/* init mac */
memcpy(origin_info->mac, fac_info.mac, MAC_ADDR_SIZE);
/* init extFw dev_name: dev_name + _ + hw_ver */
strcpy((char*)origin_info->dev_name, (char*)fac_info.dev_name);
size = strlen(fac_info.dev_name);
*(origin_info->dev_name + size) = '_';
strcpy((char*)origin_info->dev_name + size + 1, (char*)fac_info.hw_ver);
#ifdef CONFIG_LTE_MODULE_IN_UP_BIN
/* init lte info */
size = ds_read(MODULE_SPEC_PATH, &module_spec, sizeof(MODULE_SPEC));
if (size < sizeof(MODULE_SPEC))
{
UPGRADE_ERROR("Reading module_spec failed.");
goto INIT_ERROR;
}
origin_info->lte_supported = atoi(module_spec.lte);
if (origin_info->lte_supported)
{
size = ds_read(LTE_MODULE_INFO_PATH, <e_module_info, sizeof(LTE_PARAM_MODULE_INFO));
if (size < sizeof(LTE_PARAM_MODULE_INFO))
{
UPGRADE_ERROR("Reading lte module info failed.");
goto INIT_ERROR;
}
strncpy((char *)origin_info->lte_vender, (const char *)lte_module_info.vender, sizeof(origin_info->lte_vender));
strncpy((char *)origin_info->lte_product, (const char *)lte_module_info.product, sizeof(origin_info->lte_product));
origin_info->lte_version = atoi(lte_module_info.version);
}
#endif
return SLP_ENONE;
INIT_ERROR:
return SLP_ESYSTEM;
}
/* ------------------------------------------------ISP 检查,更新和控制句柄结构体--------------------------------------*/
/* 检查是否为默认 ISP */
LOCAL S32 isp_partition_is_default(ISP_HEADER *origin_isp_hdr) //判断入参是否默认值(即全为 0xFF)
{
ISP_HEADER default_value;
memset(&default_value, 0xFF, sizeof(ISP_HEADER)); //default value for ISP is FF when mkslpfw
return memcmp(origin_isp_hdr, &default_value, sizeof(ISP_HEADER));
}
/* 从 factory info 判断 mac 是否为默认 */
LOCAL S32 mac_is_default(U8 *mac) //判断 mac 是否为默认(0)
{
U8 mac_default[MAC_ADDR_SIZE];
if (NULL == mac)
{
return ERROR;
}
/* default mac value in factory info is all 0 when mkslpfw */
memset(mac_default, 0, sizeof(mac_default));
if (0 == memcmp(mac_default, mac, MAC_ADDR_SIZE))
{
return OK;
}
return ERROR;
}
/* 检查 isp 内容的合法性和是否为最新 */
LOCAL S32 chk_fw_isp(BLOCK_HEADER* blk_hdr, void* this_handler, ORIGIN_FW_INFO *origin_info) //固件升级过程中对 ISP检查
{
S32 ret = 0;
S32 i = 0;
S32 blk_num = 0;
char md5_tmp[MD5_DIGEST_SIZE] = {0};
ISP_HEADER origin_isp_hdr;
ISP_HEADER* i_hdr = NULL;
EXT_FW_BLOCK_HANDLER* ext_handler = this_handler;
if (NULL == blk_hdr || NULL == this_handler)
{
UPGRADE_ERROR("NULL pointer!");
ret = SLP_EFWEXCEPTION;
goto out;
}
/* 跳过了 BLOCK_HEADER, extFw 的开始, extFw: ISP_HEADER + extFw file */
U8* ext_fw_base = (U8*)blk_hdr + sizeof(BLOCK_HEADER);
blk_num = ntohl(blk_hdr->num);
memset(&origin_isp_hdr, 0, sizeof(ISP_HEADER));
/* 从 radio flash 中读取 ISP_HEADER */
ret = flash_read_radio((U8*)&origin_isp_hdr, sizeof(ISP_HEADER));
if (OK != ret)
{
UPGRADE_ERROR("read flash failed");
goto out;
}
if (0 == isp_partition_is_default(&origin_isp_hdr)) //如果是默认值
{
UPGRADE_DEBUG("Isp partition is default");
if (OK == mac_is_default(origin_info->mac)) //如果mac是默认值
{
/* use default device name in factory info, to match isp */
UPGRADE_DEBUG("Mac is default");
memcpy(origin_isp_hdr.dev_name, origin_info->dev_name, EXT_FW_DEVNAME_LEN);
}
else
{
UPGRADE_ERROR("Isp partition is default but mac is not default");
return SLP_EFWNOTSUPPORTED;
}
}
for (i = 0; i < blk_num; i++)
{
if (CONTENT_TYPE_ISP_CONFIG == ntohl(blk_hdr->info[i].type))
{
i_hdr = (ISP_HEADER*)ext_fw_base;
#ifdef USES_LITTLEFS
if (ntohl(i_hdr->compress_type) == COMPRESS_TYPE_LFS)
{
memset(&origin_isp_hdr, 0, sizeof(ISP_HEADER));
FILE* fp = NULL;
fp = fopen("/tmp/base-files/isp_header", "r");
if (NULL == fp)
{
ret = SLP_ESYSTEM;
goto out;
}
fread(&origin_isp_hdr, 1, sizeof(ISP_HEADER), fp);
fclose(fp);
if (0 == memcmp(i_hdr->dev_name, origin_isp_hdr.dev_name, EXT_FW_DEVNAME_LEN))
{
UPGRADE_DEBUG("lfs: block name=%s\n", i_hdr->dev_name);
ext_handler->block = i_hdr;
ext_handler->need_upgrade = EXT_FW_CHANGED;
ret = SLP_ENONE;
goto out;
}
}
#endif
if (0 == memcmp(i_hdr->dev_name, origin_isp_hdr.dev_name, EXT_FW_DEVNAME_LEN))
{
ext_handler->block = i_hdr;
UPGRADE_DEBUG("isp: device name supported");
UPGRADE_DEBUG("device_name = %s", origin_isp_hdr.dev_name);
UPGRADE_DEBUG("strlen(origin_isp_hdr.dev_name) = %d", strlen((char*)(origin_isp_hdr.dev_name)));
break;
}
}
ext_fw_base += ntohl(blk_hdr->info[i].length);
}
if (i == blk_num)
{
UPGRADE_ERROR("isp: device name not supported");
ret = SLP_EFWNOTSUPPORTED;
goto out;
}
calc_md5((U8*)i_hdr + sizeof(ISP_HEADER), ntohl(i_hdr->isp_length), (U8*)md5_tmp);
ret = memcmp(i_hdr->isp_CRC, md5_tmp, MD5_DIGEST_SIZE);
if (ret)
{
UPGRADE_ERROR("Invalid isp data in firmware");
goto out;
}
ret = memcmp(&(i_hdr->isp_ver), &(origin_isp_hdr.isp_ver), sizeof(U32));
if (ret)
{
UPGRADE_DEBUG("isp is changed");
ext_handler->need_upgrade = EXT_FW_CHANGED;
ret = SLP_ENONE;
goto out;
}
ret = memcmp(i_hdr->isp_CRC, origin_isp_hdr.isp_CRC, CRC_LEN);
if (ret)
{
UPGRADE_DEBUG("isp is changed");
ext_handler->need_upgrade = EXT_FW_CHANGED;
ret = SLP_ENONE;
goto out;
}
ret = memcmp(i_hdr->sw_ver, origin_isp_hdr.sw_ver, SW_VER_LEN);
if (ret)
{
UPGRADE_DEBUG("isp is not changed but software version is changed");
ext_handler->need_upgrade = EXT_FW_CHANGED;
ret = SLP_ENONE;
goto out;
}
UPGRADE_DEBUG("isp is not changed");
out:
return ret;
}
/* 升级 extFw */
LOCAL S32 upgrade_fw_isp(ISP_HEADER* block) //isp升级
{
S32 ret = 0;
U8* isp_buf;
U32 block_size = 0;
U32 isp_max_size = get_radio_size();
if (NULL == block)
{
UPGRADE_ERROR("NULL pointer");
ret = SLP_EFWEXCEPTION;
return ret;
}
block_size = ntohl(block->isp_length) + sizeof(ISP_HEADER);
if (block_size > isp_max_size)
{
UPGRADE_ERROR("Not enough ROM for ispconfig");
return SLP_ESYSTEM;
}
#ifdef USES_LITTLEFS
if (COMPRESS_TYPE_LFS == ntohl(block->compress_type))
{
FILE *fp = NULL;
fp = fopen(LFS_TAR_FILE_PATH, "w");
if (fp == NULL)
{
UPGRADE_ERROR("open file[%s] error", LFS_TAR_FILE_PATH);
return SLP_ESYSTEM;
}
ret = fwrite((U8 *)block + sizeof(ISP_HEADER), 1, ntohl(block->isp_length), fp);
fclose(fp);
if (ret != ntohl(block->isp_length))
{
UPGRADE_ERROR("write file[%s] error, filesize is %d, ret=%d", LFS_TAR_FILE_PATH, ntohl(block->isp_length), ret);
return SLP_ENOMEMORY;
}
else
{
UPGRADE_DEBUG("isp block size is %d\n", ntohl(block->isp_length));
}
char cmd[512] = {0};
snprintf(cmd, 512, "tar -zxvf %s -C /tmp/base-files", LFS_TAR_FILE_PATH);
system(cmd);
return SLP_ENONE;
}
#endif
isp_buf = (U8*)UPGRADE_MALLOC(isp_max_size);
if (NULL == isp_buf)
{
UPGRADE_ERROR("Not enough memory for isp_buf");
return SLP_ESYSTEM;
}
memset(isp_buf, 0xff, isp_max_size);
memcpy(isp_buf, (U8*)block, block_size);
ret = flash_write_radio(isp_buf, isp_max_size);
if (OK != ret)
{
UPGRADE_ERROR("write radio flash failed.");
UPGRADE_FREE(isp_buf);
return SLP_ESYSTEM;
}
UPGRADE_DEBUG("upgrade isp done");
UPGRADE_FREE(isp_buf);
return SLP_ENONE;
}
#ifdef CONFIG_LTE_MODULE_IN_UP_BIN
LOCAL S32 chk_lte_fw(BLOCK_HEADER* blk_hdr, void* this_handler, ORIGIN_FW_INFO *origin_info) //lte检查
{
S32 ret = 0;
S32 i = 0;
S32 blk_num = 0;
char md5_tmp[MD5_DIGEST_SIZE] = {0};
EXT_FW_BLOCK_HANDLER* ext_handler = this_handler;
ISP_HEADER* ext_header = NULL;
U8 lte_dev_name[LTE_VENDER_LEN + LTE_PRODUCT_LEN + 1] = {0};
U8* ext_fw_base = NULL;
if (NULL == blk_hdr || NULL == this_handler || NULL == origin_info)
{
UPGRADE_ERROR("lte_fw: NULL pointer!");
ret = SLP_EFWEXCEPTION;
goto out;
}
/* 跳过了 BLOCK_HEADER, extFw 的开始, extFw: ISP_HEADER + extFw file */
ext_fw_base = (U8*)blk_hdr + sizeof(BLOCK_HEADER);
ext_handler->need_upgrade = EXT_FW_NOT_CHANGED;
blk_num = ntohl(blk_hdr->num);
snprintf((char *)lte_dev_name, sizeof(lte_dev_name), "%s_%s", origin_info->lte_vender, origin_info->lte_product);
for (i = 0; i < blk_num; i++)
{
if (CONTENT_TYPE_LTE_FW == ntohl(blk_hdr->info[i].type))
{
ext_header = (ISP_HEADER*)ext_fw_base;
if (0 == strcasecmp((const char *)lte_dev_name, (const char *)ext_header->dev_name))
{
ext_handler->block = ext_header;
UPGRADE_DEBUG("lte_fw: device name %s(%u) supported", ext_header->dev_name, ntohl(ext_header->isp_length));
break;
}
if (0 == strcasecmp((const char *)lte_dev_name, "_"))
{
ext_handler->block = ext_header;
UPGRADE_WARNING("lte_fw: device name %s supported, curr fw name %s", ext_header->dev_name, lte_dev_name);
break;
}
}
ext_fw_base += ntohl(blk_hdr->info[i].length);
}
if (i == blk_num)
{
UPGRADE_ERROR("lte_fw: device name not supported");
ret = SLP_EFWNOTSUPPORTED;
goto out;
}
calc_md5((U8*)ext_header + sizeof(ISP_HEADER), ntohl(ext_header->isp_length), (U8*)md5_tmp);
ret = memcmp(ext_header->isp_CRC, md5_tmp, MD5_DIGEST_SIZE);
if (ret)
{
UPGRADE_ERROR("lte_fw: MD5 sum not match");
ret = SLP_EFWNOTSUPPORTED;
goto out;
}
if (ntohl(ext_header->isp_ver) != origin_info->lte_version)
{
UPGRADE_DEBUG("lte_fw: cur_version %d upgrade to version %d", origin_info->lte_version, ntohl(ext_header->isp_ver));
ext_handler->need_upgrade = EXT_FW_CHANGED;
ret = SLP_ENONE;
goto out;
}
UPGRADE_DEBUG("lte_fw is not changed");
ext_handler->need_upgrade = EXT_FW_NOT_CHANGED;
ret = SLP_ENONE;
out:
return ret;
}
LOCAL S32 upgrade_lte_fw(ISP_HEADER* block) //更新lte
{
S32 ret = SLP_EFWEXCEPTION;
LTE_PARAM_UPGRADE_STC upgrade_params_stc = {0};
int interval = 2;
LTE_PARAM_UPGRADE upgrade_params;
if (NULL == block)
{
UPGRADE_ERROR("NULL pointer");
return SLP_EFWEXCEPTION;
}
upgrade_params.fw_buf = (U32)((U8 *)block + sizeof(ISP_HEADER));
upgrade_params.fw_len = ntohl(block->isp_length);
upgrade_params.status = E_UPGRADE_READY;
ds_write(LTE_UPGRADE_PATH, &upgrade_params, sizeof(upgrade_params));
UPGRADE_DEBUG("notify to upgrade lte fw(%p:%d)", upgrade_params.fw_buf, upgrade_params.fw_len);
ds_read(LTE_UPGRADE_STC_PATH, &upgrade_params_stc, sizeof(upgrade_params_stc));
/* read upgrade resulte in timeout time */
while (upgrade_params_stc.upgrade_timeout >= 0)
{
ds_read(LTE_UPGRADE_PATH, &upgrade_params, sizeof(upgrade_params));
if (upgrade_params.status == E_UPGRADE_COMPLETE)
{
ret = SLP_ENONE;
UPGRADE_DEBUG("upgrade lte fw done successfully");
break;
}
else if (upgrade_params.status == E_UPGRADE_ERROR)
{
ret = SLP_EFWEXCEPTION;
UPGRADE_ERROR("lte_fw: upgrade failed");
break;
}
UPGRADE_DEBUG("upgrading lte fw status:%d timeout %d", upgrade_params.status, upgrade_params_stc.upgrade_timeout);
sleep(interval);
upgrade_params_stc.upgrade_timeout -= interval;
}
return ret;
}
#endif
#ifdef CONFIG_UITRON_EXT_UPGRADE_SUPPORT
LOCAL S32 chk_uitron_ext_fw(BLOCK_HEADER* blk_hdr, void* this_handler, ORIGIN_FW_INFO *origin_info) //Uitron检查
{
S32 ret = 0;
S32 i = 0;
S32 blk_num = 0;
U8* uitron_ext_buf=NULL;
U32 uitron_ext_size = get_uitron_ext_size();
char md5_tmp[MD5_DIGEST_SIZE] = {0};
char md5_origin[MD5_DIGEST_SIZE] = {0};
/*ISP_HEADER实际上为EXT_FW_HEADER,此时应该改为EXT_FW_HEADER更为恰当*/
ISP_HEADER* i_hdr = NULL;
EXT_FW_BLOCK_HANDLER* ext_handler = this_handler;
if (NULL == blk_hdr || NULL == this_handler)
{
UPGRADE_ERROR("NULL pointer!");
ret = SLP_EFWEXCEPTION;
goto out;
}
/* 跳过了 BLOCK_HEADER, extFw 的开始, extFw: ISP_HEADER + extFw file */
U8* ext_fw_base = (U8*)blk_hdr + sizeof(BLOCK_HEADER);
uitron_ext_buf = (U8*)UPGRADE_MALLOC(uitron_ext_size);
if (NULL == uitron_ext_buf)
{
UPGRADE_ERROR("not enough memory for uitron_ex");
return SLP_ESYSTEM;
}
memset(uitron_ext_buf, 0xff, uitron_ext_size);
/* 从 uitron_ext中读取uitron_ext */
ret = flash_read_uitron_ext(uitron_ext_buf, uitron_ext_size);
if (OK != ret)
{
UPGRADE_ERROR("read flash failed");
goto out;
}
blk_num = ntohl(blk_hdr->num);
for (i = 0; i < blk_num; i++)
{
if (CONTENT_TYPE_UITRON_EXT_FW == ntohl(blk_hdr->info[i].type))
{
i_hdr = (ISP_HEADER*)ext_fw_base;
UPGRADE_DEBUG("uitron_ext: type supported");
break;
}
ext_fw_base += ntohl(blk_hdr->info[i].length);
}
if (i == blk_num)
{
UPGRADE_ERROR("uitron_ext: type not supported");
ret = SLP_EFWNOTSUPPORTED;
goto out;
}
calc_md5((U8*)i_hdr + sizeof(ISP_HEADER), ntohl(i_hdr->isp_length), (U8*)md5_tmp);
ret = memcmp(i_hdr->isp_CRC, md5_tmp, MD5_DIGEST_SIZE);
if (ret)
{
UPGRADE_ERROR("Invalid uitron_ext in firmware");
goto out;
}
calc_md5(uitron_ext_buf, ntohl(i_hdr->isp_length), (U8*)md5_origin);
ret = memcmp(md5_tmp, md5_origin, MD5_DIGEST_SIZE);
if (ret)
{
UPGRADE_DEBUG("uitron_ext is changed");
ext_handler->block = i_hdr;
ext_handler->need_upgrade = EXT_FW_CHANGED;
ret = SLP_ENONE;
goto out;
}
UPGRADE_DEBUG("uitron_ext is not changed");
out:
UPGRADE_FREE(uitron_ext_buf);
return ret;
}
LOCAL S32 upgrade_uitron_ext_fw(ISP_HEADER* block) //升级uitron
{
S32 ret = 0;
U8* uitron_ext_buf=NULL;
U32 block_size = 0;
U32 uitron_ext_size = get_uitron_ext_size();
if (NULL == block)
{
UPGRADE_ERROR("NULL pointer");
ret = SLP_EFWEXCEPTION;
return ret;
}
block_size = ntohl(block->isp_length);
if (block_size > uitron_ext_size)
{
UPGRADE_ERROR("Not enough ROM for uitron_ext");
return SLP_ESYSTEM;
}
uitron_ext_buf = (U8*)UPGRADE_MALLOC(uitron_ext_size);
if (NULL == uitron_ext_buf)
{
UPGRADE_ERROR("Not enough memory for uitron_ex");
return SLP_ESYSTEM;
}
memset(uitron_ext_buf, 0xff, uitron_ext_size);
memcpy(uitron_ext_buf, (U8*)block + sizeof(ISP_HEADER), block_size);
ret = flash_write_uitron_ext(uitron_ext_buf, uitron_ext_size);
if (OK != ret)
{
UPGRADE_ERROR("write uitron_ext flash failed.");
UPGRADE_FREE(uitron_ext_buf);
return SLP_ESYSTEM;
}
UPGRADE_DEBUG("upgrade uitron_ext done");
UPGRADE_FREE(uitron_ext_buf);
return SLP_ENONE;
}
#endif
EXT_FW_BLOCK_HANDLER blk_hdr_tbl[] =
{
{
CONTENT_TYPE_ISP_CONFIG,
EXT_FW_NOT_CHANGED,
NULL,
chk_fw_isp,
upgrade_fw_isp
},
#ifdef CONFIG_LTE_MODULE_IN_UP_BIN
{
CONTENT_TYPE_LTE_FW,
EXT_FW_NOT_CHANGED,
NULL,
chk_lte_fw,
upgrade_lte_fw
},
#endif
#ifdef CONFIG_UITRON_EXT_UPGRADE_SUPPORT
{
CONTENT_TYPE_UITRON_EXT_FW,
EXT_FW_NOT_CHANGED,
NULL,
chk_uitron_ext_fw,
upgrade_uitron_ext_fw
},
#endif
{
0,
0,
NULL,
NULL,
NULL
}
};
/* ------------------------------------------------Firmware 检查相关函数--------------------------------------*/
LOCAL void calc_sha(U8 *content, U32 content_len, U8 *hash) //检查哈希值
{
Sha sha;
tpssl_InitSha(&sha);
tpssl_ShaUpdate(&sha, content, content_len);
tpssl_ShaFinal(&sha, hash);
}
#if 0
LOCAL S32 rsa_public_decrypt(const char *key_pem, U32 key_pem_len, U8 *content_encrypt, U32 encrypt_len, U8 *content_decrypt, U32 decrypt_len)
{
U32 idx = 0;
RsaKey rsa_key;
U8 public_key_der[UG_RSA_KEY_DER_LEN] = {0};
U32 public_key_der_len = sizeof(public_key_der);
if (0 != tpssl_Base64_Decode((U8*)key_pem, key_pem_len, public_key_der, &public_key_der_len))
{
UPGRADE_ERROR("Base64 Decode failed");
return ERROR;
}
tpssl_InitRsaKey(&rsa_key, NULL);
if (0 != tpssl_RsaPublicKeyDecode(public_key_der, &idx, &rsa_key, public_key_der_len))
{
UPGRADE_ERROR("Rsa Public Key Decode failed.");
goto RSA_VERIFY_ERR;
}
if (tpssl_RsaSSL_Verify(content_encrypt, encrypt_len, content_decrypt, decrypt_len, &rsa_key) <= 0)
{
UPGRADE_ERROR("Rsa Descrypt failed.");
goto RSA_VERIFY_ERR;
}
tpssl_FreeRsaKey(&rsa_key);
return OK;
RSA_VERIFY_ERR:
tpssl_FreeRsaKey(&rsa_key);
return ERROR;
}
#endif
LOCAL S32 rsa_sign_verify(const char *key_pem, U32 key_pem_len, U8 *sign_content, U32 sign_content_len, U8 *sign, U32 sign_len) //RSA 签名验证
{
U8 sign_decrypt[UG_RSA_KEY_DER_LEN] = {0};
U8 sign_buf[RSA_SIGN_LEN] = {0};
U8 sha1_hash[SHA1_HASH_LEN] = {0};
U32 i = 0;
for(i = 0; i < sign_len; i++)
{
sign_buf[i] = sign[sign_len - 1 - i];
}
if (OK != tpssl_rsa_public_decrypt(key_pem, key_pem_len, sign_buf,
sign_len, sign_decrypt, sizeof(sign_decrypt)))
{
return ERROR;
}
for (i = 0; i < ASN1_LEN; ++i)
{
if (g_asn1_weird_stuff[i] != sign_decrypt[i])
{
return ERROR;
}
}
calc_sha(sign_content, sign_content_len, sha1_hash);
if (0 != memcmp(sha1_hash, sign_decrypt + i, sizeof(sha1_hash)))
{
UPGRADE_DEBUG("RSA Signature wrong.");
return ERROR;
}
return OK;
}
/* 根据 vendorID 验证 RSA 签名 */
LOCAL S32 chk_fw_rsa(UPGRADE_HEAD* up_head, S32 file_size) //验证固件的 RSA 签名
{
U8 md5_tmp[MD5_DIGEST_SIZE] = {0};
U8 rsa_tmp[RSA_SIGN_LEN] = {0};
char public_key_pem[UG_RSA_KEY_PEM_LEN] = {0};
S32 public_key_fd = 0;
if ((public_key_fd = open(FW_KEY_PATH, O_RDONLY)) <= 0)
{
UPGRADE_ERROR("No firmware key pem file.");
return ERROR;
}
if (read(public_key_fd, public_key_pem, sizeof(public_key_pem)) < 0)
{
close(public_key_fd);
return ERROR;
}
close(public_key_fd);
memcpy(rsa_tmp, up_head->rsa_sign, RSA_SIGN_LEN); /* backup RSA sign first */
memset(up_head->rsa_sign, 0x0, RSA_SIGN_LEN);
if (ERROR == calc_md5((U8*)up_head, file_size, md5_tmp))
{
return ERROR;
}
if (OK != rsa_sign_verify(public_key_pem, strlen(public_key_pem), md5_tmp,
sizeof(md5_tmp), rsa_tmp, sizeof(rsa_tmp)))
{
return ERROR;
}
/* restore RSA sign */
memcpy(up_head->rsa_sign, rsa_tmp, RSA_SIGN_LEN);
UPGRADE_DEBUG("firmware RSA signiture check OK");
return OK;
}
static int checkFirmwareRSA_2048(UPGRADE_HEADER_RSA2048* uHeader, S32 file_size, unsigned int bOnlyCheck, unsigned int header_align_size) //验证使用 2048 位 RSA 密钥签名的固件
{
int signCheckOk = 0; /* for RSA sign check result */
unsigned char rsaTmp[RSA_SIGN_LEN_2048] = {0};
char public_key_pem[UG_RSA_KEY_PEM_LEN] = {0};
S32 public_key_fd = 0;
if ((public_key_fd = open(FW_KEY_PATH_2048, O_RDONLY)) <= 0)
{
UPGRADE_ERROR("No firmware key pem file.");
return ERROR;
}
if (read(public_key_fd, public_key_pem, sizeof(public_key_pem)) < 0)
{
close(public_key_fd);
return ERROR;
}
close(public_key_fd);
memcpy(rsaTmp, uHeader->rsa_sign, RSA_SIGN_LEN_2048); /* backup RSA sign first */
memset(uHeader->rsa_sign, 0x0, RSA_SIGN_LEN_2048);
signCheckOk = rsaVerifyPSSSignByBase64EncodePublicKeyBlob(
(unsigned char*)public_key_pem,
strlen(public_key_pem),
(unsigned char*)uHeader,
file_size,
rsaTmp,
RSA_SIGN_LEN_2048,
bOnlyCheck,
header_align_size);
memcpy(uHeader->rsa_sign, rsaTmp, RSA_SIGN_LEN_2048); /* restore RSA sign */
if (!signCheckOk)
{
UPGRADE_DEBUG("firmware RSA signiture check fail");
return ERROR;
}
UPGRADE_DEBUG("firmware RSA signiture check OK");
return OK;
}
/* 检查升级固件支持的 HwID 列表 */
LOCAL S32 chk_fw_hw_list(unsigned short hwIdNum, unsigned char hwIdList[0][HW_ID_LEN], ORIGIN_FW_INFO* origin_info) //检查升级固件支持的 HwID 列表
{
S32 i;
for (i = 0; i < ntohs(hwIdNum); ++i)
{
if (0 == memcmp(hwIdList[i], origin_info->hw_id, HW_ID_LEN))
{
return OK;
}
}
return ERROR;
}
#ifdef CONFIG_SYSUPGRADE_CHECK_FWLIST
/* check if FwID is in firmware's FL */
LOCAL S32 chk_fw_fl(unsigned short hwIdNum, unsigned char hwIdList[0][HW_ID_LEN], unsigned short fwIdFLNum, unsigned char fwIdFLMask[FWID_FL_MASK_LEN], ORIGIN_FW_INFO *origin_info) //检查当前设备的固件 ID 是否在固件的兼容列表(FL)中
{
S32 i;
U8 (*fw_id_fl)[FW_ID_LEN] = NULL;
U8 *fl_mask = NULL;
fw_id_fl = hwIdList + ntohs(hwIdNum);
fl_mask = fwIdFLMask;
for (i = 0; i < ntohs(fwIdFLNum); i++)
{
if (0x1 == BIT_VAL(fl_mask, i)) /* FL Mask don't support this FwID */
{
if (0 == memcmp(origin_info->fw_id, fw_id_fl[i], FW_ID_LEN))
{
UPGRADE_DEBUG("My FwID is in firmware's FL");
return OK;
}
}
}
UPGRADE_DEBUG("My FwID is not in firmware's FL");
return ERROR;
}
/* check if firmware's FwID is in BL of flash */
LOCAL S32 chk_fw_bl(TP_HEAD_INFO *tp_head, ORIGIN_FW_INFO *origin_info) //检查当前固件的 ID 是否在设备的黑名单(BL)中
{
S32 i;
for (i = 0; i < origin_info->bl_num; ++i)
{
if (0 == memcmp(origin_info->bl_id[i], tp_head->fw_id, FW_ID_LEN))
{
UPGRADE_DEBUG("firmware's FwID is in BL of flash");
return OK;
}
}
UPGRADE_DEBUG("firmware's FwID is not in BL of flash");
return ERROR;
}
#endif
/* check if firmware is really not changed in case of MD5 conflict.*/
LOCAL S32 chk_fw_md5_conflict(enum partition_index partitionIndex, U8* fw_base, S32* conflict) //检测当前固件与设备中已存在的固件是否存在 MD5 冲突,即判断即将升级的固件是否与当前存储在指定分区中的固件完全相同
{
/* 每隔1KB起始位置采样1字节共采样16B */
S32 i = 0;
const S32 sample_len = 16;
U8 sample_buf[sample_len];
if (OK != flash_md5_sample(partitionIndex, sample_buf, sample_len))
{
return ERROR;
}
for (i = 0; i < sample_len; i++)
{
if (sample_buf[i] != *(fw_base + 1024 * i))
{
UPGRADE_DEBUG("md5 conflicted!");
*conflict = 1;
return OK;
}
}
*conflict = 0;
return OK;
}
/* 根据 MD5 值判断固件的 kernel and romfs 和 bootloader 是否变化,进而判断是否需要更新相应部分 */
LOCAL S32 chk_fw_partition(char *up_head, unsigned short contentTypes, TP_HEAD_INFO *tp_head, ORIGIN_FW_INFO *origin_info) //根据 MD5 值判断固件的 kernel and romfs 和 bootloader 是否变化,进而判断是否需要更新相应部分
{
U32 fw_contents = 0x0; /* firmware content type */
S32 conflict = 0;
/* get the content parts of firmware */
fw_contents = ntohs(contentTypes);
UPGRADE_DEBUG("fw_contents = 0x%x",fw_contents);
/* up_boot.bin only */
#ifdef SLP_CAMERA_SUPPORT
/*SLP升级机型需要兼容fw_contents不带JFFS2*/
if (PARTS_UP_BOOT != (fw_contents & PARTS_UP_BOOT) && PARTS_UP_BOOT_WITHOUT_JFFS2 != (fw_contents & PARTS_UP_BOOT_WITHOUT_JFFS2))
#else
if (PARTS_UP_BOOT != (fw_contents & PARTS_UP_BOOT))
#endif
{
/* 当分区标志显示不完整时检测是否仅bootloader分区标志为0,分区完整时fw_contents的值为0x1f */
fw_contents |= CONTENT_TYPE_BOOTLOADER;
#ifdef SLP_CAMERA_SUPPORT
if (PARTS_UP_BOOT == (fw_contents & PARTS_UP_BOOT) || PARTS_UP_BOOT_WITHOUT_JFFS2 == (fw_contents & PARTS_UP_BOOT_WITHOUT_JFFS2))
#else
if (PARTS_UP_BOOT == (fw_contents & PARTS_UP_BOOT))
#endif
{
ubootNoUpgrade = 1;
}
else
{
UPGRADE_DEBUG("SLP_EFWNOTSUPPORTED");
return SLP_EFWNOTSUPPORTED;
}
}
/* check if kernel and romfs has changes */
if (0 == memcmp(tp_head->firmware_crc, origin_info->kernel_and_romfs_crc, CRC_LEN))
{
if (OK != chk_fw_md5_conflict(KERNEL,
(U8*)tp_head + origin_info->tphead_len, &conflict))
{
UPGRADE_ERROR("Read kernel and romfs partition Exception.");
return SLP_EFWEXCEPTION;
}
else
{
if (1 == conflict)
{
kern_and_romfs_changed = 1;
UPGRADE_DEBUG("kernel and romfs are changed.");
}
else
{
kern_and_romfs_changed = 0;
UPGRADE_DEBUG("kernel and romfs are not changed.");
}
}
}
else
{
kern_and_romfs_changed = 1;
UPGRADE_DEBUG("kernel and romfs are changed");
}
if (0 == access("/tmp/recovery_mode", F_OK))
{
kern_and_romfs_changed = 1;
}
/* check if bootloader has changes */
if (0 == memcmp(tp_head->uboot_crc, origin_info->bootloader_crc, CRC_LEN))
{
if (OK != chk_fw_md5_conflict(NORMAL_BOOT,
(U8*)up_head + uhTagLength + origin_info->fdt_len, &conflict))
{
UPGRADE_ERROR("Read boot partition Exception.");
return SLP_ESYSTEM;
}
else
{
if (1 == conflict)
{
boot_changed = 1;
UPGRADE_DEBUG("bootloader is changed.");
}
else
{
boot_changed = 0;
UPGRADE_DEBUG("bootloader is not changed.");
}
}
}
else
{
boot_changed = 1;
UPGRADE_DEBUG("bootloader is changed.");
}
#ifdef FDT_UPGRADE_SUPPORT
/* check if fdt has changes */
if (0 == memcmp(tp_head->fdt_crc, origin_info->fdt_crc, CRC_LEN))
{
if (OK != chk_fw_md5_conflict(FDT, (U8*)up_head + uhTagLength, &conflict))
{
UPGRADE_ERROR("Read fdt partition Exception.");
return SLP_ESYSTEM;
}
else
{
if (1 == conflict)
{
fdt_changed = 1;
UPGRADE_DEBUG("fdt is changed.");
}
else
{
fdt_changed = 0;
UPGRADE_DEBUG("fdt is not changed.");
}
}
}
else
{
fdt_changed = 1;
UPGRADE_DEBUG("fdt is changed.");
}
#endif
/* 共用固件时,存在只更新ISP参数,不更新软件的情况 */
/* firmware contents are not changed */
/* this should not happen since we have the different FwID and FwID caled from these contents */
if (!kern_and_romfs_changed && !boot_changed && !fdt_changed)
{
UPGRADE_ERROR("firmware contents are changed.");
return SLP_EFWNEWEST;
}
return SLP_ENONE;
}
/* 检查 extFw */
LOCAL S32 chk_blocks(unsigned short contentTypes, TP_HEAD_INFO *tp_head, ORIGIN_FW_INFO *origin_info) //检查 extFw
{
S32 up_contents_changed = boot_changed | kern_and_romfs_changed;
S32 i = 0;
S32 ret = 0;
U32 up_contents = 0x0; /* parts need to be upgraded */
U16 handler_found = 0;
BLOCK_HEADER* block_hdr = NULL;
up_contents = ntohs(contentTypes);
#ifdef CONFIG_TP_TAPO_SPMINIOS
if (ntohl(tp_head->jffs2RealFsLen) > 0)
{
block_hdr = (BLOCK_HEADER*)((U8*)tp_head + ntohl(tp_head->tphead_len)
+ ntohl(tp_head->kernel_len) + ntohl(tp_head->romfs_len)
+ ntohl(tp_head->jffs2RealFsLen));
}
else
{
block_hdr = (BLOCK_HEADER*)((U8*)tp_head + ntohl(tp_head->tphead_len)
+ ntohl(tp_head->kernel_len) + ntohl(tp_head->romfs_len)
+ ntohl(tp_head->jffs2_len));
}
#ifdef SLP_CAMERA_SUPPORT
/*SLP固件结构jffs2结束和ext fw block之间会多保留一个verify分区大小,与tpheader len一致*/
block_hdr = (BLOCK_HEADER*)((U8*)block_hdr + ntohl(tp_head->tphead_len));
#endif
#else
/* 由于现在去掉了 jffs2,因此 extFw 位于 jffs2 的开始 */
block_hdr = (BLOCK_HEADER*)((U8*)tp_head + ntohl(tp_head->tphead_len)
+ ntohl(tp_head->kernel_len) + ntohl(tp_head->romfs_len));
#endif
if (0 != memcmp(g_blk_hdr_magic_num, block_hdr->magic_num, BLOCK_MAGIC_NUMBER_LEN))
{
UPGRADE_ERROR("invalid ext_fw block header.");
return SLP_EFWEXCEPTION;
}
for (i = 0; i < sizeof(blk_hdr_tbl) / sizeof(EXT_FW_BLOCK_HANDLER); i++)
{
/* 当前 extFw 只有 ispconfig */
if (0 != (blk_hdr_tbl[i].type & up_contents))
{
handler_found |= blk_hdr_tbl[i].type;
ret = blk_hdr_tbl[i].chk_ext_fw(block_hdr, &(blk_hdr_tbl[i]), origin_info);
if (ret)
{
UPGRADE_ERROR("check ext_fw failed, type:0x%x", blk_hdr_tbl[i].type);
return SLP_ESYSTEM;
}
up_contents_changed |= blk_hdr_tbl[i].need_upgrade;
}
}
/* 检查是否为 up_boot 类型 */
if (handler_found != (up_contents & ~(PARTS_UP_BOOT)))
{
UPGRADE_DEBUG("ERR_SLP_HANDLER_NOT_FOUND");
return SLP_ESYSTEM;
}
if (!up_contents_changed)
{
UPGRADE_DEBUG("SLP_EFWNEWEST");
return SLP_EFWNEWEST;
}
return SLP_ENONE;
}
#ifdef MAKEROOM_BEFORE_UPGRADE
S32 precheck_firmware_required_size(CONTEXT *context) //固件预检查阶段的最小长度
{
if (NULL == context)
{
UPGRADE_DEBUG("Para is null.");
return ERROR;
}
context->precheck_len = sizeof(UPGRADE_HEAD);
return SLP_ENONE;
}
/******************************************************************************
* FUNCTION : check_RSA_version()
* AUTHOR : Wu Weizhen (wuweizheng@tp-link.com.cn)
* DESCRIPTION : check signature protocol: RSA1024 or RSA2048
* INPUT : the pointer of upgrade_header structure
*
* OUTPUT : rsaSignatureProtocol: 1:RSA1024, 2:RSA2048
* RETURN : N/A
* OTHERS :
******************************************************************************/
static void check_RSA_version(U8* buf) //检查是RSA1024还是RSA2048
{
if(NULL == buf)
{
return;
}
uint32_t data = 0;
uint8_t a;
int i;
for (i = 0; i < 4; i++)
{
a = buf[i];
data |= (a << (3-i)*8);
}
if (data == UPGRADE_HEADER_VERSION_2048)
{
rsaSignatureProtocol = 2;
}
else
{
rsaSignatureProtocol = 1;
}
}
S32 precheck_firmware(CONTEXT *context) //在固件升级流程中进行预检查,验证固件的基本合法性,包括版本、签名协议、魔数、硬件兼容性等信息
{
char *buf_start = NULL;
S32 buf_len = 0;
S32 ret = 0;
ORIGIN_FW_INFO origin_info;
if (NULL == context || NULL == context->content_start || NULL == context->content_end)
{
UPGRADE_DEBUG("Para is null.");
return ERROR;
}
buf_start = context->content_start;
check_RSA_version((U8*)context->content_start);
buf_len = context->content_end - context->content_start;
if (buf_len < HEAD_SIZE ||
memcmp(UP_HEADER_ELE(magic_num), upgrade_header_magic, MAGIC_LEN) != 0)
{
UPGRADE_DEBUG("Wrong Upgrade Firmware.");
return ERROR;
}
if(rsaSignatureProtocol == 1) //RSA2048未解密,无法解析,RSA1024则保留
{
if (buf_len < sizeof(UPGRADE_HEAD) ||
memcmp(UP_HEADER_ELE(magic_num), upgrade_header_magic, MAGIC_LEN) != 0)
{
UPGRADE_DEBUG("Wrong Upgrade Firmware.");
return ERROR;
}
/* 本地 firmware 信息初始化 */
ret = origin_info_init(&origin_info);
if (SLP_ENONE != ret)
{
UPGRADE_DEBUG("origin_info_init failed.");
return ret;
}
/* check if HwID in firmware support HwID list */
if (OK != chk_fw_hw_list(UP_HEADER_ELE(hw_id_num), UP_HEADER_ELE(hw_id_list), &origin_info))
{
UPGRADE_DEBUG("Not supported HwID.");
return SLP_EFWHWIDNOTMATCH;
}
/* check vendor ID */
if (origin_info.vendor_id != ntohs(UP_HEADER_ELE(vendor_id)))
{
UPGRADE_DEBUG("firmware vendor_id is 0x%08x and our vendor_id is 0x%08x.",
ntohs(UP_HEADER_ELE(vendor_id)), origin_info.vendor_id);
return SLP_EFWVENDORIDNOTMATCH;
}
/* check zone code */
if (origin_info.zone_code != ntohs(UP_HEADER_ELE(zone_code)))
{
UPGRADE_DEBUG("firmware zone_code is 0x%08x and our zone_code is 0x%08x.",
ntohs(UP_HEADER_ELE(zone_code)), origin_info.zone_code);
return SLP_EFWZONECODENOTMATCH;
}
UPGRADE_DEBUG("firmware precheck finished, ok to makeroom before upgrade.");
}
return SLP_ENONE;
}
#endif
S32 set_fw_rsa_checking(JSON_OBJPTR obj, JSON_OBJPTR* resp_obj) //启用或禁用固件的 RSA 签名验证功能
{
const char *enable;
if (NULL == (enable = jso_obj_get_string_origin(obj, "enable")))
{
printf("Usage:\n"
"upgrade set_fw_rsa_checking '{\"enable\": \"off\"}' Disable firmware RSA checking\n"
"upgrade set_fw_rsa_checking '{\"enable\": \"on\"}' Enable firmware RSA checking\n"
);
return SLP_EINVARG;
}
if ((!strcmp(enable,"on")) && !g_fw_rsa_checking)
{
g_fw_rsa_checking = TRUE;
UPGRADE_WARNING("Enable firmware RSA checking.");
}
else if ((!strcmp(enable,"off")) && g_fw_rsa_checking)
{
g_fw_rsa_checking = FALSE;
UPGRADE_WARNING("Disable firmware RSA checking.");
}
return OK;
}
/* 固件检查:RSA 签名认证,HwID,vendorID,zoneCode,FwID是否相同,FwIDFL,FwIDBL,partition,ExtFw */
/**
* 检查接收的 firmware
*
* @para: buf_start, 升级固件在内存中的首地址;
buf_start, 升级固件的长度;
origin_info, 保存本地 firmware 信息的结构体
*
* Return: OK/ERROR, 初始化成功/失败
*/
S32 check_firmware(U8 *buf_start, U32 buf_len, ORIGIN_FW_INFO *origin_info, S32 bOnlyCheck) //固件检查
{
S32 ret;
TP_HEAD_INFO *tp_head = NULL;
if (buf_len < HEAD_SIZE||
memcmp(UP_HEADER_ELE(magic_num), upgrade_header_magic, MAGIC_LEN) != 0)
{
UPGRADE_ERROR("Wrong Upgrade Firmware.");
return ERROR;
}
check_RSA_version(buf_start);
/* 从更新固件读取 TP HEAD */
/* get firmware's upgrade header length and get it's tp header */
uhTagLength = ntohs(UP_HEADER_ELE(tag_len));
tp_head = (TP_HEAD_INFO*)(buf_start + uhTagLength + origin_info->fdt_len + origin_info->uboot_len);
/* check rsa signiture if needed */
/* Now only the domestic version need to check RSA signature */
/* All language will need to chcek RSA */
/*if (0 == strcmp(localInfo.language, LANGUAGE_CN))*/
if (rsaSignatureProtocol == 2)
{
ret = checkFirmwareRSA_2048((UPGRADE_HEADER_RSA2048 *)buf_start, buf_len, bOnlyCheck, align_size);
}
else
{
ret = chk_fw_rsa((UPGRADE_HEAD *)buf_start, buf_len);
}
if (ret & g_fw_rsa_checking)
{
UPGRADE_ERROR("RSA%s check error.", rsaSignatureProtocol == 2 ? "2048" : "1024");
return ret;
}
/* check if HwID in firmware support HwID list */
if (OK != chk_fw_hw_list(UP_HEADER_ELE(hw_id_num), UP_HEADER_ELE(hw_id_list), origin_info))
{
UPGRADE_ERROR("Not supported HwID.");
return SLP_EFWHWIDNOTMATCH;
}
/* check vendor ID */
if (origin_info->vendor_id != ntohs(UP_HEADER_ELE(vendor_id)))
{
UPGRADE_ERROR("firmware vendor_id is 0x%08x and our vendor_id is 0x%08x.",
ntohs(UP_HEADER_ELE(vendor_id)), origin_info->vendor_id);
return SLP_EFWVENDORIDNOTMATCH;
}
/* check zone code */
if (origin_info->zone_code != ntohs(UP_HEADER_ELE(zone_code)))
{
UPGRADE_ERROR("firmware zone_code is 0x%08x and our zone_code is 0x%08x.",
ntohs(UP_HEADER_ELE(zone_code)), origin_info->zone_code);
return SLP_EFWZONECODENOTMATCH;
}
/* check if FwID is the same */
if (0 != access("/tmp/recovery_mode", F_OK))
{
if (0 == memcmp(origin_info->fw_id, tp_head->fw_id, FW_ID_LEN))
{
UPGRADE_DEBUG("FwID is the same.");
#ifdef CONFIG_LTE_MODULE_IN_UP_BIN
if (origin_info->lte_supported)
{
goto CHECK_BLOCKS;
}
#endif
return SLP_EFWNEWEST;
}
}
#ifdef CONFIG_SYSUPGRADE_CHECK_FWLIST
/* check FL and BL */
if (OK != chk_fw_fl(UP_HEADER_ELE(hw_id_num), UP_HEADER_ELE(hw_id_list), UP_HEADER_ELE(fw_id_fl_num), UP_HEADER_ELE(fw_id_fl_mask), origin_info) \
&& OK != chk_fw_bl(tp_head, origin_info))
{
return SLP_EFWNOTINFLANDBL;
}
#endif
/* check firmware partitions are enough and if contents are changed */
ret = chk_fw_partition((char *)buf_start, UP_HEADER_ELE(content_types),tp_head, origin_info);
if (SLP_ENONE != ret)
{
return ret;
}
#ifdef CONFIG_LTE_MODULE_IN_UP_BIN
CHECK_BLOCKS:
#endif
if (!bOnlyCheck || rsaSignatureProtocol != 2)
{
ret = chk_blocks(UP_HEADER_ELE(content_types), tp_head, origin_info);
if (SLP_ENONE != ret)
{
return ret;
}
}
UPGRADE_ERROR("firmware check finished, ok to upgrade.");
return SLP_ENONE;
}
S32 fw_check_before_upgrade(U8 *content_start, S32 content_len) //对固件进行只读校验,封装了 check_firmware 的调用
{
S32 ret = 0;
ORIGIN_FW_INFO origin_info;
S32 bOnlyCheck = 1;
void *upgrade_header_bak = 0; /* restore upgrade header from buf after checking */
if (NULL == content_start || content_len <= 0)
{
UPGRADE_ERROR("invalid para, content_start[%p], content_len[%d]", content_start, content_len);
return SLP_ESYSTEM;
}
check_RSA_version(content_start); //////////////////////////好像有点多余
/* 本地 firmware 信息初始化 */
ret = origin_info_init(&origin_info);
if (SLP_ENONE != ret)
{
return ret;
}
align_size = ntohs(((UPGRADE_HEADER_RSA2048*)content_start)->tag_len) + origin_info.uboot_len + sizeof(TP_HEAD_INFO);
if(bOnlyCheck)
{
upgrade_header_bak = malloc(align_size);
memcpy(upgrade_header_bak, content_start, align_size);
}
ret = check_firmware(content_start, content_len, &origin_info, bOnlyCheck);
if(bOnlyCheck)
{
memcpy(content_start, upgrade_header_bak, align_size);
free(upgrade_header_bak);
upgrade_header_bak = 0;
}
return ret;
}
#ifdef CONFIG_TAPO_NAND_UPGRADE
LOCAL inline S32 tapo_nandflash_upgrade(U8* fw_base, TP_HEAD_INFO* tp_head, U32 up_contents, ORIGIN_FW_INFO *origin_info)
{
#define UPBOOT_RESERVED_BLOCK_NUM (6)
/* 升级头的定义, 需和factory_boot和uboot中tapo_nand_upgrade.c文件中一样 */
#define UP_BOOT_MAGIC "nand_upboot.bin"
#define UPBOOT_INFO_RSV_LEN 202
typedef struct _UPBOOT_INFO
{
char magic[16];
char md5[16];
int fwLen;
int fwStatus;
int up_contents;
int reserved_block; /* UPBOOT_INFO和UPBOOT_CONTENT之间的块数 */
char mac[6]; /* 用于uboot中isp升级判断 */
char reserve[UPBOOT_INFO_RSV_LEN];
} UPBOOT_INFO;
S32 ret = SLP_ENONE;
UPBOOT_INFO upgrade_info = {0};
int fwLen = ntohl(tp_head->uboot_len) + ntohl(tp_head->tphead_len) + ntohl(tp_head->kernel_len) + ntohl(tp_head->romfs_len);
UPGRADE_ERROR("uboot + tphead + kernel + romfs = %08x", fwLen);
fwLen = g_upgrade_param.buf_len - (g_upgrade_param.fw_base - (U8 *)g_upgrade_param.buf);
UPGRADE_ERROR("Whole firmware(including isp) = %08x", fwLen);
strncpy(upgrade_info.magic, UP_BOOT_MAGIC, sizeof(upgrade_info.magic));
upgrade_info.fwLen = ntohl(fwLen);
calc_md5(fw_base, fwLen, (U8 *)upgrade_info.md5);
upgrade_info.fwStatus = 0;
upgrade_info.up_contents = ntohl(up_contents);
upgrade_info.reserved_block = ntohl(UPBOOT_RESERVED_BLOCK_NUM);
memcpy(upgrade_info.mac, origin_info->mac, MAC_ADDR_SIZE);
ret = flash_write_upboot_content(fw_base, fwLen);
if (OK != ret)
{
return ret;
}
/* up_boot内容写完之后再写UPBOOT_INFO头 */
ret = flash_write_upboot_header((U8 *)&upgrade_info, sizeof(UPBOOT_INFO));
return ret;
}
#endif
/* ------------------------------------------------Firmware 升级相关函数--------------------------------------*/
/* execute different upgrade process according to upgrade contents. */
// fw_base: 固件数据在内存中的起始地址;
// tp_head: 指向 TP_HEAD(固件内容描述头)的指针;
// up_contents: 表示要升级的内容类型(如 bootloader、kernel、romfs 等);
// origin_info: 当前设备原始固件信息(用于 CRC 校验等);
LOCAL S32 execute_upgrade(U8* fw_base, TP_HEAD_INFO* tp_head, U32 up_contents, ORIGIN_FW_INFO *origin_info) //根据升级内容执行不同的升级过程
{
S32 ret = SLP_ENONE;
UPGRADE_STATUS upgrade_status = { 0 };
UPGRADE_PROCESS is_upgrading = { 0 };
/* 此处需要在 idleworker 线程执行升级前睡眠500ms,以确保web页面已经获得下载成功的回复 */
usleep(500000);
/* 开始写flash,升级标志位置1 */
if (ds_read(UPGRADE_STATUS_PATH, &upgrade_status, sizeof(UPGRADE_STATUS)) == 0 || upgrade_status.status) // 读取升级状态文件 UPGRADE_STATUS_PATH 的内容,并判断当前是否已有升级操作正在进行。如果读取失败或当前状态为“升级中”,则返回错误,防止并发升级。
{
UPGRADE_ERROR("ds read %s fail", UPGRADE_STATUS_PATH);
return ERROR;
}
/* 下载升级固件前将/upgrade/status置为升级中状态 */
upgrade_status.status = 1;
ds_advanced_write(UPGRADE_STATUS_PATH, &upgrade_status, sizeof(UPGRADE_STATUS), DS_FLAG_NOTIFY);
UPGRADE_ERROR("execute upgrade... start writing flash");
#ifdef CONFIG_TAPO_NAND_UPGRADE //若启用 NAND Flash 升级方式,调用专用函数;否则执行标准 Flash 分区写入逻辑。
ret = tapo_nandflash_upgrade(fw_base, tp_head, up_contents, origin_info);
if (OK != ret)
{
UPGRADE_ERROR("nandflash upgrad fail");
goto out;
}
#else
S32 i = 0;
if (ntohl(tp_head->tphead_offset) == origin_info->tphead_offset)
{
#ifdef CONFIG_LTE_MODULE_IN_UP_BIN
/* upgrade lte fw first */
for (i = 0; i < sizeof(blk_hdr_tbl) / sizeof(EXT_FW_BLOCK_HANDLER); i++) // 遍历扩展固件块表 blk_hdr_tbl,查找类型为 LTE 固件(CONTENT_TYPE_LTE_FW)且需要升级的模块,并执行升级操作
{
if (blk_hdr_tbl[i].need_upgrade && blk_hdr_tbl[i].type == CONTENT_TYPE_LTE_FW)
{
ret = blk_hdr_tbl[i].upgrade_ext_fw(blk_hdr_tbl[i].block);
if (SLP_ENONE != ret)
{
UPGRADE_ERROR("upgrade lte fw failed, type:0x%x", blk_hdr_tbl[i].type);
goto out;
}
blk_hdr_tbl[i].need_upgrade = EXT_FW_NOT_CHANGED;
}
}
#endif
/* 更新 extFw */
for (i = 0; i < sizeof(blk_hdr_tbl) / sizeof(EXT_FW_BLOCK_HANDLER); i++) //遍历所有需要升级的扩展模块并执行升级
{
if (blk_hdr_tbl[i].need_upgrade)
{
ret = blk_hdr_tbl[i].upgrade_ext_fw(blk_hdr_tbl[i].block);
if (SLP_ENONE != ret)
{
UPGRADE_ERROR("upgrade ext_fw failed, type:0x%x", blk_hdr_tbl[i].type);
goto out;
}
}
}
if (NULL == tp_head->factory_info_crc || NULL == tp_head->radio_crc)
{
UPGRADE_ERROR("NULL TP HEAD CRC");
ret = SLP_EFWEXCEPTION;
goto out;
}
memcpy(tp_head->factory_info_crc, origin_info->factory_info_crc, CRC_LEN);
memcpy(tp_head->radio_crc, origin_info->radio_crc, CRC_LEN);
}
#ifdef CONFIG_TP_TAPO_MAP_ROOTFS
UPGRADE_DEBUG("map rootfs ...");
flash_rootfs_map();
#endif
int fdt_len = 0;
#ifdef FDT_UPGRADE_SUPPORT
fdt_len = ntohl(tp_head->fdt_len);
#endif
/* 写入 bootloader */
if ((up_contents & CONTENT_TYPE_BOOTLOADER) && (1 != ubootNoUpgrade))
{
ret = flash_write_boot(fw_base + fdt_len, ntohl(tp_head->uboot_len));
if (OK != ret)
{
UPGRADE_ERROR("write bootloader failed");
goto out;
}
UPGRADE_ERROR("write bootloader success");
}
#ifdef CONFIG_TP_TAPO_SPMINIOS
#ifdef SLP_CAMERA_SUPPORT
/* SLP固件的分区划分为kernel_len + romfs_len = jffs2_len*/
if (ntohl(tp_head->jffs2_len) < ntohl(tp_head->kernel_len) + ntohl(tp_head->romfs_len))
#else
if (ntohl(tp_head->jffs2_len) < ntohl(tp_head->tphead_len) + ntohl(tp_head->kernel_len) + ntohl(tp_head->romfs_len))
#endif
{
UPGRADE_ERROR("UP format error");
goto out;
}
ret = flash_write_verify(fw_base + fdt_len + ntohl(tp_head->uboot_len), ntohl(tp_head->tphead_len));
if (OK != ret)
{
UPGRADE_ERROR("backup tpheader failed");
goto out;
}
// 如果 jffs2RealFsLen 有值,则写入其指定大小;
// 否则写入 jffs2_len 指定大小;
// 根据是否启用 SLP_CAMERA_SUPPORT,写入地址不同
if (ntohl(tp_head->jffs2RealFsLen) > 0)
{
#ifdef SLP_CAMERA_SUPPORT
/*SLP固件的flash分区大小只支持将kernel_and_romfs备份至jffs2,不包含tpheader,tpheader由verify分区备份*/
ret = flash_write_jffs2(fw_base + fdt_len + ntohl(tp_head->uboot_len) + ntohl(tp_head->tphead_len), ntohl(tp_head->kernel_len) + ntohl(tp_head->romfs_len));
#else
ret = flash_write_jffs2(fw_base + fdt_len + ntohl(tp_head->uboot_len), ntohl(tp_head->tphead_len) + ntohl(tp_head->kernel_len) + ntohl(tp_head->romfs_len));
#endif
}
else
{
ret = flash_write_jffs2(fw_base + fdt_len + ntohl(tp_head->uboot_len), ntohl(tp_head->jffs2_len));
}
if (ret != OK)
{
UPGRADE_ERROR("backup failed");
goto out;
}
#endif
ret = flash_write_tpheader(fw_base + fdt_len + ntohl(tp_head->uboot_len), ntohl(tp_head->tphead_len)); //fdt
if (OK != ret)
{
UPGRADE_ERROR("write tpheader failed");
goto out;
}
#ifdef FDT_UPGRADE_SUPPORT
/* 升级fdt */
if (up_contents & CONTENT_TYPE_FDT) //fdt
{
ret = flash_write_fdt(fw_base, fdt_len);
if (OK != ret)
{
UPGRADE_ERROR("write fdt failed");
goto out;
}
UPGRADE_ERROR("write fdt success");
}
#endif
if ((up_contents & CONTENT_TYPE_KERNEL) && (up_contents & CONTENT_TYPE_ROMFS))
{
ret = flash_write_kernel(fw_base + fdt_len + ntohl(tp_head->uboot_len) + ntohl(tp_head->tphead_len), // fdt
ntohl(tp_head->kernel_len));
if (ret != OK)
{
UPGRADE_ERROR("write kernel failed");
goto out;
}
ret = flash_write_romfs(fw_base + fdt_len + ntohl(tp_head->uboot_len) + ntohl(tp_head->tphead_len)
+ ntohl(tp_head->kernel_len), ntohl(tp_head->romfs_len));
if (ret != OK)
{
UPGRADE_ERROR("write romfs failed");
goto out;
}
UPGRADE_ERROR("write romfs success");
}
#ifdef CONFIG_TP_TAPO_SPMINIOS
if (ntohl(tp_head->jffs2RealFsLen) > 0)
{
ret = flash_write_jffs2(fw_base + fdt_len + ntohl(tp_head->uboot_len) + ntohl(tp_head->tphead_len)
+ ntohl(tp_head->kernel_len) + ntohl(tp_head->romfs_len), ntohl(tp_head->jffs2RealFsLen));
}
else
{
ret = flash_write_jffs2(fw_base + fdt_len + ntohl(tp_head->uboot_len) + ntohl(tp_head->tphead_len)
+ ntohl(tp_head->kernel_len) + ntohl(tp_head->romfs_len), ntohl(tp_head->jffs2_len));
}
if (ret != OK)
{
UPGRADE_ERROR("write jffs2 failed");
goto out;
}
#endif
#endif /* end CONFIG_TAPO_NAND_UPGRADE */
upgrade_status.lastUpgradingSuccess = 1;
out:
/* 写flash结束,升级标志位置0 */
upgrade_status.status = 0;
is_upgrading.state = 0;
ds_write(UPGRADE_PROCESS_PATH, &is_upgrading, sizeof(UPGRADE_PROCESS));
ds_advanced_write(UPGRADE_STATUS_PATH, &upgrade_status, sizeof(UPGRADE_STATUS), DS_FLAG_NOTIFY);
return ret;
}
/* 获取共享内存: 成功返回 共享内存id;失败返回 ERROR */
// p_store_buf:用于返回共享内存的地址;
// key:共享内存的唯一标识符;
// 返回值:共享内存的 ID(shm_id),失败返回 ERROR。
LOCAL S32 upgrade_get_shm(U8 **p_store_buf, S32 key) //获取共享内存,因为下载的固件保存在共享内存
{
void *shm = NULL;
S32 shm_id;
if (NULL == p_store_buf)
{
return ERROR;
}
/* 如果共享内存尚未被其他模块创建,则返回ERROR */
shm_id = shmget((key_t)key, 0, IPC_CREAT|IPC_EXCL);
if (-1 != shm_id)
{
UPGRADE_ERROR("shm[%d] has not been created by other module.(%d, %s)",
key, errno, strerror(errno));
return ERROR;
}
/* 获取共享内存id */
shm_id = shmget((key_t)key, 0, 0660|IPC_CREAT);
if (-1 == shm_id)
{
UPGRADE_ERROR("get shm-id of key[%d] failed.(%d, %s)",
key, errno, strerror(errno));
return ERROR;
}
shm = shmat(shm_id, NULL, 0); //将共享内存段连接到当前进程的地址空间;
if ((void*)ERROR == shm)
{
UPGRADE_ERROR("shmat failed.");
return ERROR;
}
*p_store_buf = shm;
return shm_id;
}
LOCAL S32 upgrade_detach_shm(U8* fw_buf) //解除共享内存
{
if (NULL == fw_buf)
{
UPGRADE_ERROR("invald para");
return ERROR;
}
UPGRADE_DEBUG("fw_buf[%p]", fw_buf);
if (-1 == shmdt((void *) fw_buf))
{
UPGRADE_ERROR("shmdt failed", errno, strerror(errno));
return ERROR;
}
return OK;
}
LOCAL S32 idleworker_execute_upgrade(void * param) //调用execute_upgrade,使其运行在一个空闲任务(idle worker)线程中
{
S32 ret = OK;
#ifdef FACTORY_BOOT_SDCARD_RECOVERY
/* 进行固件备份,无论成功或失败都继续执行固件升级 */
sd_recovery_save_fw(g_upgrade_param.buf, g_upgrade_param.buf_len);
#endif
ret = execute_upgrade(g_upgrade_param.fw_base, g_upgrade_param.tp_head, g_upgrade_param.up_contents, &g_upgrade_param.origin_info);
if (ret)
{
UPGRADE_ERROR("execute_upgrade failed, exit");
}
return ret;
}
// 是一个固件升级完成后的回调函数,用于清理升级过程中使用的资源(如共享内存或文件映射),
// 并发送升级结果消息通知其他模块。它通常在升级执行完成后调用,确保系统状态更新和资源释放。
LOCAL S32 idleworker_execute_upgrade_callback(S32 ret)
{
/* 发送消息通知结果 */
EXECUTE_UPGRADE_MSG msg = { 0 };
/* 共享内存升级方式进行一次 shmat 增加一次引用计数,升级结束后需减1 */
if (g_upgrade_param.upgrade_type == EXECUTE_UPGRADE_SHM)
{
upgrade_detach_shm(g_upgrade_param.buf);
}
else if (g_upgrade_param.upgrade_type == EXECUTE_UPGRADE_FILE || g_upgrade_param.upgrade_type == EXECUTE_UPGRADE_LOCALFILE)
{
munmap(g_upgrade_mmap_addr, g_upgrade_file_size);
if (g_upgrade_file_fd != -1)
{
close(g_upgrade_file_fd);
}
}
msg.type = g_upgrade_param.upgrade_type;
msg.id = g_upgrade_param.id;
msg.ret = ret;
NSD_SEND(EXECUTE_UPGRADE_MID, (U8*)&msg, sizeof(EXECUTE_UPGRADE_MSG));
g_upgrade_param.is_upgrading = 0;
return OK;
}
/**
* 升级接收的 firmware
*
* @context: buf,升级固件的缓存
buf_len, 升级固件的长度;
origin_info, 保存本地 firmware 信息的结构体
*
* Return: OK/ERROR, 升级成功/失败
*/
LOCAL S32 do_firmware_upgrade(U8* buf, U32 buf_len, ORIGIN_FW_INFO *origin_info) //确定需要升级的部分,并将实际的升级操作调度到一个空闲任务(idle worker)中执行
{
S32 ret = 0;
TP_HEAD_INFO* tp_head;
UPGRADE_HEAD *up_head;
U8* fw_base = 0;
U32 up_contents = 0x0; /* parts need to be upgraded */
up_head = (UPGRADE_HEAD*)buf;
up_contents = ntohs(up_head->content_types);
fw_base = buf + ntohs(up_head->tag_len);
tp_head = (TP_HEAD_INFO*)(buf + ntohs(up_head->tag_len) + origin_info->fdt_len + origin_info->uboot_len);
/* decide upgrade parts if flash layout not changed */
if (ntohl(tp_head->tphead_offset) == origin_info->tphead_offset)
{
/* firmware contains bootloader which is not changed */
if (!boot_changed)
{
up_contents &= ~CONTENT_TYPE_BOOTLOADER;
UPGRADE_DEBUG("Bootloader won't be upgraded.");
}
/* firmware contains kernel and romfs which are not changed */
if (!kern_and_romfs_changed)
{
up_contents &= ~(CONTENT_TYPE_KERNEL | CONTENT_TYPE_ROMFS);
UPGRADE_DEBUG("Kernel and romfs won't be upgraded.");
}
#ifdef FDT_UPGRADE_SUPPORT
/* firmware contains fdt which are not changed */
if (!fdt_changed) //fdt
{
up_contents &= ~CONTENT_TYPE_FDT;
UPGRADE_ERROR("fdt won't be upgraded.");
}
#endif
}
g_upgrade_param.buf = buf;
g_upgrade_param.buf_len = buf_len;
g_upgrade_param.fw_base = g_upgrade_param.buf + (fw_base - buf);
g_upgrade_param.tp_head = g_upgrade_param.buf + ((U8 *)tp_head - buf);
g_upgrade_param.up_contents = up_contents;
memcpy(&g_upgrade_param.origin_info, origin_info, sizeof(ORIGIN_FW_INFO));
/* 将耗时的execut_upgrade函数放到idleworker中完成 */
ret = iw_add_worker(idleworker_execute_upgrade, NULL, 0,
idleworker_execute_upgrade_callback);
if (ERROR == ret)
{
UPGRADE_ERROR("add idle worker failed.");
ret = SLP_EFWEXCEPTION;
goto error_out;
}
UPGRADE_ERROR("add job to idleworker success");
return SLP_ENONE;
error_out:
return ret;
}
/****************************************/
#define REBOOT_DELAY_SECOND 1
/* 延时重启 */
LOCAL void system_reboot_delay(S32 data)
{
reboot(RB_AUTOBOOT);
}
S32 reboot_delay()
{
if (inet_add_timer(system_reboot_delay, 0, REBOOT_DELAY_SECOND, EXECUTE_SINGLE) == -1)
{
return ERROR;
}
return OK;
}
LOCAL U32 red_led_gpio = 0;
LOCAL U32 green_led_gpio = 0;
LOCAL void upgrading_led()
{
LED_STATE_MSG led_msg;
memset(&led_msg, 0, sizeof(led_msg));
led_msg.state = LED_STATE_FW_UPGRADING;
NSD_SEND(LED_STATE_MID, (U8 *)&led_msg, sizeof(led_msg));
}
void upgrade_success_led()
{
LED_STATE_MSG led_msg;
memset(&led_msg, 0, sizeof(led_msg));
led_msg.state = LED_STATE_FW_UPGRADE_SUC;
NSD_SEND(LED_STATE_MID, (U8 *)&led_msg, sizeof(led_msg));
}
void upgrade_fail_led()
{
LED_STATE_MSG led_msg;
memset(&led_msg, 0, sizeof(led_msg));
led_msg.state = LED_STATE_FW_UPGRADE_FAIL;
NSD_SEND(LED_STATE_MID, (U8 *)&led_msg, sizeof(led_msg));
}
LOCAL void upgrade_check_fail_led()
{
LED_STATE_MSG led_msg;
memset(&led_msg, 0, sizeof(led_msg));
led_msg.state = LED_STATE_FW_CHECK_FAIL;
NSD_SEND(LED_STATE_MID, (U8 *)&led_msg, sizeof(led_msg));
}
void led_init()
{
GPIO_CFG gpio;
memset(&gpio, 0, sizeof(gpio));
ds_read(GPIO_CFG_PATH, &gpio, sizeof(gpio));
red_led_gpio = gpio.red_led_gpio;
green_led_gpio = gpio.green_led_gpio;
}
LOCAL S32 firmware_upgrade_core(U8 *content_start, S32 content_len) //调用检查和升级函数以及一些led指示灯函数实现升级流程
{
ORIGIN_FW_INFO origin_info;
S32 ret = 0;
CLIENT_INFO client_info;
S32 bOnlyCheck = 0; //执行升级操作,不只检查文件签名
if (NULL == content_start || content_len <= 0)
{
UPGRADE_ERROR("invalid para, content_start[%p], content_len[%d]", content_start, content_len);
return SLP_ESYSTEM;
}
check_RSA_version(content_start);
/* 本地 firmware 信息初始化 */
ret = origin_info_init(&origin_info);
if (SLP_ENONE != ret)
{
UPGRADE_ERROR("init origin info fail");
goto FW_ERROR;
}
memset(&client_info, 0, sizeof(CLIENT_INFO));
ds_read(CLOUD_STATUS_CLIENT_INFO_PATH, &client_info, sizeof(CLIENT_INFO));
/* 检查固件 */
ret = check_firmware(content_start, content_len, &origin_info, bOnlyCheck);
if (SLP_ENONE != ret)
{
upgrade_check_fail_led();
if (DOWNLOAD_FW_SUCCESS == client_info.fw_download_status)
{
client_info.fw_verify_status = VERIFY_STAT_FAIL;
ds_write(CLOUD_STATUS_CLIENT_INFO_PATH, &client_info, sizeof(CLIENT_INFO));
}
UPGRADE_ERROR("check firmware erro");
goto FW_ERROR;
}
if (DOWNLOAD_FW_SUCCESS == client_info.fw_download_status)
{
client_info.fw_verify_status = VERIFY_STAT_SUCCESS;
ds_write(CLOUD_STATUS_CLIENT_INFO_PATH, &client_info, sizeof(CLIENT_INFO));
}
upgrading_led();
/* 进行固件升级 */
ret = do_firmware_upgrade(content_start, content_len, &origin_info);
if (ret)
{
UPGRADE_ERROR("upgrade firmware failed");
upgrade_fail_led();
goto FW_ERROR;
}
/* 升级结果应该在各源头的消息接收函数中处理,下不应有代码 */
UPGRADE_DEBUG("upgrade firmware over");
return SLP_ENONE;
FW_ERROR:
return ret;
}
LOCAL S32 fw_file_upgrade(char *path) //文件路径中读取固件并升级
{
int ret = 0;
struct stat sb;
if (path == NULL)
{
UPGRADE_ERROR("path empty");
return SLP_ESYSTEM;
}
ds_stop_module_for_upgrade();
g_upgrade_file_fd = open(path, O_RDONLY);
if (g_upgrade_file_fd < 0)
{
UPGRADE_ERROR("cannot open file path");
return SLP_ESYSTEM;
}
/* 获取文件大小 */
if (fstat(g_upgrade_file_fd, &sb) < 0)
{
UPGRADE_ERROR("get file size error");
goto ERROR_OUT;
}
g_upgrade_file_size = sb.st_size;
UPGRADE_ERROR("file size: %d", g_upgrade_file_size);
g_upgrade_mmap_addr = mmap(NULL, g_upgrade_file_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, g_upgrade_file_fd, 0);
if (g_upgrade_mmap_addr == MAP_FAILED)
{
UPGRADE_ERROR("mmap error");
goto ERROR_OUT;
}
ret = firmware_upgrade_core((U8 *)g_upgrade_mmap_addr, g_upgrade_file_size);
if (OK != ret)
{
UPGRADE_ERROR("firmware_upgrade add idleworker failed");
munmap(g_upgrade_mmap_addr, g_upgrade_file_size);
goto ERROR_OUT;
}
return OK;
ERROR_OUT:
if (g_upgrade_file_fd != -1)
{
close(g_upgrade_file_fd);
}
return ERROR;
}
LOCAL S32 upgrade_file_method(UPGRADE_MSG *msg)
{
return fw_file_upgrade(msg->u.file_path);
}
LOCAL S32 upgrade_shm_method(UPGRADE_MSG *msg) //共享内存中读取固件并升级
{
S32 ret = 0;
S32 shm_id = 0;
U8* shm_fw_buf = NULL;
shm_id = upgrade_get_shm(&shm_fw_buf, msg->u.shm_key);
if (ERROR == shm_id)
{
UPGRADE_ERROR("fw_get_shm fail");
return SLP_ESYSTEM;
}
/* 调用固件升级函数 */
ret = firmware_upgrade_core(shm_fw_buf, msg->fw_len);
/* 升级不成功,任务未传递给 idleworker ,引用计数需减1 */
if (ret != OK)
{
upgrade_detach_shm(shm_fw_buf);
}
return ret;
}
LOCAL S32 upgrade_mem_method(UPGRADE_MSG *msg)
{
return firmware_upgrade_core(msg->u.addr, msg->fw_len);
}
LOCAL UPGRADE_METHOD g_upgrade_method_list[] = {
{EXECUTE_UPGRADE_FILE, upgrade_file_method},
{EXECUTE_UPGRADE_SHM, upgrade_shm_method},
{EXECUTE_UPGRADE_MEM, upgrade_mem_method},
{EXECUTE_UPGRADE_LOCALFILE, upgrade_file_method},
};
void fw_upgrade_ready_cb(void *handler, U8 *mbuf, U32 mlen, U32 sender_dms_id) //根据三种方式进行升级
{
S32 ret = 0;
S32 i = 0;
UPGRADE_MSG *msg = NULL;
EXECUTE_UPGRADE_MSG exec_msg = { 0 };
UPGRADE_PROCESS is_upgrading = { 0 };
if (NULL == mbuf)
{
UPGRADE_ERROR("mbuf is null");
ret = SLP_ESYSTEM;
goto EXIT;
}
msg = (UPGRADE_MSG *)mbuf;
if (g_upgrade_param.is_upgrading)
{
UPGRADE_ERROR("other firmware_upgrade is in progress.");
return;
}
lock_text_segments();
g_upgrade_param.is_upgrading = 1;
g_upgrade_param.upgrade_type = msg->type;
g_upgrade_param.id = msg->id;
if (ds_read(UPGRADE_PROCESS_PATH, &is_upgrading, sizeof(UPGRADE_PROCESS)) == 0)
{
UPGRADE_ERROR("read upgrade_status error.");
return;
}
/* 升级固件前将/upgrade/status/is_upgrading置为升级中状态 */
is_upgrading.state = 1;
ds_write(UPGRADE_PROCESS_PATH, &is_upgrading, sizeof(UPGRADE_PROCESS));
UPGRADE_ERROR("upgrade recv message, type: %d, id: %d", msg->type, msg->id);
for (i = 0; i < sizeof(g_upgrade_method_list) / sizeof(UPGRADE_METHOD); i++)
{
if (msg->type == g_upgrade_method_list[i].upgrade_type)
{
ret = g_upgrade_method_list[i].method(msg);
break;
}
}
EXIT:
if (OK != ret)
{
UPGRADE_ERROR("firmware upgrade fail and firmware not changed");
/* 如固件校验失败,由 upgrade 回复升级失败消息,校验成功则由 idleworker 回复消息 */
exec_msg.type = msg->type;
exec_msg.id = msg->id;
exec_msg.ret = ret;
is_upgrading.state = 0;
ds_write(UPGRADE_PROCESS_PATH, &is_upgrading, sizeof(UPGRADE_PROCESS));
msg_send(EXECUTE_UPGRADE_MID, (U8 *)&exec_msg, sizeof(EXECUTE_UPGRADE_MSG));
g_upgrade_param.is_upgrading = 0;
}
return;
}
梳理一下这段代码的结构
最新发布