• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 common functions source file
15  */
16 
17 #include <stddef.h>
18 #include <stdint.h>
19 #include <stdbool.h>
20 #include "common_def.h"
21 #include "upg_config.h"
22 #if (UPG_CFG_SUPPORT_FILE_SYSTEM == YES)
23 #include "fcntl.h"
24 #include "unistd.h"
25 #include "sys/stat.h"
26 #include "sys/vfs.h"
27 #include "dfx_file_operation.h"
28 #endif /* (UPG_CFG_SUPPORT_FILE_SYSTEM == YES) */
29 #include "upg_common_porting.h"
30 #include "errcode.h"
31 #include "securec.h"
32 #include "partition.h"
33 #include "upg_alloc.h"
34 #include "upg_otp_reg.h"
35 #include "upg.h"
36 #include "upg_porting.h"
37 #include "upg_config.h"
38 #include "upg_debug.h"
39 #include "upg_common.h"
40 
41 #define NOT_START_FLAG      0xFF
42 #define STARTED_FLAG        0x0F
43 #define FINISHED_FLAG       0x00
44 #define UPG_FINISH_HALF_FLAG 0xFFFF
45 #define UPG_FINISH_ALL_FLAG 0
46 #define UPG_ABNORMAL_FLAG 0x5a5a5a5a
47 #define PER_FILE_STORAGE_MAX_SIZE   4294967295
48 
49 STATIC upg_storage_ctx_t g_upg_ctx = {0};
upg_get_ctx(void)50 upg_storage_ctx_t *upg_get_ctx(void)
51 {
52     return &g_upg_ctx;
53 }
54 
55 /* 获取升级标记结构到RAM中 */
upg_alloc_and_get_upgrade_flag(fota_upgrade_flag_area_t ** upg_flag)56 errcode_t upg_alloc_and_get_upgrade_flag(fota_upgrade_flag_area_t **upg_flag)
57 {
58     uint32_t start_addr = 0;
59     errcode_t ret_val;
60 
61     ret_val = upg_get_upgrade_flag_flash_start_addr(&start_addr);
62     if (ret_val != ERRCODE_SUCC) {
63         upg_log_err("[UPG] upg_get_upgrade_flag_flash_start_addr fail\r\n");
64         return ret_val;
65     }
66 
67     *upg_flag = (fota_upgrade_flag_area_t*)upg_malloc(sizeof(fota_upgrade_flag_area_t));
68     if (*upg_flag == NULL) {
69         upg_log_err("[UPG] upg_alloc_and_get_upgrade_flag upg_malloc fail\r\n");
70         return ERRCODE_MALLOC;
71     }
72 
73     ret_val = upg_flash_read(start_addr, sizeof(fota_upgrade_flag_area_t), (uint8_t *)(*upg_flag));
74     if (ret_val != ERRCODE_SUCC) {
75         upg_log_err("[UPG] upg_alloc_and_get_upgrade_flag read flash fail\r\n");
76         upg_free(*upg_flag);
77         *upg_flag = NULL;
78         return ret_val;
79     }
80 
81     return ERRCODE_SUCC;
82 }
83 
84 /*
85  * 获取在当前Flash上指定固件镜像的地址信息。该地址为flash上的相对地址,是相对flash基地址的偏移
86  * image_id      固件的镜像ID
87  * start_address 返回该镜像的起始地址
88  * size          返回该镜像区域的大小
89  */
upg_get_partition_info(uint32_t image_id,uint32_t * start_address,uint32_t * size)90 errcode_t upg_get_partition_info(uint32_t image_id, uint32_t *start_address, uint32_t *size)
91 {
92     errcode_t ret_val = ERRCODE_SUCC;
93     partition_information_t image_info = {0};
94 
95     if (image_id == PARAMS_PARTITION_IMAGE_ID) {
96         /* 参数区地址信息 */
97         image_info.type = PARTITION_BY_ADDRESS;
98         image_info.part_info.addr_info.addr = PARAMS_PARTITION_START_ADDR;
99         image_info.part_info.addr_info.size = PARAMS_PARTITION_LENGTH;
100 #if UPG_CFG_SUPPORT_RESOURCES_FILE == YES
101     } else if (image_id == UPG_IMAGE_ID_RES_INDEX) {
102         image_info.type = PARTITION_BY_PATH;
103 #endif
104     } else {
105         ret_val = upg_get_image_info(image_id, &image_info);
106         if (ret_val != ERRCODE_SUCC) {
107             return ret_val;
108         }
109     }
110 
111     if (image_info.type == PARTITION_BY_ADDRESS) {
112         *start_address = image_info.part_info.addr_info.addr;
113         *size = image_info.part_info.addr_info.size;
114     } else { /* PARTITION_BY_PATH */
115         *start_address = 0;
116         *size = uapi_upg_get_storage_size();
117     }
118 
119     return ret_val;
120 }
121 
upg_img_id_convert_to_partition_id(uint32_t image_id,partition_ids_t * item_id)122 STATIC errcode_t upg_img_id_convert_to_partition_id(uint32_t image_id, partition_ids_t *item_id)
123 {
124     upg_image_partition_ids_map_t *map = NULL;
125     uint32_t cnt = upg_get_ids_map(&map);
126     if (cnt == 0 || map == NULL || item_id == NULL) {
127         return ERRCODE_FAIL;
128     }
129     for (uint32_t i = 0; i < cnt; i++) {
130         if (map[i].image_id == image_id) {
131             *item_id = map[i].item_id;
132             return ERRCODE_SUCC;
133         }
134     }
135     return ERRCODE_FAIL;
136 }
137 
upg_get_image_info(uint32_t image_id,partition_information_t * image_info)138 errcode_t upg_get_image_info(uint32_t image_id, partition_information_t *image_info)
139 {
140     partition_ids_t item_id;
141     if (image_info == NULL || upg_img_id_convert_to_partition_id(image_id, &item_id) != ERRCODE_SUCC) {
142         return ERRCODE_PARTITION_INVALID_PARAMS;
143     }
144 
145     return uapi_partition_get_info(item_id, image_info);
146 }
147 
148 #if (UPG_CFG_SUPPORT_FILE_SYSTEM == NO)
149 /*
150  * 读取升级包中的数据到buffer中
151  * read_offset 相对升级包开头的偏移
152  * buffer      读取数据buffer指针
153  * read_len    输入buffer的长度,输出实际读到的数据长度
154  */
upg_read_fota_pkg_data(uint32_t read_offset,uint8_t * buffer,uint32_t * read_len)155 errcode_t upg_read_fota_pkg_data(uint32_t read_offset, uint8_t *buffer, uint32_t *read_len)
156 {
157     errcode_t ret_val;
158     uint32_t start_addr = 0;
159     uint32_t size = 0;
160     uint32_t actual_len;
161 
162     ret_val = upg_get_fota_partiton_area_addr(&start_addr, &size);
163     if (ret_val != ERRCODE_SUCC) {
164         return ret_val;
165     }
166 
167     if (read_offset >= size || *read_len == 0) {
168         return ERRCODE_UPG_INVALID_PARAMETER;
169     }
170 
171     actual_len = ((read_offset + *read_len) > size) ? (size - read_offset) : *read_len;
172     start_addr += read_offset;
173 
174     ret_val = upg_flash_read(start_addr, actual_len, (uint8_t *)buffer);
175     if (ret_val != ERRCODE_SUCC) {
176         return ret_val;
177     }
178 
179     *read_len = actual_len;
180     return ERRCODE_SUCC;
181 }
182 
upg_package_get_storage_max_size(uint32_t * size)183 STATIC errcode_t upg_package_get_storage_max_size(uint32_t *size)
184 {
185     uint32_t start_addr = 0;
186     uint32_t fota_size = 0;
187     errcode_t ret = upg_get_fota_partiton_area_addr(&start_addr, &fota_size);
188     if (ret != ERRCODE_SUCC) {
189         return ret;
190     }
191 
192     fota_size -= UPG_META_DATA_LENGTH + UPG_UPGRADE_FLAG_LENGTH;
193     *size = fota_size;
194     return ERRCODE_SUCC;
195 }
196 #else
upg_read_fota_pkg_data(uint32_t read_offset,uint8_t * buffer,uint32_t * read_len)197 errcode_t upg_read_fota_pkg_data(uint32_t read_offset, uint8_t *buffer, uint32_t *read_len)
198 {
199     uint32_t len = 0;
200     struct stat stat_buff = {0};
201     errcode_t ret_code = ERRCODE_SUCC;
202     uint32_t ret = (uint32_t)stat(upg_get_pkg_file_path(), &stat_buff);
203     if (ret != 0 || stat_buff.st_size == 0) {
204         return ERRCODE_UPG_EMPTY_FILE;
205     }
206 
207     /* create ota image file */
208     int32_t rd_fd = open(upg_get_pkg_file_path(), O_RDONLY);
209     if (rd_fd < 0) {
210         return ERRCODE_UPG_FILE_OPEN_FAIL;
211     }
212 
213     if ((long int)read_offset >= (long int)stat_buff.st_size) {
214         upg_log_err("[UPG] The read_offset is more than file size!\r\n");
215         ret_code = ERRCODE_UPG_FILE_READ_FAIL;
216         goto end;
217     }
218 
219     long int left_len = ((long int)(read_offset + *read_len) > stat_buff.st_size) ?
220                         stat_buff.st_size - (long int)read_offset : (long int)(*read_len);
221     ret = (uint32_t)lseek(rd_fd, read_offset, SEEK_SET);
222     if (ret != read_offset) {
223         ret_code = ERRCODE_UPG_FILE_SEEK_FAIL;
224         goto end;
225     }
226 
227     while (left_len > 0) {
228         int32_t tmp = read(rd_fd, buffer + len, (size_t)left_len);
229         if (tmp <= 0) {
230             upg_log_err("[UPG] read_fota_pkg_data failed\r\n");
231             ret_code = ERRCODE_UPG_FILE_READ_FAIL;
232             goto end;
233         }
234         left_len -= tmp;
235         len += (uint32_t)tmp;
236     }
237 
238 end:
239     *read_len = len;
240     (void)close(rd_fd);
241     return ret_code;
242 }
243 
upg_package_get_storage_max_size(uint32_t * size)244 STATIC errcode_t upg_package_get_storage_max_size(uint32_t *size)
245 {
246     struct statfs sfs;
247     int result;
248     uint64_t free_size;
249     (void)memset_s(&sfs, sizeof(sfs), 0, sizeof(sfs));
250 
251     result = statfs(upg_get_pkg_file_dir(), &sfs);
252     if (result != 0 || sfs.f_type == 0) {
253         upg_log_err("[UPG] statfs failed! Invalid argument!\r\n");
254         return ERRCODE_FAIL;
255     }
256 
257     free_size = (uint64_t)sfs.f_bsize * sfs.f_bfree;
258     if (free_size <= PER_FILE_STORAGE_MAX_SIZE) {
259         *size = (uint32_t)free_size;
260     } else {
261         *size = PER_FILE_STORAGE_MAX_SIZE;
262     }
263     return ERRCODE_SUCC;
264 }
265 #endif
266 
267 /*
268  * 获取本地存储空间可存储升级包的最大空间
269  * 返回最大空间
270  */
uapi_upg_get_storage_size(void)271 uint32_t uapi_upg_get_storage_size(void)
272 {
273     if (upg_is_inited() == false) {
274         return 0;
275     }
276 
277     uint32_t size;
278     if (upg_package_get_storage_max_size(&size) != ERRCODE_SUCC) {
279         return 0;
280     }
281     return size;
282 }
283 
284 /*
285  * 获取升级包包头结构指针
286  * pkg_header 返回升级包头结构指针,指针指向的空间在函数内分配,需要使用者使用完后调用upg_free释放。
287  *            (如果采用直接访问flash的方式,返回升级包头所在的flash地址)
288  */
upg_get_package_header(upg_package_header_t ** pkg_header)289 errcode_t upg_get_package_header(upg_package_header_t **pkg_header)
290 {
291 #if (UPG_CFG_DIRECT_FLASH_ACCESS == NO)
292     errcode_t ret;
293     uint32_t actual_len = (uint32_t)sizeof(upg_package_header_t);
294 
295     *pkg_header = upg_malloc(sizeof(upg_package_header_t));
296     if (*pkg_header == NULL) {
297         return ERRCODE_MALLOC;
298     }
299 
300     ret = upg_read_fota_pkg_data(0, (uint8_t *)(*pkg_header), &actual_len);
301     if (ret != ERRCODE_SUCC || actual_len != sizeof(upg_package_header_t)) {
302         upg_free(*pkg_header);
303         *pkg_header = NULL;
304         return ret;
305     }
306 #else
307     uint32_t start_addr = 0;
308     uint32_t size = 0;
309     errcode_t ret;
310     ret = upg_get_fota_partiton_area_addr(&start_addr, &size);
311     if (ret != ERRCODE_SUCC) {
312         return ret;
313     }
314 
315     *pkg_header = (upg_package_header_t*)(uintptr_t)(start_addr + upg_get_flash_base_addr());
316 #endif /* #if UPG_CFG_DIRECT_FLASH_ACCESS */
317 
318     return ERRCODE_SUCC;
319 }
320 
321 /*
322  * 获取镜像哈希表结构指针
323  * pkg_header 升级包头结构指针
324  * img_hash_table 返回对应的升级镜像HASH表头指针,指针指向的空间在函数内分配,需要使用者使用完后调用upg_free释放。
325  *                (如果采用直接访问flash的方式,返回升级镜像哈希表所在的flash地址)
326  */
upg_get_pkg_image_hash_table(const upg_package_header_t * pkg_header,upg_image_hash_node_t ** img_hash_table)327 errcode_t upg_get_pkg_image_hash_table(const upg_package_header_t *pkg_header,
328                                        upg_image_hash_node_t **img_hash_table)
329 {
330     uint32_t offset;
331     errcode_t ret_val;
332 
333     if (pkg_header->info_area.image_hash_table_addr == 0) {
334         offset = (uint32_t)sizeof(upg_package_header_t);
335     } else {
336         offset = pkg_header->info_area.image_hash_table_addr;
337     }
338 
339 #if (UPG_CFG_DIRECT_FLASH_ACCESS == NO)
340     /* 由于ImageHashTable为了16字节对齐有填充字段,此处的长度不能使用image_num * sizeof(upg_image_hash_node_t)) */
341     uint32_t actual_len = pkg_header->info_area.image_hash_table_length;
342 
343     *img_hash_table = upg_malloc(actual_len);
344     if (*img_hash_table == NULL) {
345         return ERRCODE_MALLOC;
346     }
347 
348     ret_val = upg_read_fota_pkg_data(offset, (uint8_t *)(*img_hash_table), &actual_len);
349     if (ret_val != ERRCODE_SUCC || actual_len != pkg_header->info_area.image_hash_table_length) {
350         upg_free(*img_hash_table);
351         *img_hash_table = NULL;
352         return ret_val;
353     }
354 
355 #else
356     uint32_t start_addr = 0;
357     uint32_t size = 0;
358 
359     ret_val = upg_get_fota_partiton_area_addr(&start_addr, &size);
360     if (ret_val != ERRCODE_SUCC) {
361         return ret_val;
362     }
363 
364     start_addr += offset;
365 
366     *img_hash_table = (upg_image_hash_node_t*)(uintptr_t)(start_addr + upg_get_flash_base_addr());
367 #endif /* #if UPG_CFG_DIRECT_FLASH_ACCESS */
368 
369     return ERRCODE_SUCC;
370 }
371 
372 /*
373  * 获取升级镜像的头结构指针
374  * img_hash_table 升级镜像HASH表节点指针
375  * img_header 返回对应的升级镜像头指针,指针指向的空间在函数内分配,需要使用者使用完后调用upg_free释放。
376  *            (如果采用直接访问flash的方式,返回镜像头所在的flash地址)
377  */
upg_get_pkg_image_header(const upg_image_hash_node_t * img_hash_table,upg_image_header_t ** img_header)378 errcode_t upg_get_pkg_image_header(const upg_image_hash_node_t *img_hash_table, upg_image_header_t **img_header)
379 {
380 #if (UPG_CFG_DIRECT_FLASH_ACCESS == NO)
381     errcode_t ret_val;
382     uint32_t actual_len = (uint32_t)sizeof(upg_image_header_t);
383 
384     *img_header = upg_malloc(sizeof(upg_image_header_t));
385     if (*img_header == NULL) {
386         return ERRCODE_MALLOC;
387     }
388 
389     ret_val = upg_read_fota_pkg_data(img_hash_table->image_addr, (uint8_t *)(*img_header), &actual_len);
390     if (ret_val != ERRCODE_SUCC || actual_len != sizeof(upg_image_header_t)) {
391         upg_free(*img_header);
392         *img_header = NULL;
393         return ret_val;
394     }
395 #else
396     uint32_t start_addr = 0;
397     uint32_t size = 0;
398     errcode_t ret_val;
399     ret_val = upg_get_fota_partiton_area_addr(&start_addr, &size);
400     if (ret_val != ERRCODE_SUCC) {
401         return ret_val;
402     }
403 
404     start_addr += img_hash_table->image_addr;
405 
406     *img_header = (upg_image_header_t*)(uintptr_t)(start_addr + upg_get_flash_base_addr());
407 #endif /* #if UPG_CFG_DIRECT_FLASH_ACCESS */
408 
409     return ERRCODE_SUCC;
410 }
411 
412 /*
413  * 获取升级镜像的数据指针
414  * img_header 升级镜像头结构指针
415  * data_offset 相对升级镜像数据开头的偏移
416  * data_len 输入要获取数据的长度,输出实际获取到的数据长度
417  * img_data 返回升级镜像数据的指针
418             如果未采用直接访问flash方式(即UPG_CFG_DIRECT_FLASH_ACCESS==NO),返回的指针指向的空间在函数内分配,使用者使用完后
419                 必须调用upg_free释放。
420  *          如果采用直接访问flash的方式(即UPG_CFG_DIRECT_FLASH_ACCESS==YES),返回指针为数据所在的flash地址,使用者无需释放。
421  */
upg_get_pkg_image_data(const upg_image_header_t * img_header,uint32_t data_offset,uint32_t * data_len,uint8_t ** img_data)422 errcode_t upg_get_pkg_image_data(const upg_image_header_t *img_header,
423                                  uint32_t data_offset, uint32_t *data_len, uint8_t **img_data)
424 {
425 #if (UPG_CFG_DIRECT_FLASH_ACCESS == NO)
426     errcode_t ret_val;
427     *img_data = upg_malloc(*data_len);
428     if (*img_data == NULL) {
429         return ERRCODE_MALLOC;
430     }
431 
432     ret_val = upg_copy_pkg_image_data(img_header, data_offset, data_len, *img_data);
433     if (ret_val != ERRCODE_SUCC) {
434         upg_free(*img_data);
435         *img_data = NULL;
436         return ret_val;
437     }
438 #else
439     uint32_t start_addr = 0;
440     uint32_t size = 0;
441     uint32_t actual_len;
442     errcode_t ret_val;
443     uint32_t aligned_image_len = upg_aligned(img_header->image_len, 16); /* 16-byte alignment */
444 
445     ret_val = upg_get_fota_partiton_area_addr(&start_addr, &size);
446     if (ret_val != ERRCODE_SUCC) {
447         return ret_val;
448     }
449 
450     if (data_offset >= aligned_image_len || img_data == NULL ||
451         data_len == NULL || *data_len == 0) {
452         return ERRCODE_UPG_INVALID_PARAMETER;
453     }
454 
455     actual_len = (data_offset + *data_len > aligned_image_len) ? (aligned_image_len - data_offset) : *data_len;
456 
457     start_addr += img_header->image_offset;
458     *img_data = (uint8_t*)(uintptr_t)(start_addr + data_offset + upg_get_flash_base_addr());
459     *data_len = actual_len;
460 #endif /* #if UPG_CFG_DIRECT_FLASH_ACCESS */
461     return ERRCODE_SUCC;
462 }
463 
464 /*
465  * 拷贝升级镜像指定范围的数据至buffer中
466  * img_header 升级镜像头结构指针
467  * data_offset 相对升级镜像数据开头的偏移
468  * data_len 输出要拷贝的数据的长度,输出实际拷贝的数据长度
469  * img_data 保存数据的buffer指针,buffer的空间需要使用者分配
470  */
upg_copy_pkg_image_data(const upg_image_header_t * img_header,uint32_t data_offset,uint32_t * data_len,uint8_t * img_data)471 errcode_t upg_copy_pkg_image_data(const upg_image_header_t *img_header,
472                                   uint32_t data_offset, uint32_t *data_len, uint8_t *img_data)
473 {
474     errcode_t ret_val;
475     uint32_t aligned_image_len = upg_aligned(img_header->image_len, 16); /* 16-byte alignment */
476     uint32_t actual_len;
477 
478     if (data_offset >= aligned_image_len || img_data == NULL ||
479         data_len == NULL || *data_len == 0) {
480         return ERRCODE_UPG_INVALID_PARAMETER;
481     }
482 
483     actual_len = (data_offset + *data_len > aligned_image_len) ? (aligned_image_len - data_offset) : *data_len;
484 
485     ret_val = upg_read_fota_pkg_data(img_header->image_offset + data_offset, img_data, &actual_len);
486     if (ret_val != ERRCODE_SUCC) {
487         return ret_val;
488     }
489 
490     *data_len = actual_len;
491     return ERRCODE_SUCC;
492 }
493 
494 #if UPG_CFG_SUPPORT_IMAGE_ON_FILE_SYSTEM == YES
upg_read_old_image_data_from_fs(const char * file_path,uint32_t read_offset,uint8_t * buffer,uint32_t * read_len)495 STATIC errcode_t upg_read_old_image_data_from_fs(const char *file_path, uint32_t read_offset,
496                                                  uint8_t *buffer, uint32_t *read_len)
497 {
498     uint16_t len = 0;
499     struct stat stat_buff = {0};
500     uint32_t ret = stat(file_path, &stat_buff);
501     if (ret != 0 || stat_buff.st_size == 0) {
502         return ERRCODE_UPG_EMPTY_FILE;
503     }
504 
505     /* create ota image file */
506     FILE *rd_fd = fopen(file_path, "rb");
507     if (rd_fd == NULL) {
508         upg_log_err("[UPG] open %s fail!\r\n", file_path);
509         return ERRCODE_UPG_FILE_OPEN_FAIL;
510     }
511 
512     if ((long int)read_offset > stat_buff.st_size) {
513         upg_log_err("[UPG] The read_offset is more than file size!\r\n");
514         ret = ERRCODE_UPG_FILE_READ_FAIL;
515         goto end;
516     }
517 
518     long int left_len = ((long int)(read_offset + *read_len) > stat_buff.st_size) ?
519                         stat_buff.st_size - (long int)read_offset : (long int)(*read_len);
520     ret = fseek(rd_fd, read_offset, SEEK_SET);
521     if (ret != 0) {
522         upg_log_err("[UPG] seek file fail!\r\n");
523         ret = ERRCODE_UPG_FILE_SEEK_FAIL;
524         goto end;
525     }
526 
527     while (left_len > 0) {
528         uint16_t tmp_read = fread(buffer + len, 1, left_len, rd_fd);
529         if (tmp_read == 0) {
530             if (ferror(rd_fd)) {
531                 upg_log_err("[UPG] read file fail!\r\n");
532                 ret = ERRCODE_UPG_FILE_READ_FAIL;
533                 goto end;
534             }
535         }
536         left_len -= tmp_read;
537         len += tmp_read;
538     }
539 
540 end:
541     *read_len = len;
542     (void)fclose(rd_fd);
543     return ret;
544 }
545 #endif
546 
547 /*
548  * 从指定image_id的镜像所在的地址上读取数据到buffer中
549  * write_offset 相对镜像起始地址的偏移
550  * buffer       存储数据的buffer指针
551  * write_len    buffer的长度
552  * image_id     镜像的ID
553  */
upg_read_old_image_data(uint32_t read_offset,uint8_t * buffer,uint32_t * read_len,uint32_t image_id)554 errcode_t upg_read_old_image_data(uint32_t read_offset, uint8_t *buffer, uint32_t *read_len, uint32_t image_id)
555 {
556     errcode_t ret_val;
557     partition_information_t image_info = {0};
558 
559     if (image_id == PARAMS_PARTITION_IMAGE_ID) {
560         /* 参数区地址信息 */
561         image_info.type = PARTITION_BY_ADDRESS;
562         image_info.part_info.addr_info.size = PARAMS_PARTITION_LENGTH;
563         image_info.part_info.addr_info.addr = PARAMS_PARTITION_START_ADDR;
564     } else {
565         ret_val = upg_get_image_info(image_id, &image_info);
566         if (ret_val != ERRCODE_SUCC) {
567             return ret_val;
568         }
569     }
570 
571     if (image_info.type == PARTITION_BY_ADDRESS) {
572         uint32_t app_address = image_info.part_info.addr_info.addr;
573         ret_val = upg_flash_read(app_address + read_offset, *read_len, (uint8_t *)buffer);
574     } else { /* 分区类型:PARTITION_BY_PATH */
575 #if UPG_CFG_SUPPORT_IMAGE_ON_FILE_SYSTEM == YES
576         ret_val = upg_read_old_image_data_from_fs(
577             (const char *)image_info.part_info.file_path, read_offset, buffer, read_len);
578 #else
579         ret_val = ERRCODE_UPG_INVALID_IMAGE_ID;
580 #endif
581     }
582     return ret_val;
583 }
584 
upg_get_firmware_flag_address(uint32_t firmware_index,uint32_t current_loop,uint32_t * flag_addr)585 STATIC errcode_t upg_get_firmware_flag_address(uint32_t firmware_index, uint32_t current_loop, uint32_t *flag_addr)
586 {
587     uint32_t fota_flag_addr = 0;
588     uint32_t addr;
589 
590     errcode_t ret = upg_get_upgrade_flag_flash_start_addr(&fota_flag_addr);
591     if (ret != ERRCODE_SUCC) {
592         return ret;
593     }
594 
595     if (firmware_index == UPG_IMAGE_ID_NV) {
596         addr = fota_flag_addr + offsetof(fota_upgrade_flag_area_t, nv_flag);
597         addr += current_loop * (uint32_t)sizeof(uint8_t);
598     } else {
599         addr = fota_flag_addr + offsetof(fota_upgrade_flag_area_t, firmware_flag);
600         addr += (firmware_index * UPG_FLAG_RETYR_TIMES) + (current_loop * (uint32_t)sizeof(uint8_t));
601     }
602 
603     *flag_addr = addr;
604     return ERRCODE_SUCC;
605 }
606 
607 /*
608  * 设置指定固件的升级标记
609  * firmware_index为升级包中的固件(除NV之外的镜像)的序号
610  * 如升级包中包含 固件0、固件1、固件2、NV、固件3,其中固件3的序号为3而不是4
611  */
upg_set_firmware_update_status(fota_upgrade_flag_area_t * upg_flag,uint32_t firmware_index,upg_image_status_switch_t switch_status)612 errcode_t upg_set_firmware_update_status(fota_upgrade_flag_area_t *upg_flag,
613                                          uint32_t firmware_index, upg_image_status_switch_t switch_status)
614 {
615     uint32_t write_len = 0;
616     uint32_t flag_addr = 0;
617     uint8_t *firmware_flag;
618     uint32_t i;
619 
620     if (firmware_index == UPG_IMAGE_ID_NV) {
621         firmware_flag = upg_flag->nv_flag;
622     } else {
623         firmware_flag = upg_flag->firmware_flag[firmware_index];
624     }
625 
626     /* 获取第一个非0的flag, 即第i次重试的flag */
627     for (i = 0; i < UPG_FLAG_RETYR_TIMES; i++) {
628         if (firmware_flag[i] != 0) {
629             break;
630         }
631     }
632 
633     if (i >= UPG_FLAG_RETYR_TIMES) {
634         return ERRCODE_SUCC;
635     }
636 
637     errcode_t ret = upg_get_firmware_flag_address(firmware_index, i, &flag_addr);
638     if (ret != ERRCODE_SUCC) {
639         return ret;
640     }
641 
642     if ((switch_status == UPG_IMAGE_STATUS_SWITCH_TO_STARTED) && (firmware_flag[i] == NOT_START_FLAG)) {
643         /* 当前flag为NOT_START, 要切换成STARTED */
644         write_len = 1;
645         firmware_flag[i] = STARTED_FLAG;
646     } else if ((switch_status == UPG_IMAGE_STATUS_SWITCH_TO_RETRY) && (firmware_flag[i] == STARTED_FLAG)) {
647         /* 当前flag为STARTED, 要切换成RETRY, 即当前flag置为0 */
648         write_len = 1;
649         firmware_flag[i] = FINISHED_FLAG;
650     } else if (switch_status == UPG_IMAGE_STATUS_SWITCH_TO_FINISHED) {
651         /* 要切换成FINISH,即全部flag置为0 */
652         write_len = UPG_FLAG_RETYR_TIMES - i;
653         (void)memset_s(&firmware_flag[i], write_len, FINISHED_FLAG, write_len);
654     } else {
655         /* 其他情况不做处理 */
656         return ERRCODE_SUCC;
657     }
658 
659     ret = upg_flash_write(flag_addr, write_len, (uint8_t *)&(firmware_flag[i]), false);
660     if (ret != ERRCODE_SUCC) {
661         upg_log_err("[UPG] upg_flash_write upgrader flag fail. ret = 0x%x\r\n", ret);
662         return ret;
663     }
664 
665     if (i >= UPG_FLAG_RETYR_TIMES - 1 && firmware_flag[i] == FINISHED_FLAG) {
666         upg_log_err("[UPG] retry times all failed\r\n");
667         upg_set_temporary_result(UPG_RESULT_RETRY_ALL_FAILED);
668         return ERRCODE_UPG_RETRY_ALL_FAIL;
669     }
670     return ERRCODE_SUCC;
671 }
672 
673 /*
674  * 获取升级包中的升级镜像的升级标记状态(NOT_STARTED/STARTED/RETRY/FINISHED)
675  * firmware_index为升级包中的固件(除NV之外的镜像)的序号
676  * 如升级包中包含 固件0、固件1、固件2、NV、固件3,其中固件3的序号为3而不是4
677  * 如为NV镜像,firmware_index参数可忽略
678  */
upg_get_image_update_status(fota_upgrade_flag_area_t * upg_flag,uint32_t firmware_index,uint32_t image_id)679 upg_image_status_t upg_get_image_update_status(fota_upgrade_flag_area_t *upg_flag,
680                                                uint32_t firmware_index, uint32_t image_id)
681 {
682     uint8_t *firmware_flag;
683     uint8_t finished_flag[UPG_FLAG_RETYR_TIMES] = { FINISHED_FLAG, FINISHED_FLAG, FINISHED_FLAG };
684     uint8_t init_flag[UPG_FLAG_RETYR_TIMES] = { NOT_START_FLAG, NOT_START_FLAG, NOT_START_FLAG };
685     uint32_t i;
686 
687     if (image_id == UPG_IMAGE_ID_NV) {
688         firmware_flag = upg_flag->nv_flag;
689     } else {
690         firmware_flag = upg_flag->firmware_flag[firmware_index];
691     }
692 
693     if (memcmp(firmware_flag, finished_flag, UPG_FLAG_RETYR_TIMES) == 0) {
694         /* 3个flag都是0x00, 处理完成状态 */
695         return UPG_IMAGE_STATUS_FINISHED;
696     } else if (memcmp(firmware_flag, init_flag, UPG_FLAG_RETYR_TIMES) == 0) {
697         /* 3个flag都是0xFF, 未开始处理状态 */
698         return UPG_IMAGE_STATUS_NOT_STARTED;
699     } else {
700         /* 获取第一个非0的flag,即当前正在处理的第i次重试的flag */
701         for (i = 0; i < UPG_FLAG_RETYR_TIMES; i++) {
702             if (firmware_flag[i] != 0) {
703                 break;
704             }
705         }
706 
707         if (firmware_flag[i] == STARTED_FLAG) {
708             return UPG_IMAGE_STATUS_STARTED;
709         } else if (firmware_flag[i] == NOT_START_FLAG) {
710             return UPG_IMAGE_STATUS_RETRY;
711         } else {
712             return UPG_IMAGE_STATUS_INVALID;
713         }
714     }
715 }
716 
717 /* 擦除metadata数据区 */
upg_flash_erase_metadata_pages(void)718 errcode_t upg_flash_erase_metadata_pages(void)
719 {
720     return ERRCODE_SUCC;
721 }
722 
723 /* 设置升级结果(临时保存) */
upg_set_temporary_result(upg_result_t result)724 void upg_set_temporary_result(upg_result_t result)
725 {
726     upg_get_ctx()->temporary_result = result;
727 }
728 
729 /* 获取临时保存的升级结果 */
upg_get_temporary_result(void)730 upg_result_t upg_get_temporary_result(void)
731 {
732     return upg_get_ctx()->temporary_result;
733 }
734 
735 /* 将升级结果保存至Flash升级标记区 */
upg_set_update_result(upg_result_t result)736 void upg_set_update_result(upg_result_t result)
737 {
738     uint32_t fota_flag_addr = 0;
739     uint32_t result_tmp = (uint32_t)result;
740     errcode_t ret = upg_get_upgrade_flag_flash_start_addr(&fota_flag_addr);
741     if (ret != ERRCODE_SUCC) {
742         return;
743     }
744 
745     uint32_t result_addr = fota_flag_addr + offsetof(fota_upgrade_flag_area_t, update_result);
746     ret = upg_flash_write(result_addr, sizeof(uint32_t), (uint8_t *)&(result_tmp), false);
747     if (ret != ERRCODE_SUCC) {
748         return;
749     }
750     return;
751 }
752 
753 /* 检查是否所有镜像都已完成升级(包括升级失败但是已尝试最大次数) */
upg_check_image_update_complete(const fota_upgrade_flag_area_t * upg_flag,uint32_t image_num)754 bool upg_check_image_update_complete(const fota_upgrade_flag_area_t *upg_flag, uint32_t image_num)
755 {
756     uint32_t firmware_index;
757     const uint8_t *firmware_flag;
758     uint8_t finish_flag[UPG_FLAG_RETYR_TIMES] = {FINISHED_FLAG, FINISHED_FLAG, FINISHED_FLAG};
759 
760     for (firmware_index = 0; firmware_index < upg_flag->firmware_num; firmware_index++) {
761         firmware_flag = upg_flag->firmware_flag[firmware_index];
762         /* 存在升级包未完成升级 */
763         if (memcmp(firmware_flag, finish_flag, UPG_FLAG_RETYR_TIMES) != 0) {
764             return false;
765         }
766     }
767 
768     /* 存在nv升级包,并且nv升级准备工作未完成 */
769     if (upg_flag->firmware_num != image_num && upg_flag->nv_flag[0] != STARTED_FLAG) { /* index 0:start flag */
770         return false;
771     }
772     return true;
773 }
774 
upg_write_complete_flag(uint32_t fota_flag_addr,uint32_t complete_flag)775 STATIC void upg_write_complete_flag(uint32_t fota_flag_addr, uint32_t complete_flag)
776 {
777     if (complete_flag != UPG_ABNORMAL_FLAG) {
778         uint32_t flag_addr = fota_flag_addr + offsetof(fota_upgrade_flag_area_t, complete_flag);
779         upg_log_info("[UPG] write complete: 0x%x\r\n", complete_flag);
780         if (upg_flash_write(flag_addr, sizeof(uint32_t), (uint8_t *)&(complete_flag), false) != ERRCODE_SUCC) {
781             return;
782         }
783     }
784 
785 #if (UPG_CFG_SUPPORT_RESOURCES_FILE == YES)
786     if (complete_flag == 0) {
787         dfx_file_delete(upg_get_res_file_index_path());
788     }
789 #endif
790 }
791 /* 设置升级完成标记 */
upg_set_complete_flag(uint32_t image_num,errcode_t result,bool direct_finish)792 void upg_set_complete_flag(uint32_t image_num, errcode_t result, bool direct_finish)
793 {
794     uint32_t fota_flag_addr = 0;
795     uint32_t complete_flag = UPG_ABNORMAL_FLAG;
796     bool image_complete = false;
797 
798     errcode_t ret = upg_get_upgrade_flag_flash_start_addr(&fota_flag_addr);
799     if (ret != ERRCODE_SUCC) {
800         return;
801     }
802 
803     fota_upgrade_flag_area_t upg_flag;
804     ret = upg_flash_read(fota_flag_addr, sizeof(fota_upgrade_flag_area_t), (uint8_t *)(&upg_flag));
805     if (ret != ERRCODE_SUCC) {
806         upg_log_err("[UPG] upg_flash_read flag fail\r\n");
807         return;
808     }
809 
810     do {
811         /*
812          * 1. 当前程序中升级流程返回失败,直接结束升级流程(如整包校验失败),
813          *    则升级流程失败,结束升级,将flag置成 UPG_FINISH_ALL_FLAG;
814          */
815         if (direct_finish && (upg_flag.complete_flag != UPG_FINISH_ALL_FLAG)) {
816             complete_flag = UPG_FINISH_ALL_FLAG;
817             /* 保存升级结果至升级标记区内 */
818             upg_set_update_result(upg_get_temporary_result());
819             break;
820         }
821 
822         /*
823          * 2. 当前程序中升级流程返回成功,
824          *    即当前程序中支持升级的所有镜像成功升级,但存在还需要升级的镜像,则将flag置成 UPG_FINISH_HALF_FLAG;
825          */
826         image_complete = upg_check_image_update_complete(&upg_flag, image_num);
827         if (result == ERRCODE_SUCC && !image_complete) {
828             if (upg_flag.complete_flag != UPG_FINISH_HALF_FLAG) {
829                 complete_flag = UPG_FINISH_HALF_FLAG;
830             }
831         } else if (image_complete && (upg_flag.complete_flag != UPG_FINISH_ALL_FLAG)) {
832             /*
833              * 3. 若升级包中所有镜像成功升级,将flag置成 UPG_FINISH_ALL_FLAG;
834              */
835             complete_flag = UPG_FINISH_ALL_FLAG;
836             if (result == ERRCODE_SUCC) {
837                 upg_set_temporary_result(UPG_RESULT_UPDATE_SUCCESS);
838             }
839             /* 保存升级结果至升级标记区内 */
840             upg_set_update_result(upg_get_temporary_result());
841         } else if (upg_get_temporary_result() == UPG_RESULT_RETRY_ALL_FAILED &&
842             (upg_flag.complete_flag != UPG_FINISH_ALL_FLAG)) {
843             /*
844              * 4. 当前程序中升级流程返回失败,但最后一个已处理的镜像的3个flag全0,即已经重试最大次数,仍然失败,
845              *    则升级流程失败,结束升级,将flag置成 UPG_FINISH_ALL_FLAG;
846              */
847             complete_flag = UPG_FINISH_ALL_FLAG;
848             upg_set_update_result(upg_get_temporary_result());
849         }
850     } while (0);
851 
852     /* 升级标记需要修改 */
853     upg_write_complete_flag(fota_flag_addr, complete_flag);
854 }
855 
856 /* 获取升级结果 */
uapi_upg_get_result(upg_result_t * result,uint32_t * last_image_index)857 errcode_t uapi_upg_get_result(upg_result_t *result, uint32_t *last_image_index)
858 {
859     if (result == NULL || last_image_index == NULL) {
860         return ERRCODE_UPG_NULL_POINTER;
861     }
862     fota_upgrade_flag_area_t *upg_flag_info;
863     errcode_t ret = upg_alloc_and_get_upgrade_flag(&upg_flag_info);
864     if (ret != ERRCODE_SUCC || upg_flag_info == NULL) {
865         return ret;
866     }
867 
868     *result = upg_flag_info->update_result;
869     *last_image_index = UINT32_MAX;
870     upg_free(upg_flag_info);
871     return ERRCODE_SUCC;
872 }
873 
874 /* 获取注册函数列表 */
upg_get_func_list(void)875 upg_func_t *upg_get_func_list(void)
876 {
877     return &(g_upg_ctx.func_list);
878 }
879 
upg_is_inited(void)880 bool upg_is_inited(void)
881 {
882     return g_upg_ctx.inited;
883 }
884 
upg_get_status(void)885 STATIC upg_status_t upg_get_status(void)
886 {
887     uint8_t temp = 0;
888     upg_status_t status = UPG_STATUS_NONE;
889     uint32_t flag_addr = 0;
890     fota_upgrade_flag_area_t *upg_flag_info = NULL;
891     if (upg_alloc_and_get_upgrade_flag(&upg_flag_info) != ERRCODE_SUCC) {
892         return status;
893     }
894 
895     do {
896         if (upg_flag_info->head_magic != UPG_HEAD_MAGIC || upg_flag_info->head_end_magic != UPG_END_MAGIC) {
897             status = UPG_STATUS_NONE;
898             break;
899         }
900 
901         if (upg_flag_info->complete_flag != 0) {
902             status = UPG_STATUS_UPDATING;
903             break;
904         }
905 
906         if (upg_flag_info->ver_change_flag == 0) {
907             status = UPG_STATUS_NONE;
908             break;
909         }
910 
911         if (upg_flag_info->update_result == UPG_RESULT_UPDATE_SUCCESS) {
912             status = UPG_STATUS_SUCC;
913         } else {
914             status = UPG_STATUS_FAIL;
915         }
916         if (upg_get_upgrade_flag_flash_start_addr(&flag_addr) != ERRCODE_SUCC) {
917             status = UPG_STATUS_NONE;
918             break;
919         }
920 
921         flag_addr += offsetof(fota_upgrade_flag_area_t, ver_change_flag);
922         if (upg_flash_write(flag_addr, sizeof(uint8_t), &temp, false) != ERRCODE_SUCC) {
923             status = UPG_STATUS_NONE;
924         }
925     } while (0);
926 
927     upg_free(upg_flag_info);
928     return status;
929 }
930 
uapi_upg_init(const upg_func_t * func_list)931 errcode_t uapi_upg_init(const upg_func_t *func_list)
932 {
933     if (upg_is_inited()) {
934         return ERRCODE_UPG_ALREADY_INIT;
935     }
936 
937     if (func_list != NULL) {
938         g_upg_ctx.func_list.malloc = func_list->malloc;
939         g_upg_ctx.func_list.free = func_list->free;
940         g_upg_ctx.func_list.serial_putc = func_list->serial_putc;
941     }
942     g_upg_ctx.temporary_result = UPG_RESULT_MAX;
943     g_upg_ctx.packge_len = 0;
944     g_upg_ctx.inited = true;
945     g_upg_ctx.upg_status = upg_get_status();
946     return ERRCODE_SUCC;
947 }
948 
949 #if (UPG_CFG_ANTI_ROLLBACK_SUPPORT == YES)
upg_anti_rollback_version_verify(const upg_package_header_t * pkg_header,const upg_image_header_t * img_header)950 errcode_t upg_anti_rollback_version_verify(
951     const upg_package_header_t *pkg_header, const upg_image_header_t *img_header)
952 {
953     // NV及资源文件不做防回滚
954     if (img_header->image_id == UPG_IMAGE_ID_NV || img_header->image_id == UPG_IMAGE_ID_RES_INDEX ||
955         img_header->image_id == UPG_IMAGE_ID_RES_DATA) {
956         return ERRCODE_SUCC;
957     }
958     uint32_t image_id = img_header->image_id;
959     uint32_t key_ver = pkg_header->key_area.fota_key_version_ext;
960     uint32_t code_ver = img_header->version_ext;
961     uint32_t otp_ver;
962 
963     errcode_t ret = upg_get_board_rollback_version(image_id, &otp_ver);
964     if (ret != ERRCODE_SUCC) {
965         return ret;
966     }
967 
968     uint32_t board_key_mask;
969     uint32_t board_code_mask;
970 
971     ret = upg_get_board_version_mask(image_id, &board_key_mask, &board_code_mask);
972     if (ret != ERRCODE_SUCC) {
973         return ret;
974     }
975     if (((key_ver & board_key_mask) < (otp_ver & board_key_mask)) ||
976         ((code_ver & board_code_mask) < (otp_ver & board_code_mask))) {
977         return ERRCODE_FAIL;
978     }
979     upg_log_info("[UPG] upg verify: anti rollback version_verify ok. image_id = 0x%x\r\n", img_header->image_id);
980     return ERRCODE_SUCC;
981 }
982 
upg_anti_rollback_version_update(const upg_image_header_t * img_header)983 errcode_t upg_anti_rollback_version_update(const upg_image_header_t *img_header)
984 {
985     // NV及资源文件不做防回滚
986     if (img_header->image_id == UPG_IMAGE_ID_NV || img_header->image_id == UPG_IMAGE_ID_RES_INDEX ||
987         img_header->image_id == UPG_IMAGE_ID_RES_DATA) {
988         return ERRCODE_SUCC;
989     }
990 
991     uint32_t image_id = img_header->image_id;
992     uint32_t key_ver = 0;
993     uint32_t board_key_mask = 0;
994     uint32_t code_ver = 0;
995     uint32_t board_code_mask = 0;
996     uint32_t new_ver;
997     uint32_t old_ver;
998 
999     errcode_t ret = upg_get_board_rollback_version(image_id, &old_ver);
1000     if (ret != ERRCODE_SUCC) {
1001         return ret;
1002     }
1003 
1004     // 获取更新后的板端的掩码
1005     ret = upg_get_board_version_mask(image_id, &board_key_mask, &board_code_mask);
1006     if (ret != ERRCODE_SUCC) {
1007         return ret;
1008     }
1009      // 获取更新后的板端镜像版本
1010     ret = upg_get_board_version(image_id, &key_ver, &code_ver);
1011     if (ret != ERRCODE_SUCC) {
1012         return ret;
1013     }
1014     if ((code_ver & board_code_mask) < (old_ver & board_code_mask) ||
1015         (key_ver & board_key_mask) < (old_ver & board_key_mask)) {
1016         return ERRCODE_FAIL;
1017     }
1018 
1019     new_ver = (code_ver & board_code_mask) | (key_ver & board_key_mask);
1020     return upg_set_board_rollback_version(image_id, &new_ver);
1021 }
1022 #endif
1023