1 /*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 * Description: UPG upgrade functions source file
15 */
16
17 #include <stdint.h>
18 #include <stddef.h>
19 #include "common_def.h"
20 #include "upg_definitions.h"
21 #include "errcode.h"
22 #include "upg_lzmadec.h"
23 #include "upg_common.h"
24 #include "upg_common_porting.h"
25 #include "upg_alloc.h"
26 #include "partition.h"
27 #include "upg_porting.h"
28 #include "upg_patch.h"
29 #include "upg_config.h"
30 #include "upg_debug.h"
31 #include "securec.h"
32 #include "upg_encry.h"
33
uapi_upg_lzma_ota_image(const upg_image_header_t * image,uint8_t * header,uint32_t head_len,uint32_t app_size,uint32_t read_offset)34 errcode_t uapi_upg_lzma_ota_image(const upg_image_header_t *image, uint8_t *header, uint32_t head_len,
35 uint32_t app_size, uint32_t read_offset)
36 {
37 errcode_t ret;
38 CLzmaDec p;
39 upg_lzma_decode2_data_t val_tmp = { 0 };
40
41 ret = upg_lzma_init(&p, &val_tmp, header, head_len);
42 if (ret != ERRCODE_SUCC) {
43 return ret;
44 }
45
46 val_tmp.image_id = image->image_id;
47 val_tmp.in_offset = read_offset;
48 val_tmp.out_offset = 0;
49 val_tmp.compress_len = image->image_len - head_len;
50
51 if (app_size < val_tmp.decompress_len) {
52 upg_log_err("[UPG] app size is not enough! app_size = 0x%x, decompress_len = 0x%x\r\n",
53 app_size, val_tmp.decompress_len);
54 upg_lzma_deinit(&p, &val_tmp);
55 return ERRCODE_UPG_NO_ENOUGH_SPACE;
56 }
57
58 ret = upg_lzma_decode(&p, &val_tmp, image);
59 if (ret != SZ_OK) {
60 upg_log_err("[UPG] upg_lzma_decode fail ret = 0x%x\r\n", ret);
61 ret = ERRCODE_UPG_DECOMPRESS_FAIL;
62 }
63 upg_lzma_deinit(&p, &val_tmp);
64 return ret;
65 }
66
67 /* FOTA压缩升级 */
uapi_upg_compress_image_update(const upg_image_header_t * image)68 errcode_t uapi_upg_compress_image_update(const upg_image_header_t *image)
69 {
70 uint32_t read_offset = image->image_offset;
71 errcode_t ret;
72 uint8_t header[LZMA_HEAD_ALIGN_SIZE] = { 0 };
73 uint32_t read_len = (uint32_t)sizeof(header);
74 uint32_t app_address = 0; /* 镜像所在分区 */
75 uint32_t app_size = 0; /* 镜像大小 */
76
77 /* 读压缩头 */
78 ret = upg_copy_pkg_image_data(image, 0, &read_len, header);
79 if (ret != ERRCODE_SUCC) {
80 return ret;
81 }
82 #ifdef CONFIG_MIDDLEWARE_SUPPORT_UPG_COMPRESS_ENCRY
83 /* 初始化加解密配置 */
84 ret = upg_cryto_init(image);
85 if (ret != ERRCODE_SUCC) {
86 return ret;
87 }
88 /* 解密压缩头 */
89 ret = upg_decry_fota_pkt(header, read_len, image);
90 if (ret != ERRCODE_SUCC) {
91 goto destory;
92 }
93 #endif
94 read_offset += read_len;
95 ret = upg_get_partition_info(image->image_id, &app_address, &app_size);
96 if (ret != ERRCODE_SUCC) {
97 goto destory;
98 }
99
100 ret = uapi_upg_lzma_ota_image(image, header, sizeof(header), app_size, read_offset);
101 if (ret != ERRCODE_SUCC) {
102 goto destory;
103 }
104
105 destory:
106 #ifdef CONFIG_MIDDLEWARE_SUPPORT_UPG_COMPRESS_ENCRY
107 upg_cryto_deinit(image);
108 #endif
109 return ret;
110 }
111
112 /* FOTA差分升级 */
uapi_upg_diff_image_update(const upg_image_header_t * image)113 errcode_t uapi_upg_diff_image_update(const upg_image_header_t *image)
114 {
115 #if (UPG_CFG_DIFF_UPGRADE_SUPPORT == YES)
116 errcode_t ret = ERRCODE_SUCC;
117 ret = fota_pkg_task_apply_code_diff(image);
118
119 return ret;
120 #else
121 unused(image);
122 return ERRCODE_UPG_NOT_SUPPORTED;
123 #endif
124 }
125
126 /* FOTA全镜像升级 */
uapi_upg_full_image_update(const upg_image_header_t * image)127 errcode_t uapi_upg_full_image_update(const upg_image_header_t *image)
128 {
129 uint32_t read_offset = image->image_offset;
130 errcode_t ret;
131 uint32_t write_offset = 0;
132 uint32_t app_address = 0;
133 uint32_t app_size = 0;
134 errcode_t ret_val = upg_get_partition_info(image->image_id, &app_address, &app_size);
135 if (ret_val != ERRCODE_SUCC) {
136 return ret_val;
137 }
138
139 if (app_size < image->image_len) {
140 return ERRCODE_FAIL;
141 }
142
143 uint32_t read_len = 0;
144 uint32_t tmp_len = 0;
145
146 uint8_t *buffer = upg_malloc(UPG_FLASH_PAGE_SIZE);
147 if (buffer == NULL) {
148 return ERRCODE_MALLOC;
149 }
150
151 while (read_len < image->image_len) {
152 tmp_len = ((image->image_len - read_len) > UPG_FLASH_PAGE_SIZE) ?
153 UPG_FLASH_PAGE_SIZE : (image->image_len - read_len);
154 ret = upg_read_fota_pkg_data(read_offset + read_len, (uint8_t *)buffer, &tmp_len);
155 if (ret != ERRCODE_SUCC) {
156 upg_free(buffer);
157 return ret;
158 }
159
160 #if defined(UPG_CFG_SUPPORT_ERASE_WHOLE_IMAGE) && defined(YES) && (UPG_CFG_SUPPORT_ERASE_WHOLE_IMAGE == YES)
161 ret = upg_write_new_image_data(write_offset + read_len, (uint8_t *)buffer, &tmp_len, image->image_id, false);
162 #else
163 ret = upg_write_new_image_data(write_offset + read_len, (uint8_t *)buffer, &tmp_len, image->image_id, true);
164 #endif
165 if (ret != ERRCODE_SUCC || tmp_len == 0) {
166 upg_free(buffer);
167 return ret;
168 }
169
170 read_len += tmp_len;
171
172 // 踢狗
173 upg_watchdog_kick();
174
175 upg_calculate_and_notify_process(tmp_len);
176 }
177
178 upg_free(buffer);
179 buffer = NULL;
180 return ERRCODE_SUCC;
181 }
182