/** NVT utilities for command customization @file na51055_utils.c @ingroup @note Copyright Novatek Microelectronics Corp. 2019. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "nvt_ivot_soc_utils.h" #include "nvt_ivot_pack.h" #include #include #include #define FW_PART1_SIZE_OFFSET (RTOS_CODEINFO_OFFSET + 0x1C) //ref to CodeInfo.S on rtos (addr of _section_01_size) #define UINT32_SWAP(data) (((((u32)(data)) & 0x000000FF) << 24) | \ ((((u32)(data)) & 0x0000FF00) << 8) | \ ((((u32)(data)) & 0x00FF0000) >> 8) | \ ((((u32)(data)) & 0xFF000000) >> 24)) ///< Swap [31:24] with [7:0] and [23:16] with [15:8]. extern HEADINFO gHeadInfo; static int nvt_decrypt_kernel(void); int atoi(const char *str) { return (int)simple_strtoul(str, '\0', 10); } #if defined(CONFIG_NVT_LINUX_SPINAND_BOOT) || defined(CONFIG_NVT_IVOT_SOC_FW_UPDATE_SUPPORT) || defined(CONFIG_NVT_LINUX_SPINOR_BOOT) || defined(CONFIG_NVT_LINUX_EMMC_BOOT) int nvt_part_config(char *p_cmdline, EMB_PARTITION *partition_ptr) { EMB_PARTITION *p_partition = NULL; uint32_t i, part_num, pst_part_num, ro_attr; int exist_linux = 0; int ret = 0; char cmd[512]; char buf[40]; #if defined(CONFIG_NVT_IVOT_SOC_FW_UPDATE_SUPPORT) #if defined(CONFIG_NVT_SPI_NAND) struct mtd_info *nand = get_nand_dev_by_index(nand_curr_device); #elif defined(CONFIG_NVT_IVOT_EMMC) struct mmc *mmc = find_mmc_device(CONFIG_NVT_IVOT_EMMC); #endif /* CONFIG_NVT_SPI_NAND */ #endif /* CONFIG_NVT_IVOT_SOC_FW_UPDATE_SUPPORT */ #if defined(CONFIG_NVT_LINUX_EMMC_BOOT) /* MMC device doesn't need to init mtdparts parameter */ if (p_cmdline == NULL) { return 0; } #endif /* CONFIG_NVT_LINUX_EMMC_BOOT */ if (partition_ptr == NULL) { p_partition = emb_partition_info_data_curr; ret = nvt_getfdt_emb((ulong)nvt_fdt_buffer, p_partition); if (ret < 0) { printf("failed to get partition resource.\r\n"); return -1; } } else { /* Receive partition table from argu */ p_partition = partition_ptr; } #if defined(CONFIG_NVT_SPI_NAND) sprintf(cmd, "nand0=spi_nand.0"); ret = env_set("mtdids", cmd); if (ret) { printf("%s: error set\n", __func__); return ret; } sprintf(cmd, "mtdparts=spi_nand.0:"); #elif defined(CONFIG_NVT_SPI_NOR) sprintf(cmd, "nor0=spi_nor.0"); ret = env_set("mtdids", cmd); if (ret) { printf("%s: error set\n", __func__); return ret; } sprintf(cmd, "mtdparts=spi_nor.0:"); if (p_cmdline != NULL) { /* To find if mtdparts string existed. If yes, it needs to expand mtdparts environment */ char *mtdparts_off = NULL; mtdparts_off = strstr((char *)p_cmdline, "mtdparts="); if (mtdparts_off) { p_cmdline = mtdparts_off; *p_cmdline = '\0'; } strcat(p_cmdline, "mtdparts=spi_nor.0:"); } #elif defined(CONFIG_NVT_IVOT_EMMC) if (p_cmdline != NULL) { /* To find if mtdparts string existed. If yes, it needs to expand mtdparts environment */ char *nvtemmcpart_off = NULL; nvtemmcpart_off = strstr((char *)p_cmdline, "nvtemmcpart="); if (nvtemmcpart_off) { p_cmdline = nvtemmcpart_off; *p_cmdline = '\0'; } strcat(p_cmdline, "nvtemmcpart="); } #else return 0; #endif part_num = 0; pst_part_num = 0; ro_attr = 0; /* To parse mtdparts for rootfs partition table */ for (i = 0 ; i < EMB_PARTITION_INFO_COUNT ; i++) { const EMB_PARTITION *p = p_partition + i; unsigned int PartitionSize = 0, PartitionOffset = 0; #if defined(CONFIG_NVT_SPI_NAND) PartitionSize = p->PartitionSize; PartitionOffset = p->PartitionOffset; #elif defined(CONFIG_NVT_IVOT_EMMC) PartitionSize = p->PartitionSize; PartitionOffset = p->PartitionOffset; #else PartitionSize = p->PartitionSize; PartitionOffset = p->PartitionOffset; #endif if (p->EmbType != EMBTYPE_UNKNOWN && PartitionSize == 0) { printf("%s skip mtdpart config of partition[%d], because its size is 0\n%s", ANSI_COLOR_YELLOW, i, ANSI_COLOR_RESET); continue; } switch (p->EmbType) { case EMBTYPE_UITRON: sprintf(buf, "0x%x@0x%x(uitron),", PartitionSize, PartitionOffset); strcat(cmd, buf); if (p_cmdline != NULL) { #if defined(CONFIG_NVT_IVOT_EMMC) sprintf(buf, "0x%x@0x%x(uitron)ro,", PartitionSize, PartitionOffset); strcat(p_cmdline, buf); #endif } break; case EMBTYPE_FDT: if (p->OrderIdx == 0) { sprintf(buf, "0x%x@0x%x(fdt),", PartitionSize, PartitionOffset); strcat(cmd, buf); } else { sprintf(buf, "0x%x@0x%x(fdt%d),", PartitionSize, PartitionOffset, p->OrderIdx); strcat(cmd, buf); } if (p_cmdline != NULL) { #if defined(CONFIG_NVT_IVOT_EMMC) if (p->OrderIdx == 0) { sprintf(buf, "0x%x@0x%x(fdt)ro,", PartitionSize, PartitionOffset); strcat(p_cmdline, buf); } else { sprintf(buf, "0x%x@0x%x(fdt%d)ro,", PartitionSize, PartitionOffset, p->OrderIdx); strcat(p_cmdline, buf); } #endif } break; case EMBTYPE_ATF: sprintf(buf, "0x%x@0x%x(atf),", PartitionSize, PartitionOffset); strcat(cmd, buf); if (p_cmdline != NULL) { #if defined(CONFIG_NVT_IVOT_EMMC) sprintf(buf, "0x%x@0x%x(atf)ro,", PartitionSize, PartitionOffset); strcat(p_cmdline, buf); #endif } break; case EMBTYPE_UBOOT: sprintf(buf, "0x%x@0x%x(uboot),", PartitionSize, PartitionOffset); strcat(cmd, buf); if (p_cmdline != NULL) { #if defined(CONFIG_NVT_IVOT_EMMC) sprintf(buf, "0x%x@0x%x(uboot)ro,", PartitionSize, PartitionOffset); strcat(p_cmdline, buf); #endif } break; case EMBTYPE_UENV: sprintf(buf, "0x%x@0x%x(uenv),", PartitionSize, PartitionOffset); strcat(cmd, buf); if (p_cmdline != NULL) { #if defined(CONFIG_NVT_IVOT_EMMC) strcat(p_cmdline, buf); #endif } break; case EMBTYPE_LINUX: exist_linux = 1; sprintf(buf, "0x%x@0x%x(linux),", PartitionSize, PartitionOffset); strcat(cmd, buf); if (p_cmdline != NULL) { #if defined(CONFIG_NVT_IVOT_EMMC) sprintf(buf, "0x%x@0x%x(linux)ro,", PartitionSize, PartitionOffset); strcat(p_cmdline, buf); #endif } break; case EMBTYPE_RAMFS: sprintf(buf, "0x%x@0x%x(ramfs),", PartitionSize, PartitionOffset); strcat(cmd, buf); if (p_cmdline != NULL) { #if defined(CONFIG_NVT_IVOT_EMMC) strcat(p_cmdline, buf); #endif } break; case EMBTYPE_ROOTFS: sprintf(buf, "0x%x@0x%x(rootfs%d),", PartitionSize, PartitionOffset, p->OrderIdx); strcat(cmd, buf); if (p_cmdline != NULL) { #if defined(CONFIG_NVT_IVOT_EMMC) strcat(p_cmdline, buf); /* Multiple rootfs partitions if OrderIdx > 0 */ ro_attr = p->OrderIdx; #endif } break; case EMBTYPE_ROOTFSL: sprintf(buf, "0x%x@0x%x(rootfsl%d),", PartitionSize, PartitionOffset, p->OrderIdx); strcat(cmd, buf); if (p_cmdline != NULL) { #if defined(CONFIG_NVT_IVOT_EMMC) strcat(p_cmdline, buf); /* Multiple rootfs partitions if OrderIdx > 0 */ ro_attr = p->OrderIdx; #endif } break; case EMBTYPE_RTOS: if (p->OrderIdx == 0) { sprintf(buf, "0x%x@0x%x(rtos),", PartitionSize, PartitionOffset); strcat(cmd, buf); } else { sprintf(buf, "0x%x@0x%x(rtos%d),", PartitionSize, PartitionOffset, p->OrderIdx); strcat(cmd, buf); } if (p_cmdline != NULL) { #if defined(CONFIG_NVT_IVOT_EMMC) if (p->OrderIdx == 0) { sprintf(buf, "0x%x@0x%x(rtos)ro,", PartitionSize, PartitionOffset); strcat(p_cmdline, buf); } else { sprintf(buf, "0x%x@0x%x(rtos%d)ro,", PartitionSize, PartitionOffset, p->OrderIdx); strcat(p_cmdline, buf); } #endif } break; case EMBTYPE_APP: sprintf(buf, "0x%x@0x%x(app),", PartitionSize, PartitionOffset); strcat(cmd, buf); if (p_cmdline != NULL) { #if defined(CONFIG_NVT_IVOT_EMMC) sprintf(buf, "0x%x@0x%x(app),", PartitionSize, PartitionOffset); strcat(p_cmdline, buf); #endif } break; case EMBTYPE_TEEOS: sprintf(buf, "0x%x@0x%x(teeos),", PartitionSize, PartitionOffset); strcat(cmd, buf); if (p_cmdline != NULL) { #if defined(CONFIG_NVT_IVOT_EMMC) sprintf(buf, "0x%x@0x%x(teeos),", PartitionSize, PartitionOffset); strcat(p_cmdline, buf); #endif } break; case EMBTYPE_AI: sprintf(buf, "0x%x@0x%x(ai),", PartitionSize, PartitionOffset); strcat(cmd, buf); if (p_cmdline != NULL) { #if defined(CONFIG_NVT_IVOT_EMMC) sprintf(buf, "0x%x@0x%x(ai)ro,", PartitionSize, PartitionOffset); strcat(p_cmdline, buf); #endif } break; case EMBTYPE_USER: sprintf(buf, "0x%x@0x%x(user%u_%d),", PartitionSize, PartitionOffset, GET_USER_PART_NUM(p->EmbType), p->OrderIdx); strcat(cmd, buf); if (p_cmdline != NULL) { #if defined(CONFIG_NVT_IVOT_EMMC) strcat(p_cmdline, buf); #endif } break; case EMBTYPE_USERRAW: sprintf(buf, "0x%x@0x%x(userraw%u_%d),", PartitionSize, PartitionOffset, GET_USER_PART_NUM(p->EmbType), p->OrderIdx); strcat(cmd, buf); if (p_cmdline != NULL) { #if defined(CONFIG_NVT_IVOT_EMMC) strcat(p_cmdline, buf); #endif } break; case EMBTYPE_BANK: if (p->OrderIdx == 0) { sprintf(buf, "0x%x@0x%x(bank),", PartitionSize, PartitionOffset); strcat(cmd, buf); } else { sprintf(buf, "0x%x@0x%x(bank%d),", PartitionSize, PartitionOffset, p->OrderIdx); strcat(cmd, buf); } if (p_cmdline != NULL) { #if defined(CONFIG_NVT_IVOT_EMMC) if (p->OrderIdx == 0) { sprintf(buf, "0x%x@0x%x(bank)ro,", PartitionSize, PartitionOffset); strcat(p_cmdline, buf); } else { sprintf(buf, "0x%x@0x%x(bank%d)ro,", PartitionSize, PartitionOffset, p->OrderIdx); strcat(p_cmdline, buf); } #endif } break; default: break; } } // for pure rtos project, dont enter to make rootfs cmdline if (p_cmdline != NULL && exist_linux) { /* To add entire nand mtd device */ #if defined(CONFIG_NVT_IVOT_EMMC) sprintf(buf, "0x%llx@0(total),", mmc->capacity / MMC_MAX_BLOCK_LEN); strcat(p_cmdline, buf); #endif /* * Add bootarg rootfs extension parameter */ p_cmdline[strlen(p_cmdline) - 1] = ' '; ret = nvt_getfdt_rootfs_mtd_num((ulong)nvt_fdt_buffer, &part_num, &ro_attr); if (ret < 0) { printf("%s We can't find your root device, \ please check if your dts is without partition_rootfs name %s\n", ANSI_COLOR_RED, ANSI_COLOR_RESET); return -1; } #if (defined(CONFIG_NVT_UBIFS_SUPPORT) || (defined(CONFIG_NVT_LINUX_SPINAND_BOOT) && defined(CONFIG_NVT_SQUASH_SUPPORT))) #if (defined(CONFIG_NVT_LINUX_SPINAND_BOOT) && defined(CONFIG_NVT_SQUASH_SUPPORT)) ro_attr = 1; #endif if (ro_attr > 0) { sprintf(buf, " ubi.mtd=%d ro ", part_num); } else { sprintf(buf, " ubi.mtd=%d rw ", part_num); } strcat(p_cmdline, buf); #elif defined(CONFIG_NVT_EXT4_SUPPORT) || (defined(CONFIG_NVT_LINUX_EMMC_BOOT) && defined(CONFIG_NVT_SQUASH_SUPPORT)) sprintf(buf, " root=/dev/mmcblk2p%d nvt_pst=/dev/mmcblk2p%d ", part_num, pst_part_num); strcat(p_cmdline, buf); #elif defined(CONFIG_NVT_LINUX_RAMDISK_SUPPORT) printf("RAMDISK boot\n"); #else /* * To handle non-ubifs rootfs type (squashfs/jffs2) */ if (ro_attr > 0) { sprintf(buf, " root=/dev/mtdblock%d ro ", part_num); } else { sprintf(buf, " root=/dev/mtdblock%d ", part_num); } strcat(p_cmdline, buf); #endif /* _NVT_ROOTFS_TYPE_ */ } /* To handle uboot mtd env config */ cmd[strlen(cmd) - 1] = '\0'; ret = env_set("mtdparts", cmd); sprintf(cmd, "printenv mtdparts"); run_command(cmd, 0); return ret; } #endif /* CONFIG_NVT_LINUX_SPINAND_BOOT || CONFIG_NVT_LINUX_AUTODETECT || CONFIG_NVT_LINUX_SPINOR_BOOT || defined(CONFIG_NVT_LINUX_EMMC_BOOT) */ #ifdef CONFIG_NVT_IVOT_SOC_FW_UPDATE_SUPPORT static int nvt_getfdt_rtos_addr_size(ulong addr, ulong *fdt_rtos_addr, ulong *fdt_rtos_len); static int nvt_getfdt_dram_addr_size(ulong addr, ulong *fdt_rtos_addr, ulong *fdt_rtos_len); static int nvt_runfw_bin_chk_valid(ulong addr) { unsigned int size = gHeadInfo.Resv1[0]; NVTPACK_VERIFY_OUTPUT np_verify = {0}; NVTPACK_GET_PARTITION_INPUT np_get_input; NVTPACK_MEM mem_in = {(void *)addr, size}; memset(&np_get_input, 0, sizeof(np_get_input)); if (nvtpack_verify(&mem_in, &np_verify) != NVTPACK_ER_SUCCESS) { printf("verify failed.\r\n"); return -1; } if (np_verify.ver != NVTPACK_VER_16072017) { printf("wrong all-in-one bin version\r\n"); return -1; } return 0; } static int nvt_on_partition_enum_copy_to_dest(unsigned int id, NVTPACK_MEM *p_mem, void *p_user_data) { EMB_PARTITION *pEmb = (EMB_PARTITION *)p_user_data; ulong src_addr = 0, dst_addr = 0, dst_size = 0; //NVTPACK_BFC_HDR *pBFC = (NVTPACK_BFC_HDR *)p_mem->p_data; #ifdef CONFIG_ARM64 bool ret; #endif /* Copy to dest address */ switch (pEmb[id].EmbType) { case EMBTYPE_LOADER: printf("RUNFW: Ignore T.bin loader\n"); break; case EMBTYPE_FDT: dst_addr = (ulong)nvt_fdt_buffer; dst_size = p_mem->len; src_addr = (ulong)p_mem->p_data; printf("RUNFW: Copy FDT from 0x%08x to 0x%08x with length %d bytes\r\n", (ulong)p_mem->p_data, (ulong)dst_addr, dst_size); break; case EMBTYPE_UITRON: case EMBTYPE_ECOS: case EMBTYPE_UBOOT: case EMBTYPE_DSP: case EMBTYPE_RTOS: case EMBTYPE_AI: break; case EMBTYPE_LINUX: dst_addr = CONFIG_LINUX_SDRAM_START; dst_size = p_mem->len; src_addr = (ulong)p_mem->p_data; printf("RUNFW: Copy Linux from 0x%08x to 0x%08x with length %d bytes\r\n", (ulong)p_mem->p_data, (ulong)dst_addr, dst_size); #ifdef CONFIG_ARM64 char cmd[256] = {0}; sprintf(cmd, "0x%x", _BOARD_LINUX_ADDR_); env_set("kernel_comp_addr_r", cmd); sprintf(cmd, "0x%x", dst_size); env_set("kernel_comp_size", cmd); #endif break; case EMBTYPE_ROOTFS: #ifdef CONFIG_NVT_LINUX_RAMDISK_SUPPORT /* Check if the image type is Ramdisk, if not skip it */ #ifdef CONFIG_NVT_BIN_CHKSUM_SUPPORT src_addr = (ulong)p_mem->p_data; src_addr += 64; #endif image_header_t *hdr = (image_header_t *)src_addr; if (image_check_type(hdr, IH_TYPE_RAMDISK) == 0 || pEmb[id].OrderIdx != 0) { nvt_dbg(MSG, "not a ramdisk rootfs skip it : id%d\n", id); return 0; } #ifdef CONFIG_NVT_PCIE_CASCADE /* To check if is the ep rootfs type, if yes, we don't need to copy it here. * it will be handled by pcie boot flow */ ret = nvt_runfw_bin_eprootfs_chk_exist(nvt_fdt_buffer, id); if (ret) { nvt_dbg(MSG, "skip ep rootfs\n"); return 0; } #endif /* CONFIG_NVT_PCIE_CASCADE */ nvt_ramdisk_size = ALIGN_CEIL(p_mem->len, 4096); nvt_ramdisk_addr = _BOARD_LINUX_ADDR_ + _BOARD_LINUX_SIZE_ - nvt_ramdisk_size - 0x10000; dst_addr = nvt_ramdisk_addr; dst_size = nvt_ramdisk_size; src_addr = (ulong)p_mem->p_data; #ifdef CONFIG_NVT_BIN_CHKSUM_SUPPORT // Skip nvt head info src_addr += 64; dst_size -= 64; #endif printf("copy sd to ram: ramdisk addr:%x size:%d\n", dst_addr, dst_size); if ((dst_size) > CONFIG_RAMDISK_SDRAM_SIZE) { printf("%sRUNFW: The ramdisk image size %d bytes is larger than %d bytes, can't boot. %s\r\n", ANSI_COLOR_RED, dst_size, CONFIG_RAMDISK_SDRAM_SIZE, ANSI_COLOR_RESET); printf("%sRUNFW: Please check your modelext dram partition.%s\r\n", ANSI_COLOR_RED, ANSI_COLOR_RESET); while (1); } else if ((nvt_ramdisk_addr + dst_size) > src_addr) { printf("%sRUNFW: The ramdisk image size 0x%lx bytes + ramdisk address 0x%lx will overlaps ramdisk src 0x%lx %s\r\n", ANSI_COLOR_RED, dst_size, nvt_ramdisk_addr, src_addr, ANSI_COLOR_RESET); printf("%sRUNFW: Please check your CONFIG_NVT_ALL_IN_ONE_IMG_SIZE and _BOARD_LINUX_SIZE_.%s\r\n", ANSI_COLOR_RED, ANSI_COLOR_RESET); while (1); } else { printf("RUNFW: Copy RAMDISK from 0x%08x to 0x%08x with length %d bytes\r\n", (unsigned int)src_addr, (unsigned int)dst_addr, dst_size); } #endif /* CONFIG_NVT_LINUX_RAMDISK_SUPPORT */ break; default: break; } if (dst_size != 0) { memcpy((void *)dst_addr, (void *)src_addr, dst_size); flush_dcache_range((ulong)dst_addr, (ulong)(dst_addr + dst_size)); } return 0; } #define GZ_BUF_SIZE 0x4000 //16KB are enough unsigned char gz_buf[0x4000] = {0}; unsigned char *mp_gz_buf_curr = gz_buf; static void *gz_alloc(void *x, unsigned items, unsigned size) { void *p = NULL; if (mp_gz_buf_curr + ALIGN_CEIL_4(size) > gz_buf + GZ_BUF_SIZE) { printf("gzip temp memory not enough, need more: %d bytes\r\n", ALIGN_CEIL_4(size)); return p; } p = (void *)(mp_gz_buf_curr); mp_gz_buf_curr += ALIGN_CEIL_4(size); return p; } static void gz_free(void *x, void *addr, unsigned nb) { mp_gz_buf_curr = gz_buf; } static int gz_uncompress(unsigned char *in, unsigned char *out, unsigned int insize, unsigned int outsize) { int err; z_stream stream = {0}; stream.next_in = (Bytef *)in; stream.avail_in = insize; stream.next_out = (Bytef *)out; stream.avail_out = outsize; stream.zalloc = (alloc_func)gz_alloc; stream.zfree = (free_func)gz_free; stream.opaque = (voidpf)0; err = inflateInit(&stream); if (err != Z_OK) { printf("Failed to inflateInit, err = %d\r\n", err); return -1; } err = inflate(&stream, Z_NO_FLUSH); inflateEnd(&stream); if (err == Z_STREAM_END) { return stream.total_out; } return 0; } static int nvt_on_rtos_partition_enum_copy_to_dest(unsigned int id, NVTPACK_MEM *p_mem, void *p_user_data) { int ret = 0; ulong rtos_addr, rtos_size; ulong dram_addr, dram_size; EMB_PARTITION *pEmb = (EMB_PARTITION *)p_user_data; NVTPACK_BFC_HDR *pBFC = (NVTPACK_BFC_HDR *)p_mem->p_data; nvt_getfdt_rtos_addr_size((ulong)nvt_fdt_buffer, &rtos_addr, &rtos_size); /* Copy to dest address */ switch (pEmb[id].EmbType) { case EMBTYPE_RTOS: /* Boot compressed uitron or non-compressed uitron */ if (pBFC->uiFourCC == MAKEFOURCC('B', 'C', 'L', '1')) { printf("RUNFW: Boot compressed rtos at 0x%08x with length %d bytes\r\n", (ulong)p_mem->p_data, p_mem->len); if ((cpu_to_be32(pBFC->uiAlgorithm) & 0xFF) == 11) { /* lzma compressed image*/ printf("%sDecompressed lzma rtos%s \r\n", ANSI_COLOR_YELLOW, ANSI_COLOR_RESET); size_t Compsz = cpu_to_be32(pBFC->uiSizeComp); size_t Uncompsz = cpu_to_be32(pBFC->uiSizeUnComp); ret = lzmaBuffToBuffDecompress((unsigned char *)rtos_addr, &Uncompsz, (unsigned char *)(p_mem->p_data + sizeof(NVTPACK_BFC_HDR)), Compsz); if (ret != 0) { printf("Decompressed lzma fail\n"); return ret; } else { flush_dcache_range((ulong)rtos_addr, (ulong)(rtos_addr + Uncompsz)); } } else { /* lz77 compressed image*/ lz_uncompress((unsigned char *)(p_mem->p_data + sizeof(NVTPACK_BFC_HDR)), (unsigned char *)rtos_addr, cpu_to_be32(pBFC->uiSizeComp)); flush_dcache_range((ulong)rtos_addr, (ulong)(rtos_addr + rtos_size)); } } else { nvt_getfdt_dram_addr_size((ulong)nvt_fdt_buffer, &dram_addr, &dram_size); printf("RUNFW: Copy rtos from 0x%08x to 0x%08x with length %d bytes\r\n", (ulong)p_mem->p_data, (ulong)rtos_addr, p_mem->len); memcpy((void *)rtos_addr, (void *)p_mem->p_data, p_mem->len); flush_dcache_range((ulong)rtos_addr, (ulong)(rtos_addr + p_mem->len)); //check partial compress load BININFO *pbininfo = (BININFO *)(rtos_addr + BIN_INFO_OFFSET_RTOS); SHMINFO *p_shminfo = (SHMINFO *)CONFIG_SMEM_SDRAM_BASE; //Pass HEADINFO_RESV_IDX_DRAM_SIZE information to freeRTOS (MMU mapping necessary) //Once fail => dram_size = 0 pbininfo->head.Resv1[HEADINFO_RESV_IDX_DRAM_SIZE] = dram_size; if (pbininfo->head.Resv1[HEADINFO_RESV_IDX_BOOT_FLAG] & BOOT_FLAG_PARTLOAD_EN) { u32 part1_size = *(u32 *)(rtos_addr + FW_PART1_SIZE_OFFSET); //align to block size part1_size = ALIGN_CEIL(part1_size, _EMBMEM_BLK_SIZE_); printf("part1_size_aligned=%08X\r\n", part1_size); pBFC = (NVTPACK_BFC_HDR *)((UINT32)p_mem->p_data + part1_size); if (pBFC->uiFourCC == MAKEFOURCC('B', 'C', 'L', '1')) { printf("RUNFW: decompress gzip.\r\n"); UINT32 uiLength = UINT32_SWAP(pBFC->uiSizeComp); UINT32 uiSizeComp = UINT32_SWAP(pBFC->uiSizeComp); UINT32 uiSizeUnComp = UINT32_SWAP(pBFC->uiSizeUnComp); UINT32 uiAddrCompress = ((UINT32)pBFC) + sizeof(NVTPACK_BFC_HDR); int decoded_size = gz_uncompress((unsigned char *)(uiAddrCompress) , (unsigned char *)(rtos_addr + part1_size) , uiLength , uiSizeUnComp); if (decoded_size == 0) { printf("Decompressed gzip fail\n"); return -1; } flush_dcache_range((ulong)rtos_addr, (ulong)(rtos_addr + pbininfo->head.BinLength)); } } //update LdLoadSize p_shminfo->boot.LdLoadSize = pbininfo->head.BinLength; flush_dcache_range((ulong)p_shminfo, (ulong)p_shminfo + sizeof(SHMINFO)); } break; default: break; } return 0; } static int nvt_runfw_bin_unpack_to_dest(ulong addr) { u32 i; EMB_PARTITION *pEmb = emb_partition_info_data_curr; int ret = 0; unsigned int size = gHeadInfo.Resv1[0]; NVTPACK_GET_PARTITION_INPUT np_get_input; NVTPACK_ENUM_PARTITION_INPUT np_enum_input; NVTPACK_MEM mem_in = {(void *)addr, size}; NVTPACK_MEM mem_out = {0}; memset(&np_get_input, 0, sizeof(np_get_input)); memset(&np_enum_input, 0, sizeof(np_enum_input)); ret = nvt_getfdt_emb((ulong)nvt_fdt_buffer, pEmb); if (ret < 0) { printf("failed to get current partition resource.\r\n"); return -1; } /* Check for all partition existed */ for (i = 1; i < EMB_PARTITION_INFO_COUNT; i++) { if (pEmb[i].PartitionSize != 0) { switch (pEmb[i].EmbType) { case EMBTYPE_FDT: #ifndef _NVT_LINUX_SMP_ON_ case EMBTYPE_UITRON: #endif case EMBTYPE_UBOOT: case EMBTYPE_LINUX: #ifdef CONFIG_NVT_LINUX_RAMDISK_SUPPORT case EMBTYPE_ROOTFS: #endif //check this type exist in all-in-one np_get_input.id = i; np_get_input.mem = mem_in; if (nvtpack_check_partition(pEmb[i], &np_get_input, &mem_out) != NVTPACK_ER_SUCCESS) { printf("RUNFW boot: need partition[%d]\n", i); return -1; } break; } } } /* Enum all partition to do necessary handling */ np_enum_input.mem = mem_in; np_enum_input.p_user_data = pEmb; /* Loading images */ np_enum_input.fp_enum = nvt_on_partition_enum_copy_to_dest; if (nvtpack_enum_partition(&np_enum_input) != NVTPACK_ER_SUCCESS) { printf("failed sanity.\r\n"); return -1; } /* Make sure images had been already copied */ flush_dcache_all(); return 0; } static int nvt_runfw_bin_unpack_to_dest_rtos(ulong addr) { u32 i; EMB_PARTITION *pEmb = emb_partition_info_data_curr; int ret = 0; unsigned int size = gHeadInfo.Resv1[0]; NVTPACK_GET_PARTITION_INPUT np_get_input; NVTPACK_ENUM_PARTITION_INPUT np_enum_input; NVTPACK_MEM mem_in = {(void *)addr, size}; NVTPACK_MEM mem_out = {0}; memset(&np_get_input, 0, sizeof(np_get_input)); memset(&np_enum_input, 0, sizeof(np_enum_input)); ret = nvt_getfdt_emb((ulong)nvt_fdt_buffer, pEmb); if (ret < 0) { printf("failed to get current partition resource.\r\n"); return -1; } /* Check for all partition existed */ for (i = 1; i < EMB_PARTITION_INFO_COUNT; i++) { if (pEmb[i].PartitionSize != 0) { switch (pEmb[i].EmbType) { case EMBTYPE_FDT: case EMBTYPE_RTOS: case EMBTYPE_UBOOT: //check this type exist in all-in-one np_get_input.id = i; np_get_input.mem = mem_in; if (nvtpack_check_partition(pEmb[i], &np_get_input, &mem_out) != NVTPACK_ER_SUCCESS) { printf("RUNFW boot: need partition[%d]\n", i); return -1; } break; } } } /* Enum all partition to do necessary handling */ np_enum_input.mem = mem_in; np_enum_input.p_user_data = pEmb; /* Loading images */ np_enum_input.fp_enum = nvt_on_rtos_partition_enum_copy_to_dest; if (nvtpack_enum_partition(&np_enum_input) != NVTPACK_ER_SUCCESS) { printf("failed sanity.\r\n"); return -1; } /* Make sure images had been already copied */ flush_dcache_all(); return 0; } static ulong uimage_gen_dcrc(const image_header_t *hdr) { ulong data = image_get_data(hdr); ulong len = image_get_data_size(hdr); return crc32_wd(0, (unsigned char *)data, len, CHUNKSZ_CRC32); } static ulong uimage_gen_hcrc(const image_header_t *hdr) { ulong hcrc; ulong len = image_get_header_size(); image_header_t header; /* Copy header so we can blank CRC field for re-calculation */ memmove(&header, (char *)hdr, image_get_header_size()); image_set_hcrc(&header, 0); return crc32(0, (unsigned char *)&header, len); } static int uimage_gen_fake_header(image_header_t *hdr, unsigned long size, unsigned long type) { if(!hdr){ printf("uimage_gen_fake_header():hdr is NULL\n"); return -1; } hdr->ih_magic = UINT32_SWAP(0x27051956); hdr->ih_hcrc = UINT32_SWAP(0); hdr->ih_time = UINT32_SWAP(0); hdr->ih_size = UINT32_SWAP(size); if(type == 2){ hdr->ih_load = UINT32_SWAP(0x8000); hdr->ih_ep = UINT32_SWAP(0x8000); }else{ hdr->ih_load = UINT32_SWAP(0); hdr->ih_ep = UINT32_SWAP(0); } hdr->ih_dcrc = UINT32_SWAP(0); hdr->ih_os = 5; hdr->ih_arch = 2; hdr->ih_type = type; hdr->ih_comp = 0; hdr->ih_name[0] = 0; hdr->ih_dcrc = UINT32_SWAP(uimage_gen_dcrc(hdr)); hdr->ih_hcrc = UINT32_SWAP(uimage_gen_hcrc(hdr)); return 0; } inline static int is_gzip_image(unsigned long image) { return (((NVTPACK_BFC_HDR*)image)->uiFourCC == MAKEFOURCC('B', 'C', 'L', '1')); } static int nvt_ker_img_ungzip_linux(unsigned long linux_addr, unsigned long workbuf) { unsigned long gzip_image_size = 0; unsigned long image_size = 0; NVTPACK_BFC_HDR *bfc = NULL; if(!is_gzip_image(linux_addr)) { nvt_dbg(IND, "not gzip linux\n"); return 0; } //extract linux's size(gzipped & original) bfc = (NVTPACK_BFC_HDR*)linux_addr; gzip_image_size = UINT32_SWAP(bfc->uiSizeComp); image_size = UINT32_SWAP(bfc->uiSizeUnComp); //copy gzipped linux to working buffer memcpy((char*)workbuf, (char*)linux_addr, gzip_image_size+sizeof(NVTPACK_BFC_HDR)); //uncompress linux nvt_dbg(IND, "gz_uncompress linux\n"); if(image_size > CONFIG_NVT_UIMAGE_SIZE){ nvt_dbg(ERR, "fail to gz_uncompress linux, image over size (%lu)\n", image_size); return -1; } if(gz_uncompress((unsigned char*)(workbuf+sizeof(NVTPACK_BFC_HDR)), (void*)(linux_addr+sizeof(image_header_t)), gzip_image_size, image_size) == 0){ nvt_dbg(ERR, "fail to gz_uncompress linux\n"); return -1; } //generate a fake uboot header so that uboot can recognize and boot linux nvt_dbg(IND, "generating uImage header for linux\n"); if(uimage_gen_fake_header((image_header_t*)linux_addr, image_size, 2)) { nvt_dbg(ERR, "fail to generate fake uboot header for linux\n"); return -1; } return 0; } static int nvt_ramdisk_img_ungzip_linux(unsigned long ramdisk_addr, unsigned long workbuf) { unsigned long gzip_image_size = 0; unsigned long image_size = 0; NVTPACK_BFC_HDR *bfc = NULL; if(!is_gzip_image(ramdisk_addr)) { nvt_dbg(IND, "not gzip ramdisk\n"); return 0; } //extract ramdisk's size(gzipped & original) bfc = (NVTPACK_BFC_HDR*)ramdisk_addr; gzip_image_size = UINT32_SWAP(bfc->uiSizeComp); image_size = UINT32_SWAP(bfc->uiSizeUnComp); //copy gzipped ramdisk to a working buffer memcpy((char*)workbuf, (char*)ramdisk_addr, gzip_image_size+sizeof(NVTPACK_BFC_HDR)); //uncompress ramdisk nvt_dbg(IND, "gz_uncompress ramdisk\n"); if(gz_uncompress((unsigned char*)(workbuf+sizeof(NVTPACK_BFC_HDR)), (void*)(ramdisk_addr+sizeof(image_header_t)), gzip_image_size, image_size) == 0) { nvt_dbg(ERR, "fail to gz_uncompress ramdisk\n"); return -1; } //generate a fake uboot header so that uboot can recognize ramdisk nvt_dbg(IND, "generating uImage header for ramdisk\n"); if(uimage_gen_fake_header((image_header_t*)ramdisk_addr, image_size, 3)) { nvt_dbg(ERR, "fail to generate fake uboot header for ramdisk\n"); return -1; } return 0; } #ifdef CONFIG_NVT_LINUX_AUTODETECT static int nvt_getfdt_dram_addr_size(ulong addr, ulong *fdt_rtos_addr, ulong *fdt_rtos_len) { int len; int nodeoffset; /* next node offset from libfdt */ const u32 *nodep; /* property node pointer */ nodeoffset = fdt_path_offset((const void *)addr, "/nvt_memory_cfg/dram"); if (nodeoffset < 0) { *fdt_rtos_addr = 0; *fdt_rtos_len = 0; return -1; } nodep = fdt_getprop((const void *)addr, nodeoffset, "reg", &len); if (len == 0) { *fdt_rtos_addr = 0; *fdt_rtos_len = 0; return -1; } *fdt_rtos_addr = be32_to_cpu(nodep[0]); *fdt_rtos_len = be32_to_cpu(nodep[1]); return 0; } static int nvt_getfdt_rtos_addr_size(ulong addr, ulong *fdt_rtos_addr, ulong *fdt_rtos_len) { int len; int nodeoffset; /* next node offset from libfdt */ const u32 *nodep; /* property node pointer */ nodeoffset = fdt_path_offset((const void *)addr, "/nvt_memory_cfg/rtos"); if (nodeoffset < 0) { *fdt_rtos_addr = 0; *fdt_rtos_len = 0; return -1; } nodep = fdt_getprop((const void *)addr, nodeoffset, "reg", &len); if (len == 0) { *fdt_rtos_addr = 0; *fdt_rtos_len = 0; return -1; } *fdt_rtos_addr = be32_to_cpu(nodep[0]); *fdt_rtos_len = be32_to_cpu(nodep[1]); return 0; } static int nvt_boot_linux_bin_auto(void) { char cmd[256] = {0}; int ret = 0; image_header_t *hdr; unsigned long size; unsigned int is_secure = 0; #ifdef CONFIG_NVT_IVOT_OPTEE_SUPPORT #ifdef CONFIG_NVT_IVOT_OPTEE_SECBOOT_SUPPORT NVT_SMC_EFUSE_DATA efuse_data = {0}; efuse_data.cmd = NVT_SMC_EFUSE_IS_SECURE; is_secure = nvt_ivot_optee_efuse_operation(&efuse_data); #endif #endif #if defined(CONFIG_NVT_LINUX_SPINOR_BOOT) || defined(CONFIG_NVT_LINUX_EMMC_BOOT) loff_t part_off = 0, part_size = 0; u32 align_size = 0; u64 align_off = 0; get_part("linux", &part_off, &part_size); #endif if (nvt_detect_fw_tbin()) { /* Check fw is valid */ nvt_runfw_bin_chk_valid((ulong)CONFIG_NVT_RUNFW_SDRAM_BASE); /* Copy linux binary to destination address */ ret = nvt_runfw_bin_unpack_to_dest((ulong)CONFIG_NVT_RUNFW_SDRAM_BASE); if (ret < 0) { return ret; } } else { // get uImage size firstly #if defined(CONFIG_NVT_LINUX_SPINAND_BOOT) || (defined(CONFIG_NVT_LINUX_RAMDISK_SUPPORT) && defined(CONFIG_NVT_SPI_NAND)) sprintf(cmd, "nand read 0x%lx linux 0x%lx", CONFIG_LINUX_SDRAM_START, is_secure==0?sizeof(image_header_t):sizeof(HEADINFO)); #elif defined(CONFIG_NVT_LINUX_SPINOR_BOOT) || (defined(CONFIG_NVT_LINUX_RAMDISK_SUPPORT) && defined(CONFIG_NVT_SPI_NOR)) align_size = ALIGN_CEIL(sizeof(image_header_t), ARCH_DMA_MINALIGN); sprintf(cmd, "sf read 0x%x 0x%llx 0x%x", CONFIG_LINUX_SDRAM_START, part_off, is_secure==0? align_size:sizeof(HEADINFO)); #elif defined(CONFIG_NVT_LINUX_EMMC_BOOT) || (defined(CONFIG_NVT_LINUX_RAMDISK_SUPPORT) && defined(CONFIG_NVT_IVOT_EMMC)) align_off = ALIGN_CEIL(part_off, MMC_MAX_BLOCK_LEN) / MMC_MAX_BLOCK_LEN; sprintf(cmd, "mmc read 0x%x 0x%llx 0x%x", CONFIG_LINUX_SDRAM_START, align_off, 2); #else /* Check for FPGA pure T.bin boot flow */ #ifndef _EMBMEM_NONE_ #error Error config in uboot... #endif #endif run_command(cmd, 0); if (is_secure == 0) { hdr = (image_header_t *)CONFIG_LINUX_SDRAM_START; size = image_get_data_size(hdr) + sizeof(image_header_t); } else { HEADINFO *encrypt_header = (HEADINFO *)(CONFIG_LINUX_SDRAM_START); size = encrypt_header->BinLength; } // Reading Linux kernel image #if defined(CONFIG_NVT_LINUX_SPINAND_BOOT) || (defined(CONFIG_NVT_LINUX_RAMDISK_SUPPORT) && defined(CONFIG_NVT_SPI_NAND)) sprintf(cmd, "nand read 0x%x linux 0x%x", CONFIG_LINUX_SDRAM_START, size); #elif defined(CONFIG_NVT_LINUX_SPINOR_BOOT) || (defined(CONFIG_NVT_LINUX_RAMDISK_SUPPORT) && defined(CONFIG_NVT_SPI_NOR)) align_size = ALIGN_CEIL(size, ARCH_DMA_MINALIGN); sprintf(cmd, "sf read 0x%x 0x%llx 0x%x", CONFIG_LINUX_SDRAM_START, part_off, align_size); #elif defined(CONFIG_NVT_LINUX_EMMC_BOOT) || (defined(CONFIG_NVT_LINUX_RAMDISK_SUPPORT) && defined(CONFIG_NVT_IVOT_EMMC)) printf("%s %d %d \n", __func__, __LINE__, size); align_size = ALIGN_CEIL(size, MMC_MAX_BLOCK_LEN) / MMC_MAX_BLOCK_LEN; sprintf(cmd, "mmc read 0x%x 0x%llx 0x%x", CONFIG_LINUX_SDRAM_START, align_off, align_size); printf("%s %d %d \n", __func__, __LINE__, size); #else /* Check for FPGA pure T.bin boot flow */ #ifndef _EMBMEM_NONE_ #error Error config in uboot... #endif #endif run_command(cmd, 0); nvt_ker_img_size = size; #ifdef CONFIG_ARM64 nvt_ker_img_addr = _BOARD_LINUX_ADDR_; char cmd[256] = {0}; sprintf(cmd, "0x%x", _BOARD_LINUX_ADDR_); env_set("kernel_comp_addr_r", cmd); sprintf(cmd, "0x%x", size); env_set("kernel_comp_size", cmd); #else nvt_ker_img_addr = CONFIG_LINUX_SDRAM_START; #endif } if (is_secure != 0) { ret = nvt_decrypt_kernel(); if (ret < 0) { nvt_dbg(ERR, "nvt_decrypt_kernel fail ret %d\r\n",ret); return -1; } } #ifndef CONFIG_NVT_SPI_NONE /* To check whether the kernel is nvt gzip format or not */ ret = nvt_ker_img_ungzip_linux(CONFIG_LINUX_SDRAM_START, CONFIG_LINUX_SDRAM_BASE); if (ret < 0) { nvt_dbg(ERR, "The nvt kernel image unzip failed with ret=%d \r\n",ret); return -1; } nvt_dbg(IND, "linux_addr:0x%08x\n", nvt_ker_img_addr); nvt_dbg(IND, "linux_size:0x%08x\n", nvt_ker_img_size); #endif return 0; } static u32 nvt_get_32bits_data(ulong addr, bool is_little_endian) { u_int32_t value = 0; u_int8_t *pb = (u_int8_t *)addr; if (is_little_endian) { if (addr & 0x3) { //NOT word aligned value = (*pb); value |= (*(pb + 1)) << 8; value |= (*(pb + 2)) << 16; value |= (*(pb + 3)) << 24; } else { value = *(u_int32_t *)addr; } } else { value = (*pb) << 24; value |= (*(pb + 1)) << 16; value |= (*(pb + 2)) << 8; value |= (*(pb + 3)); } return value; } static int nvt_boot_rtos_bin_auto(void) { ulong rtos_addr = 0, rtos_size = 0; char cmd[256] = {0}; int ret = 0; unsigned int tmp_addr = 0; u_int32_t codesize = 0; u32 align_size = 0; char *pCodeInfo = NULL; BININFO *pbininfo = NULL; SHMINFO *p_shminfo = (SHMINFO *)CONFIG_SMEM_SDRAM_BASE; #if defined(CONFIG_NVT_SPI_NOR) || defined(CONFIG_NVT_IVOT_EMMC) loff_t part_off = 0, part_size = 0; #endif #if defined(CONFIG_NVT_IVOT_DUAL_RTOS) unsigned int boot_bank = nvt_decide_dual_rtos_idx(); #else unsigned int boot_bank = 0; #endif char rtos_name[8] = {0}; switch(boot_bank) { case 0: strcpy(rtos_name, "rtos"); break; case 1: strcpy(rtos_name, "rtos1"); break; default: printf("%s no healthy rtos can be used. %s\r\n", ANSI_COLOR_RED, ANSI_COLOR_RESET); while(1); } nvt_getfdt_rtos_addr_size((ulong)nvt_fdt_buffer, &rtos_addr, &rtos_size); if (nvt_detect_fw_tbin()) { /* Check fw is valid */ nvt_runfw_bin_chk_valid((ulong)CONFIG_NVT_RUNFW_SDRAM_BASE); /* Copy itron binary to destination address */ ret = nvt_runfw_bin_unpack_to_dest_rtos((ulong)CONFIG_NVT_RUNFW_SDRAM_BASE);; if (ret < 0) { return ret; } } else { // get rtos image size firstly #if defined(CONFIG_NVT_LINUX_SPINAND_BOOT) || (defined(CONFIG_NVT_LINUX_RAMDISK_SUPPORT) && defined(CONFIG_NVT_SPI_NAND)) sprintf(cmd, "nand read 0x%x %s 0x500", rtos_addr, rtos_name); #elif defined(CONFIG_NVT_LINUX_SPINOR_BOOT) || (defined(CONFIG_NVT_LINUX_RAMDISK_SUPPORT) && defined(CONFIG_NVT_SPI_NOR)) get_part(rtos_name, &part_off, &part_size); sprintf(cmd, "sf read 0x%x 0x%llx 0x500 ", rtos_addr, part_off); #elif defined(CONFIG_NVT_LINUX_EMMC_BOOT) || (defined(CONFIG_NVT_LINUX_RAMDISK_SUPPORT) && defined(CONFIG_NVT_IVOT_EMMC)) get_part(rtos_name, &part_off, &part_size); sprintf(cmd, "mmc read 0x%x 0x%llx 4", rtos_addr, part_off / MMC_MAX_BLOCK_LEN); #endif printf("=>run cmd : %s\n", cmd); run_command(cmd, 0); // Reading rtos image NVTPACK_BFC_HDR *pbfc = (NVTPACK_BFC_HDR *)rtos_addr; if (pbfc->uiFourCC == MAKEFOURCC('B', 'C', 'L', '1')) { printf("Compressed rtos\n"); /* rtos image size will be put in the end of rtos region */ size_t firmware_size = cpu_to_be32(pbfc->uiSizeComp) + sizeof(NVTPACK_BFC_HDR); tmp_addr = rtos_addr + rtos_size - firmware_size; if ((firmware_size + cpu_to_be32(pbfc->uiSizeUnComp)) > rtos_size) { printf("%s Attention!!! rtos starting address at 0x%08x with size 0x%08x (uncompressed) is larger than temp buffer address!! 0x%08x %s\r\n", ANSI_COLOR_RED, rtos_addr, cpu_to_be32(pbfc->uiSizeUnComp), tmp_addr, ANSI_COLOR_RESET); printf("%s It can't decompress %s\r\n", ANSI_COLOR_RED, ANSI_COLOR_RESET); while (1); } #if defined(CONFIG_NVT_LINUX_SPINAND_BOOT) || (defined(CONFIG_NVT_LINUX_RAMDISK_SUPPORT) && defined(CONFIG_NVT_SPI_NAND)) sprintf(cmd, "nand read 0x%x %s 0x%x ", tmp_addr, rtos_name, firmware_size); #elif defined(CONFIG_NVT_LINUX_SPINOR_BOOT) || (defined(CONFIG_NVT_LINUX_RAMDISK_SUPPORT) && defined(CONFIG_NVT_SPI_NOR)) sprintf(cmd, "sf read 0x%x 0x%llx 0x%x ", tmp_addr, part_off, firmware_size); #elif defined(CONFIG_NVT_LINUX_EMMC_BOOT) || (defined(CONFIG_NVT_LINUX_RAMDISK_SUPPORT) && defined(CONFIG_NVT_IVOT_EMMC)) align_size = ALIGN_CEIL(firmware_size, MMC_MAX_BLOCK_LEN) / MMC_MAX_BLOCK_LEN; sprintf(cmd, "mmc read 0x%x 0x%llx 0x%x", tmp_addr, part_off / MMC_MAX_BLOCK_LEN, align_size); #endif printf("=>run cmd : %s\n", cmd); run_command(cmd, 0); debug("auto boot bfc UnCompsz:%d Compsz:%d Algorithm: %x \n", cpu_to_be32(pbfc->uiSizeUnComp), cpu_to_be32(pbfc->uiSizeComp), cpu_to_be32(pbfc->uiAlgorithm)); if ((cpu_to_be32(pbfc->uiAlgorithm) & 0xFF) == 11) { /* lzma compressed image*/ size_t Compsz = cpu_to_be32(pbfc->uiSizeComp); size_t Uncompsz = cpu_to_be32(pbfc->uiSizeUnComp); printf("Decompressed lzma rtos\n"); flush_dcache_range((ulong)tmp_addr, (ulong)(tmp_addr + firmware_size)); ret = lzmaBuffToBuffDecompress((unsigned char *)rtos_addr, &Uncompsz, (unsigned char *)(tmp_addr + sizeof(NVTPACK_BFC_HDR)), Compsz); if (ret != 0) { printf("Decompressed lzma fail\n"); } flush_dcache_range((ulong)rtos_addr, (ulong)(rtos_addr + Uncompsz)); } else { /* lz77 compressed image*/ lz_uncompress((unsigned char *)(tmp_addr + sizeof(NVTPACK_BFC_HDR)), (unsigned char *)rtos_addr, cpu_to_be32(pbfc->uiSizeComp)); flush_dcache_range((ulong)rtos_addr, (ulong)(rtos_addr + rtos_size)); } } else { int i; pbininfo = (BININFO *)(rtos_addr + BIN_INFO_OFFSET_RTOS); printf("Non-compressed rtos\n"); if (pbininfo->head.Resv1[HEADINFO_RESV_IDX_BOOT_FLAG] & BOOT_FLAG_PARTLOAD_EN) { // fllush whole rtos memory to invalidate cache on partial load flush_dcache_range((ulong)rtos_addr, (ulong)(rtos_addr + rtos_size)); // preload some to get part-1 size for partial load and partial compressed load u32 preload_size = ALIGN_CEIL(FW_PART1_SIZE_OFFSET, _EMBMEM_BLK_SIZE_); #if defined(CONFIG_NVT_LINUX_SPINAND_BOOT) || (defined(CONFIG_NVT_LINUX_RAMDISK_SUPPORT) && defined(CONFIG_NVT_SPI_NAND)) sprintf(cmd, "nand read 0x%x %s 0x%x ", rtos_addr, rtos_name, preload_size); #elif defined(CONFIG_NVT_LINUX_SPINOR_BOOT) || (defined(CONFIG_NVT_LINUX_RAMDISK_SUPPORT) && defined(CONFIG_NVT_SPI_NOR)) align_size = ALIGN_CEIL(preload_size, ARCH_DMA_MINALIGN); sprintf(cmd, "sf read 0x%x 0x%llx 0x%x", rtos_addr, part_off, align_size); #elif defined(CONFIG_NVT_LINUX_EMMC_BOOT) || (defined(CONFIG_NVT_LINUX_RAMDISK_SUPPORT) && defined(CONFIG_NVT_IVOT_EMMC)) align_size = ALIGN_CEIL(preload_size, MMC_MAX_BLOCK_LEN) / MMC_MAX_BLOCK_LEN; sprintf(cmd, "mmc read 0x%x 0x%llx 0x%x", rtos_addr, part_off / MMC_MAX_BLOCK_LEN, align_size); #endif run_command(cmd, 0); //partial-load or partial-compressed-load u32 part1_size = *(u32 *)(rtos_addr + FW_PART1_SIZE_OFFSET); printf("part1_size=%08X,preload_size=%08X\r\n", part1_size, preload_size); //align to block size part1_size = ALIGN_CEIL(part1_size, _EMBMEM_BLK_SIZE_); printf("part1_size_aligned=%08X\r\n", part1_size); //sprintf(cmd, "nand read 0x%x 0x%x 0x%x", (unsigned int)dst_addr, base_ofs+ofs, size); #if defined(CONFIG_NVT_LINUX_SPINAND_BOOT) || (defined(CONFIG_NVT_LINUX_RAMDISK_SUPPORT) && defined(CONFIG_NVT_SPI_NAND)) align_size = part1_size; sprintf(cmd, "nand read 0x%x %s 0x%x ", rtos_addr, rtos_name, align_size); //update LdLoadSize p_shminfo->boot.LdLoadSize = align_size; #elif defined(CONFIG_NVT_LINUX_SPINOR_BOOT) || (defined(CONFIG_NVT_LINUX_RAMDISK_SUPPORT) && defined(CONFIG_NVT_SPI_NOR)) align_size = ALIGN_CEIL(part1_size, ARCH_DMA_MINALIGN); sprintf(cmd, "sf read 0x%x 0x%llx 0x%x", rtos_addr, part_off, align_size); //update LdLoadSize p_shminfo->boot.LdLoadSize = align_size; #elif defined(CONFIG_NVT_LINUX_EMMC_BOOT) || (defined(CONFIG_NVT_LINUX_RAMDISK_SUPPORT) && defined(CONFIG_NVT_IVOT_EMMC)) align_size = ALIGN_CEIL(part1_size, MMC_MAX_BLOCK_LEN) / MMC_MAX_BLOCK_LEN; sprintf(cmd, "mmc read 0x%x 0x%llx 0x%x", rtos_addr, part_off / MMC_MAX_BLOCK_LEN, align_size); //update LdLoadSize p_shminfo->boot.LdLoadSize = align_size * MMC_MAX_BLOCK_LEN; #endif flush_dcache_range((ulong)p_shminfo, (ulong)p_shminfo + sizeof(SHMINFO)); } else { //full load #if defined(CONFIG_NVT_LINUX_SPINAND_BOOT) || (defined(CONFIG_NVT_LINUX_RAMDISK_SUPPORT) && defined(CONFIG_NVT_SPI_NAND)) sprintf(cmd, "nand read 0x%x %s 0x%x ", rtos_addr, rtos_name, pbininfo->head.BinLength); #elif defined(CONFIG_NVT_LINUX_SPINOR_BOOT) || (defined(CONFIG_NVT_LINUX_RAMDISK_SUPPORT) && defined(CONFIG_NVT_SPI_NOR)) sprintf(cmd, "sf read 0x%x 0x%llx 0x%x ", rtos_addr, part_off, pbininfo->head.BinLength); #elif defined(CONFIG_NVT_LINUX_EMMC_BOOT) || (defined(CONFIG_NVT_LINUX_RAMDISK_SUPPORT) && defined(CONFIG_NVT_IVOT_EMMC)) sprintf(cmd, "mmc read 0x%x 0x%llx 0x%x", rtos_addr, part_off / MMC_MAX_BLOCK_LEN, pbininfo->head.BinLength / MMC_MAX_BLOCK_LEN); #endif //update LdLoadSize p_shminfo->boot.LdLoadSize = pbininfo->head.BinLength; flush_dcache_range((ulong)p_shminfo, (ulong)p_shminfo + sizeof(SHMINFO)); } printf("=>run cmd : %s\n", cmd); run_command(cmd, 0); // fllush whole rtos memory to invalidate cache flush_dcache_range((ulong)rtos_addr, (ulong)(rtos_addr + rtos_size)); } } pCodeInfo = (char *)(rtos_addr + RTOS_CODEINFO_OFFSET); pbininfo = (BININFO *)(rtos_addr + BIN_INFO_OFFSET_RTOS); if (strncmp(pCodeInfo, "CODEINFO", 8) != 0) { printf("invalid CODEINFO\r\n"); return -1; } /* dram partition rtos address should be the same with headinfo address */ if (rtos_addr != pbininfo->head.CodeEntry) { printf("dram partition rtos addr (%08X) != headinfo(%08X)\r\n" , rtos_addr , pbininfo->head.CodeEntry); return -1; } /* To check if code size is larger than rtos_addr + rtos_size (Not image size) */ codesize = nvt_get_32bits_data((ulong)(&pCodeInfo[RTOS_CODEINFO_SUB_ZI_LIMIT]), true) - rtos_addr; if (codesize > rtos_size) { printf("uBoot uiCodeSize(%08X) > dram partition rtos size(%08X)\r\n" , codesize , rtos_size); return -1; } #if defined(CONFIG_NVT_IVOT_DUAL_RTOS) nvt_update_dual_rtos_info(pbininfo, boot_bank); #endif printf("rtos starting.... 0x%08x\n", rtos_addr); { typedef void (*BRANCH_CB)(void); BRANCH_CB p_func = (BRANCH_CB)rtos_addr; p_func(); } return 0; } #if defined(CONFIG_NVT_LINUX_RAMDISK_SUPPORT) static int nvt_boot_rootfs_bin_auto(void) { int nodeoffset = 0; int nextoffset = 0; const unsigned long long *val = NULL; u64 ramdisk_partition_addr; int len = 0, ret; char cmd[256] = {0}; char tmp_translate[64] = {0}; unsigned int ramdisk_partition_addr_32 = 0; image_header_t *hdr; unsigned int hdr_tmp = 0; u64 align_off = 0; // get rootfs partition info from fdt #if defined(CONFIG_NVT_IVOT_EMMC) char path[128] = {0}; #if (defined(CONFIG_TARGET_NA51090) || defined(CONFIG_TARGET_NA51090_A64)) sprintf(path, "/mmc@%x/partition_rootfs", IOADDR_SDIO2_REG_BASE); #else sprintf(path, "/mmc@%x/partition_rootfs", IOADDR_SDIO3_REG_BASE); #endif nodeoffset = fdt_path_offset((void *)nvt_fdt_buffer, path); #elif defined(CONFIG_NVT_SPI_NOR) nodeoffset = fdt_path_offset((void *)nvt_fdt_buffer, "/nor/partition_rootfs"); #else nodeoffset = fdt_path_offset((void *)nvt_fdt_buffer, "/nand/partition_rootfs"); #endif if (nodeoffset < 0) { printf("nvt_boot_rootfs_bin_auto get fdt information (partition_rootfs) error\n"); return -1; } val = (const unsigned long long *)fdt_getprop((const void *)nvt_fdt_buffer, nodeoffset, "reg", &len); if (len <= 0) { printf("get fdt partition_rootfs reg value error\n"); return -1; } ramdisk_partition_addr = be64_to_cpu(val[0]); //sprintf(&hdr_tmp,"%x",ramdisk_partition_addr); //hdr = (image_header_t *)hdr_tmp; sprintf(tmp_translate, "%llx", ramdisk_partition_addr); ramdisk_partition_addr_32 = atoi(tmp_translate); printf("ramdisk_partition_addr_32:%u\n", ramdisk_partition_addr_32); // get uImage size firstly (Loading header only) nvt_ramdisk_addr = (ulong)memalign(CONFIG_SYS_CACHELINE_SIZE, 0x20000); if (!nvt_ramdisk_addr) { printf("nvt_ramdisk_addr alloc fail\n"); return -1; } #if defined(CONFIG_NVT_LINUX_SPINAND_BOOT) || (defined(CONFIG_NVT_LINUX_RAMDISK_SUPPORT) && defined(CONFIG_NVT_SPI_NAND)) sprintf(cmd, "nand read 0x%x 0x%llx 0x%x", nvt_ramdisk_addr, ramdisk_partition_addr, sizeof(image_header_t)); #elif defined(CONFIG_NVT_LINUX_SPINOR_BOOT) || (defined(CONFIG_NVT_LINUX_RAMDISK_SUPPORT) && defined(CONFIG_NVT_SPI_NOR)) u32 align_size = 0; align_size = ALIGN_CEIL(sizeof(image_header_t), ARCH_DMA_MINALIGN); sprintf(cmd, "sf read 0x%x 0x%llx 0x%x", nvt_ramdisk_addr, ramdisk_partition_addr, align_size); #elif defined(CONFIG_NVT_LINUX_EMMC_BOOT) || (defined(CONFIG_NVT_LINUX_RAMDISK_SUPPORT) && defined(CONFIG_NVT_IVOT_EMMC)) align_off = ALIGN_CEIL(ramdisk_partition_addr, MMC_MAX_BLOCK_LEN) / MMC_MAX_BLOCK_LEN; sprintf(cmd, "mmc read 0x%x 0x%llx 0x%x", nvt_ramdisk_addr, align_off, 2); #endif run_command(cmd, 0); hdr = (image_header_t *)nvt_ramdisk_addr; nvt_ramdisk_size = image_get_data_size(hdr) + sizeof(image_header_t); nvt_ramdisk_size = ALIGN_CEIL(nvt_ramdisk_size, 4096); if(nvt_ramdisk_addr) free((void *)nvt_ramdisk_addr); nvt_ramdisk_addr = _BOARD_LINUX_ADDR_ + _BOARD_LINUX_SIZE_ - nvt_ramdisk_size - 0x10000; /* Check whether the Linux and ramdisk region is overlap or not */ if (nvt_ramdisk_addr > nvt_ker_img_addr) { if ((nvt_ker_img_addr + nvt_ker_img_size) > nvt_ramdisk_addr) { nvt_dbg(ERR, "Image overlap: linux addr 0x%08lx linux size 0x%08lx ramdisk addr 0x%08lx ramdisk size 0x%08lx\n", nvt_ker_img_addr, nvt_ker_img_size, nvt_ramdisk_addr, nvt_ker_img_addr); return -1; } } else { if ((nvt_ramdisk_addr + nvt_ramdisk_size) > nvt_ker_img_addr) { nvt_dbg(ERR, "Image overlap: linux addr 0x%08lx linux size 0x%08lx ramdisk addr 0x%08lx ramdisk size 0x%08lx\n", nvt_ker_img_addr, nvt_ker_img_size, nvt_ramdisk_addr, nvt_ker_img_addr); return -1; } } //nvt_ramdisk_size = ALIGN_CEIL(p_mem->len, 4096); nvt_dbg(IND, "ramdisk_addr:0x%08x\n", nvt_ramdisk_addr); nvt_dbg(IND, "ramdisk_size:0x%08x\n", nvt_ramdisk_size); #if defined(CONFIG_NVT_LINUX_SPINAND_BOOT) || (defined(CONFIG_NVT_LINUX_RAMDISK_SUPPORT) && defined(CONFIG_NVT_SPI_NAND)) sprintf(cmd, "nand read 0x%x 0x%llx 0x%x", nvt_ramdisk_addr, ramdisk_partition_addr, nvt_ramdisk_size); #elif defined(CONFIG_NVT_LINUX_SPINOR_BOOT) || (defined(CONFIG_NVT_LINUX_RAMDISK_SUPPORT) && defined(CONFIG_NVT_SPI_NOR)) align_size = ALIGN_CEIL(nvt_ramdisk_size, ARCH_DMA_MINALIGN); sprintf(cmd, "sf read 0x%x 0x%llx 0x%x", nvt_ramdisk_addr, ramdisk_partition_addr, align_size); #elif defined(CONFIG_NVT_LINUX_EMMC_BOOT) || (defined(CONFIG_NVT_LINUX_RAMDISK_SUPPORT) && defined(CONFIG_NVT_IVOT_EMMC)) u32 align_size = 0; align_size = ALIGN_CEIL(nvt_ramdisk_size, MMC_MAX_BLOCK_LEN) / MMC_MAX_BLOCK_LEN; align_off = ALIGN_CEIL(ramdisk_partition_addr, MMC_MAX_BLOCK_LEN) / MMC_MAX_BLOCK_LEN; sprintf(cmd, "mmc read 0x%x 0x%llx 0x%x", nvt_ramdisk_addr, align_off, align_size); #else printf("can not get ramdisk from flash/emmc, please check flash type or boot type\n"); #endif run_command(cmd, 0); /* To check whether the ramdisk format is nvt gzip format or not */ ret = nvt_ramdisk_img_ungzip_linux(nvt_ramdisk_addr, CONFIG_LINUX_SDRAM_BASE); if (ret < 0) { nvt_dbg(ERR, "The nvt ramdisk image unzip failed with ret=%d \r\n",ret); return -1; } return 0; } #endif /* CONFIG_NVT_LINUX_RAMDISK_SUPPORT */ static int nvt_boot_fw_init_detect(void) { ulong rtos_addr = 0, rtos_size = 0; int len = 0; int nodeoffset; /* next node offset from libfdt */ const char *nodep; /* property node pointer */ printf("NVT firmware boot.....\n"); nodeoffset = fdt_path_offset((const void *)nvt_fdt_buffer, "/nvt_info"); if (nodeoffset >= 0) { nodep = fdt_getprop((const void *)nvt_fdt_buffer, nodeoffset, "UBOOT_ONLY_LOAD_LINUX", &len); if (nodep != NULL || len != 0) { if (strcmp(nodep, "UBOOT_ONLY_LOAD_LINUX_ON") == 0) { //printf("nvt_boot_fw_init_detect: Only load linux...\r\n"); rtos_disable_anchor = 1; } } } if (nvt_getfdt_rtos_addr_size((ulong)nvt_fdt_buffer, &rtos_addr, &rtos_size) != 0 || rtos_size == 0 || rtos_disable_anchor == 1) { nvt_boot_linux_bin_auto(); #if defined(CONFIG_NVT_LINUX_RAMDISK_SUPPORT) if (!nvt_detect_fw_tbin()) { nvt_boot_rootfs_bin_auto(); } #endif } else { nvt_boot_rtos_bin_auto(); } return 0; } #else /* !CONFIG_NVT_LINUX_AUTODETECT */ static int nvt_boot_linux_bin(void) { char cmd[256] = {0}; #if defined(CONFIG_NVT_LINUX_SPINAND_BOOT) sprintf(cmd, "nand read 0x%x linux ", CONFIG_LINUX_SDRAM_START); run_command(cmd, 0); #elif defined(CONFIG_NVT_LINUX_SPINOR_BOOT) loff_t part_off = 0, part_size = 0; /* Get linux partition offset and size */ get_part("linux", &part_off, &part_size); sprintf(cmd, "sf read 0x%x 0x%llx 0x%llx", CONFIG_LINUX_SDRAM_START, part_off, part_size); ret = run_command(cmd, 0); #elif defined(CONFIG_NVT_LINUX_SD_BOOT) /* CONFIG_NVT_LINUX_SD_BOOT */ sprintf(cmd, "fatload mmc 0:1 0x%x uImage.bin ", CONFIG_LINUX_SDRAM_START); run_command(cmd, 0); #elif defined(CONFIG_NVT_LINUX_EMMC_BOOT) /* CONFIG_NVT_LINUX_EMMC_BOOT */ loff_t part_off = 0, part_size = 0; /* Get linux partition offset and size */ get_part("linux", &part_off, &part_size); sprintf(cmd, "mmc read 0x%x 0x%llx 0x%llx ", CONFIG_LINUX_SDRAM_START, part_off, part_size); run_command(cmd, 0); #else /* !defined(CONFIG_NVT_LINUX_SPINAND_BOOT) && !defined(CONFIG_NVT_LINUX_SD_BOOT) */ int ret = 0; /* Check fw is valid */ nvt_runfw_bin_chk_valid((ulong)CONFIG_NVT_RUNFW_SDRAM_BASE); /* Copy linux binary to destination address */ ret = nvt_runfw_bin_unpack_to_dest((ulong)CONFIG_NVT_RUNFW_SDRAM_BASE); if (ret < 0) { return ret; } #endif /* CONFIG_NVT_LINUX_SPINAND_BOOT */ } static int nvt_boot_fw_init(void) { char cmd[256] = {0}; printf("NVT firmware boot.....\n"); #ifndef _NVT_LINUX_SMP_ON_ #endif /* !_NVT_LINUX_SMP_ON_ */ #ifdef _CPU2_NONE_ /* Core1 will turn off core2 if core2 is not linux */ while (1); #endif /* _CPU2_NONE_ */ nvt_boot_linux_bin(); return 0; } #endif /* CONFIG_NVT_LINUX_AUTODETECT */ #endif /* CONFIG_NVT_IVOT_SOC_FW_UPDATE_SUPPORT */ #ifdef CONFIG_NVT_IVOT_OPTEE_SUPPORT static void get_bininfo_size_offset(unsigned char* bininfo,unsigned int* size,unsigned int *offset) { *size = bininfo[4] | bininfo[5]<<8 | bininfo[6] << 16 | bininfo[7] << 24; *offset = bininfo[0] | bininfo[1] << 8 | bininfo[2] << 16 | bininfo[3] <<24; } unsigned char test_aes_key[16]={0x04,0x03,0x02,0x01,0x08,0x07,0x06,0x05,0x12,0x11,0x10,0x09,0x16,0x15,0x14,0x013}; //unsigned char test_aes_key_fake[16]={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x9,0x10,0x11,0x12,0x13,0x14,0x15,0x16}; #endif static int nvt_decrypt_kernel(void) { #ifdef CONFIG_NVT_IVOT_OPTEE_SUPPORT #ifdef CONFIG_NVT_IVOT_OPTEE_SECBOOT_SUPPORT #if 1 NVT_SMC_EFUSE_DATA efuse_data = {0}; efuse_data.cmd = NVT_SMC_EFUSE_IS_DATA_ENCRYPTED; if (1 != nvt_ivot_optee_efuse_operation(&efuse_data)) { printf("data encrypt not enable\n"); return 0; } #endif HEADINFO *headinfo = (HEADINFO *)CONFIG_LINUX_SDRAM_START; unsigned int crypto_offset =0; unsigned int crypto_size = 0; unsigned char *encrypt_buf = NULL; unsigned char * bininfo = headinfo->BinInfo_3; int ret =0; get_bininfo_size_offset(headinfo->BinInfo_3, &crypto_size, &crypto_offset); encrypt_buf = (unsigned char *)((unsigned long)CONFIG_LINUX_SDRAM_START + crypto_offset); unsigned int total_size = headinfo->BinLength; // crypto_size is alignmnet 16, so the uImage size and crypto_size may not the same unsigned int decrypt_size = total_size - crypto_offset; NVT_SMC_AES_DATA aes_data={0}; aes_data.crypto_type = NVT_SMC_AES_CRYPTO_DECRYPTION; aes_data.aes_mode = NVT_SMC_AES_MODE_CBC; aes_data.key_buf = (unsigned char *)test_aes_key; memset(aes_data.IV,0,16); #if 0 //using key in buffer aes_data.efuse_field = -1; #else //using key in efuse aes_data.efuse_field = 0; #endif aes_data.key_size = 16; aes_data.input_data = (unsigned char *)encrypt_buf; aes_data.input_size = crypto_size; aes_data.output_data = (unsigned char *)CONFIG_LINUX_SDRAM_START; ret = nvt_ivot_optee_aes_operation(&aes_data); if(ret != 0) { printf("nvt_ivot_optee_aes_operation fail\r\n",ret); return -1; } if(decrypt_size > crypto_size) { //there are some data not encrypt, need copy to buf unsigned char * tmp = (unsigned char *)CONFIG_LINUX_SDRAM_START; memcpy(&tmp[crypto_size], &encrypt_buf[crypto_size], (decrypt_size - crypto_size)); } if(ret != 0) { printf("nvt_ivot_optee_aes_cbc_decrypt fail ret:%d\n",ret); return -1; } return 0; #endif #else printf("not support decrypt!\n"); return -1; #endif } static int nvt_set_bootargs_by_dts(const void *fdt_addr) { int nodeoffset; void *val = NULL; if (fdt_addr == NULL) { nvt_dbg(ERR, "fdt_addr is NULL\n"); return -1; } nodeoffset = fdt_path_offset((void *)fdt_addr, "/chosen"); if (nodeoffset > 0) { val = (void *)fdt_getprop((const void *)fdt_addr, nodeoffset, "bootargs", NULL); if (val != NULL) { if (env_get("bootargs") != NULL) { char buf[1024] = {0}; sprintf(buf, "%s", env_get("bootargs")); strcat(buf, val); env_set("bootargs", (void *)buf); } else { env_set("bootargs", (void *)val); } } else { nvt_dbg(ERR, "can not find bootargs on device tree\n"); return -1; } } else { nvt_dbg(ERR, "can not find /chosen on device tree\n"); return -1; } return 0; } int do_nvt_boot_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { int ret = 0; char cmdline[512] = {0}; char cmd[256] = {0}; char buf[255] = {0}; unsigned int is_secure = 0; if (nvt_set_bootargs_by_dts(nvt_fdt_buffer) < 0) { return -1; } /* * To handle bootargs expanding for the kernel /proc/cmdline */ nvt_dbg(FUNC, "boot time: %lu(us)\n", get_nvt_timer0_cnt()); sprintf(buf, "%s ", env_get("bootargs")); strcat(cmdline, buf); /* * Loading linux kernel */ #ifdef CONFIG_NVT_IVOT_SOC_FW_UPDATE_SUPPORT #ifdef CONFIG_NVT_LINUX_AUTODETECT ret = nvt_boot_fw_init_detect(); if (ret < 0) { printf("boot firmware init failed\n"); return ret; } #else /* !CONFIG_NVT_LINUX_AUTODETECT */ ret = nvt_boot_fw_init(); if (ret < 0) { printf("boot firmware init failed\n"); return ret; } #endif /* CONFIG_NVT_LINUX_AUTODETECT */ #else /* !CONFIG_NVT_IVOT_SOC_FW_UPDATE_SUPPORT */ /* FIXME: To do customized boot */ #endif /* CONFIG_NVT_IVOT_SOC_FW_UPDATE_SUPPORT */ nvt_dbg(FUNC, "boot time: %lu(us)\n", get_nvt_timer0_cnt()); nvt_tm0_cnt_end = get_nvt_timer0_cnt(); /* boot time recording */ #ifdef CONFIG_ARM64 sprintf(buf, "bootts=%lu,%lu resume_addr=0x%08lx print-fatal-signals=1 ", nvt_tm0_cnt_beg, nvt_tm0_cnt_end, nvt_shminfo_comm_core2_start); #else sprintf(buf, "bootts=%lu,%lu resume_addr=0x%08lx user_debug=0xff ", nvt_tm0_cnt_beg, nvt_tm0_cnt_end, nvt_shminfo_comm_core2_start); #endif strcat(cmdline, buf); env_set("bootargs", cmdline); nvt_dbg(IND, "bootargs:%s\n", cmdline); /* To assign relocated fdt address */ sprintf(buf, "0x%08x ", _BOARD_LINUX_MAXBLK_ADDR_ + _BOARD_LINUX_MAXBLK_SIZE_); env_set("fdt_high", buf); /* The following will setup the lmb memory parameters for bootm cmd */ sprintf(buf, "0x%08x ", _BOARD_LINUX_ADDR_ + _BOARD_LINUX_SIZE_); env_set("bootm_size", buf); env_set("bootm_mapsize", buf); sprintf(buf, "0x%08x ", _BOARD_LINUX_ADDR_); env_set("bootm_low", buf); #ifdef CONFIG_ARM64 sprintf(cmd, "booti"); #else sprintf(cmd, "bootm"); #endif image_print_contents((void*)CONFIG_LINUX_SDRAM_START); /* * Issue boot command */ #if defined(CONFIG_NVT_LINUX_RAMDISK_SUPPORT) sprintf(buf, "0x%08x ", nvt_ramdisk_addr + nvt_ramdisk_size); env_set("initrd_high", buf); if (nvt_ramdisk_addr == 0) { printf("!Stop boot because your ramdisk address is wrong!!! addr: 0x%08x \n", nvt_ramdisk_addr); while (1); } nvt_dbg(FUNC, "boot time: %lu(us)\n", get_nvt_timer0_cnt()); /************************************************************************************************ * ARM64: uImage.lzma => Uimage header + Image(LZMA compression type) * The booti will be responsible for decompress Image, so we need to skip the image_header_t size * ARM32: uImage => Uboot doesn't need to decompress kernel image, the compressed image will be decompressed by Linux stage. ************************************************************************************************/ #ifdef CONFIG_ARM64 sprintf(cmd, "%s %x %lx %lx", cmd, CONFIG_LINUX_SDRAM_START+sizeof(image_header_t), nvt_ramdisk_addr, (ulong)nvt_fdt_buffer); #else sprintf(cmd, "%s %x %lx %lx", cmd, CONFIG_LINUX_SDRAM_START, nvt_ramdisk_addr, (ulong)nvt_fdt_buffer); #endif printf("%s\n", cmd); #else printf("%s Linux Image is at %x, uboot fdt image is at %lx, loader tmp fdt address is at %x %s\n", ANSI_COLOR_YELLOW, CONFIG_LINUX_SDRAM_START, (ulong)nvt_fdt_buffer, nvt_readl((ulong)nvt_shminfo_boot_fdt_addr), ANSI_COLOR_RESET); #ifdef CONFIG_ARM64 sprintf(cmd, "%s %x - %lx", cmd, CONFIG_LINUX_SDRAM_START+sizeof(image_header_t), (ulong)nvt_fdt_buffer); #else sprintf(cmd, "%s %x - %lx", cmd, CONFIG_LINUX_SDRAM_START, (ulong)nvt_fdt_buffer); #endif printf("%s\n", cmd); #endif /* CONFIG_NVT_LINUX_RAMDISK_SUPPORT */ nvt_dbg(FUNC, "boot time: %lu(us)\n", get_nvt_timer0_cnt()); nvt_dbg(FUNC, "Uboot boot time: \n\tstart:\t%lu us\n\tending:\t%lu us \r\n", nvt_tm0_cnt_beg, nvt_tm0_cnt_end); run_command(cmd, 0); return 0; } U_BOOT_CMD( nvt_boot, 1, 0, do_nvt_boot_cmd, "To do nvt platform boot init.", "\n" ); #ifdef CONFIG_NVT_IVOT_SOC_FW_UPDATE_SUPPORT int do_nvt_update_all_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { ulong addr = 0, size = 0; int ret = 0; if (argc != 3) { return CMD_RET_USAGE; } size = cmd_get_data_size(argv[0], 4); if (size < 0) { return 1; } addr = simple_strtoul(argv[1], NULL, 16); size = simple_strtoul(argv[2], NULL, 10); printf("%s addr: 0x%08lx, size: 0x%08lx(%lu) bytes %s\r\n", ANSI_COLOR_YELLOW, addr, size, size, ANSI_COLOR_RESET); ret = nvt_process_all_in_one(addr, size, 0); if (ret < 0) { printf("Update nvt all-in-one image failed.\n"); return ret; } return 0; } U_BOOT_CMD( nvt_update_all, 3, 0, do_nvt_update_all_cmd, "To Update all-in-one image from memory address and size \n", "[address(hex)][size(dec)] \n" ); #endif /* CONFIG_NVT_IVOT_SOC_FW_UPDATE_SUPPORT */ //This is encrypt / decrypt sample code #define SAMPLE_CODE_KEYMANAGER 0 #define SAMPLE_CODE_CPUFILLKEY 1 #define SAMPLE_CODE_TYPE SAMPLE_CODE_KEYMANAGER #define SAMPLE_CODE_ENC_TYPE_EBC 0 #define SAMPLE_CODE_ENC_TYPE_CBC 1 #define SAMPLE_CODE_ENC_TYPE SAMPLE_CODE_ENC_TYPE_EBC static UINT8 car_in[16] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16}; static UINT8 iv_in[16] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16}; #if(SAMPLE_CODE_TYPE == SAMPLE_CODE_CPUFILLKEY) static UINT8 cpu_key[16] = {0x04, 0x03, 0x02, 0x01, 0x08, 0x07, 0x06, 0x05, 0x12, 0x11, 0x10, 0x09, 0x16, 0x15, 0x14, 0x13}; #endif int do_nvt_encrypt_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { int index_cnt; UINT32 test_buf; UINT32 test_buf2; UINT32 test_buf_align; UINT32 test_buf2_align; u8 *output; u8 *output2; #if(SAMPLE_CODE_TYPE == SAMPLE_CODE_KEYMANAGER) u32 key_set = EFUSE_OTP_1ST_KEY_SET_FIELD; #endif CRYPT_OP crypt_op_param = {0}; test_buf = (UINT32)malloc(16 + 64 * 4); test_buf_align = (UINT32)((test_buf + 63) & 0xFFFFFFC0); test_buf2 = test_buf_align + 100; test_buf2_align = (UINT32)((test_buf2 + 63) & 0xFFFFFFC0); output = (UINT8 *)test_buf_align; output2 = (UINT8 *)test_buf2_align; #if(SAMPLE_CODE_TYPE == SAMPLE_CODE_KEYMANAGER) if (strncmp(argv[1], "0", 1) == 0) { key_set = EFUSE_OTP_1ST_KEY_SET_FIELD; } else if (strncmp(argv[1], "1", 1) == 0) { key_set = EFUSE_OTP_2ND_KEY_SET_FIELD; } else if (strncmp(argv[1], "2", 1) == 0) { key_set = EFUSE_OTP_3RD_KEY_SET_FIELD; } else if (strncmp(argv[1], "3", 1) == 0) { key_set = EFUSE_OTP_4TH_KEY_SET_FIELD; } else if (strncmp(argv[1], "4", 1) == 0) { key_set = EFUSE_OTP_5TH_KEY_SET_FIELD; } else { return CMD_RET_USAGE; } #endif #if (SAMPLE_CODE_ENC_TYPE == SAMPLE_CODE_ENC_TYPE_EBC) crypt_op_param.op_mode = CRYPTO_EBC; #else crypt_op_param.op_mode = CRYPTO_CBC; #endif crypt_op_param.en_de_crypt = CRYPTO_ENCRYPT; crypt_op_param.src_addr = (UINT32)car_in; crypt_op_param.dst_addr = (UINT32)output; crypt_op_param.length = 16; crypt_op_param.iv = (UINT32)iv_in; #if(SAMPLE_CODE_TYPE == SAMPLE_CODE_KEYMANAGER) if (crypto_data_operation(key_set, crypt_op_param) != 0) { printf("Encrypt operation fail [%d] set\r\n", (int)(key_set + 1)); #else if (crypto_data_operation_by_key(cpu_key, crypt_op_param) != 0) { printf("Encrypt operation fail by cpu fill key\r\n"); for (index_cnt = 0; index_cnt < 16; index_cnt++) { printf("%2x ", cpu_key[index_cnt]); } #endif } else { #if(SAMPLE_CODE_TYPE == SAMPLE_CODE_KEYMANAGER) printf("Encrypt operation success [%d] set\r\n", (int)(key_set + 1)); #endif printf("Source =>\r\n"); for (index_cnt = 0; index_cnt < 16; index_cnt++) { printf("%2x ", car_in[index_cnt]); } printf("\r\n"); printf("Destination =>\r\n"); for (index_cnt = 0; index_cnt < 16; index_cnt++) { printf("%2x ", output[index_cnt]); } printf("\r\n"); } #if (SAMPLE_CODE_ENC_TYPE == SAMPLE_CODE_ENC_TYPE_EBC) crypt_op_param.op_mode = CRYPTO_EBC; #else crypt_op_param.op_mode = CRYPTO_CBC; #endif crypt_op_param.en_de_crypt = CRYPTO_DECRYPT; crypt_op_param.src_addr = (UINT32)output; crypt_op_param.dst_addr = (UINT32)output2; crypt_op_param.length = 16; #if(SAMPLE_CODE_TYPE == SAMPLE_CODE_KEYMANAGER) if (crypto_data_operation(key_set, crypt_op_param) != 0) { printf("Decrypt operation fail [%d] set\r\n", (int)(key_set + 1)); #else if (crypto_data_operation_by_key(cpu_key, crypt_op_param) != 0) { printf("Decrypt operation fail by cpu fill key\r\n"); for (index_cnt = 0; index_cnt < 16; index_cnt++) { printf("%2x ", cpu_key[index_cnt]); } #endif } else { #if(SAMPLE_CODE_TYPE == SAMPLE_CODE_KEYMANAGER) printf("Decrypt operation success [%d] set\r\n", (int)(key_set + 1)); #endif for (index_cnt = 0; index_cnt < 16; index_cnt++) { printf("%2x ", output2[index_cnt]); } printf("\r\n"); } printf("do_nvt_encrypt_cmd sample code done\r\n"); if (test_buf) { free((unsigned char *)test_buf); } return 0; } U_BOOT_CMD( nvt_encrypt, 2, 0, do_nvt_encrypt_cmd, "To encrypt via key manager sample", "[keyset(0~4)]\n" ); static UINT8 key_sample[16] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16}; static UINT8 encrypt_sample[16] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16}; static UINT8 key_sample0[16] = {0x04, 0x03, 0x02, 0x01, 0x08, 0x07, 0x06, 0x05, 0x12, 0x11, 0x10, 0x09, 0x16, 0x15, 0x14, 0x13}; static UINT8 key_sample1[16] = {0x24, 0xaa, 0x0d, 0x9b, 0xf1, 0xae, 0x31, 0xb4, 0x28, 0x51, 0xe4, 0xc4, 0xd1, 0x71, 0x1d, 0x1e}; static UINT8 key_sample2[16] = {0x95, 0x4d, 0x81, 0xc5, 0x5a, 0xcc, 0x2b, 0xe5, 0xdd, 0xc8, 0x74, 0xc3, 0x9f, 0xaf, 0xcf, 0x5c}; static UINT8 key_sample3[16] = {0x04, 0x03, 0x02, 0x01, 0x08, 0x07, 0x06, 0x05, 0x12, 0x11, 0x10, 0x09, 0x16, 0x15, 0x14, 0x13}; int do_nvt_write_key_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { s32 result; int index_cnt; UINT32 test_buf; UINT32 test_buf_align; UINT32 test_buf2; UINT32 test_buf2_align; UINT8 pKey[16]; UINT8 *output; UINT8 *output2; u32 key_set = EFUSE_OTP_2ND_KEY_SET_FIELD; CRYPT_OP crypt_op_param; if (strncmp(argv[1], "0", 1) == 0) { key_set = EFUSE_OTP_1ST_KEY_SET_FIELD; memcpy((void *)pKey, (void *)key_sample3, 16); } else if (strncmp(argv[1], "1", 1) == 0) { key_set = EFUSE_OTP_2ND_KEY_SET_FIELD; memcpy((void *)pKey, (void *)key_sample1, 16); } else if (strncmp(argv[1], "2", 1) == 0) { key_set = EFUSE_OTP_3RD_KEY_SET_FIELD; memcpy((void *)pKey, (void *)key_sample2, 16); } else if (strncmp(argv[1], "3", 1) == 0) { key_set = EFUSE_OTP_4TH_KEY_SET_FIELD; memcpy((void *)pKey, (void *)key_sample3, 16); } else if (strncmp(argv[1], "4", 1) == 0) { key_set = EFUSE_OTP_5TH_KEY_SET_FIELD; memcpy((void *)pKey, (void *)key_sample3, 16); } else { return CMD_RET_USAGE; } result = otp_write_key(key_set, pKey); if (result < 0) { printf("Write [%d] key operation fail [%d] \r\n", (int)(key_set), result); return 0; } else { printf("Write [%d] key operation success\r\n", (int)(key_set)); } test_buf = (UINT32)malloc(16 + 64); test_buf_align = (UINT32)((test_buf + 63) & 0xFFFFFFC0); output = (UINT8 *)test_buf_align; test_buf2 = (UINT32)malloc(16 + 64); test_buf2_align = (UINT32)((test_buf2 + 63) & 0xFFFFFFC0); output2 = (UINT8 *)test_buf2_align; memset((char *)test_buf2_align, 0x0, 16); memset((char *)test_buf_align, 0x0, 16); crypt_op_param.op_mode = CRYPTO_EBC; crypt_op_param.en_de_crypt = CRYPTO_ENCRYPT; crypt_op_param.src_addr = (UINT32)encrypt_sample; crypt_op_param.dst_addr = (UINT32)output; //<<<-------------(1) crypt_op_param.length = 16; //Encrypt via key manager by using specific key set if (crypto_data_operation(key_set, crypt_op_param) != 0) { printf("Encrypt operation fail [%d] set\r\n", (int)(key_set)); free((void *)test_buf); free((void *)test_buf2); return 0; } else { printf("Encrypt operation success [%d] set\r\n", (int)(key_set)); printf("Source =>\r\n"); for (index_cnt = 0; index_cnt < 16; index_cnt++) { printf("%2x ", pKey[index_cnt]); } printf("\r\n"); printf("Destination =>\r\n"); for (index_cnt = 0; index_cnt < 16; index_cnt++) { printf("%2x ", output[index_cnt]); } printf("\r\n"); } //Encrypt via fill key by using CPU crypt_op_param.dst_addr = (UINT32)output2; ////<<<-------------(2) crypto_data_operation_by_key(pKey, crypt_op_param); printf("Verification via CPU fill key=>\r\n"); for (index_cnt = 0; index_cnt < 16; index_cnt++) { printf("%2x ", output2[index_cnt]); } printf("\r\n"); //(1) vs (2) result should the same if (memcmp((void *)output2, (void *)output, 16) != 0) { printf("write key fail [%d] set\r\n", (int)(key_set + 1)); printf("OTP operation\r\n"); for (index_cnt = 0; index_cnt < 16; index_cnt++) { printf("%2x ", output[index_cnt]); } printf("\r\n"); printf("Fill key operation\r\n"); for (index_cnt = 0; index_cnt < 16; index_cnt++) { printf("%2x ", output2[index_cnt]); } } else { printf("write key success [%d] set\r\n", (int)(key_set + 1)); } free((void *)test_buf); free((void *)test_buf2); return 0; } U_BOOT_CMD( nvt_write_key, 6, 0, do_nvt_write_key_cmd, "To write key via OTP sample", "[Option] key set (0~4)=> 0 is dedicate for secure boot\n" "[0] => 1st key set (0 is dedicate for secure boot)\n" "[1] => 2nd key set\n" "[2] => 3rd key set\n" "[3] => 4th key set\n" "[4] => 5th key set\n" ); int do_nvt_read_lock_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { u32 key_set_read_lock = SECUREBOOT_1ST_KEY_SET_READ_LOCK; if (strncmp(argv[1], "0", 1) == 0) { key_set_read_lock = SECUREBOOT_1ST_KEY_SET_READ_LOCK; } else if (strncmp(argv[1], "1", 1) == 0) { key_set_read_lock = SECUREBOOT_2ND_KEY_SET_READ_LOCK; } else if (strncmp(argv[1], "2", 1) == 0) { key_set_read_lock = SECUREBOOT_3RD_KEY_SET_READ_LOCK; } else if (strncmp(argv[1], "3", 1) == 0) { key_set_read_lock = SECUREBOOT_4TH_KEY_SET_READ_LOCK; } else if (strncmp(argv[1], "4", 1) == 0) { key_set_read_lock = SECUREBOOT_5TH_KEY_SET_READ_LOCK; } else { return CMD_RET_USAGE; } enable_secure_boot(key_set_read_lock); return 0; } U_BOOT_CMD( nvt_read_lock, 6, 0, do_nvt_read_lock_cmd, "To let key set X un-readable", "[Option] key set (0~4)=> 0 is dedicate for secure boot\n" "[0] => 1st key set (0 is dedicate for secure boot)\n" "[1] => 2nd key set\n" "[2] => 3rd key set\n" "[3] => 4th key set\n" "[4] => 5th key set\n" ); static UINT8 read_key_data[16]; int do_nvt_read_key_set_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { u32 key_set = EFUSE_OTP_1ST_KEY_SET_FIELD; unsigned int field_index = 0; unsigned int key_value =0; unsigned int key_field_index = 0; int i=0; int ret=0; if (strncmp(argv[1], "0", 1) == 0) { key_set = EFUSE_OTP_1ST_KEY_SET_FIELD; } else if (strncmp(argv[1], "1", 1) == 0) { key_set = EFUSE_OTP_2ND_KEY_SET_FIELD; } else if (strncmp(argv[1], "2", 1) == 0) { key_set = EFUSE_OTP_3RD_KEY_SET_FIELD; } else if (strncmp(argv[1], "3", 1) == 0) { key_set = EFUSE_OTP_4TH_KEY_SET_FIELD; } else if (strncmp(argv[1], "4", 1) == 0) { key_set = EFUSE_OTP_5TH_KEY_SET_FIELD; } else { return CMD_RET_USAGE; } switch(key_set) { case EFUSE_OTP_1ST_KEY_SET_FIELD: field_index = 16; break; case EFUSE_OTP_2ND_KEY_SET_FIELD: field_index = 20; break; case EFUSE_OTP_3RD_KEY_SET_FIELD: field_index = 24; break; case EFUSE_OTP_4TH_KEY_SET_FIELD: field_index = 28; break; case EFUSE_OTP_5TH_KEY_SET_FIELD: field_index = 12; break; default: printf("key field error :%d\n",key_set); return -1; } for(i=0; i< 4;i++) { key_field_index = field_index + i; #ifdef CONFIG_TARGET_NA51089 //NT98560 //28,9,30,31 if(key_field_index == 29 && is_new_key_rule()) { key_field_index-= 20; } #else //NT98636 #if (defined(CONFIG_TARGET_NA51090) || defined(CONFIG_TARGET_NA51090_A64)) //28,9,10,11, not necessary determine old/new version if(key_field_index >= 29 && is_new_key_rule()) { key_field_index-= 20; } #else //NT9852x/NT98528 //Keep original usage #endif #endif key_value = otp_key_manager(key_field_index); printf("\033[0;31mkey[%2d][0x%08x]\033[0m\n",key_field_index, key_value); read_key_data[i*4] = (unsigned char)(key_value & 0x000000ff); read_key_data[i*4+1] = (unsigned char)((key_value & 0x0000ff00)>>8); read_key_data[i*4+2] = (unsigned char)((key_value & 0x00ff0000)>>16); read_key_data[i*4+3] = (unsigned char)((key_value & 0xff000000)>>24); } #if 1 printf("key value:%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\r\n", read_key_data[0],read_key_data[1],read_key_data[2],read_key_data[3], read_key_data[4],read_key_data[5],read_key_data[6],read_key_data[7], read_key_data[8],read_key_data[9],read_key_data[10],read_key_data[11], read_key_data[12],read_key_data[13],read_key_data[14],read_key_data[15]); #endif return 0; } U_BOOT_CMD( nvt_read_key_set, 6, 0, do_nvt_read_key_set_cmd, "To read key set X ", "[Option] key set (0~4)\n" "[0] => 1st key set\n" "[1] => 2nd key set\n" "[2] => 3rd key set\n" "[3] => 4th key set\n" "[4] => 5th key set\n" ); int do_nvt_lock_key_set_engine_access_right_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { u32 key_set = EFUSE_OTP_1ST_KEY_SET_FIELD; unsigned int field_index = 0; unsigned int key_value =0; int i=0; int ret=0; if (strncmp(argv[1], "0", 1) == 0) { key_set = EFUSE_OTP_1ST_KEY_SET_FIELD; } else if (strncmp(argv[1], "1", 1) == 0) { key_set = EFUSE_OTP_2ND_KEY_SET_FIELD; } else if (strncmp(argv[1], "2", 1) == 0) { key_set = EFUSE_OTP_3RD_KEY_SET_FIELD; } else if (strncmp(argv[1], "3", 1) == 0) { key_set = EFUSE_OTP_4TH_KEY_SET_FIELD; } else if (strncmp(argv[1], "4", 1) == 0) { key_set = EFUSE_OTP_5TH_KEY_SET_FIELD; } else { return CMD_RET_USAGE; } if(otp_set_key_engine_access_right(key_set) >= 0) printf("=>Set key[%d]'s engine key manager access right success\r\n", key_set); else printf("=>Set key[%d]'s engine key manager access right fail\r\n", key_set); return 0; } U_BOOT_CMD( nvt_key_set_engine_right, 6, 0, do_nvt_lock_key_set_engine_access_right_cmd, "To read key set X ", "[Option] key set (0~4)\n" "[0] => 1st key set\n" "[1] => 2nd key set\n" "[2] => 3rd key set\n" "[3] => 4th key set\n" "[4] => 5th key set\n" ); int do_nvt_secure_en_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { if (!strncmp(argv[1], "secure_en", 9)) { printf("=>[secure_en]\r\n"); efuse_secure_en(); printf("is_secure_enable()=%d\r\n", is_secure_enable()); } else if (!strncmp(argv[1], "data_encrypt", 12)) { printf("=>[efuse_data_area_encrypt_en]\r\n"); efuse_data_area_encrypt_en(); printf("is_data_area_encrypted()=%d\r\n", is_data_area_encrypted()); } else if (!strncmp(argv[1], "rsa_en", 6)) { printf("=>[efuse_signature_rsa_en]\r\n"); efuse_signature_rsa_en(); printf("is_signature_rsa()=%d\r\n", is_signature_rsa()); } else if (!strncmp(argv[1], "rsa_chk_en", 10)) { printf("=>[efuse_signature_rsa_chksum_en]\r\n"); efuse_signature_rsa_chksum_en(); printf("is_signature_rsa_chsum_enable()=%d\r\n", is_signature_rsa_chsum_enable()); } else if (!strncmp(argv[1], "jtag_disable", 12)) { printf("=>[jtag_disable]\r\n"); efuse_jtag_dis(); printf("is_JTAG_DISABLE_en()=%d\r\n", is_JTAG_DISABLE_en()); } else if (!strncmp(argv[1], "uniqueue_id", 11)) { UINT32 h, l; printf("=>[uniqueue_id]=>"); if(efuse_get_unique_id(&l, &h) < 0) { printf("unique ID[0x%08x][0x%08x] error\r\n", (int)h, (int)l); } else { printf("unique ID[0x%08x][0x%08x] success\r\n", (int)h, (int)l); } } else if (!strncmp(argv[1], "quary", 5)) { printf("=>[quary]\r\n"); printf(" is_secure_enable()=%d\r\n", is_secure_enable()); printf(" is_data_area_encrypted()=%d\r\n", is_data_area_encrypted()); printf(" is_signature_rsa()=%d\r\n", is_signature_rsa()); printf("is_signature_rsa_chsum_enable()=%d\r\n", is_signature_rsa_chsum_enable()); printf(" is_JTAG_DISABLE_en()=%d\r\n", is_JTAG_DISABLE_en()); printf(" is_1st_key_programmed()=%d\r\n", is_1st_key_programmed()); printf(" is_2nd_key_programmed()=%d\r\n", is_2nd_key_programmed()); printf(" is_3rd_key_programmed()=%d\r\n", is_3rd_key_programmed()); printf(" is_4th_key_programmed()=%d\r\n", is_4th_key_programmed()); printf(" is_5th_key_programmed()=%d\r\n", is_5th_key_programmed()); printf(" is_1st_key_read_lock()=%d\r\n", is_1st_key_read_lock()); printf(" is_2nd_key_read_lock()=%d\r\n", is_2nd_key_read_lock()); printf(" is_3rd_key_read_lock()=%d\r\n", is_3rd_key_read_lock()); printf(" is_4th_key_read_lock()=%d\r\n", is_4th_key_read_lock()); printf(" is_5th_key_read_lock()=%d\r\n", is_5th_key_read_lock()); printf(" is_new_key_rule()=%d\r\n", is_new_key_rule()); } else { return CMD_RET_USAGE; } return 0; } U_BOOT_CMD( nvt_secure_en, 2, 0, do_nvt_secure_en_cmd, "secure enable related API", "[Option] \n" " [secure_en]\n" " [data_encrypt]\n" " [rsa_en]\n" " [rsa_chk_en]\n" " [jtag_disable]\n" " [quary]\n" " [uniqueue_id]\n" ); int do_nvt_jtag_dis_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { efuse_jtag_dis(); return 0; } U_BOOT_CMD( nvt_jtag_disable, 1, 0, do_nvt_jtag_dis_cmd, "jtag disable", "After jtag disable, JTAG will disable forever\n" ); int do_nvt_uart_disable_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { uart_disable_anchor = 1; return 0; } U_BOOT_CMD( nvt_uart_disable, 1, 0, do_nvt_uart_disable_cmd, "To disable uart print", "In order to accelerate the boot speed, we will control the uart print function\n" ); int do_nvt_rtos_disable_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { rtos_disable_anchor = 1; return 0; } U_BOOT_CMD( nvt_rtos_disable, 1, 0, do_nvt_rtos_disable_cmd, "To disable uboot boot rtos", "In order to disable fastboot, u-boot boot linux directly but rather rtos\n" ); #ifdef CONFIG_NVT_IVOT_DDR_RANGE_SCAN_SUPPORT int do_nvt_ddr_scan(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { #if (defined(CONFIG_TARGET_NA51090) || defined(CONFIG_TARGET_NA51090_A64)) if (argc < 2) { nvt_ddr_scan(0); } else { nvt_ddr_scan(simple_strtoul(argv[1], NULL, 16)); } #else nvt_ddr_scan(); #endif return 0; } #if (defined(CONFIG_TARGET_NA51090) || defined(CONFIG_TARGET_NA51090_A64)) U_BOOT_CMD( nvt_ddr_scan, 2, 1, do_nvt_ddr_scan, "nvt ddr scan", "" ); #else U_BOOT_CMD( nvt_ddr_scan, 1, 1, do_nvt_ddr_scan, "nvt ddr scan", "" ); #endif #endif