You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
551 lines
14 KiB
C
551 lines
14 KiB
C
/*****************************************************************************
|
|
* file lib/process/pd_upgrade.c
|
|
* author WangBo
|
|
* version 1.0.0
|
|
* date 07-Feb-2023
|
|
* brief This file provides all the softwave upgrade related operation functions.
|
|
******************************************************************************
|
|
* Attention
|
|
*
|
|
* <h2><center>© COPYRIGHT(c) 2024 LandPower</center></h2>
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without modification,
|
|
* are permitted provided that the following conditions are met:
|
|
* 1. Redistributions of source code must retain the above copyright notice,
|
|
* this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
* and/or other materials provided with the distribution.
|
|
* 3. Neither the name of LandPower nor the names of its contributors may be used to
|
|
* endorse or promote products derived from this software without specific
|
|
* prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
******************************************************************************/
|
|
|
|
/* Includes ------------------------------------------------------------------*/
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#ifdef CFG_DEV_TYPE_LAND_PD
|
|
/* 标准 C 库头文件 */
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <dirent.h>
|
|
#include <fcntl.h>
|
|
#include <string.h>
|
|
#include <typedef.h>
|
|
|
|
/* 第三方头文件 */
|
|
|
|
/* 私有头文件 */
|
|
#include "main.h"
|
|
#include "pd_upgrade.h"
|
|
#include "pd_dau.h"
|
|
#include "pd_csg.h"
|
|
#include "pd_dbg.h"
|
|
|
|
/* Private define ------------------------------------------------------------*/
|
|
#define PD_UPG_READ_SIZE (1024*1024)
|
|
#define PD_UPG_HARDWARE_VERSON "GIS6.0"
|
|
|
|
/* Private macro -------------------------------------------------------------*/
|
|
|
|
/* Private typedef -----------------------------------------------------------*/
|
|
typedef void (*pd_upg_sighandler)(int);
|
|
|
|
/* Private variables ---------------------------------------------------------*/
|
|
static pd_upg_ctrl_t pd_upg_ctrl;
|
|
static const char *pd_upg_type_str[PD_UPG_SEL_MAX] =
|
|
{
|
|
"all",
|
|
"cmu",
|
|
"dau"
|
|
};
|
|
|
|
/* Private function prototypes -----------------------------------------------*/
|
|
|
|
/* Internal functions --------------------------------------------------------*/
|
|
/* description: 调用 system 下发 shell 命令
|
|
param: cmd_line -- 需要执行的命令
|
|
return: */
|
|
int _pd_upg_system(const char *cmd_line)
|
|
{
|
|
int ret = 0;
|
|
pd_upg_sighandler old_handler;
|
|
|
|
old_handler = signal(SIGCHLD, SIG_DFL);
|
|
ret = system(cmd_line);
|
|
signal(SIGCHLD, old_handler);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* description: 提取升级数据写成文件
|
|
param: addr -- 起始地址
|
|
len -- 大小
|
|
name -- 文件名字
|
|
return: E_NONE - 成功, E_XXXX - 失败 */
|
|
int32_t _pd_upg_write_file(int32_t addr, int32_t size, const char *name)
|
|
{
|
|
int fp_wr = -1;
|
|
int fp_rd = -1;
|
|
char *buf = NULL;
|
|
int32_t len = 0;
|
|
int32_t len_wr = 0;
|
|
int32_t len_rd = 0;
|
|
int32_t rv = E_NONE;
|
|
|
|
/* 打开文件 */
|
|
fp_wr = open(name, O_WRONLY | O_CREAT | O_TRUNC, 0777);
|
|
if (fp_wr <= 0)
|
|
{
|
|
DBG(DBG_M_PD_UPGRADE, "Open %s failed!\n", name);
|
|
return E_SYS_CALL;
|
|
}
|
|
|
|
fp_rd = open(PD_UPG_SOFTWARE, O_RDONLY);
|
|
if (fp_rd <= 0)
|
|
{
|
|
close(fp_wr);
|
|
DBG(DBG_M_PD_UPGRADE, "Open " PD_UPG_SOFTWARE " failed!\n");
|
|
return E_SYS_CALL;
|
|
}
|
|
|
|
/* 偏移到读取位置 */
|
|
if (lseek(fp_rd, addr, SEEK_SET) < 0)
|
|
{
|
|
close(fp_wr);
|
|
close(fp_rd);
|
|
rv = E_SYS_CALL;
|
|
DBG(DBG_M_PD_UPGRADE, "Fseek %d failed!\n", addr);
|
|
return E_SYS_CALL;
|
|
}
|
|
|
|
/* 申请 buf */
|
|
buf = (char*)XMALLOC_Q(MTYPE_UPGRADE, PD_UPG_READ_SIZE);
|
|
if (!buf)
|
|
{
|
|
close(fp_wr);
|
|
close(fp_rd);
|
|
DBG(DBG_M_PD_UPGRADE, "Malloc failed!\n");
|
|
return E_MEM;
|
|
}
|
|
|
|
while (len < size)
|
|
{
|
|
len_rd = read(fp_rd, buf, PD_UPG_READ_SIZE);
|
|
if (len_rd > 0)
|
|
{
|
|
len_wr = write(fp_wr, buf, len_rd);
|
|
if(len_wr != len_rd)
|
|
{
|
|
DBG(DBG_M_PD_UPGRADE, "Write %s error!\n", name);
|
|
rv = E_SYS_CALL;
|
|
break;
|
|
}
|
|
}
|
|
else if(0 == len_rd)
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
DBG(DBG_M_PD_UPGRADE, "Read " PD_UPG_SOFTWARE " error!\n");
|
|
rv = E_SYS_CALL;
|
|
break;
|
|
}
|
|
|
|
len += len_rd;
|
|
}
|
|
|
|
close(fp_rd);
|
|
close(fp_wr);
|
|
XFREE(MTYPE_UPGRADE, buf);
|
|
_pd_upg_system("sync");
|
|
sleep(1);
|
|
|
|
return rv;
|
|
}
|
|
|
|
/* description: 升级 CMU
|
|
param:
|
|
return: E_NONE - 成功, E_XXXX - 失败 */
|
|
int32_t _pd_upg_upgrade_dau(void)
|
|
{
|
|
uint8_t i = 0;
|
|
int32_t offset = 0;
|
|
int32_t lenth = 0;
|
|
int32_t rv = E_ERROR;
|
|
|
|
/* 查找升级文件 */
|
|
for (i = 0; i < PD_UPG_AREA_MAX; i++)
|
|
{
|
|
if (0 == pd_upg_ctrl.head.arr_info[i].len)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (PD_UPG_TYPE_DAU == pd_upg_ctrl.head.arr_info[i].type)
|
|
{
|
|
offset = pd_upg_ctrl.head.arr_info[i].start;
|
|
lenth = pd_upg_ctrl.head.arr_info[i].len;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* 没有找到 */
|
|
if (0 == lenth)
|
|
{
|
|
snprintf(pd_upg_ctrl.msg, 128, "DAU file is not found.");
|
|
DBG(DBG_M_PD_UPGRADE, "DAU file is not found.\n");
|
|
return E_NOT_FOUND;
|
|
}
|
|
|
|
/* 读取并写升级文件 */
|
|
rv = _pd_upg_write_file(offset, lenth, DEBUG_DAU_FILE);
|
|
if (rv != E_NONE)
|
|
{
|
|
snprintf(pd_upg_ctrl.msg, 128, "DAU write file error.");
|
|
return E_NOT_FOUND;
|
|
}
|
|
|
|
return E_NONE;
|
|
}
|
|
|
|
/* description: 升级 CMU
|
|
param:
|
|
return: E_NONE - 成功, E_XXXX - 失败 */
|
|
int32_t _pd_upg_upgrade_cmu(void)
|
|
{
|
|
char cmd[128] = {0};
|
|
uint8_t i = 0;
|
|
int32_t offset = 0;
|
|
int32_t lenth = 0;
|
|
int32_t rv = E_ERROR;
|
|
|
|
/* 查找升级文件 */
|
|
for (i = 0; i < PD_UPG_AREA_MAX; i++)
|
|
{
|
|
if (0 == pd_upg_ctrl.head.arr_info[i].len)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (PD_UPG_TYPE_CMU == pd_upg_ctrl.head.arr_info[i].type)
|
|
{
|
|
offset = pd_upg_ctrl.head.arr_info[i].start;
|
|
lenth = pd_upg_ctrl.head.arr_info[i].len;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* 没有找到 */
|
|
if (0 == lenth)
|
|
{
|
|
snprintf(pd_upg_ctrl.msg, 128, "CMU file is not found.");
|
|
DBG(DBG_M_PD_UPGRADE, "CMU file is not found.\n");
|
|
return E_NOT_FOUND;
|
|
}
|
|
|
|
/* 先备份原始文件 */
|
|
snprintf(cmd, 128, "cp -rf %s bak", PD_UPG_CMU_FILE);
|
|
_pd_upg_system(cmd);
|
|
_pd_upg_system("sync");
|
|
sleep(1);
|
|
|
|
/* 读取并写升级文件 */
|
|
rv = _pd_upg_write_file(offset, lenth, PD_UPG_CMU_FILE_BAK);
|
|
if (rv != E_NONE)
|
|
{
|
|
snprintf(pd_upg_ctrl.msg, 128, "CMU write file error.");
|
|
return E_NOT_FOUND;
|
|
}
|
|
|
|
if (rename(PD_UPG_CMU_FILE_BAK, PD_UPG_CMU_FILE) != 0)
|
|
{
|
|
snprintf(pd_upg_ctrl.msg, 128, "CMU file rename error.");
|
|
DBG(DBG_M_PD_UPGRADE, "Can't rename file %s!\n", PD_UPG_CMU_FILE_BAK);
|
|
return E_SYS_CALL;
|
|
}
|
|
DBG(DBG_M_PD_UPGRADE, "Upgrade CMU Ok.\n");
|
|
|
|
return E_NONE;
|
|
}
|
|
|
|
/* description: 升级系统
|
|
param:
|
|
return: E_NONE - 成功, E_XXXX - 失败 */
|
|
int32_t _pd_upg_upgrade(void)
|
|
{
|
|
if (PD_UPG_SEL_ALL == pd_upg_ctrl.upg_type || PD_UPG_SEL_CMU == pd_upg_ctrl.upg_type)
|
|
{
|
|
LD_E_RETURN(DBG_M_PD_UPGRADE, _pd_upg_upgrade_cmu());
|
|
}
|
|
|
|
if (PD_UPG_SEL_ALL == pd_upg_ctrl.upg_type || PD_UPG_SEL_DAU == pd_upg_ctrl.upg_type)
|
|
{
|
|
LD_E_RETURN(DBG_M_PD_UPGRADE, _pd_upg_upgrade_dau());
|
|
}
|
|
|
|
return E_NONE;
|
|
}
|
|
|
|
/* description: 检测硬件版本号是否匹配
|
|
param:
|
|
return: E_NONE - 成功, E_XXXX - 失败 */
|
|
int32_t _pd_upg_hardware_check(void)
|
|
{
|
|
if (strncmp(pd_upg_ctrl.head.hard_ver, PD_UPG_HARDWARE_VERSON, strlen(PD_UPG_HARDWARE_VERSON)))
|
|
{
|
|
DBG(DBG_M_PD_UPGRADE, "Hardware version(%s) not match\n", pd_upg_ctrl.head.hard_ver);
|
|
return E_ERROR;
|
|
}
|
|
|
|
return E_NONE;
|
|
}
|
|
|
|
|
|
/* description: 验证升级文件, CRC 校验升级文件并对比每段分区确定是否需要升级
|
|
param:
|
|
return: E_NONE - 成功, E_XXXX - 失败 */
|
|
int32_t _pd_upg_verify_file(void)
|
|
{
|
|
int32_t rv = 0;
|
|
int fd = 0;
|
|
unsigned int crc = 0;
|
|
char *buf = NULL;
|
|
|
|
/*读取升级文件头信息*/
|
|
fd = open(PD_UPG_SOFTWARE, O_RDONLY);
|
|
if (fd < 0)
|
|
{
|
|
DBG(DBG_M_PD_UPGRADE, "Open file "PD_UPG_SOFTWARE" failed!\n");
|
|
return E_SYS_CALL;
|
|
}
|
|
|
|
rv = read(fd, &pd_upg_ctrl.head, sizeof(pd_upg_head_t));
|
|
if (rv != sizeof(pd_upg_head_t) || pd_upg_ctrl.head.magic != PD_UPG_MAGICNUM)
|
|
{
|
|
close(fd);
|
|
DBG(DBG_M_PD_UPGRADE, "Read len %d(%d), magic %x(%x)\n",
|
|
rv, sizeof(pd_upg_head_t), pd_upg_ctrl.head.magic, PD_UPG_MAGICNUM);
|
|
return E_NOT_IDENTIFY;
|
|
}
|
|
|
|
/*crc校验*/
|
|
buf = (char*)XMALLOC_Q(MTYPE_UPGRADE, PD_UPG_BLOCK_SIZE);
|
|
if (!buf)
|
|
{
|
|
close(fd);
|
|
DBG(DBG_M_PD_UPGRADE, "Malloc error!\n");
|
|
return E_MEM;
|
|
}
|
|
|
|
while (1)
|
|
{
|
|
rv = read(fd, buf, PD_UPG_BLOCK_SIZE);
|
|
if (rv < 0)
|
|
{
|
|
DBG(DBG_M_PD_UPGRADE, "Read failed!\n");
|
|
rv = E_SYS_CALL;
|
|
break;
|
|
}
|
|
else if(rv == 0)
|
|
{
|
|
rv = E_NONE;
|
|
break;
|
|
}
|
|
|
|
crc = crc32(crc, buf, (unsigned long)rv);
|
|
}
|
|
|
|
if (E_NONE == rv)
|
|
{
|
|
if (crc != pd_upg_ctrl.head.crc)
|
|
{
|
|
DBG(DBG_M_PD_UPGRADE, "CRC error!\n");
|
|
rv = E_ERROR;;
|
|
}
|
|
}
|
|
|
|
/* 释放资源 */
|
|
XFREE(MTYPE_UPGRADE, buf);
|
|
close(fd);
|
|
DBG(DBG_M_PD_UPGRADE, "Verfiy upgrade success.\n");
|
|
return rv;
|
|
}
|
|
|
|
/* description: 检测是否存在满足升级的条件
|
|
param:
|
|
return: E_NONE - 成功, E_XXXX - 失败 */
|
|
int32_t _pd_upg_file_check(void)
|
|
{
|
|
int32_t rv = 0;
|
|
|
|
/* 读取升级文件并校验 */
|
|
rv = _pd_upg_verify_file();
|
|
if (rv != E_NONE)
|
|
{
|
|
snprintf(pd_upg_ctrl.msg, 128, "App CRC verify error.");
|
|
return rv;
|
|
}
|
|
|
|
/* 硬件版本号检查 */
|
|
rv = _pd_upg_hardware_check();
|
|
if (rv != E_NONE)
|
|
{
|
|
snprintf(pd_upg_ctrl.msg, 128, "Hardware is not match.");
|
|
return rv;
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
/* description: 软件升级处理线程
|
|
param: parm -- 控制结构体
|
|
return: */
|
|
void *_pd_upg_handle(void *parm)
|
|
{
|
|
char cmd[128] = {0};
|
|
int32_t rv = E_ERROR;
|
|
|
|
while(1)
|
|
{
|
|
/* 文件检查 */
|
|
rv = _pd_upg_file_check();
|
|
if (rv != E_NONE)
|
|
{
|
|
break;
|
|
}
|
|
|
|
/* 升级系统 */
|
|
rv = _pd_upg_upgrade();
|
|
if (rv != E_NONE)
|
|
{
|
|
break;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
/* 保存升级原始文件 */
|
|
snprintf(cmd, 128, "mv " PD_UPG_SOFTWARE " bak");
|
|
_pd_upg_system(cmd);
|
|
_pd_upg_system("sync");
|
|
sleep(1);
|
|
|
|
/* 处理升级结果 */
|
|
if (E_NONE == rv)
|
|
{
|
|
DBG(DBG_M_PD_UPGRADE, "Upgrade ok.\n");
|
|
if (pd_upg_ctrl.upgrade_result)
|
|
{
|
|
pd_upg_ctrl.upgrade_result(1, "App and dua update successful.");
|
|
}
|
|
|
|
/* 升级成功, 主动重启 */
|
|
log_notice(LOG_UPGRADE, "Upgrade %s ok.", pd_upg_type_str[pd_upg_ctrl.upg_type]);
|
|
reboot_system(LOG_UPGRADE, REBOOT_UPGRADE_ALL);
|
|
}
|
|
else
|
|
{
|
|
DBG(DBG_M_PD_UPGRADE, "Upgrade failed.\n");
|
|
if (pd_upg_ctrl.upgrade_result)
|
|
{
|
|
pd_upg_ctrl.upgrade_result(0, pd_upg_ctrl.msg);
|
|
}
|
|
}
|
|
|
|
pd_upg_ctrl.is_start = FALSE;
|
|
pthread_exit(NULL);
|
|
return NULL;
|
|
}
|
|
|
|
/* description: 启动升级线程
|
|
param:
|
|
return: E_NONE - 成功, E_XXXX - 失败 */
|
|
int32_t _pd_upg_start(void)
|
|
{
|
|
struct sched_param param;
|
|
pthread_attr_t attr;
|
|
pthread_t pid;
|
|
int32_t rv = 0;
|
|
|
|
/* 创建线程 配置线程 RR 调度, 优先级 50 */
|
|
pthread_attr_init(&attr);
|
|
param.sched_priority = 50;
|
|
pthread_attr_setschedpolicy(&attr, SCHED_RR);
|
|
pthread_attr_setschedparam(&attr, ¶m);
|
|
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
|
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
|
rv = pthread_create(&pid, &attr, _pd_upg_handle, NULL);
|
|
if (rv != 0)
|
|
{
|
|
log_err(LOG_UPGRADE, "PD can't create pthread %d!", rv);
|
|
return E_SYS_CALL;
|
|
}
|
|
else
|
|
{
|
|
thread_m_add("UPGRADE", pid);
|
|
}
|
|
pthread_attr_destroy(&attr);
|
|
|
|
return E_NONE;
|
|
}
|
|
|
|
/* Interface functions -------------------------------------------------------*/
|
|
/* description: 软件升级开始
|
|
param: from -- 来自谁的升级 PD_UPG_FROM_xxx
|
|
type -- 升级类型 PD_UPG_SEL_xxx
|
|
return: E_NONE - 成功, E_XXXX - 失败 */
|
|
int32_t pd_upg_start(uint8_t from, uint8_t type)
|
|
{
|
|
int32_t rv = E_NONE;
|
|
|
|
if (pd_upg_ctrl.is_start == FALSE)
|
|
{
|
|
DBG(DBG_M_PD_UPGRADE, "Start upgrade system.\n");
|
|
|
|
pd_upg_ctrl.is_start = TRUE;
|
|
pd_upg_ctrl.upg_from = from;
|
|
pd_upg_ctrl.upg_type = type;
|
|
if (PD_UPG_FROM_CSG == from)
|
|
{
|
|
pd_upg_ctrl.upgrade_result = csg_upgrade_result_send;
|
|
}
|
|
else if(PD_UPG_FROM_DBG == from)
|
|
{
|
|
//pd_upg_ctrl.upgrade_result = debug_upgrade_result_send;
|
|
}
|
|
else
|
|
{
|
|
pd_upg_ctrl.upgrade_result = NULL;
|
|
}
|
|
|
|
/* 初始化模块. */
|
|
LD_E_RETURN(DBG_M_PD_UPGRADE, _pd_upg_start());
|
|
}
|
|
else
|
|
{
|
|
DBG(DBG_M_PD_UPGRADE, "Upgrade is busy!\n");
|
|
rv = E_TIMEOUT;
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
#endif
|
|
/************************ (C) COPYRIGHT LandPower ***** END OF FILE ****/
|