• 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 for different chip
15  */
16 
17 #include <stddef.h>
18 #include <stdint.h>
19 #include <stdbool.h>
20 #include "errcode.h"
21 #include "common_def.h"
22 #include "upg_debug.h"
23 #include "partition.h"
24 #include "securec.h"
25 #include "upg_porting.h"
26 #include "tcxo.h"
27 #include "non_os.h"
28 #include "cpu_utils.h"
29 #if (UPG_CFG_VERIFICATION_SUPPORT == YES)
30 #include "efuse.h"
31 #endif
32 #include "efuse_porting.h"
33 #include "sfc.h"
34 #include "watchdog.h"
35 #include "upg_alloc.h"
36 #include "upg_config.h"
37 #include "upg_definitions_porting.h"
38 #include "upg_common.h"
39 #include "upg_common_porting.h"
40 #ifndef WS63_PRODUCT_NONE
41 #include "osal_addr.h"
42 #endif
43 #ifdef CONFIG_MIDDLEWARE_SUPPORT_UPG_SAMPLE_VERIFY
44 #include "secure_verify_boot.h"
45 #endif
46 
47 #define MS_ID_ADDR        0xF8
48 #define CHIP_ID_ADDR      OTP_CHIP_ID_START
49 #define TCXO_REBOOT_DELAY 500ULL
50 
51 #define uapi_array_size(_array)  (sizeof(_array) / sizeof((_array)[0]))
52 
53 static upg_image_partition_ids_map_t g_img_partition_map[] = {
54     {FLASH_BOOT_IMAGE_ID, PARTITION_FLASH_BOOT_IMAGE},
55     {APPLICATION_IMAGE_ID, PARTITION_APP_IMAGE},
56     {HILINK_IMAGE_ID, PARTITION_HILINK_IMAGE},
57 };
58 
59 /* 获取镜像ID和分区ID的map表
60  * map: 镜像ID和分区ID的映射表
61  * 返回map表中映射数量
62  */
upg_get_ids_map(upg_image_partition_ids_map_t ** map)63 uint32_t upg_get_ids_map(upg_image_partition_ids_map_t **map)
64 {
65     *map = g_img_partition_map;
66     return uapi_array_size(g_img_partition_map);
67 }
68 
69 /*
70  * recovery/APP支持升级的镜像ID
71  * 注意增删ID时同步更新升级ID的数量
72  */
73 #define UPDATE_IMAGE_SET \
74     { FLASH_BOOT_IMAGE_ID, APPLICATION_IMAGE_ID, UPG_IMAGE_ID_NV, HILINK_IMAGE_ID}
75 #define UPDATE_IMAGE_SET_CNT 4 /* 镜像ID列表长度 */
76 
77 static uint32_t g_ws63_support_upg_id[] = UPDATE_IMAGE_SET;
78 static upg_image_collections_t g_ws63_upg_collect = { g_ws63_support_upg_id, UPDATE_IMAGE_SET_CNT };
79 /* 获取当前程序支持的升级镜像 */
uapi_upg_get_image_id_collection(void)80 upg_image_collections_t *uapi_upg_get_image_id_collection(void)
81 {
82     return &g_ws63_upg_collect;
83 }
84 
85 /* 获取升级包路径 */
upg_get_pkg_file_path(void)86 char *upg_get_pkg_file_path(void)
87 {
88     return UPG_FILE_NAME;
89 }
90 
91 /* 获取资源索引路径 */
upg_get_res_file_index_path(void)92 char *upg_get_res_file_index_path(void)
93 {
94     return UPG_RES_INDEX_PATH;
95 }
96 
97 /* 获取升级包所在目录 */
upg_get_pkg_file_dir(void)98 char *upg_get_pkg_file_dir(void)
99 {
100     return UPG_FILE_PATH;
101 }
102 
103 /* 本次支持升级的镜像ID集合,若为空则无镜像限制 */
upg_img_in_set(uint32_t img_id)104 bool upg_img_in_set(uint32_t img_id)
105 {
106     upg_image_collections_t *collect = uapi_upg_get_image_id_collection();
107     if (collect == NULL || collect->img_ids_cnt == 0) {
108         return true;
109     }
110 
111     for (uint32_t i = 0; i < collect->img_ids_cnt; i++) {
112         if (collect->img_ids[i] == img_id) {
113             return true;
114         }
115     }
116     return false;
117 }
118 
119 /*
120  * 获取FOTA升级标记区的Flash起始地址,该地址为在flash上的相对地址,是相对flash基地址的偏移
121  * start_address 返回升级标记区的起始地址
122  */
upg_get_upgrade_flag_flash_start_addr(uint32_t * start_address)123 errcode_t upg_get_upgrade_flag_flash_start_addr(uint32_t *start_address)
124 {
125     errcode_t ret_val;
126     partition_information_t info;
127 
128     ret_val = uapi_partition_get_info(PARTITION_FOTA_DATA, &info);
129     if (ret_val != ERRCODE_SUCC) {
130         return ret_val;
131     }
132 
133     /* FOTA升级标记区在FOTA分区的最后 */
134     *start_address = info.part_info.addr_info.addr + info.part_info.addr_info.size - FOTA_DATA_FLAG_AREA_LEN;
135     return ERRCODE_SUCC;
136 }
137 
138 /*
139  * 获取FOTA升级进度恢复标记区的Flash起始地址,该地址为在flash上的相对地址,是相对flash基地址的偏移
140  * start_address 返回标记区的起始地址
141  * size 返回包含标记区和flag区的总长度
142  */
upg_get_progress_status_start_addr(uint32_t * start_address,uint32_t * size)143 errcode_t upg_get_progress_status_start_addr(uint32_t *start_address, uint32_t *size)
144 {
145     partition_information_t info;
146     errcode_t ret_val = uapi_partition_get_info(PARTITION_FOTA_DATA, &info);
147     if (ret_val != ERRCODE_SUCC) {
148         return ret_val;
149     }
150 
151     *start_address = info.part_info.addr_info.addr + info.part_info.addr_info.size - UPG_UPGRADE_FLAG_LENGTH;
152     *size = UPG_UPGRADE_FLAG_LENGTH;
153     return ERRCODE_SUCC;
154 }
155 
156 /*
157  * 获取在Flash上预留的FOTA分区的地址和长度,该地址为在flash上的相对地址,是相对flash基地址的偏移
158  * start_address 返回FOTA分区的起始地址
159  * size          返回FOTA分区大小(包含升级标记区和缓存区、状态区)
160  */
upg_get_fota_partiton_area_addr(uint32_t * start_address,uint32_t * size)161 errcode_t upg_get_fota_partiton_area_addr(uint32_t *start_address, uint32_t *size)
162 {
163     partition_information_t info;
164     errcode_t ret_val = uapi_partition_get_info(PARTITION_FOTA_DATA, &info);
165     if (ret_val != ERRCODE_SUCC) {
166         return ret_val;
167     }
168     *start_address = info.part_info.addr_info.addr;
169     *size = info.part_info.addr_info.size;
170     return ERRCODE_SUCC;
171 }
172 
173 /*
174  * 重启
175  */
upg_reboot(void)176 void upg_reboot(void)
177 {
178     uapi_tcxo_delay_ms(TCXO_REBOOT_DELAY);
179     hal_reboot_chip();
180 }
181 
182 #ifdef WS63_PRODUCT_NONE
183 /*
184  * 升级进度上报回调
185  */
186 #define UPG_PROCESS_REPORT_DEC 10
187 #define UPG_PROCESS_REPORT_OVER 100
188 #define UPG_PROCESS_REPORT_PERCENT_LEN 3
189 
upg_progress_callbck(uint32_t percent)190 STATIC void upg_progress_callbck(uint32_t percent)
191 {
192     serial_puts("[UPG] upg percent : ");
193     char tmp_char[UPG_PROCESS_REPORT_PERCENT_LEN];
194     if (percent == UPG_PROCESS_REPORT_OVER) {
195         serial_puts("1");
196     }
197     int index = 0;
198     tmp_char[index++] = '0' + ((percent / UPG_PROCESS_REPORT_DEC) % UPG_PROCESS_REPORT_DEC);
199     tmp_char[index++] = '0' + (percent % UPG_PROCESS_REPORT_DEC);
200     tmp_char[index++] = '\0';
201     serial_puts(tmp_char);
202     serial_puts(" %\r");
203     if (percent == UPG_PROCESS_REPORT_OVER) {
204         serial_puts("\n");
205     }
206 }
207 
upg_progress_callback_register(void)208 void upg_progress_callback_register(void)
209 {
210     errcode_t ret = uapi_upg_register_progress_callback(upg_progress_callbck);
211     if (ret != ERRCODE_SUCC) {
212         upg_log_err("[UPG] upgrade progress callback regist failed\r\n");
213     }
214 }
215 #endif
216 
217 /*
218  * 防止看门狗超时,踢狗
219  */
upg_watchdog_kick(void)220 void upg_watchdog_kick(void)
221 {
222     uapi_watchdog_kick();
223 }
224 
upg_get_flash_base_addr(void)225 uint32_t upg_get_flash_base_addr(void)
226 {
227     return FLASH_START;
228 }
229 
upg_get_flash_size(void)230 uint32_t upg_get_flash_size(void)
231 {
232     return UPG_FLASH_SIZE;
233 }
234 void non_os_enter_critical(void);
235 
236 void non_os_exit_critical(void);
237 // 升级读flash接口需支持跨页读取
upg_flash_read(const uint32_t flash_offset,const uint32_t size,uint8_t * ram_data)238 errcode_t upg_flash_read(const uint32_t flash_offset, const uint32_t size, uint8_t *ram_data)
239 {
240     errcode_t ret = ERRCODE_FAIL;
241 #if defined (CONFIG_DRIVER_SUPPORT_SFC)
242     ret = uapi_sfc_reg_read(flash_offset, (uint8_t *)ram_data, size);
243     if (ret != ERRCODE_SUCC) {
244 #else
245     ret = (errcode_t)memcpy_s((uint8_t *)(uintptr_t)(flash_offset + FLASH_START), size, (void *)ram_data, size);
246     if (ret != EOK) {
247 #endif
248         return ERRCODE_FAIL;
249     }
250     return ERRCODE_SUCC;
251 }
252 
253 // 升级写flash接口需支持跨页写入和写前擦功能
254 errcode_t upg_flash_write(const uint32_t flash_offset, uint32_t size, const uint8_t *ram_data, bool do_erase)
255 {
256     errcode_t ret = ERRCODE_FAIL;
257     if (do_erase == true) {
258         ret = upg_flash_erase(flash_offset, size);
259         if (ret != ERRCODE_SUCC) {
260             return ret;
261         }
262     }
263     /* 写入flash */
264     uint32_t lock = (uint32_t)osal_irq_lock();
265 
266 #if defined (CONFIG_DRIVER_SUPPORT_SFC)
267     ret = uapi_sfc_reg_write(flash_offset, (uint8_t *)ram_data, size);
268     if (ret != ERRCODE_SUCC) {
269 #else
270     ret = (errcode_t)memcpy_s((uint8_t *)(uintptr_t)(flash_offset + FLASH_START), size, (void *)ram_data, size);
271     if (ret != EOK) {
272 #endif
273         osal_irq_restore(lock);
274         goto write_failed;
275     }
276     osal_irq_restore(lock);
277 
278 #if UPG_FLASH_FUNC_DEBUG == YES
279     uint8_t *cmp_data = upg_malloc(size);
280     if (cmp_data == NULL) {
281         return ERRCODE_MALLOC;
282     }
283     /* 回读比较 */
284     ret = (errcode_t)memcpy_s(cmp_data, size, (uint8_t *)(uintptr_t)(flash_offset + FLASH_START), size);
285     if (ret != EOK) {
286         goto write_failed;
287     }
288     ret = (errcode_t)memcmp(cmp_data, ram_data, size);
289     if (ret != EOK) {
290         goto write_failed;
291     }
292 #endif
293 write_failed:
294 #if UPG_FLASH_FUNC_DEBUG == YES
295     upg_free(cmp_data);
296 #endif
297     return ret;
298 }
299 
300 #define FLASH_PAGE_SIZE_BIT_LENGTH 12
301 #define BYTE_4K_MASK              0xFFF
302 #define BYTE_4K                   0x1000
303 
304 errcode_t upg_flash_erase(const uint32_t flash_offset, const uint32_t size)
305 {
306     errcode_t ret = ERRCODE_FAIL;
307     // 地址向前4K对齐,大小向上4K补齐
308     uint32_t end_addr = flash_offset + size;
309     uint32_t start_sector = flash_offset & ~BYTE_4K_MASK;
310     uint32_t end_sector = (end_addr & BYTE_4K_MASK) == 0 ? end_addr : (end_addr & ~BYTE_4K_MASK) + BYTE_4K;
311     uint32_t hal_erase_size = end_sector - start_sector;
312     uint32_t first_size = flash_offset - start_sector;
313     uint32_t last_size = end_sector - end_addr;
314 
315     uint8_t *writeback_first_data = upg_malloc(BYTE_4K);
316     if (writeback_first_data == NULL) {
317         return ERRCODE_MALLOC;
318     }
319     uint8_t *writeback_last_data = upg_malloc(BYTE_4K);
320     if (writeback_last_data == NULL) {
321         upg_free(writeback_first_data);
322         return ERRCODE_MALLOC;
323     }
324     if (first_size != 0) {
325         ret = upg_flash_read(start_sector, first_size, writeback_first_data);
326         if (ret != ERRCODE_SUCC) {
327             goto end;
328         }
329     }
330     if (last_size != 0) {
331         ret = upg_flash_read(end_addr, last_size, writeback_last_data);
332         if (ret != ERRCODE_SUCC) {
333             goto end;
334         }
335     }
336     // 擦除
337     ret = uapi_sfc_reg_erase(start_sector, hal_erase_size);
338     if (ret != ERRCODE_SUCC) {
339             goto end;
340     }
341     // 回写
342     if (first_size != 0) {
343         ret = upg_flash_write(start_sector, first_size, writeback_first_data, false);
344         if (ret != ERRCODE_SUCC) {
345             goto end;
346         }
347     }
348     if (last_size != 0) {
349         ret = upg_flash_write(end_addr, last_size, writeback_last_data, false);
350         if (ret != ERRCODE_SUCC) {
351             goto end;
352         }
353     }
354 end:
355     upg_free(writeback_first_data);
356     upg_free(writeback_last_data);
357     return ret;
358 }
359 
360 #if (UPG_CFG_VERIFICATION_SUPPORT == YES)
361 /*
362  * 获取校验用的root_public_key
363  */
364 uint8_t *upg_get_root_public_key(void)
365 {
366 #if (UPG_CFG_DIRECT_FLASH_ACCESS == YES)
367     /* 使用Upgrader_External_Public_Key校验Key Area的签名  */
368     partition_information_t info;
369     errcode_t ret_val = uapi_partition_get_info(PARTITION_FLASH_ROOT_PUBLIC_KEYS_AREA, &info);
370     if (ret_val != ERRCODE_SUCC) {
371         return NULL;
372     }
373     uint32_t rootkey_buff_addr = info.part_info.addr_info.addr + upg_get_flash_base_addr();
374     root_public_key *rootkey_buff = (root_public_key *)(uintptr_t)rootkey_buff_addr;
375     return (uint8_t *)(rootkey_buff->root_key_area);
376 #else
377     upg_package_header_t *pkg_header = NULL;
378     errcode_t ret;
379     ret = upg_get_package_header(&pkg_header);
380     if (ret != ERRCODE_SUCC || pkg_header == NULL) {
381         upg_log_err("[UPG] upg_get_package_header fail\r\n");
382         return NULL;
383     }
384     static uint8_t public_key[PUBLIC_KEY_LEN];
385     memcpy_s(public_key, sizeof(public_key), (pkg_header->key_area.fota_external_public_key), PUBLIC_KEY_LEN);
386     upg_free(pkg_header);
387     return public_key;
388 #endif
389 }
390 
391 STATIC errcode_t check_fota_msid(const uint32_t msid_ext, const uint32_t mask_msid_ext)
392 {
393     unused(msid_ext);
394     unused(mask_msid_ext);
395     uint32_t msid = 0;
396     errcode_t ret = uapi_efuse_read_buffer((uint8_t *)&msid, MS_ID_ADDR, sizeof(uint32_t));
397     if (ret != ERRCODE_SUCC) {
398         upg_log_err("[UPG] get msid failed. ret = 0x%x\r\n", ret);
399     }
400 
401     if ((msid_ext & mask_msid_ext) != (msid & mask_msid_ext)) {
402         upg_log_err("[UPG] upg verify: msid is wrong!\r\n");
403     }
404 
405     return ERRCODE_SUCC; // msid地址未确定,先返回成功
406 }
407 
408 /*
409  * 检查FOTA升级包中的信息与板端是否匹配
410  * pkg_header 升级包包头指针
411  * 检查成功,返回 ERRCODE_SUCC
412  */
413 errcode_t upg_check_fota_information(const upg_package_header_t *pkg_header)
414 {
415     upg_key_area_data_t *key_area = (upg_key_area_data_t *)&(pkg_header->key_area);
416     upg_fota_info_data_t *fota_info = (upg_fota_info_data_t *)&(pkg_header->info_area);
417     errcode_t ret;
418 
419     ret = check_fota_msid(key_area->msid_ext, key_area->mask_msid_ext);
420     if (ret != ERRCODE_SUCC) {
421         return ret;
422     }
423 
424     ret = check_fota_msid(fota_info->msid_ext, fota_info->mask_msid_ext);
425     if (ret != ERRCODE_SUCC) {
426         return ret;
427     }
428 
429     return ERRCODE_SUCC;
430 }
431 #endif
432 
433 errcode_t upg_get_efuse_addr(uint32_t image_id, uint32_t *start_addr)
434 {
435     switch (image_id) {
436         case FLASH_BOOT_IMAGE_ID:
437             *start_addr = EFUSE_FLASHBOOT_ROLLBACK_VERSION;
438             break;
439         case APPLICATION_IMAGE_ID:
440             *start_addr = EFUSE_APP_ROLLBACK_VERSION;
441             break;
442         default:
443             return ERRCODE_FAIL;
444     }
445     return ERRCODE_SUCC;
446 }
447 
448 errcode_t upg_get_board_rollback_version(uint32_t image_id, uint32_t *anti_rollback_ver)
449 {
450     uint32_t efuse_offset;
451     errcode_t ret = upg_get_efuse_addr(image_id, &efuse_offset);
452     if (ret != ERRCODE_SUCC) {
453         return ret;
454     }
455     return (errcode_t)uapi_efuse_read_buffer((uint8_t *)anti_rollback_ver, efuse_offset, sizeof(uint32_t));
456 }
457 
458 errcode_t upg_get_board_version_mask(uint32_t image_id, uint32_t *key_mask, uint32_t *code_mask)
459 {
460     unused(image_id);
461     *key_mask = 0x0;
462     *code_mask = 0xFFFFFFFF;
463     return ERRCODE_SUCC;
464 }
465 
466 errcode_t upg_get_board_version(uint32_t image_id, uint32_t *key_ver, uint32_t *code_ver)
467 {
468     unused(image_id);
469     upg_package_header_t     *pkg_header = NULL;
470     upg_image_hash_node_t *img_hash_table = NULL;
471     upg_image_header_t *img_header = NULL;
472     errcode_t ret = upg_get_package_header(&pkg_header);
473     if (ret != ERRCODE_SUCC || pkg_header == NULL) {
474         upg_log_err("[UPG] upg_get_package_header fail\r\n");
475         return ret;
476     }
477     ret = upg_get_pkg_image_hash_table(pkg_header, &img_hash_table);
478     if (ret != ERRCODE_SUCC || img_hash_table == NULL) {
479         upg_log_err("[UPG] upg_get_pkg_image_hash_table fail\r\n");
480         upg_free(pkg_header);
481         return ret;
482     }
483     upg_fota_info_data_t *fota_info = (upg_fota_info_data_t *)&(pkg_header->info_area);
484     for (uint32_t i = 0; i < fota_info->image_num; i++) {
485         ret = upg_get_pkg_image_header((const upg_image_hash_node_t *)&(img_hash_table[i]), &img_header);
486         if (ret != ERRCODE_SUCC || img_header == NULL) {
487             upg_log_err("[UPG] upg_get_pkg_image_header fail\r\n");
488             upg_free(pkg_header);
489             upg_free(img_hash_table);
490             break;
491         }
492         if (img_header->image_id == image_id) {
493             break;
494         }
495     }
496     *key_ver = pkg_header->key_area.fota_key_version_ext;
497     *code_ver = img_header->version_ext;
498     upg_free(pkg_header);
499     upg_free(img_hash_table);
500     upg_free(img_header);
501     return ret;
502 }
503 
504 errcode_t upg_set_board_rollback_version(uint32_t image_id, uint32_t *anti_rollback_ver)
505 {
506     uint32_t efuse_offset;
507     errcode_t ret = upg_get_efuse_addr(image_id, &efuse_offset);
508     if (ret != ERRCODE_SUCC) {
509         return ret;
510     }
511     uint32_t version = *anti_rollback_ver;
512     return (errcode_t)uapi_efuse_write_buffer(efuse_offset, (uint8_t *)&version, sizeof(uint32_t));
513 }
514 
515 uint32_t global_interrupt_lock(void);
516 void global_interrupt_restore(uint32_t);
517 
518 static void *upg_malloc_port(uint32_t size)
519 {
520     void *upg_ptr = NULL;
521 #ifndef WS63_PRODUCT_NONE
522     upg_ptr = osal_kmalloc(size, 0);
523 #else
524     uint32_t upg_irq = global_interrupt_lock();
525     upg_ptr = malloc(size);
526     global_interrupt_restore(upg_irq);
527 #endif
528     return upg_ptr;
529 }
530 
531 static void upg_free_port(void *addr)
532 {
533 #ifndef WS63_PRODUCT_NONE
534     osal_kfree(addr);
535 #else
536     uint32_t irq = global_interrupt_lock();
537     free(addr);
538     global_interrupt_restore(irq);
539 #endif
540 }
541 
542 static void ws63_upg_putc(const char c)
543 {
544 #ifndef WS63_PRODUCT_NONE
545     unused(c);
546 #else
547     serial_putc(c);
548 #endif
549 }
550 
551 errcode_t ws63_upg_init(void)
552 {
553     errcode_t ret;
554     upg_func_t upg_func = {0};
555     upg_func.malloc = upg_malloc_port;
556     upg_func.free = upg_free_port;
557     upg_func.serial_putc = ws63_upg_putc;
558     ret = uapi_upg_init(&upg_func);
559     if (ret != ERRCODE_SUCC) {
560         upg_log_err("[UPG] upgrade init failed!\r\n");
561         return ret;
562     }
563 #ifdef WS63_PRODUCT_NONE
564     upg_progress_callback_register();
565 #endif
566     upg_log_info("[UPG] upgrade init OK!\r\n");
567     return ret;
568 }
569 
570 #if defined(UPG_CFG_SUPPORT_ERASE_WHOLE_IMAGE) && defined(YES) && (UPG_CFG_SUPPORT_ERASE_WHOLE_IMAGE == YES)
571 errcode_t upg_erase_whole_image(const upg_image_header_t *img_header)
572 {
573     errcode_t ret;
574     partition_information_t info;
575     ret = upg_get_image_info(img_header->image_id, &info);
576     if (ret != ERRCODE_SUCC) {
577         return ret;
578     }
579     ret = upg_flash_erase(info.part_info.addr_info.addr, info.part_info.addr_info.size);
580     if (ret != ERRCODE_SUCC) {
581         return ret;
582     }
583     return ERRCODE_SUCC;
584 }
585 #endif