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 storage functions source file
15 */
16
17 #include <stddef.h>
18 #include <stdio.h>
19 #include <stdint.h>
20 #include <stdbool.h>
21 #include "securec.h"
22 #include "upg_config.h"
23 #if (UPG_CFG_SUPPORT_FILE_SYSTEM == YES)
24 #include "fcntl.h"
25 #include "sys/stat.h"
26 #include "sys/vfs.h"
27 #endif /* (UPG_CFG_SUPPORT_FILE_SYSTEM == YES) */
28 #include "errcode.h"
29 #include "common_def.h"
30 #include "partition.h"
31 #include "upg_definitions.h"
32 #include "upg_common.h"
33 #include "upg_common_porting.h"
34 #include "upg_alloc.h"
35 #include "upg_verify.h"
36 #include "upg_porting.h"
37 #include "upg_debug.h"
38
39 STATIC errcode_t upg_package_storage_write(uint32_t offset, const uint8_t *buff, uint16_t len, uint32_t pkg_len);
40
upg_prepare_erase(uint32_t package_len)41 STATIC errcode_t upg_prepare_erase(uint32_t package_len)
42 {
43 errcode_t ret;
44 uint32_t status_start_addr;
45 uint32_t status_size;
46 unused(package_len);
47 ret = upg_get_progress_status_start_addr(&status_start_addr, &status_size);
48 if (ret != ERRCODE_SUCC) {
49 return ret;
50 }
51 #if (UPG_CFG_SUPPORT_FILE_SYSTEM == NO)
52 partition_information_t info;
53 ret = uapi_partition_get_info(PARTITION_FOTA_DATA, &info);
54 if (ret != ERRCODE_SUCC) {
55 return ret;
56 }
57 ret = upg_flash_erase(info.part_info.addr_info.addr, package_len);
58 if (ret != ERRCODE_SUCC) {
59 return ret;
60 }
61 #endif
62 ret = upg_flash_erase(status_start_addr, status_size);
63 if (ret != ERRCODE_SUCC) {
64 return ret;
65 }
66 return ret;
67 }
68 /*
69 * 存储升级包前对Flash的准备工作(包括擦除升级区、初始化升级标记中的head_before_offset和Head_magic)
70 * prepare_info 分区准备信息,如升级包总长度
71 */
uapi_upg_prepare(upg_prepare_info_t * prepare_info)72 errcode_t uapi_upg_prepare(upg_prepare_info_t *prepare_info)
73 {
74 if (upg_is_inited() == false) {
75 return ERRCODE_UPG_NOT_INIT;
76 }
77
78 errcode_t ret;
79 uint32_t flag_start_addr;
80 if (prepare_info == NULL || prepare_info->package_len == 0) {
81 return ERRCODE_UPG_INVALID_PARAMETER;
82 }
83
84 #if (UPG_CFG_SUPPORT_FILE_SYSTEM == NO)
85 if (prepare_info->package_len > uapi_upg_get_storage_size()) {
86 return ERRCODE_UPG_INVALID_PARAMETER;
87 }
88 #endif
89
90 upg_storage_ctx_t *ctx = upg_get_ctx();
91 ctx->packge_len = prepare_info->package_len;
92
93 do {
94 /* 擦除FOTA区 */
95 ret = upg_prepare_erase(prepare_info->package_len);
96 if (ret != ERRCODE_SUCC) {
97 break;
98 }
99
100 /* 初始化head_before_offset */
101 ret = upg_get_upgrade_flag_flash_start_addr(&flag_start_addr);
102 if (ret != ERRCODE_SUCC) {
103 break;
104 }
105 uint32_t flash_offset = flag_start_addr + offsetof(fota_upgrade_flag_area_t, head_before_offset);
106 /* head_before_offset为FOTA区起始地址相对APP分区的偏移地址 */
107 uint32_t head_before_offset = 0;
108 ret = upg_flash_write(flash_offset, sizeof(uint32_t), (uint8_t *)&head_before_offset, false);
109 if (ret != ERRCODE_SUCC) {
110 break;
111 }
112
113 /* 初始化 package_length */
114 flash_offset = flag_start_addr + offsetof(fota_upgrade_flag_area_t, package_length);
115 ret = upg_flash_write(flash_offset, sizeof(uint32_t), (uint8_t *)&prepare_info->package_len, false);
116 if (ret != ERRCODE_SUCC) {
117 break;
118 }
119
120 /* 初始化 Head_magic */
121 uint32_t head_magic = UPG_HEAD_MAGIC;
122 flash_offset = flag_start_addr + offsetof(fota_upgrade_flag_area_t, head_magic);
123 ret = upg_flash_write(flash_offset, sizeof(uint32_t), (uint8_t *)&head_magic, false);
124 if (ret != ERRCODE_SUCC) {
125 break;
126 }
127 } while (0);
128 return ret;
129 }
130
131 /* 重置升级标记,准备升级 */
uapi_upg_reset_upgrade_flag(void)132 errcode_t uapi_upg_reset_upgrade_flag(void)
133 {
134 errcode_t ret = 0;
135 uint32_t flag_start_addr;
136 uint32_t upg_flag_address = 0;
137 uint32_t status_size;
138
139 if (upg_is_inited() == false) {
140 return ERRCODE_UPG_NOT_INIT;
141 }
142
143 ret = upg_get_progress_status_start_addr(&upg_flag_address, &status_size);
144 if (ret != ERRCODE_SUCC) {
145 return ret;
146 }
147
148 ret = upg_get_upgrade_flag_flash_start_addr(&flag_start_addr);
149 if (ret != ERRCODE_SUCC) {
150 return ret;
151 }
152
153 /* 擦除标记区前,读取package_len */
154 uint32_t package_len = 0;
155 uint32_t flash_offset = flag_start_addr + offsetof(fota_upgrade_flag_area_t, package_length);
156 ret = upg_flash_read(flash_offset, sizeof(uint32_t), (uint8_t *)&package_len);
157 if (ret != ERRCODE_SUCC) {
158 return ret;
159 }
160
161 /* 擦除标记区 */
162 ret = upg_flash_erase(upg_flag_address, status_size);
163 if (ret != ERRCODE_SUCC) {
164 return ret;
165 }
166
167 /* 初始化 head_before_offset */
168 flash_offset = flag_start_addr + offsetof(fota_upgrade_flag_area_t, head_before_offset);
169 uint32_t head_before_offset = 0;
170 ret = upg_flash_write(flash_offset, sizeof(uint32_t), (uint8_t *)&head_before_offset, false);
171 if (ret != ERRCODE_SUCC) {
172 return ret;
173 }
174
175 /* 初始化 Head_magic */
176 uint32_t head_magic = UPG_HEAD_MAGIC;
177 flash_offset = flag_start_addr + offsetof(fota_upgrade_flag_area_t, head_magic);
178 ret = upg_flash_write(flash_offset, sizeof(uint32_t), (uint8_t *)&head_magic, false);
179 if (ret != ERRCODE_SUCC) {
180 return ret;
181 }
182
183 /* 回写package_length */
184 flash_offset = flag_start_addr + offsetof(fota_upgrade_flag_area_t, package_length);
185 return upg_flash_write(flash_offset, sizeof(uint32_t), (uint8_t *)&package_len, false);
186 }
187
upg_check_buff(const uint8_t * buff,uint16_t len)188 STATIC errcode_t upg_check_buff(const uint8_t *buff, uint16_t len)
189 {
190 if (buff == NULL) {
191 return ERRCODE_UPG_NULL_POINTER;
192 }
193 if (len == 0) {
194 return ERRCODE_UPG_INVALID_BUFF_LEN;
195 }
196
197 return ERRCODE_SUCC;
198 }
199
200 /*
201 * 升级包存入本地存储空间
202 * offset 要存入本地存储空间的位置(相对起始位置的偏移)
203 * buff 要存入的数据包数据指针
204 * len 要存入的数据包长度(4字节对齐)
205 */
upg_write_package(uint32_t offset,const uint8_t * buff,uint16_t len)206 STATIC errcode_t upg_write_package(uint32_t offset, const uint8_t *buff, uint16_t len)
207 {
208 if (!upg_is_inited()) {
209 return ERRCODE_UPG_NOT_INIT;
210 }
211
212 errcode_t ret = upg_check_buff(buff, len);
213 if (ret != ERRCODE_SUCC) {
214 return ret;
215 }
216
217 upg_storage_ctx_t *ctx = upg_get_ctx();
218 if (ctx->packge_len == 0) {
219 return ERRCODE_UPG_NOT_PREPARED;
220 }
221
222 return upg_package_storage_write(offset, buff, len, ctx->packge_len);
223 }
224
225 /*
226 * 升级包存入本地存储空间,异步接口
227 * offset 要存入本地存储空间的位置(相对起始位置的偏移)
228 * buff 要存入的数据包数据指针
229 * len 要存入的数据包长度(4字节对齐)
230 * callback 写入完成的回调函数。
231 */
uapi_upg_write_package_async(uint32_t offset,const uint8_t * buff,uint16_t len,uapi_upg_write_done_cb callback)232 errcode_t uapi_upg_write_package_async(uint32_t offset, const uint8_t *buff, uint16_t len,
233 uapi_upg_write_done_cb callback)
234 {
235 errcode_t ret = upg_write_package(offset, buff, len);
236 if (ret != ERRCODE_SUCC) {
237 return ret;
238 }
239
240 if (callback != NULL) {
241 callback(ret);
242 }
243 return ret;
244 }
245
246 /*
247 * 升级包存入本地存储空间,同步接口
248 * offset 要存入本地存储空间的位置(相对起始位置的偏移)
249 * buff 要存入的数据包数据指针
250 * len 要存入的数据包长度(4字节对齐)
251 */
uapi_upg_write_package_sync(uint32_t offset,const uint8_t * buff,uint16_t len)252 errcode_t uapi_upg_write_package_sync(uint32_t offset, const uint8_t *buff, uint16_t len)
253 {
254 return upg_write_package(offset, buff, len);
255 }
256
257 /*
258 * 从本地存储空间读取升级包数据
259 * offset 要读取的本地存储空间的位置(相对与升级包起始位置的偏移)
260 * buff 存放数据包的空间指针
261 * len 要读取的数据包长度(4字节对齐)
262 */
uapi_upg_read_package(uint32_t offset,uint8_t * buff,uint32_t len)263 errcode_t uapi_upg_read_package(uint32_t offset, uint8_t *buff, uint32_t len)
264 {
265 if (upg_is_inited() == false) {
266 return ERRCODE_UPG_NOT_INIT;
267 }
268
269 errcode_t ret = upg_check_buff(buff, (uint16_t)len);
270 if (ret != ERRCODE_SUCC) {
271 return ret;
272 }
273
274 return upg_read_fota_pkg_data(offset, buff, (uint32_t *)&len);
275 }
276
upg_get_firmware_number_in_package(const upg_package_header_t * pkg_header,uint32_t * firmware_num)277 STATIC errcode_t upg_get_firmware_number_in_package(const upg_package_header_t *pkg_header, uint32_t *firmware_num)
278 {
279 errcode_t ret;
280 upg_image_hash_node_t *img_hash_table = NULL;
281
282 uint32_t image_num = pkg_header->info_area.image_num;
283 uint32_t fw_num = 0;
284
285 if (image_num > UPG_FIRMWARE_MAX_NUM) {
286 return ERRCODE_UPG_WRONG_IMAGE_NUM;
287 }
288
289 ret = upg_get_pkg_image_hash_table((const upg_package_header_t *)pkg_header, &img_hash_table);
290 if (ret != ERRCODE_SUCC || img_hash_table == NULL) {
291 upg_log_err("[UPG] upg_get_pkg_image_hash_table fail\r\n");
292 return ret;
293 }
294
295 for (uint32_t i = 0; i < image_num; i++) {
296 if (img_hash_table[i].image_id != UPG_IMAGE_ID_NV) {
297 fw_num++;
298 }
299 }
300 *firmware_num = fw_num;
301 upg_free(img_hash_table);
302 return ret;
303 }
304
305 /*
306 * 申请开始本地升级
307 * firmware_num 升级包中firmware数量
308 */
upg_upgrade_request(uint32_t firmware_num)309 STATIC errcode_t upg_upgrade_request(uint32_t firmware_num)
310 {
311 uint32_t flag_start_address = 0;
312 errcode_t ret = upg_get_upgrade_flag_flash_start_addr(&flag_start_address);
313 if (ret != ERRCODE_SUCC) {
314 return ret;
315 }
316
317 /* 写入firmware_num */
318 uint32_t flash_offset = (uint32_t)flag_start_address + offsetof(fota_upgrade_flag_area_t, firmware_num);
319 ret = upg_flash_write(flash_offset, sizeof(uint32_t), (uint8_t *)(&firmware_num), false);
320 if (ret != ERRCODE_SUCC) {
321 return ret;
322 }
323
324 /* 写入Head_end_magic */
325 uint32_t head_end_magic = UPG_END_MAGIC;
326 flash_offset = (uint32_t)flag_start_address + offsetof(fota_upgrade_flag_area_t, head_end_magic);
327 ret = upg_flash_write(flash_offset, sizeof(uint32_t), (uint8_t *)&(head_end_magic), false);
328 if (ret != ERRCODE_SUCC) {
329 return ret;
330 }
331
332 return ERRCODE_SUCC;
333 }
334
uapi_upg_request_upgrade(bool reset)335 errcode_t uapi_upg_request_upgrade(bool reset)
336 {
337 errcode_t ret;
338 upg_package_header_t *pkg_header = NULL;
339 uint32_t firmware_num = 0;
340
341 if (upg_is_inited() == false) {
342 return ERRCODE_UPG_NOT_INIT;
343 }
344
345 ret = upg_get_package_header(&pkg_header);
346 if (ret != ERRCODE_SUCC || pkg_header == NULL) {
347 upg_log_err("[UPG] upg_get_package_header fail\r\n");
348 return ret;
349 }
350
351 #if (UPG_CFG_VERIFICATION_SUPPORT == YES)
352 ret = uapi_upg_verify_file((const upg_package_header_t *)pkg_header);
353 if (ret != ERRCODE_SUCC) {
354 upg_free(pkg_header);
355 upg_log_err("[UPG] uapi_upg_verify_file fail, ret = 0x%x\r\n", ret);
356 return ret;
357 }
358 #endif
359
360 ret = upg_get_firmware_number_in_package((const upg_package_header_t *)pkg_header, &firmware_num);
361 if (ret != ERRCODE_SUCC) {
362 upg_free(pkg_header);
363 upg_log_err("[UPG] upg_get_firmware_number_in_package fail, ret = 0x%x\r\n", ret);
364 return ret;
365 }
366
367 upg_free(pkg_header);
368
369 ret = upg_upgrade_request(firmware_num);
370 if (ret != ERRCODE_SUCC) {
371 upg_log_err("[UPG] upg_upgrade_request fail. ret = 0x%x\r\n", ret);
372 return ret;
373 }
374 /* app中下载后直接开始升级流程,升级流程结束后重启 */
375 if (reset) {
376 /* IOT设备重启 */
377 upg_reboot();
378 }
379 return ERRCODE_SUCC;
380 }
381
382 #if (UPG_CFG_SUPPORT_FILE_SYSTEM == YES)
upg_package_storage_write(uint32_t offset,const uint8_t * buff,uint16_t len,uint32_t pkg_len)383 STATIC errcode_t upg_package_storage_write(uint32_t offset, const uint8_t *buff, uint16_t len, uint32_t pkg_len)
384 {
385 uint16_t write_len = 0;
386 static FILE *wr_fd = NULL;
387 static uint32_t wr_pos = 0;
388 errcode_t ret = ERRCODE_SUCC;
389
390 if (wr_fd == NULL && (upg_get_pkg_file_path() != NULL)) {
391 /* 第一次调用,打开文件 */
392 wr_fd = fopen(upg_get_pkg_file_path(), "wb");
393 if (wr_fd == NULL) {
394 return ERRCODE_UPG_FILE_OPEN_FAIL;
395 }
396 }
397
398 if (offset != wr_pos) {
399 ret = ERRCODE_UPG_INVALID_OFFSET;
400 goto end;
401 }
402
403 uint16_t left_len = (uint16_t)((wr_pos + len > pkg_len) ? pkg_len - wr_pos : len);
404 while (left_len > 0) {
405 /* 一次未写完,可多次读取 */
406 uint16_t tmp = (uint16_t)fwrite(buff + write_len, 1, left_len, wr_fd);
407 if (tmp == 0) {
408 /* 写入失败,中断写入操作 */
409 upg_log_err("[UPG] set file error : %d\r\n", ferror(wr_fd));
410 ret = ERRCODE_UPG_FILE_WRITE_FAIL;
411 goto end;
412 }
413 left_len -= tmp;
414 write_len += tmp;
415 }
416 wr_pos = (uint32_t)ftell(wr_fd);
417 end:
418 if (ret != ERRCODE_SUCC || wr_pos >= pkg_len) {
419 /* 失败或者全部写完后,关闭文件 */
420 fclose(wr_fd);
421 wr_fd = NULL;
422 wr_pos = 0;
423 }
424 return ret;
425 }
426 #else
upg_package_storage_write(uint32_t offset,const uint8_t * buff,uint16_t len,uint32_t pkg_len)427 STATIC errcode_t upg_package_storage_write(uint32_t offset, const uint8_t *buff, uint16_t len, uint32_t pkg_len)
428 {
429 uint32_t start_addr = 0;
430 uint32_t size = 0;
431 errcode_t ret = upg_get_fota_partiton_area_addr(&start_addr, &size);
432 if (ret != ERRCODE_SUCC) {
433 return ret;
434 }
435
436 size -= UPG_META_DATA_LENGTH + UPG_UPGRADE_FLAG_LENGTH;
437 if (offset >= size || offset + len > size || offset >= pkg_len || offset + len > pkg_len) {
438 return ERRCODE_UPG_NO_ENOUGH_SPACE;
439 }
440
441 return upg_flash_write(start_addr + offset, len, buff, false); /* prepare过程已擦除整个fota区,此处不需写前擦 */
442 }
443 #endif
444
uapi_upg_get_status(void)445 upg_status_t uapi_upg_get_status(void)
446 {
447 return upg_get_ctx()->upg_status;
448 }