/* * Copyright (C) 2017-2021 Alibaba Group Holding Limited * * SPDX-License-Identifier: GPL-2.0+ */ #include #include #include #include #include #include #include "../../../lib/sec_library/include/csi_sec_img_verify.h" extern int csi_efuse_api_int(void); extern int csi_efuse_api_unint(void); extern int csi_efuse_read_raw(uint32_t addr, void *data, uint32_t cnt); extern int csi_efuse_write_raw(uint32_t addr, const void *data, uint32_t cnt); extern uint32_t rambus_crypto_init(void); int image_have_head(unsigned long img_src_addr) { uint8_t *buffer = (uint8_t *)img_src_addr; if (memcmp(header_magic, &buffer[4], 4) == 0) { return 1; } return 0; } int csi_sec_init(void) { int ret; char *version; /* Initialize eFuse module */ ret = csi_efuse_api_int(); if (ret) { printf("efuse init faild[%d]\n", ret); goto exit; } ret = rambus_crypto_init(); if (ret) { printf("rambus_crypto_init faild[%d]\n", ret); goto exit; } csi_sec_get_lib_version(&version); csi_sec_set_boot_stage(0); printf("sec version: %s \n", version); exit: return ret; } #define LIGHT_MAC1ADDR_OFF 176 void designware_get_mac_from_fuse(unsigned char *mac) { int ret; /* Initialize eFuse module */ ret = csi_efuse_api_int(); if (ret) { printf("efuse init faild[%d]\n", ret); return; } ret = csi_efuse_read_raw(LIGHT_MAC1ADDR_OFF, mac, 6); if (ret) { printf("efuse macaddr read faild[%d]\n", ret); return; } } static int strtou32(const char *str, unsigned int base, u32 *result) { char *ep; *result = simple_strtoul(str, &ep, base); if (ep == str || *ep != '\0') return -EINVAL; return 0; } static int confirm_prog(void) { puts("Warning: Programming fuses is an irreversible operation!\n" " This may brick your system.\n" " Use this command only if you are sure of " "what you are doing!\n" "\nReally perform this fuse programming? \n"); if (confirm_yesno()) return 1; puts("Fuse programming aborted\n"); return 0; } static int do_fuse(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { const char *op = argc >= 2 ? argv[1] : NULL; int confirmed = argc >= 3 && !strcmp(argv[2], "-y"); u32 addr, cnt, val; u8 *data; int ret, i; /* Initialize eFuse module */ ret = csi_efuse_api_int(); if (ret) { printf("efuse init faild[%d]\n", ret); goto err; } argc -= 2 + confirmed; argv += 2 + confirmed; if (argc < 1 || strtou32(argv[0], 0, &addr)) return CMD_RET_USAGE; if (!strcmp(op, "read")) { if (argc == 1) cnt = 1; else if (argc != 2 || strtou32(argv[1], 0, &cnt)) return CMD_RET_USAGE; printf("Reading addr %u:\n", addr); { data = malloc(cnt); ret = csi_efuse_read_raw(addr, data, cnt); if (ret) { free(data); goto err; } for (i = 0; i < cnt; i++) printf(" 0x%.2x", data[i]); free(data); } putc('\n'); } else if (!strcmp(op, "write")) { if (argc < 2) return CMD_RET_USAGE; data = malloc(argc - 1); printf("Programming addr %u to\n", addr); for (i = 1; i < argc; i++) { if (strtou32(argv[i], 16, &val)) return CMD_RET_USAGE; data[i-1] = val; printf(" 0x%.2x\n", val); } cnt = argc - 1; if (!confirmed && !confirm_prog()) { free(data); return CMD_RET_FAILURE; } ret = csi_efuse_write_raw(addr, data, cnt); if (ret) { free(data); goto err; } free(data); } else { return CMD_RET_USAGE; } return 0; err: puts("ERROR\n"); return CMD_RET_FAILURE; } #if CONFIG_IS_ENABLED(LIGHT_SEC_BOOT_WITH_VERIFY_VAL_A) || CONFIG_IS_ENABLED(LIGHT_SEC_BOOT_WITH_VERIFY_VAL_B) || CONFIG_IS_ENABLED(LIGHT_SEC_BOOT_WITH_VERIFY_ANT_REF) /* Secure function for image verificaiton here */ int get_image_version(unsigned long img_src_addr) { img_header_t *img = (img_header_t *)img_src_addr; uint8_t magiccode[4] = {0}; magiccode[3] = img->magic_num & 0xff; magiccode[2] = (img->magic_num & 0xff00) >> 8; magiccode[1] = (img->magic_num & 0xff0000) >> 16; magiccode[0] = (img->magic_num & 0xff000000) >> 24; if (memcmp(header_magic, magiccode, 4) == 0) { return -1; } return img->image_version; } int get_image_size(unsigned long img_src_addr) { img_header_t *img = (img_header_t *)img_src_addr; uint8_t magiccode[4] = {0}; magiccode[3] = img->magic_num & 0xff; magiccode[2] = (img->magic_num & 0xff00) >> 8; magiccode[1] = (img->magic_num & 0xff0000) >> 16; magiccode[0] = (img->magic_num & 0xff000000) >> 24; if (memcmp(header_magic, magiccode, 4) == 0) { return -1; } return img->image_size; } void dump_image_header_info(long addr) { img_header_t *phead = (img_header_t *)addr; printf("\n---------------------------------------------\n"); printf("entry point: 0x%x\n", phead->entry_point); printf("image size: %d Bytes\n", phead->image_size); printf("head version: 0x%x\n", phead->head_version); printf("image version: 0x%x\n", phead->image_version); printf("image checksum: 0x%x\n", phead->image_checksum); printf("image run addr: 0x%llx\n", phead->image_run_addr); printf("image offset: 0x%x\n", phead->image_offset); printf("image digest scheme: %d\n", phead->digest_scheme); printf("image sign scheme: %d\n", phead->signature_scheme); printf("image encrypt type: %d\n", phead->encrypt_type); printf("\n---------------------------------------------\n"); } int verify_customer_image(img_type_t type, long addr) { int ret; const char *image_name = ""; /* Double check image number */ if (image_have_head(addr) == 0) return -1; /* Dump image header information here */ dump_image_header_info(addr); /* Call customer image verification function */ if ((type == T_TF) || (type == T_TEE) || (type == T_KRLIMG)) { ret = csi_sec_custom_image_verify(addr, UBOOT_STAGE_ADDR); if (ret) { printf("Image(%d) is verified fail, Please go to check!\n\n", type); return ret; } } else if (type == T_UBOOT) { ret = csi_sec_uboot_image_verify(addr, addr - PUBKEY_HEADER_SIZE); if (ret) { printf("Image(%s) is verified fail, Please go to check!\n\n", "uboot"); return ret; } } return 0; } #else U_BOOT_CMD( efuse, CONFIG_SYS_MAXARGS, 0, do_fuse, "eFuse sub-system", "read [] - read 1 or 'cnt' fuse bytes,\n" " starting at 'addr'\n" "efuse write [-y] [...] - program 1 or\n" " several fuse bytes, starting at 'addr'\n" ); #endif