rel_1.6.0 init

This commit is contained in:
guocheng.kgc 2020-06-18 20:06:52 +08:00 committed by shengdong.dsd
commit 27b3e2883d
19359 changed files with 8093121 additions and 0 deletions

View file

@ -0,0 +1,80 @@
## Contents
```sh
hal
├── aos.mk
├── Config.in
├── ota_hal_host.c
├── ota_hal_module.c
├── ota_hal_os.c
├── ota_hal_os.h
├── ota_hal_plat.c
├── ota_hal_plat.h
└── README.md
```
## Introduction
An over-the-air update is the wireless delivery of new software or data to smart devices, especially IoT devices. Wireless carriers and OEMs typically use over-the-air (OTA) updates to deploy the new operating systems and the software app to these devices.
## Features
1. Differential incremental upgrade;
2. Dual banker:AB partition upgrade to support rollback to old version;
3. Secure download channel;
4. Firmware digital signature verification.
## Dependencies
Linkkit MQTT channel
Linkkit CoAP channel
## API
User service APIs:
```c
typedef struct {
unsigned char inited; /*If is inted*/
char pk[20+1];/*Product Key*/
char ps[64+1];/*Product secret*/
char dn[32+1];/*Device name*/
char ds[64+1];/*Device secret*/
OTA_PROTCOL_E trans_protcol; /*default:0--> MQTT 1-->COAP*/
OTA_PROTCOL_E dl_protcol; /*default:3--> HTTPS 1-->COAP 2-->HTTP*/
unsigned char sign_type; /*default:0--> sha256 1--> md5 2-->RSA*/
char ota_ver[OTA_MAX_VER_LEN]; /*OTA FW version*/
char sys_ver[OTA_MAX_VER_LEN]; /*OTA System version*/
ota_transport_t *h_tr; /*OTA tansport manager*/
ota_download_t *h_dl; /*OTA download manager*/
void* h_ch; /*OTA channel handle:mqtt,coap*/
} ota_service_t;
/*OTA export service APIs*/
int ota_service_init(ota_service_t* ctx);
int ota_service_deinit(ota_service_t* ctx);
```
for sample code please check [otaapp](../../../app/example/otaapp/).
## RTOS build
```sh
cd ROOT DIR;
aos make otaapp@board;
```
## run CLI CMDs
1. connect network
```
netmgr connect ssid passwd
```
2. run ota demo
```
OTA_APP pk dn ds ps
```
## Reference
* [AliOS-Things OTA使用说明](https://github.com/alibaba/AliOS-Things/wiki/OTA-Tutorial)
* [OTA flash分区说明文档](https://github.com/alibaba/AliOS-Things/wiki/OTA-Flash-Partitions-Overview)
* [云端一体化差分+安全升级AliOS Things物联网升级“利器”](https://mp.weixin.qq.com/s/Pb8Lleuww1r7qQJHu5ON8g)

View file

@ -0,0 +1,71 @@
NAME := ota_hal
$(NAME)_MBINS_TYPE := kernel
$(NAME)_VERSION := 1.0.0
$(NAME)_SUMMARY := ota porting HAL APIs
#default gcc
ifeq ($(COMPILER),)
$(NAME)_CFLAGS += -Wall -Werror
else ifeq ($(COMPILER),gcc)
$(NAME)_CFLAGS += -Wall -Werror
endif
$(NAME)_COMPONENTS += base64
$(NAME)_SOURCES := \
ota_hal_module.c \
ota_hal_os.c \
ifeq ($(CONFIG_SUPPORT_MCU_OTA), ENABLE)
$(NAME)_SOURCES += ota_hal_mcu.c
endif
ifneq (,$(filter linux,$(HOST_MCU_FAMILY)))
$(NAME)_SOURCES += ota_hal_host.c
else
ifneq (,$(filter esp32,$(HOST_MCU_FAMILY)))
GLOBAL_DEFINES += AOS_OTA_BANK_DUAL
GLOBAL_DEFINES += AOS_OTA_DISABLE_MD5
$(NAME)_SOURCES += ota_hal_$(HOST_MCU_FAMILY).c
else
ifneq (,$(filter bk7231u,$(HOST_MCU_FAMILY)))
$(NAME)_SOURCES += ota_hal_beken.c
else
ifneq (,$(filter bk7231s,$(HOST_MCU_FAMILY)))
$(NAME)_SOURCES += ota_hal_beken.c
else
ifneq (,$(filter rtl8710bn,$(HOST_MCU_FAMILY)))
else
ifneq (,$(filter asr5501,$(HOST_MCU_FAMILY)))
GLOBAL_DEFINES += AOS_OTA_DISABLE_MD5
GLOBAL_DEFINES += OTA_BOOT_PAPA_COMPATIBAL
else
$(NAME)_SOURCES += ota_hal_plat.c
endif
endif
endif
endif
endif
endif
ifneq (,$(filter rtl8710bn esp8266,$(HOST_MCU_FAMILY)))
GLOBAL_DEFINES += AOS_OTA_BANK_DUAL
GLOBAL_DEFINES += AOS_OTA_DISABLE_MD5
endif
ifeq ($(FEATURE_SUPPORT_ITLS),y)
GLOBAL_DEFINES += AOS_OTA_ITLS
$(NAME)_COMPONENTS += itls
else
$(NAME)_COMPONENTS += imbedtls
endif
ifeq ($(MD5_CHECK),0)
GLOBAL_DEFINES += AOS_OTA_DISABLE_MD5
endif
GLOBAL_INCLUDES += . \
../inc \
../src/verify/crc \
../src/2nd_boot

View file

@ -0,0 +1,541 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include "aos/kernel.h"
#include "aos/kv.h"
#include "hal/soc/flash.h"
#include "ota_hal_plat.h"
#include "ota_hal_os.h"
#include "ota_log.h"
#define KV_HAL_OTA_CRC16 "hal_ota_get_crc16"
#define OTA_UPG_FLAG 0xA55A
#define OTA_PINGPONG_FLAG 0xB55B
typedef struct
{
uint32_t ota_len;
uint32_t ota_crc;
} ota_reboot_info_t;
typedef struct
{
uint32_t dst_adr;
uint32_t src_adr;
uint32_t size;
uint16_t crc;
uint16_t upg_flag;
} __attribute__((packed)) ota_hdl_t;
static ota_reboot_info_t ota_info = {0};
static ota_crc16_ctx contex = {0};
static uint32_t _off_set = 0;
static uint16_t hal_ota_get_crc16(void);
static void hal_ota_save_crc16(uint16_t crc16);
#ifdef AOS_OTA_BANK_DUAL
#define OTA_IMAGE_A 0
#define OTA_IMAGE_B 1
#define KV_HAL_OTA_HDR "hal_ota_get_hdr"
typedef struct
{
uint32_t version;
uint32_t hdr_num;
struct
{
uint32_t img_ID;
uint32_t hdr_len;
uint32_t checksum;
uint32_t img_len;
uint32_t img_offset;
uint32_t flash_offset;
}ota_file[2];
}ota_hdr_t;
static ota_hdr_t ota_hdr_info = {0};
static uint8_t ota_index = 0;
static uint8_t ota_hdr_check = 0;
static int hal_get_ota_hdr(void)
{
int len, ret;
len = sizeof(ota_hdr_t);
ret = aos_kv_get(KV_HAL_OTA_HDR, &ota_hdr_info, &len);
return ret;
}
static int hal_ota_save_hdr(void)
{
int len, ret;
len = sizeof(ota_hdr_t);
ret = aos_kv_set(KV_HAL_OTA_HDR, &ota_hdr_info, len, 1);
return ret;
}
static void hal_get_ota_index(void)
{
uint32_t offset, boot_addr;
hal_logic_partition_t *partition_info;
offset = 0x00;
hal_flash_read(HAL_PARTITION_PARAMETER_1, &offset, (void *)&boot_addr, sizeof(boot_addr));
partition_info = hal_flash_get_info(HAL_PARTITION_OTA_TEMP);
if(boot_addr == partition_info->partition_start_addr) {
ota_index = OTA_IMAGE_A; //update to image A
}
else {
ota_index = OTA_IMAGE_B; //update to image B
}
return;
}
static int hal_verify_ota_head(void)
{
char imgid[5];
if(~ota_hdr_info.version) {
OTA_LOG_E("check ota version error %x", ota_hdr_info.version);
return 1;
}
if(ota_hdr_info.hdr_num != 2) {
OTA_LOG_E("check ota number error %d", ota_hdr_info.hdr_num);
return 1;
}
memset(imgid, 0, sizeof(imgid));
memcpy(imgid, (char *)&ota_hdr_info.ota_file[0].img_ID, 4);
if(strcmp(imgid, "OTA1")) {
OTA_LOG_E("OTA1 image id error.");
return 1;
}
memcpy(imgid, (char *)&ota_hdr_info.ota_file[1].img_ID, 4);
if(strcmp(imgid, "OTA2")) {
OTA_LOG_E("OTA2 image id error.");
return 1;
}
if(ota_hdr_info.ota_file[0].checksum == 0) {
OTA_LOG_E("OTA1 checksum is zaro.");
return 1;
}
if(ota_hdr_info.ota_file[1].checksum == 0) {
OTA_LOG_E("OTA2 checksum is zaro.");
return 1;
}
return 0;
}
static int hal_verify_ota_checksum(uint8_t crc_partition_idx, uint32_t crc_len)
{
uint8_t *f_data;
ota_crc16_ctx ctx;
uint16_t ota_crc;
uint32_t i = 0, j = 0, len = 0, checksum = 0;
ota_crc16_final(&contex, &ota_info.ota_crc);//download crc
if(ota_info.ota_crc == 0) {
OTA_LOG_E("crc is zaro.");
return -1;
}
f_data = (uint8_t *)aos_malloc(0x1000);
if(f_data == NULL) {
OTA_LOG_E("hal_ota_crc16_compute malloc fail.");
return -1;
}
_off_set = 0;
ota_crc16_init(&ctx);
while(i < crc_len) {
if((0x1000 + i) < crc_len) {
len = 0x1000;
}
else {
len = crc_len - i;
}
hal_flash_read(crc_partition_idx, &_off_set, f_data, len);
/*update checksum*/
for(j = 0; j < len; j++) {
checksum += f_data[j];
}
/*update crc16*/
ota_crc16_update(&ctx, f_data, len);
i += len;
}
ota_crc16_final(&ctx, &ota_crc);
if(f_data) {
aos_free(f_data);
}
/*verify crc*/
if(ota_info.ota_crc != ota_crc) {
OTA_LOG_E("crc check error: download_crc=0x%x, comput_crc=0x%x.", ota_info.ota_crc, ota_crc);
return -1;
}
/*verify checksum*/
if(ota_hdr_info.ota_file[ota_index].checksum != checksum) {
OTA_LOG_E("checksum error: gen_chcksum=0x%x, comput_checksum=0x%x.",
ota_hdr_info.ota_file[ota_index].checksum, checksum);
return -1;
}
return 0;
}
static int ota_init(void *something)
{
ota_boot_param_t *param = (ota_boot_param_t *)something;
uint32_t offset = 0, delta = 0;
hal_logic_partition_t *partition_info;
if(param == NULL) {
return;
}
offset = param->off_bp;
hal_flash_dis_secure(0, 0, 0);//disable flash protect
hal_get_ota_index();
if(offset == 0) {
OTA_LOG_I("ota start :%d off:%d", ota_index, offset);
if(ota_index == OTA_IMAGE_A) {
partition_info = hal_flash_get_info(HAL_PARTITION_APPLICATION);
hal_flash_erase(HAL_PARTITION_APPLICATION, 0, partition_info->partition_length);
}
else {
partition_info = hal_flash_get_info(HAL_PARTITION_OTA_TEMP);
hal_flash_erase(HAL_PARTITION_OTA_TEMP, 0, partition_info->partition_length);
}
_off_set = 0;
ota_hdr_check = 0;
memset(&ota_info, 0, sizeof(ota_info));
memset(&ota_hdr_info, 0, sizeof(ota_hdr_info));
ota_crc16_init(&contex);
}
else {
OTA_LOG_I("header:%d off:%d", ota_hdr_check, offset);
ota_info.ota_len = offset;
ota_info.ota_crc = 0;
if(hal_get_ota_hdr()) {
OTA_LOG_E("get ota header fail");
return -1;
}
if(offset < sizeof(ota_hdr_t)) {
ota_hdr_check = 0;
}
else {
OTA_LOG_I("verfiy header");
ota_hdr_check = hal_verify_ota_head();
if(ota_hdr_check == 0) {
if(offset < ota_hdr_info.ota_file[1].img_offset) {
delta = offset - sizeof(ota_hdr_t);
if(ota_index == OTA_IMAGE_A) {
_off_set = delta;
}
}
else {
delta = offset - ota_hdr_info.ota_file[1].img_offset;
if(ota_index == OTA_IMAGE_B) {
_off_set = delta;
}
}
}
else {
OTA_LOG_E("check ota header error.");
return -1;
}
}
contex.crc = hal_ota_get_crc16();
}
OTA_LOG_I("ota init over");
return 0;
}
static int ota_read(int* off, char* out_buf, int out_buf_len)
{
if(ota_index == OTA_IMAGE_A) {
hal_flash_read(HAL_PARTITION_APPLICATION, off, out_buf, out_buf_len);
}
else {
hal_flash_read(HAL_PARTITION_OTA_TEMP, off, out_buf, out_buf_len);
}
return 0;
}
static int ota_write(int* off, char* in_buf, int in_buf_len)
{
uint32_t offset = 0;
if(ota_hdr_check) {
OTA_LOG_E("check ota header fail.");
return -1;
}
else {
/*OTA_LOG_I(".");*/
}
if(ota_info.ota_len < sizeof(ota_hdr_t)) {
OTA_LOG_I("ota header w check:%d", ota_hdr_check);
offset = sizeof(ota_hdr_t) - ota_info.ota_len;
if(in_buf_len < offset) {
memcpy((uint8_t *)&ota_hdr_info + ota_info.ota_len, in_buf, in_buf_len);
}
else {
memcpy((uint8_t *)&ota_hdr_info + ota_info.ota_len, in_buf, offset);
ota_hdr_check = hal_verify_ota_head();
if(ota_hdr_check == 0 && ota_index == OTA_IMAGE_A) {
ota_crc16_update(&contex, in_buf + offset, in_buf_len - offset);
hal_flash_write(HAL_PARTITION_APPLICATION, &_off_set, in_buf + offset, in_buf_len - offset);
}
}
}
else {
if(ota_index == OTA_IMAGE_A) {
if(ota_info.ota_len + in_buf_len < ota_hdr_info.ota_file[1].img_offset) {
ota_crc16_update(&contex, in_buf, in_buf_len);
hal_flash_write(HAL_PARTITION_APPLICATION, &_off_set, in_buf, in_buf_len);
}
else {
if(ota_info.ota_len < ota_hdr_info.ota_file[1].img_offset) {
offset = ota_hdr_info.ota_file[1].img_offset - ota_info.ota_len;
ota_crc16_update(&contex, in_buf, offset);
hal_flash_write(HAL_PARTITION_APPLICATION, &_off_set, in_buf, offset);
}
}
}
else {
if(ota_info.ota_len > ota_hdr_info.ota_file[1].img_offset) {
ota_crc16_update(&contex, in_buf, in_buf_len);
hal_flash_write(HAL_PARTITION_OTA_TEMP, &_off_set, in_buf, in_buf_len);
}
else {
if(ota_info.ota_len + in_buf_len > ota_hdr_info.ota_file[1].img_offset) {
offset = ota_hdr_info.ota_file[1].img_offset - ota_info.ota_len;
ota_crc16_update(&contex, in_buf + offset, in_buf_len - offset);
hal_flash_write(HAL_PARTITION_OTA_TEMP, &_off_set, in_buf + offset, in_buf_len - offset);
}
}
}
}
ota_info.ota_len += in_buf_len;
return 0;
}
static int ota_boot(void *something)
{
int ret = 0;
uint32_t offset;
uint32_t crc_partition_idx, crc_len;
hal_logic_partition_t *partition_info;
ota_boot_param_t *param;
ota_hdl_t ota_hdl, ota_hdl_rb;
param = (ota_boot_param_t *)something;
if (param == NULL) {
OTA_LOG_E("finish type is null.");
return -1;
}
if(ota_hdr_check) {
OTA_LOG_E("check ota head fail.");
return -1;
}
if(param->res_type == OTA_FINISH) {
if(ota_index == OTA_IMAGE_A) {
crc_partition_idx = HAL_PARTITION_APPLICATION;
crc_len = ota_hdr_info.ota_file[0].img_len;
partition_info = hal_flash_get_info(HAL_PARTITION_APPLICATION);
}
else {
crc_partition_idx = HAL_PARTITION_OTA_TEMP;
crc_len = ota_hdr_info.ota_file[1].img_len;
partition_info = hal_flash_get_info(HAL_PARTITION_OTA_TEMP);
}
ret = hal_verify_ota_checksum(crc_partition_idx, crc_len);
if(ret) {
return -1;
}
offset = 0x00;
hal_flash_erase(HAL_PARTITION_PARAMETER_1, offset, sizeof(ota_hdl));
offset = 0x00;
memset(&ota_hdl, 0, sizeof(ota_hdl_t));
ota_hdl.dst_adr = partition_info->partition_start_addr;
ota_hdl.upg_flag = OTA_PINGPONG_FLAG;
hal_flash_write(HAL_PARTITION_PARAMETER_1, &offset, (const void *)&ota_hdl, sizeof(ota_hdl));
offset = 0x00;
memset(&ota_hdl_rb, 0, sizeof(ota_hdl_t));
hal_flash_read(HAL_PARTITION_PARAMETER_1, &offset, &ota_hdl_rb, sizeof(ota_hdl_rb));
if(memcmp(&ota_hdl, &ota_hdl_rb, sizeof(ota_hdl_t)) != 0) {
OTA_LOG_I("write boot address fail.\r\n");
return -1;
}
}
else {
ret = hal_ota_save_hdr();
if(ret) {
OTA_LOG_E("save ota header fail.");
return -1;
}
hal_ota_save_crc16(contex.crc);
}
hal_reboot();
return ret;
}
#else
static int hal_ota_switch_to_new_fw(void)
{
hal_logic_partition_t *partition_info;
uint32_t offset;
ota_hdl_t ota_hdl, ota_hdl_rb;
offset = 0x00;
hal_flash_erase(HAL_PARTITION_PARAMETER_1, offset, sizeof(ota_hdl_t));
offset = 0x00;
memset(&ota_hdl, 0, sizeof(ota_hdl_t));
partition_info = hal_flash_get_info(HAL_PARTITION_APPLICATION);
ota_hdl.dst_adr = partition_info->partition_start_addr;
partition_info = hal_flash_get_info(HAL_PARTITION_OTA_TEMP);
ota_hdl.src_adr = partition_info->partition_start_addr;
ota_hdl.size = ota_info.ota_len;
ota_hdl.crc = ota_info.ota_crc;
ota_hdl.upg_flag = OTA_UPG_FLAG;
hal_flash_write(HAL_PARTITION_PARAMETER_1, &offset, (const void *)&ota_hdl, sizeof(ota_hdl_t));
offset = 0x00;
memset(&ota_hdl_rb, 0, sizeof(ota_hdl_t));
hal_flash_read(HAL_PARTITION_PARAMETER_1, &offset, &ota_hdl_rb, sizeof(ota_hdl_t));
if(memcmp(&ota_hdl, &ota_hdl_rb, sizeof(ota_hdl_t)) != 0) {
OTA_LOG_I("OTA header compare failed.\r\n");
return -1;
}
/* reboot */
hal_reboot();
return 0;
}
static int ota_init(void *something)
{
ota_boot_param_t *param = (ota_boot_param_t *)something;
if(param == NULL) {
return -1;
}
hal_logic_partition_t *part_info = hal_flash_get_info(HAL_PARTITION_OTA_TEMP);
if(part_info->partition_length < param->len || param->len == 0) {
return -1;
}
ota_info.ota_len = param->off_bp;
hal_flash_dis_secure(0, 0, 0);//disable flash protect
if(param->off_bp == 0) {
hal_flash_erase(HAL_PARTITION_OTA_TEMP, 0, part_info->partition_length);
ota_crc16_init(&contex);
}
else {
contex.crc = hal_ota_get_crc16();
OTA_LOG_I("--------get crc16 context.crc=%d!--------\n", contex.crc);
}
return 0;
}
static int ota_write(int *off_set, char *in_buf , int in_buf_len)
{
int ret = 0;
if(ota_info.ota_len == 0) {
_off_set = 0;
ota_crc16_init(&contex);
memset(&ota_info, 0, sizeof(ota_info));
}
ota_crc16_update(&contex, in_buf, in_buf_len);
ret = hal_flash_write(HAL_PARTITION_OTA_TEMP, &_off_set, in_buf, in_buf_len);
ota_info.ota_len += in_buf_len;
return ret;
}
static int ota_read(int *off_set, char *out_buf , int out_buf_len)
{
hal_flash_read(HAL_PARTITION_OTA_TEMP, off_set, out_buf, out_buf_len);
return 0;
}
static int ota_boot(void *something)
{
ota_boot_param_t *param = (ota_boot_param_t *)something;
if(param == NULL) {
return -1;
}
if(param->res_type == OTA_FINISH) {
ota_crc16_final(&contex, &ota_info.ota_crc);
OTA_LOG_I("beken set boot\n");
hal_ota_switch_to_new_fw();
}
else if(param->res_type == OTA_BREAKPOINT) {
OTA_LOG_I("-------save bp crc=%d--------------\n", contex.crc);
hal_ota_save_crc16(contex.crc);
}
return 0;
}
#endif
static uint16_t hal_ota_get_crc16(void)
{
int len = 2;
uint16_t crc16 = 0;
aos_kv_get(KV_HAL_OTA_CRC16, &crc16, &len);
return crc16;
}
static void hal_ota_save_crc16(uint16_t crc16)
{
aos_kv_set(KV_HAL_OTA_CRC16, &crc16, 2, 1);
}
static int ota_rollback(void *something)
{
int offset = 0x00;
int param_part = HAL_PARTITION_PARAMETER_1;
ota_boot_param_t param_w, param_r;
memset(&param_w, 0, sizeof(ota_boot_param_t));
hal_flash_read(param_part, (uint32_t*)&offset, &param_w, sizeof(ota_boot_param_t));
if((param_w.boot_count != 0) && (param_w.boot_count != 0xff)) {
ota_crc16_ctx ctx1;
unsigned short crc;
param_w.upg_flag = 0;
param_w.boot_count = 0; /*Clear bootcount to avoid rollback*/
ota_crc16_init(&ctx1);
ota_crc16_update(&ctx1, &param_w, sizeof(ota_boot_param_t) - sizeof(unsigned short));
ota_crc16_final(&ctx1, &crc);
param_w.param_crc = crc;
offset = 0x00;
hal_flash_erase(param_part, offset, sizeof(ota_boot_param_t));
offset = 0x00;
hal_flash_write(param_part, (uint32_t*)&offset, &param_w, sizeof(ota_boot_param_t));
offset = 0x00;
memset(&param_r, 0, sizeof(ota_boot_param_t));
hal_flash_read(param_part, (uint32_t*)&offset, &param_r, sizeof(ota_boot_param_t));
if(memcmp(&param_w, &param_r, sizeof(ota_boot_param_t)) != 0) {
OTA_LOG_E("rollback failed\n");
return -1;
}
}
return 0;
}
const char *aos_get_app_version(void);
static const char *ota_get_version(unsigned char dev_type)
{
if(dev_type) {
return "v1.0.0-20180101-1000";//SYSINFO_APP_VERSION;
} else {
return aos_get_app_version();
}
}
ota_hal_module_t ota_hal_module = {
.init = ota_init,
.write = ota_write,
.read = ota_read,
.boot = ota_boot,
.rollback = ota_rollback,
.version = ota_get_version,
};

View file

@ -0,0 +1,153 @@
#include "esp_ota_ops.h"
#include "ota_log.h"
#include "ota_hal_plat.h"
#include <string.h>
#include <malloc.h>
#include "esp_spi_flash.h"
#include "rom/spi_flash.h"
#include "hal/soc/flash.h"
static esp_partition_t operate_partition;
static esp_ota_handle_t out_handle;
static esp_err_t esp_write_error;
extern void esp_restart(void);
bool esp_ota_prepare()
{
esp_err_t err;
const esp_partition_t *esp_current_partition = esp_ota_get_boot_partition();
if (esp_current_partition == NULL) {
OTA_LOG_E("Got null partition.");
return false;
}
if (esp_current_partition->type != ESP_PARTITION_TYPE_APP) {
OTA_LOG_E("Err part type");
return false;
}
esp_partition_t find_partition;
/*choose which OTA image should we write to*/
switch (esp_current_partition->subtype) {
case ESP_PARTITION_SUBTYPE_APP_FACTORY:
find_partition.subtype = ESP_PARTITION_SUBTYPE_APP_OTA_0;
break;
case ESP_PARTITION_SUBTYPE_APP_OTA_0:
find_partition.subtype = ESP_PARTITION_SUBTYPE_APP_OTA_1;
break;
case ESP_PARTITION_SUBTYPE_APP_OTA_1:
find_partition.subtype = ESP_PARTITION_SUBTYPE_APP_OTA_0;
break;
default:
find_partition.subtype = ESP_PARTITION_SUBTYPE_APP_OTA_0;
break;
}
find_partition.type = ESP_PARTITION_TYPE_APP;
const esp_partition_t *partition = esp_partition_find_first(find_partition.type, find_partition.subtype, NULL);
assert(partition != NULL);
memset(&operate_partition, 0, sizeof(esp_partition_t));
OTA_LOG_I("ota_begin part type 0x%x sub:0x%x addr:0x%x size:0x%x label:%s encry:0x%x\n", partition->type, partition->subtype, partition->address, partition->size, partition->label, partition->encrypted);
esp_write_error = ESP_OK;
err = esp_ota_begin(partition, OTA_SIZE_UNKNOWN, &out_handle);
if (err != ESP_OK) {
OTA_LOG_E("begin err=0x%x!", err);
return false;
} else {
memcpy(&operate_partition, partition, sizeof(esp_partition_t));
OTA_LOG_I("ota init OK");
return true;
}
return false;
}
static int ota_init(void *something)
{
ota_boot_param_t *param = (ota_boot_param_t *)something;
uint32_t offset = param->off_bp;
OTA_LOG_I("ota_init off:0x%x \n",offset);
if(offset==0) {
/* prepare to os update */
if (esp_ota_prepare() != true) {
return -1;
}
}
return 0;
}
static int ota_write(int* off, char* buf ,int buf_len)
{
esp_err_t err = ESP_OK;
err = esp_ota_write(out_handle, (const void *)buf, (size_t)buf_len);
if (err != ESP_OK) {
esp_write_error = err;
OTA_LOG_E("write err=%x", err);
return -1;
}
return 0;
}
static int ota_boot(void *something)
{
esp_err_t err = ESP_OK;
ota_boot_param_t *param = (ota_boot_param_t *)something;
if (param == NULL) {
return -1;
}
if (param->res_type == OTA_FINISH) {
if (esp_ota_end(out_handle) != ESP_OK) {
OTA_LOG_E("end failed!");
return -1;
}
if(esp_write_error ) {
OTA_LOG_E("write_error %d!",esp_write_error);
return -1;
}
err = esp_ota_set_boot_partition(&operate_partition);
if (err != ESP_OK) {
OTA_LOG_E("set part failed! err=0x%x", err);
return -1;
}
OTA_LOG_I("restart system!");
esp_restart();
}
else if (param->res_type==OTA_BREAKPOINT) {
}
else {
return -1;
}
return 0;
}
static int ota_read(int* off, char* out_buf, int out_buf_len)
{
return hal_flash_read(HAL_PARTITION_OTA_TEMP, (uint32_t*)off, out_buf, out_buf_len);
}
static int ota_rollback(void *something)
{
return 0;
}
const char *aos_get_app_version(void);
static const char *ota_get_version(unsigned char dev_type)
{
if(dev_type) {
return "v1.0.0-20180101-1000";//SYSINFO_APP_VERSION;
} else {
return SYSINFO_APP_VERSION;
}
}
ota_hal_module_t ota_hal_module = {
.init = ota_init,
.write = ota_write,
.read = ota_read,
.boot = ota_boot,
.rollback = ota_rollback,
.version = ota_get_version,
};

View file

@ -0,0 +1,216 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include "ota_log.h"
#include "ota_hal_plat.h"
static FILE* ota_fd = NULL;
static int offset = 0;
#if defined PLAT_RASPBERRY /*raspberry*/
static int boot_part = 2;
static int boot_part_in = 3;
#define OTA_IMAGE_FILE "/dev/mmcblk0p"
#else
static int boot_part = 4;
static int boot_part_in = 5;
#define OTA_IMAGE_FILE "rkflash0p"
#endif
int getCmdVal(const char *cmd)
{
char ps[1024]={0};
FILE *ptr = NULL;
char *sstr = NULL;
if((ptr=popen(cmd, "r"))!=NULL)
{
while(fgets(ps, 1024, ptr)!=NULL)
{
}
pclose(ptr);
ptr = NULL;
OTA_LOG_I("ret:%s\n",ps);
}
else
{
OTA_LOG_E("popen %s error\n", ps);
}
sstr = strstr(ps, "mender_boot_part=");
if (sstr) {
sscanf(sstr, "%*[^ ]%d", &boot_part);
OTA_LOG_I("mender_boot_part:%d \n", boot_part);
}
#if defined PLAT_RASPBERRY
if(boot_part == 3) {
boot_part_in = 2;
} else {
boot_part_in = 3;
}
#else
if(boot_part == 5) {
boot_part_in = 4;
} else {
boot_part_in = 5;
}
#endif
OTA_LOG_I("ota init:%d boot_part_in:%d\n", boot_part,boot_part_in);
return 0;
}
static int ota_init(void *something)
{
char path[64] = {0};
int ret = 0;
ota_boot_param_t * param = (ota_boot_param_t*)something;
getCmdVal("fw_printenv mender_boot_part");
snprintf(path,sizeof(path),"%s%d",OTA_IMAGE_FILE,boot_part_in);
offset= param->off_bp;
OTA_LOG_I("init off: %d size:0x%x \n", offset,param->len);
if(param->len == 0) {
OTA_LOG_E("ota init size error:");
return -1;
}
#if !defined PLAT_RASPBERRY
if(param->len > 0x3100000){
OTA_LOG_E("firmware size is too big.\n");
return -1;
}
#endif
if(offset!=0){ /*breakpoint resume*/
if(ota_fd==NULL){
if((ota_fd = fopen(path, "a+"))==NULL) {
OTA_LOG_E("init err: %d, %s\n", ret, strerror(errno));
return -1;
}
if(ftell(ota_fd)<=0){
OTA_LOG_E("init error: %d, %s\n", ret, strerror(errno));
return -1;
}
}
}
return ret;
}
int ota_write(int *off_set, char *in_buf, int in_buf_len)
{
int ret = 0;
if(ota_fd == NULL)
{
char path[64] = {0};
snprintf(path,sizeof(path),"%s%d",OTA_IMAGE_FILE,boot_part_in);
ota_fd = fopen(path, "w");
}
ret = fwrite(in_buf, in_buf_len, 1, ota_fd);
if (ret < 0) {
OTA_LOG_E("write err: %d, %d ,%s\n", ret, in_buf_len,
strerror(errno));
return -1;
}
return 0;
}
static int ota_read(int *off_set, char *out_buf, int out_buf_len)
{
if (ota_fd != NULL) {
fflush(ota_fd);
fclose(ota_fd);
ota_fd = NULL;
}
int ret = 0;
if(ota_fd == NULL)
{
char path[64] = {0};
snprintf(path,sizeof(path),"%s%d",OTA_IMAGE_FILE,boot_part_in);
ota_fd = fopen(path, "r");
}
ret = fseek(ota_fd, *off_set, SEEK_SET);
ret = fread(out_buf, out_buf_len, 1, ota_fd);
if (ret != 1) {
OTA_LOG_E("read err: %d, %d ,%s\n", ret, out_buf_len, strerror(errno));
return -1;
}
fclose(ota_fd);
ota_fd = NULL;
*off_set += out_buf_len;
return 0;
}
static int ota_boot(void *something)
{
int ret = 0;
if (ota_fd != NULL) {
fflush(ota_fd);
fclose(ota_fd);
ota_fd = NULL;
}
char cmd1[64] = { 0 };
ota_boot_param_t *param = (ota_boot_param_t *)something;
if (param==NULL){
OTA_LOG_E("boot err\n");
return -1;
}
if (param->res_type==OTA_FINISH) {
sprintf(cmd1, "fw_setenv mender_boot_part %d",boot_part_in);
ret = system(cmd1);
if(ret < 0) {
OTA_LOG_E("set boot part err.\n");
return -1;
}
OTA_LOG_E("boot:%s \n",cmd1);
memset(cmd1,0x00,sizeof(cmd1));
sprintf(cmd1, "fw_setenv upgrade_available 1");
ret = system(cmd1);
if(ret < 0) {
OTA_LOG_E("upgrade_available err\n");
return -1;
}
OTA_LOG_E("boot:%s \n",cmd1);
memset(cmd1,0x00,sizeof(cmd1));
sprintf(cmd1, "sync;reboot");
ret = system(cmd1);
if(ret < 0) {
OTA_LOG_E("sync err\n");
return -1;
}
}
OTA_LOG_I("Rebooting and updating FLASH now....\n");
return 0;
}
static int ota_rollback(void *something)
{
char cmd1[128] = {0};
int ret = 0;
sprintf(cmd1, "fw_setenv upgrade_available 0; fw_setenv bootcount 0; sync");
ret = system(cmd1);
if(ret < 0) {
OTA_LOG_E("roll system fail .");
}
OTA_LOG_I("roll:%s \n",cmd1);
return 0;
}
const char *aos_get_app_version(void);
static const char *ota_get_version(unsigned char dev_type)
{
if(dev_type) {
return "v1.0.0-20180101-1000";//SYSINFO_APP_VERSION;
} else {
return aos_get_app_version();
}
}
ota_hal_module_t ota_hal_module = {
.init = ota_init,
.write = ota_write,
.read = ota_read,
.boot = ota_boot,
.rollback = ota_rollback,
.version = ota_get_version,
};

View file

@ -0,0 +1,87 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include "aos/kernel.h"
#include "aos/kv.h"
#include "ota_hal_plat.h"
#include "ota_hal_os.h"
#include "ota_log.h"
#include "ota_verify.h"
#include "ota_hal_mcu.h"
#define OTA_CRC16 "ota_file_crc16"
static unsigned int wdata_len = 0;
static ota_crc16_ctx ctx = {0};
static unsigned short ota_get_crc16(void)
{
int len = 2;
unsigned short crc16=0;
aos_kv_get(OTA_CRC16, &crc16, &len);
return crc16;
}
static void ota_set_crc16(unsigned short crc16)
{
aos_kv_set(OTA_CRC16, &crc16, 2, 1);
}
int ota_mcu_init(void *something)
{
int ret = 0;
ota_boot_param_t *param = (ota_boot_param_t *)something;
param->off_bp = ota_get_break_point();
if (param->off_bp >= param->len) {
param->off_bp = 0;
}
wdata_len = param->off_bp;
if (param->off_bp == 0) {
ota_crc16_init(&ctx);
} else {
ctx.crc = ota_get_crc16();
}
OTA_LOG_I("ota mcu init off:0x%08x len:%d crc:0x%04x\n", param->off_bp, param->len, ctx.crc);
return ret;
}
int ota_mcu_write(int* off, char* in_buf ,int in_buf_len)
{
int ret = 0;
if (off != NULL) {
OTA_LOG_I("recv MCU data off:%d", *off);
}
/* for only test */
wdata_len = wdata_len + in_buf_len;
OTA_LOG_I("recv MCU data wdata_len:%d, in_buf_len:%d", wdata_len, in_buf_len);
ota_crc16_update(&ctx, in_buf, in_buf_len);
return ret;
}
int ota_mcu_boot(void *something)
{
int ret = 0;
ota_boot_param_t *param = (ota_boot_param_t *)something;
if (param == NULL) {
ret = OTA_REBOOT_FAIL;
return ret;
}
if (param->res_type == OTA_FINISH) {
ota_crc16_final(&ctx, &param->crc);
ota_set_break_point(0);
ota_msleep(1500);
ota_reboot();
} else if(param->res_type == OTA_BREAKPOINT) {
OTA_LOG_I("save bp crc:0x%04x", ctx.crc);
ota_set_crc16(ctx.crc);
}
return ret;
}

View file

@ -0,0 +1,21 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef MCU_HAL_OTA_H
#define MCU_HAL_OTA_H
#ifdef __cplusplus
extern "C" {
#endif
int ota_mcu_init(void *something);
int ota_mcu_write(int* off, char* in_buf ,int in_buf_len);
int ota_mcu_boot(void *something);
#ifdef __cplusplus
}
#endif
#endif /* MCU_HAL_OTA_H */

View file

@ -0,0 +1,154 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include "ota_log.h"
#include "ota_hal_plat.h"
static ota_hal_module_t *ota_module = NULL;
void ota_hal_register_module(ota_hal_module_t *module)
{
ota_module = module;
}
int ota_hal_init(void *something)
{
#ifdef OTA_BOOT_PAPA_COMPATIBAL
struct {
unsigned int dst_adr;
unsigned int src_adr;
unsigned int len;
unsigned short crc;
unsigned int upg_flag;
unsigned char boot_count;
unsigned int rec_size;
unsigned int splict_size;
int off_bp; /*Break point offset*/
OTA_RES_TYPE_E res_type; /*result type: OTA_FINISH, OTA_BREAKPOINT*/
unsigned short param_crc; /*Parameter crc*/
} __attribute__((packed)) boot_para_more;
ota_boot_param_t *boot_para_less = (ota_boot_param_t *)something;
boot_para_more.dst_adr = boot_para_less->dst_adr ;
boot_para_more.src_adr = boot_para_less->src_adr ;
boot_para_more.len = boot_para_less->len ;
boot_para_more.crc = boot_para_less->crc ;
boot_para_more.upg_flag = boot_para_less->upg_flag ;
boot_para_more.boot_count = boot_para_less->boot_count ;
boot_para_more.rec_size = 0 ;
boot_para_more.splict_size = boot_para_less->splict_size;
boot_para_more.off_bp = boot_para_less->off_bp ;
boot_para_more.res_type = boot_para_less->res_type ;
boot_para_more.param_crc = boot_para_less->param_crc ;
something = (void *)&boot_para_more;
#endif
if (ota_module == NULL) {
return -1;
}
if (ota_module != NULL && ota_module->init != NULL) {
return ota_module->init(something);
}
return 0;
}
int ota_hal_write(int *off_set, char *in_buf , int in_buf_len)
{
if (ota_module == NULL) {
return -1;
}
if (ota_module != NULL && ota_module->write != NULL) {
return ota_module->write(off_set, in_buf, in_buf_len);
}
return 0;
}
int ota_hal_read(int *off_set, char *out_buf, int out_buf_len)
{
if (ota_module == NULL) {
return -1;
}
if (ota_module != NULL && ota_module->read != NULL) {
return ota_module->read(off_set, out_buf, out_buf_len);
}
return 0;
}
int ota_hal_boot(void *something)
{
#ifdef OTA_BOOT_PAPA_COMPATIBAL
struct {
unsigned int dst_adr;
unsigned int src_adr;
unsigned int len;
unsigned short crc;
unsigned int upg_flag;
unsigned char boot_count;
unsigned int rec_size;
unsigned int splict_size;
int off_bp; /*Break point offset*/
OTA_RES_TYPE_E res_type; /*result type: OTA_FINISH, OTA_BREAKPOINT*/
unsigned short param_crc; /*Parameter crc*/
} __attribute__((packed)) boot_para_more;
ota_boot_param_t *boot_para_less = (ota_boot_param_t *)something;
boot_para_more.dst_adr = boot_para_less->dst_adr ;
boot_para_more.src_adr = boot_para_less->src_adr ;
boot_para_more.len = boot_para_less->len ;
boot_para_more.crc = boot_para_less->crc ;
boot_para_more.upg_flag = boot_para_less->upg_flag ;
boot_para_more.boot_count = boot_para_less->boot_count ;
boot_para_more.rec_size = 0 ;
boot_para_more.splict_size = boot_para_less->splict_size;
boot_para_more.off_bp = boot_para_less->off_bp ;
boot_para_more.res_type = boot_para_less->res_type ;
boot_para_more.param_crc = boot_para_less->param_crc ;
something = (void *)&boot_para_more;
#endif
if (ota_module == NULL) {
return -1;
}
if (ota_module != NULL && ota_module->boot != NULL) {
return ota_module->boot(something);
}
return 0;
}
int ota_hal_rollback(void *something)
{
if (ota_module == NULL) {
return -1;
}
if (ota_module != NULL && ota_module->rollback != NULL) {
return ota_module->rollback(something);
}
return 0;
}
const char *ota_hal_get_version(unsigned char dev_type)
{
if (ota_module == NULL) {
return NULL;
}
if (ota_module != NULL && ota_module->version != NULL) {
return ota_module->version(dev_type);
}
return NULL;
}

View file

@ -0,0 +1,843 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <errno.h>
#include <sys/time.h>
#include <time.h>
#include <signal.h>
#include <string.h>
#include "ota_hal_os.h"
#include "ota_log.h"
#if !defined (AOS_OTA_RSA)
#if defined AOS_OTA_ITLS
#include "itls/sha256.h"
#include "itls/md5.h"
#else
#include "mbedtls/sha256.h"
#include "mbedtls/md5.h"
#endif
#endif
#if (OTA_SIGNAL_CHANNEL) == 1
#include "iot_export.h"
#include "iot_import.h"
#include "iot_export_coap.h"
#endif
#if (OTA_SIGNAL_CHANNEL) == 2
#include "iot_import.h"
#endif
#ifdef OTA_LINUX
#include <unistd.h>
#include <semaphore.h>
#include <pthread.h>
#include <sys/reboot.h>
#else
#include "aos/kernel.h"
#include "aos/kv.h"
#endif
/*Memory realloc*/
void *ota_realloc(void *ptr, int size)
{
#if defined OTA_WITH_LINKKIT
return HAL_Realloc(ptr, size);
#elif !defined OTA_LINUX
return aos_realloc(ptr, size);
#else
return realloc(ptr, size);
#endif
}
/*Memory calloc*/
void *ota_calloc(int n, int size)
{
#if defined OTA_WITH_LINKKIT
return HAL_Malloc(size);
#elif !defined OTA_LINUX
return aos_calloc(n, size);
#else
return calloc(n, size);
#endif
}
/*Reboot*/
void ota_reboot(void)
{
#if defined OTA_WITH_LINKKIT
HAL_Reboot();
#elif !defined OTA_LINUX
aos_reboot();
#else
reboot(0x1234567);
#endif
}
/*Memory malloc*/
void *ota_malloc(int size)
{
#if defined OTA_WITH_LINKKIT
return HAL_Malloc(size);
#elif !defined OTA_LINUX
return aos_malloc(size);
#else
return malloc(size);
#endif
}
/*Memory free*/
void ota_free(void *ptr)
{
#if defined OTA_WITH_LINKKIT
return HAL_Free(ptr);
#elif !defined OTA_LINUX
aos_free(ptr);
#else
free(ptr);
#endif
}
/*Semaphore init*/
void *ota_semaphore_create(void)
{
#if defined OTA_WITH_LINKKIT
return HAL_SemaphoreCreate();
#elif !defined OTA_LINUX
aos_sem_t *sem = (aos_sem_t *)ota_malloc(sizeof(aos_sem_t));
if (NULL == sem) {
return NULL;
}
if (0 != aos_sem_new(sem, 0)) {
ota_free(sem);
return NULL;
}
return sem;
#else
sem_t *sem = (sem_t *)ota_malloc(sizeof(sem_t));
if (NULL == sem) {
return NULL;
}
if (0 != sem_init(sem, 0, 0)) {
ota_free(sem);
return NULL;
}
return sem;
#endif
}
/*Semaphore wait*/
int ota_semaphore_wait(void *sem, int ms)
{
#if defined OTA_WITH_LINKKIT
return HAL_SemaphoreWait(sem, ms);
#elif !defined OTA_LINUX
return aos_sem_wait((aos_sem_t *)sem, ms);
#else
if ((~0) == ms) {
sem_wait(sem);
return 0;
} else {
struct timespec ts;
int s;
/* Restart if interrupted by handler */
do {
if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
return -1;
}
s = 0;
ts.tv_nsec += (ms % 1000) * 1000000;
if (ts.tv_nsec >= 1000000000) {
ts.tv_nsec -= 1000000000;
s = 1;
}
ts.tv_sec += ms / 1000 + s;
} while (((s = sem_timedwait(sem, &ts)) != 0) && errno == EINTR);
return (s == 0) ? 0 : -1;
}
return 0;
#endif
}
/*Semaphore post*/
void ota_semaphore_post(void *sem)
{
#if defined OTA_WITH_LINKKIT
return HAL_SemaphorePost(sem);
#elif !defined OTA_LINUX
aos_sem_signal((aos_sem_t *)sem);
#else
sem_post((sem_t *)sem);
#endif
}
/*Semaphore destroy*/
void ota_semaphore_destroy(void *sem)
{
#if defined OTA_WITH_LINKKIT
return HAL_SemaphoreDestroy(sem);
#elif !defined OTA_LINUX
aos_sem_free((aos_sem_t *)sem);
aos_free(sem);
#else
sem_destroy((sem_t *)sem);
free(sem);
#endif
}
/*Sleep ms*/
void ota_msleep(int ms)
{
#if defined OTA_WITH_LINKKIT
return HAL_SleepMs(ms);
#elif !defined OTA_LINUX
aos_msleep(ms);
#else
usleep(1000 * ms);
#endif
}
#if defined OTA_WITH_LINKKIT
;
#elif !defined OTA_LINUX
typedef struct
{
aos_task_t task;
int detached;
void * arg;
void *(*routine)(void *arg);
} task_context_t;
static void task_wrapper(void *arg)
{
task_context_t *task = arg;
task->routine(task->arg);
if (task) {
aos_free(task);
task = NULL;
}
}
#endif
#define OTA_THREAD_NAME "OTA_Thread"
#if defined AOS_OTA_TLS
#define OTA_THREAD_SIZE (8 * 1024)
#else
#define OTA_THREAD_SIZE (4 * 1024)
#endif
#define OTA_THREAD_PRI 30
/*Thread create*/
int ota_thread_create(void **thread_handle, void *(*work_routine)(void *), void *arg, void *pm, int stack_size)
{
int ret = -1;
#if defined OTA_WITH_LINKKIT
hal_os_thread_param_t task_parms;
task_parms.stack_size = OTA_THREAD_SIZE;
task_parms.name = OTA_THREAD_NAME;
ret = HAL_ThreadCreate(thread_handle, work_routine, arg, &task_parms, 0);
#elif !defined OTA_LINUX
char * tname = OTA_THREAD_NAME;
if(stack_size <= 0) {
stack_size = OTA_THREAD_SIZE;
}
task_context_t *task = aos_malloc(sizeof(task_context_t));
if (!task) {
return -1;
}
memset(task, 0, sizeof(task_context_t));
task->arg = arg;
task->routine = work_routine;
ret = aos_task_new_ext(&task->task, tname, task_wrapper, task, stack_size, OTA_THREAD_PRI);
*thread_handle = (void *)task;
#else
ret = pthread_create((pthread_t *)thread_handle, NULL, work_routine, arg);
#endif
return ret;
}
/*Thread exit*/
void ota_thread_exit(void *thread)
{
#if defined OTA_WITH_LINKKIT
return HAL_ThreadDelete(thread);
#elif !defined OTA_LINUX
aos_task_exit(0);
#else
pthread_exit(0);
#endif
}
#if defined OTA_WITH_LINKKIT
/*KV set*/
int ota_kv_set(const char *key, const void *val, int len, int sync)
{
return HAL_Kv_Set(key, val, len, sync);
}
/*KV get*/
int ota_kv_get(const char *key, void *buffer, int *len)
{
return HAL_Kv_Get(key, buffer, len);
}
#elif !defined OTA_LINUX
/*KV set*/
int ota_kv_set(const char *key, const void *val, int len, int sync)
{
return aos_kv_set(key, val, len, sync);
}
/*KV get*/
int ota_kv_get(const char *key, void *buffer, int *len)
{
return aos_kv_get(key, buffer, len);
}
#else
#define KV_FILE_PATH "./uota.kv"
#define ITEM_MAX_KEY_LEN 128
#define ITEM_MAX_VAL_LEN 256
#define ITEM_LEN 512
typedef struct
{
int flag;
int val_len;
} kv_state_t;
typedef struct
{
char key[ITEM_MAX_KEY_LEN];
char val[ITEM_MAX_VAL_LEN];
kv_state_t state;
} kv_t;
static pthread_mutex_t mutex_kv = PTHREAD_MUTEX_INITIALIZER;
/* get file size and item num */
static int hal_fopen(FILE **fp, int *size, int *num)
{
/* create an file to save the kv */
if ((*fp = fopen(KV_FILE_PATH, "a+")) == NULL) {
OTA_LOG_E("open err:%s\n", strerror(errno));
return -1;
}
fseek(*fp, 0L, SEEK_END);
if ((*size = ftell(*fp)) % ITEM_LEN) {
fclose(*fp);
return -1;
}
*num = ftell(*fp) / ITEM_LEN;
fseek(*fp, 0L, SEEK_SET);
return 0;
}
/*KV set*/
int ota_kv_set(const char *key, const void *val, int len, int sync)
{
FILE *fp = NULL;
int file_size = 0, block_num = 0, ret = 0, cur_pos = 0;
kv_t kv_item;
int i;
/* check parameter */
if (key == NULL || val == NULL) {
return -1;
}
pthread_mutex_lock(&mutex_kv);
if (hal_fopen(&fp, &file_size, &block_num) != 0) {
goto ERR;
}
for (i = 0; i < block_num; i++) {
memset(&kv_item, 0, sizeof(kv_t));
cur_pos = ftell(fp);
/* read an kv item(512 bytes) from file */
if ((ret = fread(&kv_item, 1, ITEM_LEN, fp)) != ITEM_LEN) {
goto ERR;
}
/* key compared */
if (strcmp(kv_item.key, key) == 0) {
/* set value and write to file */
memset(kv_item.val, 0, ITEM_MAX_VAL_LEN);
memcpy(kv_item.val, val, len);
kv_item.state.val_len = len;
fseek(fp, cur_pos, SEEK_SET);
fwrite(&kv_item, 1, ITEM_LEN, fp);
goto END;
}
}
/* key not compared, append an kv to file */
memset(&kv_item, 0, sizeof(kv_t));
strcpy(kv_item.key, key);
memcpy(kv_item.val, val, len);
kv_item.state.val_len = len;
fseek(fp, 0L, SEEK_END);
fwrite(&kv_item, 1, ITEM_LEN, fp);
goto END;
ERR:
if (fp == NULL) {
pthread_mutex_unlock(&mutex_kv);
return -1;
}
OTA_LOG_E("read err:%s\n", strerror(errno));
fflush(fp);
fclose(fp);
pthread_mutex_unlock(&mutex_kv);
return -1;
END:
fflush(fp);
fclose(fp);
pthread_mutex_unlock(&mutex_kv);
return 0;
}
/*KV get*/
int ota_kv_get(const char *key, void *buffer, int *len)
{
FILE *fp = NULL;
int i;
/* read from file */
int file_size = 0, block_num = 0;
kv_t kv_item;
/* check parameter */
if (key == NULL || buffer == NULL || len == NULL) {
return -1;
}
pthread_mutex_lock(&mutex_kv);
if (hal_fopen(&fp, &file_size, &block_num) != 0) {
goto ERR;
}
for (i = 0; i < block_num; i++) {
memset(&kv_item, 0, sizeof(kv_t));
/* read an kv item(512 bytes) from file */
if (fread(&kv_item, 1, ITEM_LEN, fp) != ITEM_LEN) {
goto ERR;
}
/* key compared */
if (strcmp(kv_item.key, key) == 0) {
/* set value and write to file */
*len = kv_item.state.val_len;
memcpy(buffer, kv_item.val, *len);
goto END;
}
}
goto END;
ERR:
if (fp == NULL) {
pthread_mutex_unlock(&mutex_kv);
return -1;
}
OTA_LOG_E("read err:%s\n", strerror(errno));
fflush(fp);
fclose(fp);
pthread_mutex_unlock(&mutex_kv);
return -1;
END:
fflush(fp);
fclose(fp);
pthread_mutex_unlock(&mutex_kv);
return 0;
}
#endif /*Linux end*/
/*Socket API*/
void* ota_socket_connect(char *host, int port)
{
#ifdef OTA_WITH_LINKKIT
return (void*)HAL_TCP_Establish(host, port);
#else
return 0;
#endif
}
int ota_socket_send(void* fd, char *buf, int len)
{
#ifdef OTA_WITH_LINKKIT
return HAL_TCP_Write((uintptr_t)fd, buf, len, OTA_SSL_TIMEOUT);
#else
return 0;
#endif
}
int ota_socket_recv(void* fd, char *buf, int len)
{
#ifdef OTA_WITH_LINKKIT
return HAL_TCP_Read((uintptr_t)fd, buf, len, OTA_SSL_TIMEOUT);
#else
return 0;
#endif
}
void ota_socket_close(void* fd)
{
#ifdef OTA_WITH_LINKKIT
HAL_TCP_Destroy((uintptr_t)fd);
#endif
}
/*SSL connect*/
void *ota_ssl_connect(const char *host, unsigned short port, const char *ca_crt, int ca_crt_len)
{
#ifdef OTA_WITH_LINKKIT
return (void*)HAL_SSL_Establish(host, port, ca_crt, ca_crt_len);
#else
return 0;
#endif
}
/*SSL send*/
int ota_ssl_send(void *ssl, char *buf, int len)
{
#ifdef OTA_WITH_LINKKIT
return HAL_SSL_Write((uintptr_t)ssl, buf, len, OTA_SSL_TIMEOUT);
#else
return 0;
#endif
}
/*SSL recv*/
int ota_ssl_recv(void *ssl, char *buf, int len)
{
#ifdef OTA_WITH_LINKKIT
return HAL_SSL_Read((uintptr_t)ssl, buf, len, OTA_SSL_TIMEOUT);
#else
return 0;
#endif
}
#if !defined (AOS_OTA_RSA)
/*SHA256*/
extern void mbedtls_sha256_free(mbedtls_sha256_context* ctx);
extern void mbedtls_sha256_init(mbedtls_sha256_context*ctx);
extern void mbedtls_sha256_starts(mbedtls_sha256_context*ctx, int is224);
extern void mbedtls_sha256_update(mbedtls_sha256_context*ctx, const unsigned char *input, unsigned int ilen);
extern void mbedtls_sha256_finish(mbedtls_sha256_context*ctx, unsigned char output[32]);
void ota_sha256_free(ota_sha256_context *ctx)
{
mbedtls_sha256_free((mbedtls_sha256_context*)ctx);
}
void ota_sha256_init(ota_sha256_context *ctx)
{
mbedtls_sha256_init((mbedtls_sha256_context*)ctx);
}
void ota_sha256_starts(ota_sha256_context *ctx, int is224)
{
mbedtls_sha256_starts((mbedtls_sha256_context*)ctx, is224);
}
void ota_sha256_update(ota_sha256_context *ctx, const unsigned char *input, unsigned int ilen)
{
mbedtls_sha256_update((mbedtls_sha256_context*)ctx, input, ilen);
}
void ota_sha256_finish(ota_sha256_context *ctx, unsigned char output[32])
{
mbedtls_sha256_finish((mbedtls_sha256_context*)ctx, output);
}
/*MD5*/
extern void mbedtls_md5_free(mbedtls_md5_context*ctx);
extern void mbedtls_md5_init(mbedtls_md5_context*ctx);
extern void mbedtls_md5_starts(mbedtls_md5_context*ctx);
extern void mbedtls_md5_update(mbedtls_md5_context*ctx, const unsigned char *input, unsigned int ilen);
extern void mbedtls_md5_finish(mbedtls_md5_context*ctx, unsigned char output[32]);
void ota_md5_free(ota_md5_context *ctx)
{
mbedtls_md5_free((mbedtls_md5_context*)ctx);
}
void ota_md5_init(ota_md5_context *ctx)
{
mbedtls_md5_init((mbedtls_md5_context*)ctx);
}
void ota_md5_starts(ota_md5_context *ctx)
{
mbedtls_md5_starts((mbedtls_md5_context*)ctx);
}
void ota_md5_update(ota_md5_context *ctx, const unsigned char *input, unsigned int ilen)
{
mbedtls_md5_update((mbedtls_md5_context*)ctx, input, ilen);
}
void ota_md5_finish(ota_md5_context *ctx, unsigned char output[16])
{
mbedtls_md5_finish((mbedtls_md5_context*)ctx, output);
}
/*RSA*/
extern int ali_rsa_get_pubkey_size(unsigned int keybits, unsigned int *size);
extern int ali_rsa_init_pubkey(unsigned int keybits, const unsigned char *n, unsigned int n_size,
const unsigned char *e, unsigned int e_size, ota_rsa_pubkey_t *pubkey);
extern int ali_rsa_verify(const ota_rsa_pubkey_t *pub_key, const unsigned char *dig, unsigned int dig_size,
const unsigned char *sig, unsigned int sig_size, ota_rsa_padding_t padding, bool *p_result);
int ota_rsa_get_pubkey_size(unsigned int keybits, unsigned int *size)
{
return ali_rsa_get_pubkey_size(keybits, size);
}
int ota_rsa_init_pubkey(unsigned int keybits, const unsigned char *n, unsigned int n_size,
const unsigned char *e, unsigned int e_size, ota_rsa_pubkey_t *pubkey){
return ali_rsa_init_pubkey(keybits, n, n_size, e, e_size, pubkey);
}
int ota_rsa_verify(const ota_rsa_pubkey_t *pub_key, const unsigned char *dig, unsigned int dig_size,
const unsigned char *sig, unsigned int sig_size, ota_rsa_padding_t padding, bool *p_result)
{
return ali_rsa_verify(pub_key,dig,dig_size,sig,sig_size,padding,p_result);
}
#endif
static const unsigned char base64_dec_map[128] =
{
127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 62, 127, 127, 127, 63, 52, 53,
54, 55, 56, 57, 58, 59, 60, 61, 127, 127,
127, 64, 127, 127, 127, 0, 1, 2, 3, 4,
5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 127, 127, 127, 127, 127, 127, 26, 27, 28,
29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 127, 127, 127, 127, 127
};
int ota_base64_decode(const unsigned char *src, int slen, unsigned char *dst, int *dlen)
{
unsigned int i, n;
unsigned int j, x;
unsigned char *p;
for( i = n = j = 0; i < slen; i++ )
{
if( ( slen - i ) >= 2 &&
src[i] == '\r' && src[i + 1] == '\n' )
continue;
if( src[i] == '\n' )
continue;
if( src[i] == '=' && ++j > 2 )
return -1;
if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
return -1;
if( base64_dec_map[src[i]] < 64 && j != 0 )
return -1;
n++;
}
if( n == 0 )
return 0;
n = ( ( n * 6 ) + 7 ) >> 3;
n -= j;
if( dst == 0 || *dlen < n )
{
*dlen = n;
return -2;
}
for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
{
if( *src == '\r' || *src == '\n' )
continue;
j -= ( base64_dec_map[*src] == 64 );
x = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F );
if( ++n == 4 )
{
n = 0;
if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
if( j > 1 ) *p++ = (unsigned char)( x >> 8 );
if( j > 2 ) *p++ = (unsigned char)( x );
}
}
*dlen = p - dst;
return 0;
}
/*CRC16*/
static unsigned short update_crc16(unsigned short crcIn, unsigned char byte)
{
unsigned int crc = crcIn;
unsigned int in = byte | 0x100;
do {
crc <<= 1;
in <<= 1;
if (in & 0x100) {
++crc;
}
if (crc & 0x10000) {
crc ^= 0x1021;
}
} while (!(in & 0x10000));
return crc & 0xffffu;
}
void ota_crc16_init(ota_crc16_ctx *inCtx)
{
inCtx->crc = 0;
}
void ota_crc16_update(ota_crc16_ctx *inCtx, const void *inSrc, unsigned int inLen)
{
const unsigned char *src = (const unsigned char *) inSrc;
const unsigned char *srcEnd = src + inLen;
while ( src < srcEnd ) {
inCtx->crc = update_crc16(inCtx->crc, *src++);
}
}
void ota_crc16_final(ota_crc16_ctx *inCtx, unsigned short *outResult )
{
inCtx->crc = update_crc16(inCtx->crc, 0);
inCtx->crc = update_crc16(inCtx->crc, 0);
*outResult = inCtx->crc & 0xffffu;
}
/*MQTT API*/
int ota_hal_mqtt_publish(char *topic, int qos, void *data, int len)
{
#if (OTA_SIGNAL_CHANNEL) == 1
return IOT_MQTT_Publish_Simple(NULL, topic, qos, data, len);
#else
return 0;
#endif
}
int ota_hal_mqtt_subscribe(char *topic, void *cb, void *ctx)
{
#if (OTA_SIGNAL_CHANNEL) == 1
#ifdef MQTT_AUTO_SUBSCRIBE
return IOT_MQTT_Subscribe_Sync(NULL, topic, IOTX_MQTT_QOS3_SUB_LOCAL, cb, ctx, 1000);
#else
return IOT_MQTT_Subscribe_Sync(NULL, topic, IOTX_MQTT_QOS0, cb, ctx, 1000);
#endif
#else
return 0;
#endif
}
int ota_hal_mqtt_deinit(void)
{
#if (OTA_SIGNAL_CHANNEL) == 1
return IOT_MQTT_Destroy(NULL);
#else
return 0;
#endif
}
int ota_hal_mqtt_init(void)
{
#if (OTA_SIGNAL_CHANNEL) == 1
return (IOT_MQTT_Construct(NULL) == NULL)? -1 : 0;
#else
return 0;
#endif
}
/*CoAP API*/
int ota_coap_send(void *p_context, char *p_path, void *p_message)
{
#if (OTA_SIGNAL_CHANNEL) == 2
return IOT_CoAP_SendMessage(p_context, p_path, p_message);
#else
return 0;
#endif
}
int ota_coap_parse_block(void *p_message, int type, int *num, int *more, int *size)
{
#if (OTA_SIGNAL_CHANNEL) == 2
return IOT_CoAP_ParseOption_block(p_message, type, num, more, size);
#else
return 0;
#endif
}
int ota_coap_send_block(void *p_context, char *p_path, void *p_message, int block_type, int num, int more, int size)
{
#if (OTA_SIGNAL_CHANNEL) == 2
return IOT_CoAP_SendMessage_block(p_context, p_path, p_message, block_type,num, more, size);
#else
return 0;
#endif
}
int ota_coap_get_payload(void *p_message, const char **pp_payload, int *p_len)
{
#if (OTA_SIGNAL_CHANNEL) == 2
return IOT_CoAP_GetMessagePayload(p_message, pp_payload, p_len);
#else
return 0;
#endif
}
int ota_coap_get_code(void *p_message, void *p_resp_code)
{
#if (OTA_SIGNAL_CHANNEL) == 2
return IOT_CoAP_GetMessageCode(p_message, p_resp_code);
#else
return 0;
#endif
}
int ota_coap_init(void)
{
#if (OTA_SIGNAL_CHANNEL) == 2
#define COAP_ONLINE_DTLS_SERVER_URL "coaps://%s.iot-as-coap.cn-shanghai.aliyuncs.com:5684"
int ret = 0;
iotx_coap_config_t config;
iotx_device_info_t dev;
memset(&config, 0, sizeof(config));
memset(&dev, 0, sizeof(dev));
strncpy(dev.device_id, get_ota_service()->ps, sizeof(dev.device_id)-1);
strncpy(dev.product_key, get_ota_service()->pk, sizeof(dev.product_key)-1);
strncpy(dev.device_name, get_ota_service()->dn, sizeof(dev.device_name)-1);
strncpy(dev.device_secret, get_ota_service()->ds, sizeof(dev.device_secret)-1);
config.p_devinfo = &dev;
char url[256] = { 0 };
ota_snprintf(url, sizeof(url), COAP_ONLINE_DTLS_SERVER_URL,get_ota_service()->pk);
config.p_url = url;
get_ota_service()->h_ch = (void *)ota_IOT_CoAP_Init(&config);
if (get_ota_service()->h_ch) {
ret = ota_IOT_CoAP_DeviceNameAuth(get_ota_service()->h_ch);
if (ret < 0) {
OTA_LOG_E("COAP error");
return ret;
}
}
#else
return 0;
#endif
}
int ota_coap_deinit(void)
{
#if (OTA_SIGNAL_CHANNEL) == 2
IOT_CoAP_Deinit(get_ota_service()->h_ch);
#endif
return 0;
}

View file

@ -0,0 +1,173 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef OTA_PLATFORM_OS_H_
#define OTA_PLATFORM_OS_H_
#include "ota_service.h"
#define OTA_SSL_TIMEOUT 5000
#define ota_snprintf snprintf
#ifndef false
#define false 0
#endif
#ifndef true
#define true 1
#endif
#ifndef bool
#define bool char
#endif
#ifndef NULL
#define NULL 0
#endif
#define OTA_IMAGE_MD5_LEN (16)
#define OTA_IMAGE_RESERVER_SIZE (2)
typedef struct
{
unsigned int image_magic;
unsigned int image_size;
unsigned char image_md5_value[OTA_IMAGE_MD5_LEN];
unsigned char image_reserver[OTA_IMAGE_RESERVER_SIZE];
unsigned short image_crc16;
} ota_image_t;
/*memory*/
void *ota_malloc(int size);
void *ota_realloc(void *ptr, int size);
void *ota_calloc(int n, int size);
void ota_free(void *ptr);
/*Semaphore*/
void *ota_semaphore_create(void);
int ota_semaphore_wait(void *sem, int ms);
void ota_semaphore_post(void *sem);
void ota_semaphore_destroy(void *sem);
/*Thread*/
int ota_thread_create(
void **thread_handle,
void *(*work_routine)(void *),
void *arg,
void *param,
int stack_size);
void ota_thread_exit(void *thread);
void ota_msleep(int ms);
/*KV store*/
int ota_kv_set(const char *key, const void *val, int len, int sync);
int ota_kv_get(const char *key, void *buffer, int *len);
/*Reboot*/
void ota_reboot(void);
/*Socket API*/
void* ota_socket_connect(char *host, int port);
int ota_socket_send(void* fd, char *buf, int len);
int ota_socket_recv(void* fd, char *buf, int len);
void ota_socket_close(void* fd);
/*SSL*/
void* ota_ssl_connect(const char *host, unsigned short port, const char *ca, int len);
int ota_ssl_send(void* ssl, char *buf, int len);
int ota_ssl_recv(void* ssl, char *buf, int len);
/*Verify API*/
typedef struct
{
unsigned int total[2];
unsigned int state[4];
unsigned char buffer[64];
}ota_md5_context;
typedef struct {
unsigned int total[2];
unsigned int state[8];
unsigned char buffer[64];
int is224;
}ota_sha256_context;
/*SHA256*/
void ota_sha256_free(ota_sha256_context *ctx);
void ota_sha256_init(ota_sha256_context *ctx);
void ota_sha256_starts(ota_sha256_context *ctx, int is224);
void ota_sha256_update(ota_sha256_context *ctx, const unsigned char *input, unsigned int ilen);
void ota_sha256_finish(ota_sha256_context *ctx, unsigned char output[32]);
/*MD5*/
void ota_md5_free(ota_md5_context *ctx);
void ota_md5_init(ota_md5_context *ctx);
void ota_md5_starts(ota_md5_context *ctx);
void ota_md5_update(ota_md5_context *ctx, const unsigned char *input, unsigned int ilen);
void ota_md5_finish(ota_md5_context *ctx, unsigned char output[16]);
/*CRC16*/
typedef struct {
unsigned short crc;
} ota_crc16_ctx;
void ota_crc16_init(ota_crc16_ctx *ctx);
void ota_crc16_update(ota_crc16_ctx *ctx, const void *inSrc, unsigned int inLen);
void ota_crc16_final(ota_crc16_ctx *ctx, unsigned short *outResult);
/*Base64*/
int ota_base64_decode(const unsigned char *input, int input_len, unsigned char *output, int *output_len);
/*RSA*/
#define HASH_NONE OTA_HASH_NONE
#define SHA256 OTA_SHA256
#define MD5 OTA_MD5
#define RSASSA_PKCS1_V1_5 OTA_RSASSA_PKCS1_V1_5
typedef enum {
HASH_NONE = 0,
SHA256 = 3,
MD5 = 6,
} OTA_HASH_E;
typedef enum {
RSASSA_PKCS1_V1_5 = 20,
} ota_rsa_pad_type_t;
typedef struct{
ota_rsa_pad_type_t type;
union {
struct {
OTA_HASH_E type;
} rsaes_oaep;
struct {
OTA_HASH_E type;
} rsassa_v1_5;
struct {
OTA_HASH_E type;
unsigned int salt_len;
} rsassa_pss;
} pad;
} ota_rsa_padding_t;
#define TEE_MIN_RSA_KEY_SIZE (256)
#define TEE_MAX_RSA_KEY_SIZE (2048)
typedef struct{
unsigned int magic;
unsigned int n_size;
unsigned int e_size;
unsigned char n[(TEE_MAX_RSA_KEY_SIZE >> 3)];
unsigned char e[(TEE_MAX_RSA_KEY_SIZE >> 3)];
} ota_rsa_pubkey_t;
int ota_rsa_get_pubkey_size(unsigned int keybits, unsigned int *size);
int ota_rsa_init_pubkey(unsigned int keybits, const unsigned char *n, unsigned int n_size,
const unsigned char *e, unsigned int e_size, ota_rsa_pubkey_t *pubkey);
/*MQTT*/
int ota_hal_mqtt_publish(char *topic, int qos, void *data, int len);
int ota_hal_mqtt_subscribe(char *topic, void* cb, void *ctx);
int ota_hal_mqtt_deinit(void);
int ota_hal_mqtt_init(void);
/*COAP*/
int ota_coap_send(void *p_context, char *p_path, void *p_message);
int ota_coap_send_block(void *p_context, char *p_path, void *p_message,
int block_type, int num, int more, int size);
int ota_coap_parse_block(void *p_message, int type, int *num,int *more, int *size);
int ota_coap_get_payload(void *p_message, const char **pp_payload, int *p_len);
int ota_coap_get_code(void *p_message, void *p_resp_code);
int ota_coap_init(void);
int ota_coap_deinit(void);
#endif

View file

@ -0,0 +1,362 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include "aos/kernel.h"
#include "aos/kv.h"
#include "hal/soc/flash.h"
#include "ota_hal_plat.h"
#include "ota_hal_os.h"
#include "ota_log.h"
#if defined (AOS_OTA_RECOVERY_TYPE)
#include "rec_define.h"
#endif
#if defined (BOARD_ESP8266)
#include "esp_system.h"
#include "upgrade.h"
#include "esp_wifi.h"
#elif defined (STM32L496xx)
#define OTA_CACHE_SIZE 2048
uint8_t *ota_cache = NULL;
uint8_t *ota_cache_actual = NULL;
uint32_t ota_cache_len = 0;
uint32_t ota_fw_size = 0;
uint32_t ota_receive_total_len = 0;
#endif
#define OTA_CRC16 "ota_file_crc16"
static int boot_part = HAL_PARTITION_OTA_TEMP;
static unsigned int _offset = 0;
static ota_crc16_ctx ctx = {0};
#if defined (SUPPORT_MCU_OTA)
char cur_ota_ver[OTA_MAX_VER_LEN] = {0};
#endif
unsigned short ota_get_crc16(void)
{
int len = 2;
unsigned short crc16=0;
aos_kv_get(OTA_CRC16, &crc16, &len);
return crc16;
}
void ota_set_crc16(unsigned short crc16)
{
aos_kv_set(OTA_CRC16, &crc16, 2, 1);
}
void ota_reboot_bank(void)
{
#if defined (BOARD_ESP8266)
wifi_set_sleep_type(NONE_SLEEP_T);
ota_msleep(300);
system_upgrade_init();
system_upgrade_flag_set(UPGRADE_FLAG_FINISH);
printf("---reboot_system---\n");
system_upgrade_reboot();
#elif defined (STM32L496xx) || defined (SV6266)
extern int flash_sw_bank(void);
flash_sw_bank();
#endif
}
static int ota_init(void *something)
{
int ret = 0;
ota_boot_param_t *param = (ota_boot_param_t *)something;
param->off_bp = 0;
hal_flash_dis_secure(0, 0, 0);
_offset = param->off_bp;
hal_logic_partition_t *part_info = hal_flash_get_info(boot_part);
if(part_info->partition_length < param->len || param->len == 0) {
ret = OTA_PARAM_FAIL;
return ret;
}
#if defined (STM32L496xx)
ota_fw_size = param->len;
ota_receive_total_len = _offset;
ota_cache = ota_malloc(OTA_CACHE_SIZE + 8);
if (ota_cache != NULL) {
/*Align with 8 bytes*/
ota_cache_actual = (uint8_t *)((uint32_t)ota_cache & ~0x7);
}
else {
ret = OTA_INIT_FAIL;
return ret;
}
#endif
if(param->off_bp == 0) {
int ret = 0;
ret = hal_flash_erase(boot_part, _offset, part_info->partition_length);
if(ret != 0) {
ret = OTA_INIT_FAIL;
return ret;
}
ota_crc16_init(&ctx);
}
else {
ctx.crc=ota_get_crc16();
}
OTA_LOG_I("ota init off:0x%08x part:%d len:%d crc:0x%04x\n",param->off_bp,boot_part,param->len,ctx.crc);
return ret;
}
static int ota_write(int* off, char* in_buf ,int in_buf_len)
{
int ret = 0;
#if defined (STM32L496xx)
uint32_t tocopy = 0;
if(in_buf_len > OTA_CACHE_SIZE) {
ret = OTA_UPGRADE_FAIL;
return ret;
}
ota_crc16_update(&ctx, in_buf, in_buf_len);
if (in_buf_len <= OTA_CACHE_SIZE - ota_cache_len) {
tocopy = in_buf_len;
}
else {
tocopy = OTA_CACHE_SIZE - ota_cache_len;
}
/*Start from last byte of remaing data*/
memcpy(ota_cache_actual + ota_cache_len, in_buf, tocopy);
ota_cache_len += tocopy;
if (ota_cache_len == OTA_CACHE_SIZE) {
ret = hal_flash_write(HAL_PARTITION_OTA_TEMP, &_offset, ota_cache_actual, OTA_CACHE_SIZE);
}
/*keep remaining data*/
if (in_buf_len - tocopy > 0) {
/*Now ota_cache only contains remaing data*/
memcpy(ota_cache_actual, in_buf + tocopy, in_buf_len - tocopy);
ota_cache_len = in_buf_len - tocopy;
}
ota_receive_total_len += in_buf_len;
if(ota_receive_total_len == ota_fw_size) {
if (ota_cache_len != 0) {
int ret = hal_flash_write(HAL_PARTITION_OTA_TEMP, &_offset, ota_cache_actual, ota_cache_len);
ota_free(ota_cache);
}
}
#else
ota_crc16_update(&ctx, in_buf, in_buf_len);
ret = hal_flash_write(boot_part, (uint32_t*)&_offset, in_buf, in_buf_len);
#endif
return ret;
}
static int ota_read(int* off, char* out_buf, int out_buf_len)
{
return hal_flash_read(boot_part, (uint32_t*)off, out_buf, out_buf_len);
}
static int ota_boot(void *something)
{
int ret = 0;
ota_boot_param_t *param = (ota_boot_param_t *)something;
if (param == NULL) {
ret = OTA_REBOOT_FAIL;
return ret;
}
if (param->res_type == OTA_FINISH) {
ota_crc16_final(&ctx, &param->crc);
if (param->upg_flag == OTA_DIFF) {
#if defined (AOS_OTA_RECOVERY_TYPE)
int offset = 0x00;
int param_part = HAL_PARTITION_PARAMETER_1;
PatchStatus ota_param,ota_param_r;
memset(&ota_param, 0, sizeof(PatchStatus));
ota_param.dst_adr = HAL_PARTITION_APPLICATION;
ota_param.src_adr = HAL_PARTITION_OTA_TEMP;
ota_param.len = 0;
ota_param.crc = param->crc;
ota_param.splict_size = param->splict_size;
ota_param.rec_size = param->rec_size;
ota_param.diff = 1;
ota_param.upg_flag = REC_RECOVERY_FLAG;
ota_crc16_ctx ctx1;
unsigned short crc;
ota_crc16_init(&ctx1);
ota_crc16_update(&ctx1, &ota_param, sizeof(PatchStatus) - sizeof(unsigned short));
ota_crc16_final(&ctx1, &crc);
ota_param.patch_crc = crc;
offset = 0x00;
hal_flash_erase(param_part, offset, sizeof(PatchStatus));
offset = 0x00;
hal_flash_write(param_part, (uint32_t*)&offset, &ota_param, sizeof(PatchStatus));
offset = 0x00;
memset(&ota_param_r, 0, sizeof(PatchStatus));
hal_flash_read(param_part, (uint32_t*)&offset, &ota_param_r, sizeof(PatchStatus));
if(memcmp(&ota_param, &ota_param_r, sizeof(PatchStatus)) != 0) {
ret = OTA_REBOOT_FAIL;
return ret;
}
OTA_LOG_I("diff dst:0x%08x src:0x%08x len:0x%08x, crc:0x%04x pcrc:0x%04x splict:%d.\r\n",
ota_param_r.dst_adr,ota_param_r.src_adr, ota_param_r.rec_size, ota_param_r.crc,
ota_param_r.patch_crc, ota_param_r.splict_size);
#endif
}
else {
#if defined AOS_OTA_BANK_DUAL
int offset = 0x00;
ota_crc16_ctx tmp_ctx;
unsigned short crc;
int param_part = HAL_PARTITION_PARAMETER_1;
param->src_adr = 0x00;
param->dst_adr = 0x00;
#if defined (AOS_OTA_RECOVERY_TYPE)
param->upg_flag = REC_DUAL_UPDATE_FLAG;
#else
param->upg_flag = 0x00;
#endif
ota_crc16_init(&tmp_ctx);
ota_crc16_update(&tmp_ctx, param, sizeof(ota_boot_param_t) - sizeof(unsigned short));
ota_crc16_final(&tmp_ctx, &crc);
param->param_crc = crc;
ota_boot_param_t param_r;
offset = 0x00;
hal_flash_erase(param_part, offset, sizeof(ota_boot_param_t));
offset = 0x00;
hal_flash_write(param_part, (uint32_t*)&offset, param, sizeof(ota_boot_param_t));
offset = 0x00;
memset(&param_r, 0, sizeof(ota_boot_param_t));
hal_flash_read(param_part, (uint32_t*)&offset, &param_r, sizeof(ota_boot_param_t));
if(memcmp(param, &param_r, sizeof(ota_boot_param_t)) != 0) {
return -1;
}
OTA_LOG_I("OTA finish dst:0x%08x src:0x%08x len:0x%08x, crc:0x%04x.\r\n", param_r.dst_adr, param_r.src_adr, param_r.len, param_r.crc);
ota_reboot_bank();
#else
#ifndef SV6266
int offset = 0x00;
ota_crc16_ctx ctx1;
unsigned short crc;
int param_part = HAL_PARTITION_PARAMETER_1;
#if !defined (RDA5981x) && !defined (RDA5981A)
extern int app_download_addr;
extern int kernel_download_addr;
#endif
hal_logic_partition_t *part_info = hal_flash_get_info(boot_part);
#ifndef AOS_OTA_2BOOT_UPDATE_SUPPORT
#if !defined (RDA5981x) && !defined (RDA5981A)
param->src_adr = part_info->partition_start_addr;
param->dst_adr = (param->upg_flag == OTA_APP)? (int)&app_download_addr : (int)&kernel_download_addr;
#endif
#else
param->src_adr = 0;
param->dst_adr = 0;
param->len = 0;
param->upg_flag = REC_SWAP_UPDATE_FLAG;
#endif
ota_crc16_init(&ctx1);
ota_crc16_update(&ctx1, param, sizeof(ota_boot_param_t) - sizeof(unsigned short));
ota_crc16_final(&ctx1, &crc);
param->param_crc = crc;
ota_boot_param_t param_r;
offset = 0x00;
hal_flash_erase(param_part, offset, sizeof(ota_boot_param_t)); //PARTITION_BACKUP_PARAM
offset = 0x00;
hal_flash_write(param_part, (uint32_t*)&offset, param, sizeof(ota_boot_param_t));
offset = 0x00;
memset(&param_r, 0, sizeof(ota_boot_param_t));
hal_flash_read(param_part, (uint32_t*)&offset, &param_r, sizeof(ota_boot_param_t));
if(memcmp(param, &param_r, sizeof(ota_boot_param_t)) != 0) {
ret = OTA_REBOOT_FAIL;
return ret;
}
OTA_LOG_I("OTA finish dst:0x%08x src:0x%08x len:0x%08x, crc:0x%04x.\r\n", param_r.dst_adr, param_r.src_adr, param_r.len, param_r.crc);
#else
ota_reboot_bank();
OTA_LOG_I("OTA finish, boot para self defined!");
#endif
#endif
}
ota_msleep(1500);
ota_reboot();
}
else if(param->res_type == OTA_BREAKPOINT) {
OTA_LOG_I("save bp crc:0x%04x", ctx.crc);
#if defined (STM32L496xx)
if (ota_cache_len != 0) {
int ret = hal_flash_write(HAL_PARTITION_OTA_TEMP, &_offset, ota_cache_actual, ota_cache_len);
ota_free(ota_cache);
}
#endif
ota_set_crc16(ctx.crc);
}
return ret;
}
static int ota_rollback(void *something)
{
int offset = 0x00;
int param_part = HAL_PARTITION_PARAMETER_1;
ota_boot_param_t param_w, param_r;
memset(&param_w, 0, sizeof(ota_boot_param_t));
hal_flash_read(param_part, (uint32_t*)&offset, &param_w, sizeof(ota_boot_param_t));
if((param_w.boot_count != 0) && (param_w.boot_count != 0xff)) {
ota_crc16_ctx ctx1;
unsigned short crc;
param_w.upg_flag = 0;
param_w.boot_count = 0; /*Clear bootcount to avoid rollback*/
ota_crc16_init(&ctx1);
ota_crc16_update(&ctx1, &param_w, sizeof(ota_boot_param_t) - sizeof(unsigned short));
ota_crc16_final(&ctx1, &crc);
param_w.param_crc = crc;
offset = 0x00;
hal_flash_erase(param_part, offset, sizeof(ota_boot_param_t));
offset = 0x00;
hal_flash_write(param_part, (uint32_t*)&offset, &param_w, sizeof(ota_boot_param_t));
offset = 0x00;
memset(&param_r, 0, sizeof(ota_boot_param_t));
hal_flash_read(param_part, (uint32_t*)&offset, &param_r, sizeof(ota_boot_param_t));
if(memcmp(&param_w, &param_r, sizeof(ota_boot_param_t)) != 0) {
OTA_LOG_E("rollback failed\n");
return -1;
}
}
return 0;
}
const char *aos_get_app_version(void);
static const char *ota_get_version(unsigned char dev_type)
{
if(dev_type) {
return "v1.0.0-20180101-1000";//SYSINFO_APP_VERSION;
} else {
#if defined (SUPPORT_MCU_OTA)
char mcu_ver[16] = {0};
int len = sizeof(mcu_ver);
aos_kv_get("mcu_version", mcu_ver, &len);
if (0 == strlen(mcu_ver)) {
strcpy((char *)mcu_ver, "mcu-1.0.0");
OTA_LOG_I("use default MCU version:%s", mcu_ver);
}
memset(cur_ota_ver, 0, OTA_MAX_VER_LEN);
snprintf(cur_ota_ver, OTA_MAX_VER_LEN, "%s-%s", mcu_ver, aos_get_app_version());
OTA_LOG_I("current ota version:%s", cur_ota_ver);
return (const char *)cur_ota_ver;
#else
return aos_get_app_version();
#endif
}
}
ota_hal_module_t ota_hal_module = {
.init = ota_init,
.write = ota_write,
.read = ota_read,
.boot = ota_boot,
.rollback = ota_rollback,
.version = ota_get_version,
};

View file

@ -0,0 +1,120 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef HAL_OTA_H
#define HAL_OTA_H
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
OTA_RAW = 0,
OTA_DIFF = 1,
OTA_KERNEL = 2,
OTA_APP = 4,
} OTA_UPD_TYPE_E;
typedef enum {
OTA_FINISH,
OTA_BREAKPOINT
} OTA_RES_TYPE_E;
typedef struct {
unsigned int dst_adr;
unsigned int src_adr;
unsigned int len;
unsigned short crc;
unsigned int upg_flag;
unsigned char boot_count;
unsigned int splict_size;
int off_bp; /*Break point offset*/
OTA_RES_TYPE_E res_type; /*result type: OTA_FINISH, OTA_BREAKPOINT*/
unsigned short param_crc; /*Parameter crc*/
} __attribute__((packed)) ota_boot_param_t;
typedef struct ota_hal_module_s {
int (*init)(void *something);
int (*write)(int *off_set, char *in_buf , int in_buf_len);
int (*read)(int *off_set, char *out_buf , int out_buf_len);
int (*boot)(void *something);
int (*rollback)(void *something);
const char *(*version)(unsigned char dev_type);
}ota_hal_module_t;
/**
* Arch register a new module before HAL startup
*/
void ota_hal_register_module(ota_hal_module_t *module);
/**
* init ota partition
*
* @note when ota start, maybe it need init something
* @param something extra info for ota init
*
* @return 0 : On success, 1 : If an error occurred with any step
*/
int ota_hal_init(void *something);
/**
* Write data to an area on ota partition
*
* @param off_set Point to the start address that the data is written to, and
* point to the last unwritten address after this function is
* returned, so you can call this function serval times without
* update this start address.
* @param inbuf point to the data buffer that will be written to flash
* @param in_buf_len The length of the buffer
*
* @return 0 : On success, 1 : If an error occurred with any step
*/
int ota_hal_write(int *off_set,char *in_buf , int in_buf_len);
/**
* Read data from an area on ota Flash to data buffer in RAM
*
* @param off_set Point to the start address that the data is read, and
* point to the last unread address after this function is
* returned, so you can call this function serval times without
* update this start address.
* @param out_buf Point to the data buffer that stores the data read from flash
* @param out_buf_len The length of the buffer
*
* @return 0 : On success, 1 : If an error occurred with any step
*/
int ota_hal_read(int *off_set,char *out_buf, int out_buf_len);
/**
* Set boot options when ota reboot
*
* @param something boot parms
*
* @return kNoErr : On success. kGeneralErr : If an error occurred with any step
*/
int ota_hal_boot(void *something);
/**
* Set rollback when failed to boot
*
* @param something
*
* @return kNoErr : On success. kGeneralErr : If an error occurred with any step
*/
int ota_hal_rollback(void *something);
/**
* get system version
*
* @param device type
*
* @return version
*/
const char *ota_hal_get_version(unsigned char dev_type);
#ifdef __cplusplus
}
#endif
#endif /* HAL_OTA_H */