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