2372 lines
76 KiB
C
Executable File
2372 lines
76 KiB
C
Executable File
/**
|
|
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 <common.h>
|
|
#include <fs.h>
|
|
#include <asm/io.h>
|
|
#include <nand.h>
|
|
#include <mmc.h>
|
|
#include <spi_flash.h>
|
|
#include <lzma/LzmaTools.h>
|
|
#include <linux/libfdt.h>
|
|
#include <asm/nvt-common/nvt_types.h>
|
|
#include <asm/nvt-common/modelext/emb_partition_info.h>
|
|
#include <asm/nvt-common/modelext/bin_info.h>
|
|
#include <asm/nvt-common/nvt_common.h>
|
|
#include <asm/nvt-common/shm_info.h>
|
|
#include <asm/nvt-common/nvt_ivot_optee.h>
|
|
#include <asm/nvt-common/nvt_ivot_efuse_smc.h>
|
|
#include <asm/arch/crypto.h>
|
|
#include <asm/arch/IOAddress.h>
|
|
#include <compiler.h>
|
|
#include <u-boot/zlib.h>
|
|
#include <stdlib.h>
|
|
#include "nvt_ivot_soc_utils.h"
|
|
#include "nvt_ivot_pack.h"
|
|
#include <asm/nvt-common/nvt_ivot_optee.h>
|
|
#include <asm/nvt-common/nvt_ivot_aes_smc.h>
|
|
#include <malloc.h>
|
|
|
|
#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
|