2463 lines
79 KiB
C
Executable File
2463 lines
79 KiB
C
Executable File
/**
|
|
NVT firmware update
|
|
To do all-in-one firmware check and update
|
|
@file nvt_ivot_fw_update.c
|
|
@ingroup
|
|
@note
|
|
Copyright Novatek Microelectronics Corp. 2018. 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 <u-boot/md5.h>
|
|
#include <malloc.h>
|
|
#include <nand.h>
|
|
#include <mmc.h>
|
|
#include <spi_flash.h>
|
|
|
|
#include <linux/libfdt.h>
|
|
#include <fdt.h>
|
|
#include <asm/nvt-common/nvt_types.h>
|
|
#include <asm/nvt-common/modelext/bin_info.h>
|
|
#include <asm/nvt-common/modelext/emb_partition_info.h>
|
|
#include <asm/nvt-common/shm_info.h>
|
|
#include <asm/nvt-common/nvt_common.h>
|
|
#include <asm/nvt-common/nvt_storage.h>
|
|
#include <asm/nvt-common/nvt_ivot_optee.h>
|
|
#include <asm/nvt-common/nvt_ivot_sha_smc.h>
|
|
#include <asm/nvt-common/nvt_ivot_efuse_smc.h>
|
|
#include <asm/nvt-common/nvt_ivot_rsa_smc.h>
|
|
#include <asm/arch/IOAddress.h>
|
|
#include "nvt_ivot_pack.h"
|
|
#include "nvt_display_for_fwupdate.h"
|
|
|
|
#if defined(CONFIG_NVT_FW_UPDATE_LED)
|
|
#include <asm/arch/pwm.h>
|
|
#endif
|
|
|
|
#define UPDATE_ALL_IN_ONE_RETRY_TIMES 3
|
|
#define CFG_MODEL_EXT_PARTITION 1
|
|
|
|
#define UINT32_SWAP(data) (((((UINT32)(data)) & 0x000000FF) << 24) | \
|
|
((((UINT32)(data)) & 0x0000FF00) << 8) | \
|
|
((((UINT32)(data)) & 0x00FF0000) >> 8) | \
|
|
((((UINT32)(data)) & 0xFF000000) >> 24)) ///< Swap [31:24] with [7:0] and [23:16] with [15:8].
|
|
static UINT32 g_LcdBl = TRUE;
|
|
static int curr_device = 1;
|
|
|
|
static int nvt_update_partitions(unsigned int addr, unsigned int size, u64 part_off, u64 PartitionSize)
|
|
{
|
|
char command[128];
|
|
#if defined(CONFIG_NVT_SPI_NAND)
|
|
u32 align_size = ALIGN_CEIL(size, nand_get_block_size());
|
|
#elif defined(CONFIG_NVT_SPI_NOR)
|
|
u32 align_size = ALIGN_CEIL(size, nvt_get_flash_erasesize());
|
|
#elif defined(CONFIG_NVT_IVOT_EMMC)
|
|
u32 align_size = ALIGN_CEIL(size, MMC_MAX_BLOCK_LEN);
|
|
/* Using block unit */
|
|
align_size /= MMC_MAX_BLOCK_LEN;
|
|
u64 align_off = ALIGN_CEIL(part_off, MMC_MAX_BLOCK_LEN);
|
|
/* Using block unit */
|
|
align_off /= MMC_MAX_BLOCK_LEN;
|
|
#endif
|
|
|
|
if (size > (unsigned int)PartitionSize) {
|
|
printf("%s partition size is too small (0x%08x > 0x%08llx) %s\r\n", ANSI_COLOR_RED, size, PartitionSize, ANSI_COLOR_RESET);
|
|
return -1;
|
|
}
|
|
|
|
memset(command, 0, sizeof(command));
|
|
#if defined(CONFIG_NVT_SPI_NAND)
|
|
#if defined(CONFIG_NVT_FW_UPDATE_LED) && defined(CONFIG_NVT_PWM)
|
|
pwm_setup_start(NVT_PWMLED, PWM_LED_ERASE, PWM_SIGNAL_TYPE);
|
|
#endif
|
|
sprintf(command, "nand erase 0x%llx 0x%llx", part_off, PartitionSize);
|
|
run_command(command, 0);
|
|
#if defined(CONFIG_NVT_FW_UPDATE_LED) && defined(CONFIG_NVT_PWM)
|
|
pwm_reload(NVT_PWMLED, PWM_LED_PROGRAM, PWM_SIGNAL_TYPE);
|
|
#endif
|
|
sprintf(command, "nand write 0x%x 0x%llx 0x%x", addr, part_off, align_size);
|
|
run_command(command, 0);
|
|
#elif defined(CONFIG_NVT_SPI_NOR)
|
|
#if defined(CONFIG_NVT_FW_UPDATE_LED) && defined(CONFIG_NVT_PWM)
|
|
pwm_setup_start(NVT_PWMLED, PWM_LED_ERASE, PWM_SIGNAL_TYPE);
|
|
#endif
|
|
sprintf(command, "sf erase 0x%llx +0x%llx", part_off, PartitionSize);
|
|
run_command(command, 0);
|
|
#if defined(CONFIG_NVT_FW_UPDATE_LED) && defined(CONFIG_NVT_PWM)
|
|
pwm_reload(NVT_PWMLED, PWM_LED_PROGRAM, PWM_SIGNAL_TYPE);
|
|
#endif
|
|
sprintf(command, "sf write 0x%x 0x%llx 0x%x", addr, part_off, align_size);
|
|
run_command(command, 0);
|
|
#elif defined(CONFIG_NVT_LINUX_EMMC_BOOT)
|
|
#if defined(CONFIG_NVT_FW_UPDATE_LED) && defined(CONFIG_NVT_PWM)
|
|
pwm_setup_start(NVT_PWMLED, PWM_LED_ERASE, PWM_SIGNAL_TYPE);
|
|
#endif
|
|
//sprintf(command, "mmc erase 0x%x 0x%x", part_off, align_size);
|
|
//run_command(command, 0);
|
|
#if defined(CONFIG_NVT_FW_UPDATE_LED) && defined(CONFIG_NVT_PWM)
|
|
pwm_reload(NVT_PWMLED, PWM_LED_PROGRAM, PWM_SIGNAL_TYPE);
|
|
#endif
|
|
sprintf(command, "mmc write 0x%x 0x%llx 0x%x", addr, align_off, align_size);
|
|
run_command(command, 0);
|
|
#endif /* CONFIG_NVT_LINUX_EMMC_BOOT */
|
|
#if defined(CONFIG_NVT_FW_UPDATE_LED) && defined(CONFIG_NVT_PWM)
|
|
pwm_close(NVT_PWMLED, 0);
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int nvt_read_partitions(unsigned int addr, unsigned int size, u64 part_off, unsigned int pat_id, unsigned short embtype)
|
|
{
|
|
char command[128];
|
|
|
|
memset(command, 0, sizeof(command));
|
|
#if defined(CONFIG_NVT_SPI_NAND)
|
|
#if 0
|
|
#if 1
|
|
unsigned short *buf = malloc(ALIGN_CEIL(size, nand_get_block_size()));
|
|
sprintf(command, "nand read 0x%x 0x%llx 0x%x", buf, part_off, ALIGN_CEIL(size, nand_get_block_size()));
|
|
printk("%s\n",command);
|
|
run_command(command, 0);
|
|
memcpy((void *)addr, buf,size);
|
|
free(buf);
|
|
#else
|
|
sprintf(command, "nand read 0x%x 0x%llx 0x%x", addr, part_off, ALIGN_CEIL(size, nand_get_block_size()));
|
|
printk("%s\n",command);
|
|
run_command(command, 0);
|
|
|
|
#endif
|
|
#else
|
|
/* We should avoid read size is not block size alignment problem occurred */
|
|
unsigned short *buf = malloc(nand_get_block_size());
|
|
unsigned int first_part_size = ALIGN_FLOOR(size, nand_get_block_size());
|
|
unsigned int second_part_size = size - first_part_size;
|
|
unsigned long tmp_addr = addr + first_part_size;
|
|
|
|
struct mtd_info *mtd;
|
|
u64 offset=0;
|
|
unsigned int bad_count=0;
|
|
//mtd = nand_info[nand_curr_device];
|
|
mtd = get_nand_dev_by_index(nand_curr_device);
|
|
//nand_block_isbad(mtd, offset);
|
|
for(offset=part_off; offset<= part_off+ALIGN_FLOOR(size, nand_get_block_size()); offset = offset+ nand_get_block_size())
|
|
{
|
|
if (nand_block_isbad(mtd, offset))
|
|
{
|
|
bad_count++;
|
|
}
|
|
}
|
|
sprintf(command, "nand read 0x%x 0x%llx 0x%x", addr, part_off, first_part_size);
|
|
run_command(command, 0);
|
|
if(second_part_size > 0)
|
|
{
|
|
sprintf(command, "nand read 0x%lx 0x%llx 0x%x", (unsigned long)buf, part_off+first_part_size+bad_count*nand_get_block_size(), nand_get_block_size());
|
|
run_command(command, 0);
|
|
memcpy((void *)tmp_addr, buf, second_part_size);
|
|
}
|
|
free(buf);
|
|
#endif
|
|
#elif defined(CONFIG_NVT_SPI_NOR)
|
|
sprintf(command, "sf read 0x%x 0x%llx 0x%x", addr, part_off, size);
|
|
run_command(command, 0);
|
|
#elif defined(CONFIG_NVT_LINUX_EMMC_BOOT)
|
|
u64 align_off = ALIGN_CEIL(part_off, MMC_MAX_BLOCK_LEN);
|
|
/* Using block unit */
|
|
align_off /= MMC_MAX_BLOCK_LEN;
|
|
u32 align_size = ALIGN_CEIL(size, MMC_MAX_BLOCK_LEN);
|
|
/* Using block unit */
|
|
align_size /= MMC_MAX_BLOCK_LEN;
|
|
sprintf(command, "mmc read 0x%x 0x%llx 0x%x", addr, align_off, align_size);
|
|
printf("%s\n", command);
|
|
run_command(command, 0);
|
|
#endif /* !CONFIG_NVT_LINUX_SPINAND_BOOT */
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int nvt_update_fs_partition(unsigned int addr, unsigned int size, unsigned int part_off, unsigned int part_size, EMB_PARTITION *pEmb)
|
|
{
|
|
char command[128];
|
|
|
|
#ifdef CONFIG_NVT_BIN_CHKSUM_SUPPORT
|
|
// Skip nvt head info
|
|
addr += 64;
|
|
size -= 64;
|
|
#endif
|
|
|
|
if (size > part_size) {
|
|
printf("%s partition size is too small (0x%08x > 0x%08x) %s\r\n", ANSI_COLOR_RED, size, part_size, ANSI_COLOR_RESET);
|
|
return -1;
|
|
}
|
|
|
|
memset(command, 0, sizeof(command));
|
|
#if defined(CONFIG_NVT_SPI_NAND)
|
|
#if defined(CONFIG_NVT_FW_UPDATE_LED) && defined(CONFIG_NVT_PWM)
|
|
pwm_setup_start(NVT_PWMLED, PWM_LED_ERASE, PWM_SIGNAL_TYPE);
|
|
#endif
|
|
sprintf(command, "nand erase 0x%x 0x%x", part_off, part_size);
|
|
run_command(command, 0);
|
|
sprintf(command, "nand info");
|
|
run_command(command, 0);
|
|
#elif defined(CONFIG_NVT_IVOT_EMMC)
|
|
#if defined(CONFIG_NVT_FW_UPDATE_LED) && defined(CONFIG_NVT_PWM)
|
|
pwm_setup_start(NVT_PWMLED, PWM_LED_ERASE, PWM_SIGNAL_TYPE);
|
|
#endif
|
|
#elif defined(CONFIG_NVT_SPI_NOR)
|
|
#if defined(CONFIG_NVT_FW_UPDATE_LED) && defined(CONFIG_NVT_PWM)
|
|
pwm_setup_start(NVT_PWMLED, PWM_LED_ERASE, PWM_SIGNAL_TYPE);
|
|
#endif
|
|
sprintf(command, "sf erase 0x%x +0x%x", part_off, part_size);
|
|
run_command(command, 0);
|
|
#else
|
|
printf("nvt_update_fs_partition flash not support\n");
|
|
#endif
|
|
|
|
#if defined(CONFIG_NVT_FW_UPDATE_LED) && defined(CONFIG_NVT_PWM)
|
|
pwm_reload(NVT_PWMLED, PWM_LED_PROGRAM, PWM_SIGNAL_TYPE);
|
|
#endif
|
|
|
|
#if defined(CONFIG_NVT_LINUX_RAMDISK_SUPPORT)
|
|
#if defined(CONFIG_NVT_SPI_NAND)
|
|
sprintf(command, "nand write.trimffs 0x%x 0x%x 0x%x", addr, part_off, size);
|
|
printf("%s\n",command);
|
|
run_command(command, 0);
|
|
#elif defined(CONFIG_NVT_SPI_NOR)
|
|
size = ALIGN_CEIL(size, 4096);
|
|
sprintf(command, "sf write 0x%x 0x%x 0x%x", addr, part_off, size);
|
|
run_command(command, 0);
|
|
#elif defined(CONFIG_NVT_IVOT_EMMC)
|
|
u32 align_size = ALIGN_CEIL(size, MMC_MAX_BLOCK_LEN);
|
|
/* Using block unit */
|
|
align_size /= MMC_MAX_BLOCK_LEN;
|
|
u64 align_off = ALIGN_CEIL(part_off, MMC_MAX_BLOCK_LEN);
|
|
/* Using block unit */
|
|
align_off /= MMC_MAX_BLOCK_LEN;
|
|
if (pEmb->OrderIdx == 0) {
|
|
/* Ramdisk update for rootfs partition idx 0 */
|
|
sprintf(command, "mmc write 0x%x 0x%llx 0x%x", addr, align_off, align_size);
|
|
run_command(command, 0);
|
|
} else {
|
|
/* Other partition is ext4 */
|
|
nvt_sparse_image_update(addr, part_off, size, part_size);
|
|
}
|
|
#else
|
|
printf("nvt_update_fs_partition flash not support!\n");
|
|
#endif
|
|
#elif defined(CONFIG_NVT_JFFS2_SUPPORT)
|
|
printf("Update: %s %s\n", __func__, "JFFS2");
|
|
#if defined(CONFIG_NVT_SPI_NAND)
|
|
sprintf(command, "nand write.trimffs 0x%x 0x%x 0x%x", addr, part_off, size);
|
|
run_command(command, 0);
|
|
#elif defined(CONFIG_NVT_SPI_NOR)
|
|
sprintf(command, "sf write 0x%x 0x%x 0x%x", addr, part_off, size);
|
|
run_command(command, 0);
|
|
#else
|
|
printf("flash type error, not support JFFS2\n");
|
|
#endif /* !CONFIG_NVT_LINUX_SPINAND_BOOT */
|
|
|
|
#elif defined(CONFIG_NVT_SQUASH_SUPPORT)
|
|
printf("Update: %s %s\n", __func__, "SquashFS");
|
|
#if defined(CONFIG_NVT_SPI_NAND)
|
|
sprintf(command, "nand write.trimffs 0x%x 0x%x 0x%x", addr, part_off, size);
|
|
run_command(command, 0);
|
|
#elif defined(CONFIG_NVT_SPI_NOR)
|
|
sprintf(command, "sf write 0x%x 0x%x 0x%x", addr, part_off, size);
|
|
run_command(command, 0);
|
|
#elif defined(CONFIG_NVT_IVOT_EMMC)
|
|
u32 align_size = ALIGN_CEIL(size, MMC_MAX_BLOCK_LEN);
|
|
/* Using block unit */
|
|
align_size /= MMC_MAX_BLOCK_LEN;
|
|
u64 align_off = ALIGN_CEIL(part_off, MMC_MAX_BLOCK_LEN);
|
|
/* Using block unit */
|
|
align_off /= MMC_MAX_BLOCK_LEN;
|
|
if (pEmb->OrderIdx == 0) {
|
|
/* Ramdisk update for rootfs partition idx 0 */
|
|
sprintf(command, "mmc write 0x%x 0x%llx 0x%x", addr, align_off, align_size);
|
|
run_command(command, 0);
|
|
} else {
|
|
/* Other partition is ext4 */
|
|
nvt_sparse_image_update(addr, part_off, size, part_size);
|
|
}
|
|
#else
|
|
printf("flash type error, not support SQUASH\n");
|
|
#endif /* !CONFIG_NVT_LINUX_SPINAND_BOOT */
|
|
|
|
#if defined(CONFIG_NVT_FW_UPDATE_LED) && defined(CONFIG_NVT_PWM)
|
|
pwm_close(NVT_PWMLED, 0);
|
|
#endif
|
|
#elif defined(CONFIG_NVT_EXT4_SUPPORT)
|
|
printf("Update: %s %s size=0x%08x\n", __func__, "EXT4 or FAT", size);
|
|
nvt_sparse_image_update(addr, part_off, size, part_size);
|
|
#if defined(CONFIG_NVT_FW_UPDATE_LED) && defined(CONFIG_NVT_PWM)
|
|
pwm_close(NVT_PWMLED, 0);
|
|
#endif
|
|
#else
|
|
printf("Update: %s %s\n", __func__, "UBIFS");
|
|
|
|
sprintf(command, "nand write.trimffs 0x%x 0x%x 0x%x", addr, part_off, size);
|
|
printf("%s\n", command);
|
|
run_command(command, 0);
|
|
#endif /* !CONFIG_NVT_JFFS2_SUPPORT && !CONFIG_NVT_SQUASH_SUPPORT */
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int nvt_update_user_partition(unsigned int addr, unsigned int size, unsigned int part_off, unsigned int part_size, EMB_PARTITION *pEmb)
|
|
{
|
|
char command[128];
|
|
|
|
printf("user partition %u\n", GET_USER_PART_NUM(pEmb->EmbType));
|
|
|
|
#ifdef CONFIG_NVT_BIN_CHKSUM_SUPPORT
|
|
// Skip nvt head info
|
|
addr += 64;
|
|
size -= 64;
|
|
#endif
|
|
|
|
if (size > part_size) {
|
|
printf("%s partition size is too small (0x%08x > 0x%08x) %s\r\n", ANSI_COLOR_RED, size, part_size, ANSI_COLOR_RESET);
|
|
return -1;
|
|
}
|
|
|
|
memset(command, 0, sizeof(command));
|
|
#if defined(CONFIG_NVT_LINUX_SPINAND_BOOT)
|
|
#if defined(CONFIG_NVT_FW_UPDATE_LED) && defined(CONFIG_NVT_PWM)
|
|
pwm_setup_start(NVT_PWMLED, PWM_LED_ERASE, PWM_SIGNAL_TYPE);
|
|
#endif
|
|
sprintf(command, "nand erase 0x%x 0x%x", part_off, part_size);
|
|
run_command(command, 0);
|
|
sprintf(command, "nand info");
|
|
run_command(command, 0);
|
|
#elif defined(CONFIG_NVT_LINUX_EMMC_BOOT)
|
|
#if defined(CONFIG_NVT_FW_UPDATE_LED) && defined(CONFIG_NVT_PWM)
|
|
pwm_setup_start(NVT_PWMLED, PWM_LED_ERASE, PWM_SIGNAL_TYPE);
|
|
#endif
|
|
//sprintf(command, "mmc erase 0x%x 0x%x", part_off, part_size);
|
|
//run_command(command, 0);
|
|
#else
|
|
#if defined(CONFIG_NVT_FW_UPDATE_LED) && defined(CONFIG_NVT_PWM)
|
|
pwm_setup_start(NVT_PWMLED, PWM_LED_ERASE, PWM_SIGNAL_TYPE);
|
|
#endif
|
|
sprintf(command, "sf erase 0x%x +0x%x", part_off, part_size);
|
|
run_command(command, 0);
|
|
#endif
|
|
|
|
#if defined(CONFIG_NVT_FW_UPDATE_LED) && defined(CONFIG_NVT_PWM)
|
|
pwm_reload(NVT_PWMLED, PWM_LED_PROGRAM, PWM_SIGNAL_TYPE);
|
|
#endif
|
|
|
|
#if defined(CONFIG_NVT_JFFS2_SUPPORT)
|
|
printf("Update: %s %s\n", __func__, "JFFS2");
|
|
#if defined(CONFIG_NVT_LINUX_SPINAND_BOOT)
|
|
sprintf(command, "nand write.trimffs 0x%x rootfs%u 0x%x", addr, pEmb->OrderIdx, size);
|
|
run_command(command, 0);
|
|
#else
|
|
sprintf(command, "sf write 0x%x 0x%x 0x%x", addr, part_off, size);
|
|
run_command(command, 0);
|
|
#endif /* !CONFIG_NVT_LINUX_SPINAND_BOOT */
|
|
|
|
#elif defined(CONFIG_NVT_SQUASH_SUPPORT)
|
|
printf("Update: %s %s\n", __func__, "SquashFS");
|
|
#if defined(CONFIG_NVT_LINUX_SPINAND_BOOT)
|
|
sprintf(command, "nand write 0x%x rootfs%u 0x%x", addr, pEmb->OrderIdx, size);
|
|
run_command(command, 0);
|
|
#else
|
|
sprintf(command, "sf write 0x%x 0x%x 0x%x", addr, part_off, size);
|
|
run_command(command, 0);
|
|
#endif /* !CONFIG_NVT_LINUX_SPINAND_BOOT */
|
|
|
|
#if defined(CONFIG_NVT_FW_UPDATE_LED) && defined(CONFIG_NVT_PWM)
|
|
pwm_close(NVT_PWMLED, 0);
|
|
#endif
|
|
#elif defined(CONFIG_NVT_EXT4_SUPPORT)
|
|
printf("Update: %s %s size=0x%08x\n", __func__, "EXT4 or FAT", size);
|
|
nvt_sparse_image_update(addr, part_off, size, part_size);
|
|
#if defined(CONFIG_NVT_FW_UPDATE_LED) && defined(CONFIG_NVT_PWM)
|
|
pwm_close(NVT_PWMLED, 0);
|
|
#endif
|
|
#else
|
|
printf("Update: %s %s\n", __func__, "UBIFS");
|
|
|
|
sprintf(command, "nand write.trimffs 0x%x user%u_%d 0x%x", addr, GET_USER_PART_NUM(pEmb->EmbType), pEmb->OrderIdx, size);
|
|
printf("%s\n", command);
|
|
run_command(command, 0);
|
|
#endif /* !CONFIG_NVT_JFFS2_SUPPORT && !CONFIG_NVT_SQUASH_SUPPORT */
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int nvt_update_rootfsl_partition(unsigned int addr, unsigned int size, unsigned int part_off, unsigned int part_size, EMB_PARTITION *pEmb)
|
|
{
|
|
char command[128];
|
|
|
|
#ifdef CONFIG_NVT_BIN_CHKSUM_SUPPORT
|
|
// Skip nvt head info
|
|
addr += 64;
|
|
size -= 64;
|
|
#endif
|
|
|
|
if (size > part_size) {
|
|
printf("%s partition size is too small (0x%08x > 0x%08llx) %s\r\n", ANSI_COLOR_RED, size, part_size, ANSI_COLOR_RESET);
|
|
return -1;
|
|
}
|
|
|
|
memset(command, 0, sizeof(command));
|
|
#if defined(CONFIG_NVT_LINUX_SPINAND_BOOT)
|
|
#if defined(CONFIG_NVT_FW_UPDATE_LED) && defined(CONFIG_NVT_PWM)
|
|
pwm_setup_start(NVT_PWMLED, PWM_LED_ERASE, PWM_SIGNAL_TYPE);
|
|
#endif
|
|
sprintf(command, "nand erase 0x%x 0x%x", part_off, part_size);
|
|
run_command(command, 0);
|
|
sprintf(command, "nand info");
|
|
run_command(command, 0);
|
|
#elif defined(CONFIG_NVT_LINUX_EMMC_BOOT)
|
|
#if defined(CONFIG_NVT_FW_UPDATE_LED) && defined(CONFIG_NVT_PWM)
|
|
pwm_setup_start(NVT_PWMLED, PWM_LED_ERASE, PWM_SIGNAL_TYPE);
|
|
#endif
|
|
//sprintf(command, "mmc erase 0x%x 0x%x", part_off, part_size);
|
|
//run_command(command, 0);
|
|
#else
|
|
#if defined(CONFIG_NVT_FW_UPDATE_LED) && defined(CONFIG_NVT_PWM)
|
|
pwm_setup_start(NVT_PWMLED, PWM_LED_ERASE, PWM_SIGNAL_TYPE);
|
|
#endif
|
|
sprintf(command, "sf erase 0x%x +0x%x", part_off, part_size);
|
|
run_command(command, 0);
|
|
#endif
|
|
|
|
#if defined(CONFIG_NVT_FW_UPDATE_LED) && defined(CONFIG_NVT_PWM)
|
|
pwm_reload(NVT_PWMLED, PWM_LED_PROGRAM, PWM_SIGNAL_TYPE);
|
|
#endif
|
|
|
|
#if defined(CONFIG_NVT_JFFS2_SUPPORT)
|
|
printf("Update: %s %s\n", __func__, "JFFS2");
|
|
#if defined(CONFIG_NVT_LINUX_SPINAND_BOOT)
|
|
sprintf(command, "nand write.trimffs 0x%x rootfs%u 0x%x", addr, pEmb->OrderIdx, size);
|
|
run_command(command, 0);
|
|
#else
|
|
sprintf(command, "sf write 0x%x 0x%x 0x%x", addr, part_off, size);
|
|
run_command(command, 0);
|
|
#endif /* !CONFIG_NVT_LINUX_SPINAND_BOOT */
|
|
|
|
#elif defined(CONFIG_NVT_SQUASH_SUPPORT)
|
|
printf("Update: %s %s\n", __func__, "SquashFS");
|
|
#if defined(CONFIG_NVT_LINUX_SPINAND_BOOT)
|
|
sprintf(command, "nand write 0x%x rootfs%u 0x%x", addr, pEmb->OrderIdx, size);
|
|
run_command(command, 0);
|
|
#else
|
|
sprintf(command, "sf write 0x%x 0x%x 0x%x", addr, part_off, size);
|
|
run_command(command, 0);
|
|
#endif /* !CONFIG_NVT_LINUX_SPINAND_BOOT */
|
|
|
|
#if defined(CONFIG_NVT_FW_UPDATE_LED) && defined(CONFIG_NVT_PWM)
|
|
pwm_close(NVT_PWMLED, 0);
|
|
#endif
|
|
#elif defined(CONFIG_NVT_EXT4_SUPPORT)
|
|
printf("Update: %s %s size=0x%08x\n", __func__, "EXT4 or FAT", size);
|
|
nvt_sparse_image_update(addr, part_off, size, part_size);
|
|
#if defined(CONFIG_NVT_FW_UPDATE_LED) && defined(CONFIG_NVT_PWM)
|
|
pwm_close(NVT_PWMLED, 0);
|
|
#endif
|
|
#else
|
|
printf("Update: %s %s\n", __func__, "UBIFS");
|
|
|
|
sprintf(command, "nand write.trimffs 0x%x rootfs%u 0x%x", addr, pEmb->OrderIdx, size);
|
|
printf("%s\n", command);
|
|
run_command(command, 0);
|
|
#endif /* !CONFIG_NVT_JFFS2_SUPPORT && !CONFIG_NVT_SQUASH_SUPPORT */
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int nvt_read_fs_partition(unsigned int addr, unsigned int size, unsigned int part_off, unsigned int part_size, unsigned int pat_id, EMB_PARTITION *pEmb)
|
|
{
|
|
char command[128];
|
|
int ret = 0;
|
|
|
|
memset(command, 0, sizeof(command));
|
|
#ifdef CONFIG_NVT_BIN_CHKSUM_SUPPORT
|
|
// Skip nvt head info
|
|
addr += 64;
|
|
size -= 64;
|
|
#endif
|
|
|
|
#if defined(CONFIG_NVT_SPI_NAND)
|
|
#if 0
|
|
#if 1
|
|
unsigned short *buf = malloc(ALIGN_CEIL(size, nand_get_block_size()));
|
|
sprintf(command, "nand read 0x%x 0x%x 0x%x", buf, part_off, ALIGN_CEIL(size, nand_get_block_size()));
|
|
printk("%s\n",command);
|
|
run_command(command, 0);
|
|
memcpy((void *)addr, buf,size);
|
|
free(buf);
|
|
#else
|
|
sprintf(command, "nand read 0x%x 0x%x 0x%x", addr, part_off, ALIGN_CEIL(size, nand_get_block_size()));
|
|
printk("%s\n",command);
|
|
run_command(command, 0);
|
|
|
|
#endif
|
|
#else
|
|
/* We should avoid read size is not block size alignment problem occurred */
|
|
struct mtd_info *mtd;
|
|
unsigned int offset=0;
|
|
unsigned int bad_count=0;
|
|
//mtd = nand_info[nand_curr_device];
|
|
mtd = get_nand_dev_by_index(nand_curr_device);
|
|
//nand_block_isbad(mtd, offset);
|
|
for(offset=part_off; offset<= part_off+ALIGN_FLOOR(size, nand_get_block_size()); offset = offset+ nand_get_block_size())
|
|
{
|
|
if (nand_block_isbad(mtd, offset))
|
|
{
|
|
printk("%x\n", offset);
|
|
bad_count++;
|
|
}
|
|
}
|
|
unsigned short *buf = malloc(nand_get_block_size());
|
|
unsigned int first_part_size = ALIGN_FLOOR(size, nand_get_block_size());
|
|
unsigned int second_part_size = size - first_part_size;
|
|
unsigned long tmp_addr = addr + first_part_size;
|
|
|
|
sprintf(command, "nand read 0x%x 0x%x 0x%x", addr, part_off, ALIGN_FLOOR(size, nand_get_block_size()));
|
|
run_command(command, 0);
|
|
if(second_part_size > 0)
|
|
{
|
|
sprintf(command, "nand read 0x%lx 0x%x 0x%x", (unsigned long)buf, part_off+first_part_size+bad_count*nand_get_block_size(), nand_get_block_size());
|
|
run_command(command, 0);
|
|
memcpy((void *)tmp_addr, buf, second_part_size);
|
|
}
|
|
free(buf);
|
|
#endif
|
|
#elif defined(CONFIG_NVT_SPI_NOR)
|
|
sprintf(command, "sf read 0x%x 0x%x 0x%x", addr, part_off, size);
|
|
run_command(command, 0);
|
|
#elif defined(CONFIG_NVT_LINUX_EMMC_BOOT)
|
|
printf("Read: %s %s size=0x%08x\n", __func__, "EXT4 or FAT", size);
|
|
nvt_sparse_image_readback(addr, part_off, size, part_size);
|
|
#endif /* CONFIG_NVT_LINUX_SPINAND_BOOT */
|
|
|
|
|
|
#if defined(CONFIG_NVT_UBIFS_SUPPORT) && (defined(CONFIG_NVT_LINUX_RAMDISK_SUPPORT) && defined(CONFIG_NVT_SPI_NAND))
|
|
/*test ubifs*/
|
|
printf("Read: %s %s\n", __func__, "UBIFS");
|
|
if(pEmb->EmbType == EMBTYPE_ROOTFS){
|
|
|
|
#if (defined(CONFIG_NVT_LINUX_RAMDISK_SUPPORT) && defined(CONFIG_NVT_SPI_NAND))
|
|
if (pEmb->OrderIdx == 0){
|
|
/*rootfs0 is ramdisk no need to check ubifs*/
|
|
return ret;
|
|
}
|
|
#endif
|
|
sprintf(command, "ubi part rootfs%u", pEmb->OrderIdx);
|
|
run_command(command, 0);
|
|
sprintf(command, "ubifsmount ubi:rootfs");
|
|
run_command(command, 0);
|
|
}
|
|
else if(pEmb->EmbType == EMBTYPE_APP){
|
|
sprintf(command, "ubi part app");
|
|
run_command(command, 0);
|
|
sprintf(command, "ubifsmount ubi:app");
|
|
run_command(command, 0);
|
|
}
|
|
else{
|
|
printk("partition type%x , not support UBIFS\n",pEmb->EmbType);
|
|
return -1;
|
|
}
|
|
|
|
sprintf(command, "ubifsls");
|
|
run_command(command, 0);
|
|
#elif defined(CONFIG_NVT_SQUASH_SUPPORT)
|
|
printf("Read: %s %s\n", __func__, "SQUASHFS");
|
|
#elif defined(CONFIG_NVT_EXT4_SUPPORT)
|
|
printf("Read: %s %s\n", __func__, "EXT4");
|
|
#else
|
|
printf("Read: %s\n", __func__);
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int nvt_read_rootfsl_partition(unsigned int addr, unsigned int size, unsigned int part_off, unsigned int part_size, unsigned int pat_id, EMB_PARTITION *pEmb)
|
|
{
|
|
char command[128];
|
|
int ret = 0;
|
|
|
|
memset(command, 0, sizeof(command));
|
|
|
|
#ifdef CONFIG_NVT_BIN_CHKSUM_SUPPORT
|
|
// Skip nvt head info
|
|
addr += 64;
|
|
size -= 64;
|
|
#endif
|
|
|
|
#if defined(CONFIG_NVT_SPI_NAND)
|
|
/* We should avoid read size is not block size alignment problem occurred */
|
|
unsigned short *buf = malloc(nand_get_block_size());
|
|
unsigned int first_part_size = ALIGN_FLOOR(size, nand_get_block_size());
|
|
unsigned int second_part_size = size - first_part_size;
|
|
unsigned long tmp_addr = addr + first_part_size;
|
|
|
|
sprintf(command, "nand read 0x%x 0x%x 0x%x", addr, part_off, ALIGN_FLOOR(size, nand_get_block_size()));
|
|
run_command(command, 0);
|
|
sprintf(command, "nand read 0x%lx 0x%x 0x%x", (unsigned long)buf, part_off+first_part_size, nand_get_block_size());
|
|
run_command(command, 0);
|
|
memcpy((void *)tmp_addr, buf, second_part_size);
|
|
free(buf);
|
|
#elif defined(CONFIG_NVT_SPI_NOR)
|
|
sprintf(command, "sf read 0x%x 0x%x 0x%x", addr, part_off, size);
|
|
run_command(command, 0);
|
|
#elif defined(CONFIG_NVT_LINUX_EMMC_BOOT)
|
|
printf("Read: %s %s size=0x%08x\n", __func__, "EXT4 or FAT", size);
|
|
nvt_sparse_image_readback(addr, part_off, size, part_size);
|
|
#endif /* CONFIG_NVT_LINUX_SPINAND_BOOT */
|
|
|
|
#if defined(CONFIG_NVT_UBIFS_SUPPORT)
|
|
printf("Read: %s %s\n", __func__, "UBIFS");
|
|
sprintf(command, "ubi part rootfs%u", pEmb->OrderIdx);
|
|
run_command(command, 0);
|
|
|
|
sprintf(command, "ubifsmount ubi:rootfs");
|
|
run_command(command, 0);
|
|
|
|
sprintf(command, "ubifsls");
|
|
run_command(command, 0);
|
|
#elif defined(CONFIG_NVT_SQUASH_SUPPORT)
|
|
printf("Read: %s %s\n", __func__, "SQUASHFS");
|
|
#elif defined(CONFIG_NVT_EXT4_SUPPORT)
|
|
printf("Read: %s %s\n", __func__, "EXT4");
|
|
#else
|
|
printf("Read: %s %s\n", __func__, "JFFS2");
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int nvt_read_user_partition(unsigned int addr, unsigned int size, unsigned int part_off, unsigned int part_size, unsigned int pat_id, EMB_PARTITION *pEmb)
|
|
{
|
|
char command[128];
|
|
int ret = 0;
|
|
|
|
printf("user partition %u\n", GET_USER_PART_NUM(pEmb->EmbType));
|
|
memset(command, 0, sizeof(command));
|
|
|
|
#ifdef CONFIG_NVT_BIN_CHKSUM_SUPPORT
|
|
// Skip nvt head info
|
|
addr += 64;
|
|
size -= 64;
|
|
#endif
|
|
|
|
#if defined(CONFIG_NVT_SPI_NAND)
|
|
/* We should avoid read size is not block size alignment problem occurred */
|
|
unsigned short *buf = malloc(nand_get_block_size());
|
|
unsigned int first_part_size = ALIGN_FLOOR(size, nand_get_block_size());
|
|
unsigned int second_part_size = size - first_part_size;
|
|
unsigned long tmp_addr = addr + first_part_size;
|
|
|
|
sprintf(command, "nand read 0x%x 0x%x 0x%x", addr, part_off, ALIGN_FLOOR(size, nand_get_block_size()));
|
|
run_command(command, 0);
|
|
sprintf(command, "nand read 0x%lx 0x%x 0x%x", (unsigned long)buf, part_off+first_part_size, nand_get_block_size());
|
|
run_command(command, 0);
|
|
memcpy((void *)tmp_addr, buf, second_part_size);
|
|
free(buf);
|
|
#elif defined(CONFIG_NVT_SPI_NOR)
|
|
sprintf(command, "sf read 0x%x 0x%x 0x%x", addr, part_off, size);
|
|
run_command(command, 0);
|
|
#elif defined(CONFIG_NVT_LINUX_EMMC_BOOT)
|
|
printf("Read: %s %s size=0x%08x\n", __func__, "EXT4 or FAT", size);
|
|
nvt_sparse_image_readback(addr, part_off, size, part_size);
|
|
#endif /* CONFIG_NVT_LINUX_SPINAND_BOOT */
|
|
|
|
#if defined(CONFIG_NVT_UBIFS_SUPPORT)
|
|
printf("Read: %s %s\n", __func__, "UBIFS");
|
|
sprintf(command, "ubi part rootfs%u", pEmb->OrderIdx);
|
|
run_command(command, 0);
|
|
|
|
sprintf(command, "ubifsmount ubi:rootfs");
|
|
run_command(command, 0);
|
|
|
|
sprintf(command, "ubifsls");
|
|
run_command(command, 0);
|
|
#elif defined(CONFIG_NVT_SQUASH_SUPPORT)
|
|
printf("Read: %s %s\n", __func__, "SQUASHFS");
|
|
#elif defined(CONFIG_NVT_EXT4_SUPPORT)
|
|
printf("Read: %s %s\n", __func__, "EXT4");
|
|
#else
|
|
printf("Read: %s %s\n", __func__, "JFFS2");
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
static UINT32 MemCheck_CalcCheckSum16Bit(UINT32 uiAddr,UINT32 uiLen)
|
|
{
|
|
UINT32 i,uiSum = 0;
|
|
UINT16 *puiValue = (UINT16 *)uiAddr;
|
|
|
|
for (i=0; i<(uiLen >> 1); i++)
|
|
{
|
|
uiSum += (*(puiValue + i) + i);
|
|
}
|
|
|
|
uiSum &= 0x0000FFFF;
|
|
|
|
return uiSum;
|
|
}
|
|
|
|
static int nvt_chk_last_ebr(ulong ebr_addr, u64 ebr_part_offset, EMB_PARTITION *pEmb)
|
|
{
|
|
unsigned char *buf;
|
|
u32 disk_capacity, new_size, old_size, part_addr;
|
|
int i, last_part_idx, partition_number, last_ebr_idx, first_mbr_idx;
|
|
|
|
//Find the index of the last pstore/rootfs partition
|
|
if(pEmb==NULL)
|
|
{
|
|
printf("failed to get current partition resource.\r\n");
|
|
return CMD_RET_FAILURE;
|
|
}
|
|
|
|
last_part_idx = -1;
|
|
for(i = (EMB_PARTITION_INFO_COUNT - 1) ; i >= 0 ; i--)
|
|
{
|
|
if(pEmb[i].EmbType == EMBTYPE_UNKNOWN)
|
|
continue;
|
|
else if(pEmb[i].EmbType == EMBTYPE_ROOTFS || pEmb[i].EmbType == EMBTYPE_ROOTFSL){
|
|
if(pEmb[i].PartitionSize != 0){
|
|
printf("size of last partition is not 0, no need to fix\r\n");
|
|
return CMD_RET_SUCCESS;
|
|
}
|
|
else{
|
|
last_part_idx = i;
|
|
}
|
|
break;
|
|
}
|
|
else{
|
|
printf("last partition is of type %d, not rootfs or pstore, no need to fix\r\n", pEmb[i].EmbType);
|
|
return CMD_RET_SUCCESS;
|
|
}
|
|
}
|
|
|
|
if(last_part_idx == -1){
|
|
printf("no rootfs,pstore partition, no need to fix\r\n");
|
|
return CMD_RET_SUCCESS;
|
|
}
|
|
|
|
//Find the index of the last ebr
|
|
last_ebr_idx = -1;
|
|
for(i = (EMB_PARTITION_INFO_COUNT - 1) ; i >= 0 ; i--)
|
|
if(pEmb[i].EmbType == EMBTYPE_MBR){
|
|
last_ebr_idx = i;
|
|
break;
|
|
}
|
|
|
|
if(last_ebr_idx == -1){
|
|
printf("fail to get last ebr's index\r\n");
|
|
return CMD_RET_FAILURE;
|
|
}
|
|
|
|
//Find the index of mbr
|
|
first_mbr_idx = -1;
|
|
for(i = 0 ; i < EMB_PARTITION_INFO_COUNT ; i++)
|
|
if(pEmb[i].EmbType == EMBTYPE_MBR){
|
|
first_mbr_idx = i;
|
|
break;
|
|
}
|
|
|
|
if(first_mbr_idx == -1){
|
|
printf("fail to get 1st mbr's index\r\n");
|
|
return CMD_RET_FAILURE;
|
|
}
|
|
|
|
//If ebr from argument is neither 1st mbr nor last ebr, ignore it
|
|
if(ebr_part_offset != pEmb[first_mbr_idx].PartitionOffset && ebr_part_offset != pEmb[last_ebr_idx].PartitionOffset)
|
|
return CMD_RET_SUCCESS;
|
|
|
|
//Get pstore/rootfs partition number
|
|
partition_number = 0;
|
|
for(i = 0 ; i < EMB_PARTITION_INFO_COUNT ; i++)
|
|
if(pEmb[i].EmbType == EMBTYPE_ROOTFS || pEmb[i].EmbType == EMBTYPE_ROOTFSL)
|
|
partition_number++;
|
|
|
|
//If the last partition ls logical, make sure there is a EBR partition ahead
|
|
if(partition_number >= 4){
|
|
if((last_part_idx - 1) != last_ebr_idx){
|
|
printf("last ebr index(%d) is not right ahead of the last mbr ebr index(%d)\r\n", last_ebr_idx, last_part_idx);
|
|
return CMD_RET_FAILURE;
|
|
}
|
|
}
|
|
//rootfs,pstore number < 4, there should be no ebr, so last_ebr_idx should eb equal to first_mbr_idx
|
|
else if(first_mbr_idx != last_ebr_idx){
|
|
printf("only %d rootfs,pstore partions, but mbr index(%d) != last ebr index(%d)\r\n", partition_number, first_mbr_idx, last_ebr_idx);
|
|
return CMD_RET_FAILURE;
|
|
}
|
|
|
|
//Check mbr/ebr signature
|
|
buf = (unsigned char*)ebr_addr;
|
|
if(buf[510] != 0x55 || buf[511] != 0xAA){
|
|
printf("invalid mbr ebr signature 0x%x 0x%x, they should be 0x55 0xAA\r\n", (unsigned int)buf[510], (unsigned int)buf[511]);
|
|
return CMD_RET_FAILURE;
|
|
}
|
|
#ifdef CONFIG_NVT_MMC
|
|
//Get emmc's max capacity
|
|
extern u32 get_emmc_capacity(void);
|
|
disk_capacity = get_emmc_capacity();
|
|
printf("emmc capacity is %d sectors\r\n", disk_capacity);
|
|
if(disk_capacity == 0){
|
|
printf("fail to get emmc's capacity\r\n");
|
|
return CMD_RET_FAILURE;
|
|
}
|
|
#endif
|
|
//Fix MBR's size field
|
|
if(ebr_part_offset == pEmb[first_mbr_idx].PartitionOffset){
|
|
//Fix primary partition's size
|
|
if(partition_number < 4){
|
|
new_size = disk_capacity - (u32)(pEmb[last_part_idx].PartitionOffset/MMC_MAX_BLOCK_LEN);
|
|
buf = (unsigned char*)(ebr_addr + 446 + ((partition_number - 1) * 16) + 12);
|
|
old_size = (buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24));
|
|
printf("last primary partition old size = %d ; new size = %d\r\n", old_size, new_size);
|
|
buf[0] = (new_size & 0x0FF);
|
|
buf[1] = ((new_size & 0x0FF00) >> 8);
|
|
buf[2] = ((new_size & 0x0FF0000) >> 16);
|
|
buf[3] = ((new_size & 0xFF000000) >> 24);
|
|
}
|
|
//Fix extend partition's size
|
|
else{
|
|
buf = (unsigned char*)(ebr_addr + 494 + 8);
|
|
part_addr = (buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24));
|
|
new_size = disk_capacity - part_addr;
|
|
buf = (unsigned char*)(ebr_addr + 494 + 12);
|
|
old_size = (buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24));
|
|
printf("extended partition old size = %d ; new size = %d\r\n", old_size, new_size);
|
|
buf[0] = (new_size & 0x0FF);
|
|
buf[1] = ((new_size & 0x0FF00) >> 8);
|
|
buf[2] = ((new_size & 0x0FF0000) >> 16);
|
|
buf[3] = ((new_size & 0xFF000000) >> 24);
|
|
}
|
|
}
|
|
//Fix EBR's size field
|
|
else{
|
|
new_size = disk_capacity - (u32)(pEmb[last_part_idx].PartitionOffset/MMC_MAX_BLOCK_LEN);
|
|
buf = (unsigned char*)(ebr_addr + 446 + 12);
|
|
old_size = (buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24));
|
|
printf("last ebr old size = %d ; new size = %d\r\n", old_size, new_size);
|
|
buf[0] = (new_size & 0x0FF);
|
|
buf[1] = ((new_size & 0x0FF00) >> 8);
|
|
buf[2] = ((new_size & 0x0FF0000) >> 16);
|
|
buf[3] = ((new_size & 0xFF000000) >> 24);
|
|
}
|
|
return CMD_RET_SUCCESS;
|
|
}
|
|
|
|
static int nvt_chk_app(ulong addr, unsigned int size, unsigned int pat_id){
|
|
|
|
if(MemCheck_CalcCheckSum16Bit(addr, size)!=0)
|
|
{
|
|
printf("app pat%d, res check sum fail.\r\n",pat_id);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
|
|
}
|
|
|
|
static int nvt_chk_loader(ulong addr, unsigned int size, unsigned int pat_id)
|
|
{
|
|
if(MemCheck_CalcCheckSum16Bit(addr, size)!=0)
|
|
{
|
|
printf("loader pat%d, res check sum fail.\r\n",pat_id);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int nvt_chk_modelext(ulong addr, unsigned int size, unsigned int pat_id)
|
|
{
|
|
int ret;
|
|
|
|
ret = nvt_check_isfdt(addr);
|
|
if (ret < 0)
|
|
printf("fdt pat%d, res check sum fail.\r\n", pat_id);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int nvt_chk_uitron(ulong addr, unsigned int size, unsigned int pat_id)
|
|
{
|
|
if(MemCheck_CalcCheckSum16Bit(addr, size)!=0)
|
|
{
|
|
printf("uitron pat%d, res check sum fail.\r\n", pat_id);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int nvt_chk_ecos(ulong addr, unsigned int size, unsigned int pat_id)
|
|
{
|
|
if(MemCheck_CalcCheckSum16Bit(addr, size)!=0)
|
|
{
|
|
printf("ecos pat%d, res check sum fail.\r\n",pat_id);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int nvt_chk_rtos(ulong addr, unsigned int size, unsigned int pat_id)
|
|
{
|
|
if(MemCheck_CalcCheckSum16Bit(addr, size)!=0)
|
|
{
|
|
printf("ecos pat%d, res check sum fail.\r\n",pat_id);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int nvt_chk_atf(ulong addr, unsigned int size, unsigned int pat_id)
|
|
{
|
|
if(MemCheck_CalcCheckSum16Bit(addr, size)!=0) {
|
|
printf("atf pat%d, res check sum fail.\r\n",pat_id);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int nvt_chk_teeos(ulong addr, unsigned int size, unsigned int pat_id){
|
|
|
|
|
|
#ifdef CONFIG_NVT_IVOT_OPTEE_SUPPORT
|
|
if(MemCheck_CalcCheckSum16Bit(addr, size)!=0)
|
|
{
|
|
printf("teeos pat%d, res check sum fail.\r\n",pat_id);
|
|
return -1;
|
|
}
|
|
#else
|
|
printf("please enable CONFIG_NVT_IVOT_OPTEE_SUPPORT\n");
|
|
return -1;
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
static int nvt_chk_ai(ulong addr, unsigned int size, unsigned int pat_id)
|
|
{
|
|
if(MemCheck_CalcCheckSum16Bit(addr, size)!=0)
|
|
{
|
|
printf("ai pat%d, res check sum fail.\r\n",pat_id);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int nvt_chk_uboot(ulong addr, unsigned int size, unsigned int pat_id)
|
|
{
|
|
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
|
|
#ifdef CONFIG_NVT_BIN_CHKSUM_SUPPORT
|
|
extern ulong __image_copy_start;
|
|
extern HEADINFO gHeadInfo;
|
|
ulong tag_offset;
|
|
char *tag;
|
|
NVTPACK_BFC_HDR *pbfc = (NVTPACK_BFC_HDR *)addr;
|
|
gHeadInfo.CodeEntry = (ulong)&__image_copy_start;
|
|
tag_offset = (unsigned long)gHeadInfo.BinInfo_1 - (unsigned long)gHeadInfo.CodeEntry;
|
|
tag = (char*)(addr + tag_offset);
|
|
|
|
/* This is for compression check */
|
|
if(is_secure == 0)
|
|
{
|
|
if(MemCheck_CalcCheckSum16Bit(addr, size)!=0)
|
|
{
|
|
printf("uboot pat%d, check sum fail.\r\n",pat_id);
|
|
return -1;
|
|
}
|
|
if(pbfc->uiFourCC == MAKEFOURCC('B', 'C', 'L', '1')) {
|
|
// decode 0x200 size for get BinInfo_1
|
|
const int preload_size = 0x200;
|
|
// enlarge 10 times to avoid buffer overwrite on decompressing
|
|
const int tmp_size = preload_size*10;
|
|
unsigned char *p_tmp = (unsigned char *)malloc(tmp_size);
|
|
if (p_tmp == NULL) {
|
|
printf("no mem to decode uboot.lz, req size = 0x%08X\n", tmp_size);
|
|
return -1;
|
|
}
|
|
|
|
if((cpu_to_be32(pbfc->uiAlgorithm) & 0xFF ) == 11) {
|
|
printf("uboot.lzma used, skip tag check.\r\n");
|
|
} else {
|
|
lz_uncompress((unsigned char *)(addr + sizeof(NVTPACK_BFC_HDR)),
|
|
(unsigned char *)p_tmp,
|
|
preload_size);
|
|
tag = (char*)(p_tmp + tag_offset);
|
|
if(strncmp(tag, gHeadInfo.BinInfo_1, 8) !=0 ) {
|
|
printf("uboot pat%d, tag not match %8s(expect) != %8s(bin).\r\n"
|
|
,pat_id ,gHeadInfo.BinInfo_1, tag);
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
if(MemCheck_CalcCheckSum16Bit(addr, size)!=0)
|
|
{
|
|
printf("uboot pat%d, res check sum fail.\r\n",pat_id);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
#endif /* CONFIG_NVT_BIN_CHKSUM_SUPPORT */
|
|
return 0;
|
|
}
|
|
|
|
#ifdef CONFIG_NVT_IVOT_OPTEE_SUPPORT
|
|
#ifdef CONFIG_NVT_IVOT_OPTEE_SECBOOT_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;
|
|
}
|
|
|
|
static void fill_data_r(UINT8 * s, UINT8 * target, int len)
|
|
{
|
|
int i;
|
|
|
|
for(i=0; i<len; i++)
|
|
target[len-i-1] = s[i];
|
|
}
|
|
|
|
static int nvt_chk_key(ulong addr, unsigned int size)
|
|
{
|
|
HEADINFO *head_info = (HEADINFO *)addr;
|
|
unsigned int key_size = 0;
|
|
unsigned int i=0;
|
|
unsigned int key_offset =0;
|
|
unsigned char * key_buf = NULL;
|
|
unsigned char sha256[32]={0};
|
|
unsigned char key_buf_reverse[256]={0};
|
|
int ret =0;
|
|
|
|
|
|
get_bininfo_size_offset(head_info->BinInfo_1, &key_size, &key_offset);
|
|
key_buf = (unsigned char *)(addr + key_offset);
|
|
|
|
#if 1
|
|
printf("only check N key-> key_size:%d key_offset:%d\n",key_size,key_offset);
|
|
#endif
|
|
fill_data_r(key_buf,key_buf_reverse,256);
|
|
#if 0
|
|
printf("N key reverse:\n");
|
|
for(i=0; i< 256;i++)
|
|
{
|
|
printf("%x ",key_buf_reverse[i]);
|
|
}
|
|
printf("\n");
|
|
#endif
|
|
printf("check rsa 2048 key\n");
|
|
NVT_SMC_SHA_DATA sha_data={0};
|
|
sha_data.input_data = key_buf_reverse;
|
|
sha_data.output_data = sha256;
|
|
sha_data.input_size = 256;
|
|
sha_data.sha_mode = NVT_SMC_SHA_MODE_SHA256;
|
|
ret = nvt_ivot_optee_sha_operation(&sha_data);
|
|
if(ret != 0)
|
|
{
|
|
printf("nvt_ivot_optee_sha_operation fail,ret:%d\n",ret);
|
|
return ret;
|
|
}
|
|
#if 1
|
|
printf(" rsa key reverse and sha256:\n");
|
|
for(i=0; i< 32; i++)
|
|
{
|
|
printf("%x ",*(char *)(sha256+i));
|
|
}
|
|
printf("\n");
|
|
#endif
|
|
#if 1
|
|
/*************
|
|
compare key hash from efuse
|
|
**************/
|
|
|
|
/*default set sha256 in 1,2 efuse key field, 0 efuse key field for aes key*/
|
|
|
|
//check low part-->sha256[0] ~ sha256[15]
|
|
|
|
NVT_SMC_EFUSE_DATA efuse_data = {0};
|
|
efuse_data.cmd = NVT_SMC_EFUSE_COMPARE_KEY;
|
|
efuse_data.key_data.field = EFUSE_OTP_2ND_KEY_SET_FIELD;
|
|
memcpy(efuse_data.key_data.data, &sha256[0], 16);
|
|
if(nvt_ivot_optee_efuse_operation(&efuse_data) !=1)
|
|
{
|
|
printf("compare key2 fail!, please check key in efuse or partition\n");
|
|
return -1;
|
|
}
|
|
efuse_data.key_data.field = EFUSE_OTP_3RD_KEY_SET_FIELD;
|
|
memcpy(efuse_data.key_data.data, &sha256[16], 16);
|
|
if(nvt_ivot_optee_efuse_operation(&efuse_data) !=1)
|
|
{
|
|
printf("compare key3 fail!, please check key in efuse or partition\n");
|
|
return -1;
|
|
}
|
|
|
|
printf("check rsa key ok\n");
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int nvt_chk_signature(ulong addr, unsigned int size)
|
|
{
|
|
int ret=0;
|
|
HEADINFO *head_info = (HEADINFO *)addr;
|
|
unsigned int key_size = 0;
|
|
unsigned int key_offset =0;
|
|
unsigned char * key_buf = NULL;
|
|
unsigned int signature_size = 0;
|
|
unsigned int signature_offset = 0;
|
|
unsigned char * signature_buf = NULL;
|
|
unsigned int crypto_size = 0;
|
|
unsigned int crypto_offset = 0;
|
|
unsigned char * crypto_buf = NULL;
|
|
unsigned int *sha256 = NULL;
|
|
unsigned int rsa_output[64]={0}; //usging unsigned int for address alignment 4
|
|
unsigned int current_sha256[64]={0}; //usging unsigned int for address alignment 4
|
|
unsigned int output_size = sizeof(rsa_output);
|
|
unsigned int data_size =0;
|
|
unsigned int sha256_align_size =0;
|
|
#if 1
|
|
NVT_SMC_EFUSE_DATA efuse_data = {0};
|
|
efuse_data.cmd = NVT_SMC_EFUSE_IS_RSA_KEY_CHECK;
|
|
if(1 == nvt_ivot_optee_efuse_operation(&efuse_data))
|
|
{
|
|
ret = nvt_chk_key( addr, size);
|
|
if(ret != 0)
|
|
{
|
|
printf("nvt_chk_public_key fail ret:%x\n",ret);
|
|
return -1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("rsa key check not enable\n");
|
|
}
|
|
#else
|
|
ret = nvt_chk_key( addr, size);
|
|
if(ret != 0)
|
|
{
|
|
printf("nvt_chk_public_key fail ret:%x\n",ret);
|
|
return -1;
|
|
}
|
|
#endif
|
|
get_bininfo_size_offset(head_info->BinInfo_1, &key_size, &key_offset);
|
|
key_buf = (unsigned char *)(addr + key_offset);
|
|
|
|
|
|
get_bininfo_size_offset(head_info->BinInfo_2, &signature_size, &signature_offset);
|
|
signature_buf = (unsigned char *)(addr + signature_offset);
|
|
|
|
|
|
get_bininfo_size_offset(head_info->BinInfo_3, &crypto_size, &crypto_offset);
|
|
crypto_buf = (unsigned char *)(addr + crypto_offset);
|
|
|
|
|
|
NVT_SMC_RSA_DATA rsa_data={0};
|
|
//rsa input data size should equal to n key size
|
|
unsigned char signature_buf_tmp[256]={0};
|
|
memcpy(signature_buf_tmp,signature_buf,signature_size);
|
|
rsa_data.rsa_mode = NVT_SMC_RSA_MODE_2048;
|
|
rsa_data.n_key = key_buf;
|
|
rsa_data.n_key_size = 256;
|
|
rsa_data.ed_key = (unsigned char *)((unsigned long)key_buf + 256);
|
|
rsa_data.ed_key_size = key_size - rsa_data.n_key_size;
|
|
rsa_data.input_data = signature_buf_tmp;
|
|
rsa_data.input_size = 256;
|
|
rsa_data.output_data = (unsigned char *)rsa_output;
|
|
|
|
ret = nvt_ivot_optee_rsa_operation(&rsa_data);
|
|
|
|
if(ret != 0){
|
|
printf("nvt_ivot_optee_rsa_decrypt fail ret:%d\n",ret);
|
|
return -1;
|
|
}
|
|
|
|
#if 1
|
|
unsigned int i=0;
|
|
printf("\nrsa decrypt size (%d) :\n", output_size);
|
|
for(i=0;i< (output_size/4);i++)
|
|
{
|
|
printf("%08x ",rsa_output[i]);
|
|
}
|
|
printf("\n");
|
|
#endif
|
|
|
|
#if 1
|
|
printf("crypto_buf:%x offset:%x addr:%x\n",crypto_buf,crypto_offset,addr);
|
|
printf("data size:%x\n",crypto_size);
|
|
printf("data :%x %x %x %x %x %x\n",crypto_buf[0],crypto_buf[1],crypto_buf[2],crypto_buf[3],crypto_buf[4],crypto_buf[5]);
|
|
|
|
#endif
|
|
|
|
/**
|
|
------
|
|
header
|
|
-------
|
|
key
|
|
-----
|
|
signature
|
|
----
|
|
encrypt bin
|
|
|
|
encrypt bin length = total size - encrypt bin offset
|
|
|
|
*/
|
|
|
|
data_size = head_info->BinLength - crypto_offset;
|
|
#if 1
|
|
if((data_size & 0x3f) != 0)
|
|
{
|
|
sha256_align_size = ((data_size/0x40) + 1)*0x40;
|
|
memset((unsigned char *)(crypto_buf + data_size),0, sha256_align_size - data_size);
|
|
printf("sha256 data not align 64 ,need add pending data\n");
|
|
}
|
|
else
|
|
{
|
|
sha256_align_size = data_size;
|
|
}
|
|
|
|
#endif
|
|
NVT_SMC_SHA_DATA sha_data={0};
|
|
sha_data.input_data = crypto_buf;
|
|
sha_data.output_data = (unsigned char *)current_sha256;
|
|
sha_data.input_size = sha256_align_size;
|
|
sha_data.sha_mode = NVT_SMC_SHA_MODE_SHA256;
|
|
ret = nvt_ivot_optee_sha_operation(&sha_data);
|
|
if(ret != 0)
|
|
{
|
|
printf("nvt_ivot_optee_sha_operation fail,ret:%d\n",ret);
|
|
return ret;
|
|
}
|
|
|
|
|
|
if(ret != 0)
|
|
{
|
|
printf("nvt_ivot_optee_sha256_compute fail,ret:%d\n",ret);
|
|
return -1;
|
|
}
|
|
|
|
sha256 = (unsigned int *)((unsigned long)rsa_output + 256 - 32);// the last 32 bytes are signature
|
|
#if 1
|
|
printf("\n hash img:\n");
|
|
for(i=0;i< 8;i++)
|
|
{
|
|
printf("%x ",current_sha256[i]);
|
|
}
|
|
printf("\n");
|
|
printf("\n signature data:\n");
|
|
for(i=0;i< 8;i++)
|
|
{
|
|
printf("%x ",sha256[i]);
|
|
}
|
|
printf("\n");
|
|
#endif
|
|
|
|
if(memcmp(¤t_sha256[0], sha256, 32)!= 0)
|
|
{
|
|
printf("compare hash fail!\n");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
#endif
|
|
static int nvt_chk_linux(ulong addr, unsigned int size, unsigned int pat_id)
|
|
{
|
|
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(is_secure == 0)
|
|
{
|
|
if(*(unsigned int *)(addr) == MAKEFOURCC('B', 'C', 'L', '1')) {
|
|
if(MemCheck_CalcCheckSum16Bit(addr, size) !=0) {
|
|
printf("uImage checksum fail\n");
|
|
return -1;
|
|
}
|
|
} else if(image_check_dcrc((const image_header_t*)(addr))!=1) {
|
|
printf("linux-kernel pat%d, res check sum fail.\r\n",pat_id);
|
|
return -1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("%s uImage is encryped , check by checksum\r\n",ANSI_COLOR_YELLOW);
|
|
if(MemCheck_CalcCheckSum16Bit(addr, size) !=0)
|
|
{
|
|
printf("uImage checksum fail\n");
|
|
return -1;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int nvt_chk_rootfs(ulong addr, unsigned int size, unsigned int pat_id)
|
|
{
|
|
#ifdef CONFIG_NVT_BIN_CHKSUM_SUPPORT
|
|
ulong uiContextBuf = addr;
|
|
if(*(unsigned int*)uiContextBuf == MAKEFOURCC('C','K','S','M'))
|
|
{
|
|
NVTPACK_CHKSUM_HDR* pHdr = (NVTPACK_CHKSUM_HDR*)uiContextBuf;
|
|
if(pHdr->uiVersion != NVTPACK_CHKSUM_HDR_VERSION)
|
|
{
|
|
printf("Wrong HEADER_CHKSUM_VERSION %08X(uboot) %08X(root-fs).\r\n",NVTPACK_CHKSUM_HDR_VERSION,pHdr->uiVersion);
|
|
return -1;
|
|
}
|
|
UINT32 uiLen = pHdr->uiDataOffset + pHdr->uiDataSize + pHdr->uiPaddingSize;
|
|
if(MemCheck_CalcCheckSum16Bit(uiContextBuf,uiLen)!=0)
|
|
{
|
|
printf("pat%d, res check sum fail.\r\n",pat_id);
|
|
return -1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("root-fs has no CKSM header\r\n");
|
|
return -1;
|
|
}
|
|
#endif /* CONFIG_NVT_BIN_CHKSUM_SUPPORT */
|
|
return 0;
|
|
}
|
|
|
|
int nvt_chk_all_in_one_valid(unsigned short EmbType, unsigned int addr, unsigned int size, unsigned int id)
|
|
{
|
|
switch(EmbType)
|
|
{
|
|
case EMBTYPE_LOADER:
|
|
if(nvt_chk_loader((ulong)addr,size,id)!=0)
|
|
return -1;
|
|
break;
|
|
case EMBTYPE_FDT:
|
|
if(nvt_chk_modelext((ulong)addr,size,id)!=0)
|
|
return -1;
|
|
break;
|
|
case EMBTYPE_UITRON:
|
|
if(nvt_chk_uitron((ulong)addr,size,id)!=0)
|
|
return -1;
|
|
break;
|
|
case EMBTYPE_ECOS:
|
|
if(nvt_chk_ecos((ulong)addr,size,id)!=0)
|
|
return -1;
|
|
break;
|
|
case EMBTYPE_UBOOT:
|
|
if(nvt_chk_uboot((ulong)addr,size,id)!=0)
|
|
return -1;
|
|
break;
|
|
case EMBTYPE_ATF:
|
|
if(nvt_chk_atf((ulong)addr,size,id)!=0)
|
|
return -1;
|
|
break;
|
|
case EMBTYPE_LINUX:
|
|
if(nvt_chk_linux((ulong)addr,size,id)!=0)
|
|
return -1;
|
|
break;
|
|
case EMBTYPE_ROOTFS:
|
|
if(nvt_chk_rootfs((ulong)addr,size,id)!=0)
|
|
return -1;
|
|
break;
|
|
case EMBTYPE_RTOS:
|
|
if(nvt_chk_rtos((ulong)addr,size,id)!=0)
|
|
return -1;
|
|
break;
|
|
case EMBTYPE_APP:
|
|
if(nvt_chk_app((ulong)addr,size,id)!=0){
|
|
return -1;
|
|
}
|
|
break;
|
|
case EMBTYPE_TEEOS:
|
|
if(nvt_chk_teeos((ulong)addr,size,id)!=0){
|
|
return -1;
|
|
}
|
|
break;
|
|
case EMBTYPE_AI:
|
|
if(nvt_chk_ai((ulong)addr,size,id)!=0){
|
|
return -1;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int nvt_on_partition_enum_sanity(unsigned int id, NVTPACK_MEM* p_mem, void* p_user_data)
|
|
{
|
|
int ret = 0;
|
|
#if defined(CONFIG_NVT_LINUX_SPINAND_BOOT) || defined(CONFIG_NVT_LINUX_SPINOR_BOOT) || defined(CONFIG_NVT_LINUX_EMMC_BOOT)
|
|
EMB_PARTITION* pEmb = (EMB_PARTITION*)p_user_data;
|
|
#if defined(CONFIG_NVT_LINUX_SPINAND_BOOT)
|
|
u64 PartitionSize = pEmb[id].PartitionSize;
|
|
#elif defined(CONFIG_NVT_IVOT_EMMC)
|
|
u64 PartitionSize = pEmb[id].PartitionSize;
|
|
#elif defined(CONFIG_NVT_LINUX_SPINOR_BOOT)
|
|
u64 PartitionSize = pEmb[id].PartitionSize;
|
|
#endif
|
|
unsigned int size = p_mem->len;
|
|
|
|
#ifdef CONFIG_NVT_BIN_CHKSUM_SUPPORT
|
|
// Skip rootfs nvt head info
|
|
if ((pEmb[id].EmbType == EMBTYPE_ROOTFS) || (pEmb[id].EmbType == EMBTYPE_USER) || (pEmb[id].EmbType == EMBTYPE_USERRAW)) {
|
|
size -= 64;
|
|
}
|
|
#endif
|
|
//check partition size
|
|
if(size > PartitionSize)
|
|
{
|
|
printf("Partition[%d] Size is too smaller than that you wanna update.(0x%08X > 0x%08llX)\r\n"
|
|
,id
|
|
,size
|
|
,PartitionSize);
|
|
return -1;
|
|
}
|
|
|
|
ret = nvt_chk_all_in_one_valid(pEmb[id].EmbType, (ulong)p_mem->p_data, p_mem->len, id);
|
|
#endif /* CONFIG_NVT_LINUX_SPINAND_BOOT || CONFIG_NVT_LINUX_SPINOR_BOOT || CONFIG_NVT_LINUX_EMMC_BOOT*/
|
|
return ret;
|
|
}
|
|
|
|
static int nvt_on_partition_enum_update(unsigned int id, NVTPACK_MEM* p_mem, void* p_user_data)
|
|
{
|
|
#if defined(CONFIG_NVT_LINUX_SPINAND_BOOT) || defined(CONFIG_NVT_LINUX_SPINOR_BOOT) || defined(CONFIG_NVT_LINUX_EMMC_BOOT)
|
|
EMB_PARTITION* pEmb = (EMB_PARTITION*)p_user_data;
|
|
u64 PartitionOffset = pEmb[id].PartitionOffset;
|
|
u64 PartitionSize = pEmb[id].PartitionSize;
|
|
int ret = 0;
|
|
|
|
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
|
|
|
|
switch(pEmb[id].EmbType)
|
|
{
|
|
case EMBTYPE_MBR:
|
|
printf("%s Update: MBR(EMMC only) %s\r\n", ANSI_COLOR_YELLOW, ANSI_COLOR_RESET);
|
|
nvt_chk_last_ebr((ulong)p_mem->p_data, PartitionOffset, pEmb);
|
|
ret = nvt_update_partitions((ulong)p_mem->p_data, p_mem->len, PartitionOffset, PartitionSize);
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE
|
|
nvt_display_draw(DISP_DRAW_UPDATING_BAR);
|
|
#endif
|
|
break;
|
|
case EMBTYPE_LOADER:
|
|
printf("%s Update: loader %s\r\n", ANSI_COLOR_YELLOW, ANSI_COLOR_RESET);
|
|
ret = nvt_update_partitions((ulong)p_mem->p_data, p_mem->len, PartitionOffset, PartitionSize);
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE
|
|
nvt_display_draw(DISP_DRAW_UPDATING_BAR);
|
|
#endif
|
|
break;
|
|
case EMBTYPE_FDT:
|
|
printf("%s Update: fdt %s\r\n", ANSI_COLOR_YELLOW, ANSI_COLOR_RESET);
|
|
ret = nvt_update_partitions((ulong)p_mem->p_data, p_mem->len, PartitionOffset, PartitionSize);
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE
|
|
nvt_display_draw(DISP_DRAW_UPDATING_BAR);
|
|
#endif
|
|
break;
|
|
case EMBTYPE_UITRON:
|
|
printf("%s Update: uitron %s\r\n", ANSI_COLOR_YELLOW, ANSI_COLOR_RESET);
|
|
ret = nvt_update_partitions((ulong)p_mem->p_data, p_mem->len, PartitionOffset, PartitionSize);
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE
|
|
nvt_display_draw(DISP_DRAW_UPDATING_BAR);
|
|
#endif
|
|
break;
|
|
case EMBTYPE_ECOS:
|
|
printf("%s Update: ecos %s\r\n", ANSI_COLOR_YELLOW, ANSI_COLOR_RESET);
|
|
ret = nvt_update_partitions((ulong)p_mem->p_data, p_mem->len, PartitionOffset, PartitionSize);
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE
|
|
nvt_display_draw(DISP_DRAW_UPDATING_BAR);
|
|
#endif
|
|
break;
|
|
case EMBTYPE_UBOOT:
|
|
printf("%s Update: uboot %s\r\n", ANSI_COLOR_YELLOW, ANSI_COLOR_RESET);
|
|
#if 1
|
|
if(is_secure == 1){
|
|
#ifdef CONFIG_NVT_IVOT_OPTEE_SUPPORT
|
|
#ifdef CONFIG_NVT_IVOT_OPTEE_SECBOOT_SUPPORT
|
|
//// check signature
|
|
if(nvt_chk_signature((ulong)p_mem->p_data, p_mem->len))
|
|
{
|
|
printf("check signature fail\n");
|
|
return -1;
|
|
|
|
}
|
|
#endif
|
|
#endif
|
|
}
|
|
#endif
|
|
ret = nvt_update_partitions((ulong)p_mem->p_data, p_mem->len, PartitionOffset, PartitionSize);
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE
|
|
nvt_display_draw(DISP_DRAW_UPDATING_BAR);
|
|
#endif
|
|
break;
|
|
case EMBTYPE_ATF:
|
|
printf("%s Update: ATF %s\r\n", ANSI_COLOR_YELLOW, ANSI_COLOR_RESET);
|
|
#if 1
|
|
if(is_secure == 1){
|
|
#ifdef CONFIG_NVT_IVOT_OPTEE_SUPPORT
|
|
#ifdef CONFIG_NVT_IVOT_OPTEE_SECBOOT_SUPPORT
|
|
//// check signature
|
|
if(nvt_chk_signature((ulong)p_mem->p_data, p_mem->len))
|
|
{
|
|
printf("check signature fail\n");
|
|
return -1;
|
|
|
|
}
|
|
#endif
|
|
#endif
|
|
}
|
|
#endif
|
|
ret = nvt_update_partitions((ulong)p_mem->p_data, p_mem->len, PartitionOffset, PartitionSize);
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE
|
|
nvt_display_draw(DISP_DRAW_UPDATING_BAR);
|
|
#endif
|
|
break;
|
|
case EMBTYPE_APP:
|
|
printf("%s Update: App %u %s \r\n", ANSI_COLOR_YELLOW, pEmb[id].OrderIdx, ANSI_COLOR_RESET);
|
|
ret = nvt_update_fs_partition((ulong)p_mem->p_data, p_mem->len, PartitionOffset, PartitionSize,&pEmb[id]);
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE
|
|
nvt_display_draw(DISP_DRAW_UPDATING_BAR);
|
|
#endif
|
|
break;
|
|
case EMBTYPE_LINUX:
|
|
printf("%s Update: linux %s\r\n", ANSI_COLOR_YELLOW, ANSI_COLOR_RESET);
|
|
#if 1
|
|
if(is_secure == 1){
|
|
#ifdef CONFIG_NVT_IVOT_OPTEE_SUPPORT
|
|
#ifdef CONFIG_NVT_IVOT_OPTEE_SECBOOT_SUPPORT
|
|
//// check signature
|
|
if(nvt_chk_signature((ulong)p_mem->p_data, p_mem->len))
|
|
{
|
|
printf("check signature fail\n");
|
|
return -1;
|
|
|
|
}
|
|
#endif
|
|
#endif
|
|
}
|
|
#endif
|
|
ret = nvt_update_partitions((ulong)p_mem->p_data, p_mem->len, PartitionOffset, PartitionSize);
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE
|
|
nvt_display_draw(DISP_DRAW_UPDATING_BAR);
|
|
#endif
|
|
break;
|
|
case EMBTYPE_ROOTFS:
|
|
printf("%s Update: rootfs%u %s\r\n", ANSI_COLOR_YELLOW, pEmb[id].OrderIdx, ANSI_COLOR_RESET);
|
|
ret = nvt_update_fs_partition((ulong)p_mem->p_data, p_mem->len, PartitionOffset, PartitionSize,&pEmb[id]);
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE
|
|
nvt_display_draw(DISP_DRAW_UPDATING_BAR);
|
|
#endif
|
|
break;
|
|
case EMBTYPE_ROOTFSL:
|
|
printf("%s Update: rootfs logical %u %s\r\n", ANSI_COLOR_YELLOW, pEmb[id].OrderIdx, ANSI_COLOR_RESET);
|
|
ret = nvt_update_rootfsl_partition((ulong)p_mem->p_data, p_mem->len, PartitionOffset, PartitionSize, &pEmb[id]);
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE
|
|
nvt_display_draw(DISP_DRAW_UPDATING_BAR);
|
|
#endif
|
|
break;
|
|
case EMBTYPE_RTOS:
|
|
printf("%s Update: rtos %s\r\n", ANSI_COLOR_YELLOW, ANSI_COLOR_RESET);
|
|
ret = nvt_update_partitions((ulong)p_mem->p_data, p_mem->len, PartitionOffset, PartitionSize);
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE
|
|
nvt_display_draw(DISP_DRAW_UPDATING_BAR);
|
|
#endif
|
|
break;
|
|
case EMBTYPE_TEEOS:
|
|
printf("%s Update: tee os %s\r\n", ANSI_COLOR_YELLOW, ANSI_COLOR_RESET);
|
|
#if 1
|
|
if(is_secure == 1){
|
|
#ifdef CONFIG_NVT_IVOT_OPTEE_SUPPORT
|
|
#ifdef CONFIG_NVT_IVOT_OPTEE_SECBOOT_SUPPORT
|
|
//// check signature
|
|
if(nvt_chk_signature((ulong)p_mem->p_data, p_mem->len))
|
|
{
|
|
printf("check signature fail\n");
|
|
return -1;
|
|
|
|
}
|
|
#endif
|
|
#endif
|
|
}
|
|
#endif
|
|
ret = nvt_update_partitions((ulong)p_mem->p_data, p_mem->len, PartitionOffset, PartitionSize);
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE
|
|
nvt_display_draw(DISP_DRAW_UPDATING_BAR);
|
|
#endif
|
|
break;
|
|
case EMBTYPE_AI:
|
|
printf("%s Update: ai %s\r\n", ANSI_COLOR_YELLOW, ANSI_COLOR_RESET);
|
|
ret = nvt_update_partitions((ulong)p_mem->p_data, p_mem->len, PartitionOffset, PartitionSize);
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE
|
|
nvt_display_draw(DISP_DRAW_UPDATING_BAR);
|
|
#endif
|
|
break;
|
|
case EMBTYPE_USER:
|
|
printf("%s Update: user partition %u %s\r\n", ANSI_COLOR_YELLOW, pEmb[id].OrderIdx, ANSI_COLOR_RESET);
|
|
ret = nvt_update_user_partition((ulong)p_mem->p_data, p_mem->len, PartitionOffset, PartitionSize, &pEmb[id]);
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE
|
|
nvt_display_draw(DISP_DRAW_UPDATING_BAR);
|
|
#endif
|
|
break;
|
|
case EMBTYPE_USERRAW:
|
|
printf("%s Update: user raw partition %u %s\r\n", ANSI_COLOR_YELLOW, pEmb[id].OrderIdx, ANSI_COLOR_RESET);
|
|
ret = nvt_update_partitions((ulong)p_mem->p_data, p_mem->len, PartitionOffset, PartitionSize);
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE
|
|
nvt_display_draw(DISP_DRAW_UPDATING_BAR);
|
|
#endif
|
|
break;
|
|
default:
|
|
printf("%s Update: skip partition %d, embtype=%d %s\r\n", ANSI_COLOR_YELLOW, id, pEmb[id].EmbType, ANSI_COLOR_RESET);
|
|
break;
|
|
}
|
|
|
|
#else
|
|
int ret = 0;
|
|
printf("nvt_on_partition_enum_update, not support boot type\n");
|
|
#endif /* CONFIG_NVT_LINUX_SPINAND_BOOT || CONFIG_NVT_LINUX_SPINOR_BOOT || CONFIG_NVT_LINUX_EMMC_BOOT */
|
|
return ret;
|
|
}
|
|
|
|
static int nvt_on_partition_enum_mtd_readback(unsigned int id, NVTPACK_MEM* p_mem, void* p_user_data)
|
|
{
|
|
int ret = 0;
|
|
#if defined(CONFIG_NVT_LINUX_SPINAND_BOOT) || defined(CONFIG_NVT_LINUX_SPINOR_BOOT) || defined(CONFIG_NVT_LINUX_EMMC_BOOT)
|
|
EMB_PARTITION* pEmb = (EMB_PARTITION*)p_user_data;
|
|
#if defined(CONFIG_NVT_LINUX_SPINAND_BOOT)
|
|
u64 PartitionOffset = pEmb[id].PartitionOffset;
|
|
u64 PartitionSize = pEmb[id].PartitionSize;
|
|
#elif defined(CONFIG_NVT_IVOT_EMMC)
|
|
u64 PartitionOffset = pEmb[id].PartitionOffset;
|
|
u64 PartitionSize = pEmb[id].PartitionSize;
|
|
#elif defined(CONFIG_NVT_LINUX_SPINOR_BOOT)
|
|
u64 PartitionOffset = pEmb[id].PartitionOffset;
|
|
u64 PartitionSize = pEmb[id].PartitionSize;
|
|
#else
|
|
u64 PartitionOffset = pEmb[id].PartitionOffset;
|
|
u64 PartitionSize = pEmb[id].PartitionSize;
|
|
#endif
|
|
|
|
nvt_dbg(IND, "Read back check callback\n");
|
|
switch(pEmb[id].EmbType)
|
|
{
|
|
case EMBTYPE_MBR:
|
|
printf("%s Read: MBR %s\r\n", ANSI_COLOR_YELLOW, ANSI_COLOR_RESET);
|
|
ret = nvt_read_partitions((ulong)p_mem->p_data, p_mem->len, PartitionOffset, id, pEmb[id].EmbType);
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE
|
|
nvt_display_draw(DISP_DRAW_UPDATING_BAR);
|
|
#endif
|
|
break;
|
|
case EMBTYPE_LOADER:
|
|
printf("%s Read: loader %s\r\n", ANSI_COLOR_YELLOW, ANSI_COLOR_RESET);
|
|
ret = nvt_read_partitions((ulong)p_mem->p_data, p_mem->len, PartitionOffset, id, pEmb[id].EmbType);
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE
|
|
nvt_display_draw(DISP_DRAW_UPDATING_BAR);
|
|
#endif
|
|
break;
|
|
case EMBTYPE_FDT:
|
|
printf("%s Read: fdt %s\r\n", ANSI_COLOR_YELLOW, ANSI_COLOR_RESET);
|
|
ret = nvt_read_partitions((ulong)p_mem->p_data, p_mem->len, PartitionOffset, id, pEmb[id].EmbType);
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE
|
|
nvt_display_draw(DISP_DRAW_UPDATING_BAR);
|
|
#endif
|
|
break;
|
|
case EMBTYPE_UITRON:
|
|
printf("%s Read: uitron %s\r\n", ANSI_COLOR_YELLOW, ANSI_COLOR_RESET);
|
|
ret = nvt_read_partitions((ulong)p_mem->p_data, p_mem->len, PartitionOffset, id, pEmb[id].EmbType);
|
|
nvt_read_user_partition((ulong)p_mem->p_data, p_mem->len, PartitionOffset, PartitionSize, id, &pEmb[id]);
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE
|
|
nvt_display_draw(DISP_DRAW_UPDATING_BAR);
|
|
#endif
|
|
break;
|
|
case EMBTYPE_ECOS:
|
|
printf("%s Read: ecos %s\r\n", ANSI_COLOR_YELLOW, ANSI_COLOR_RESET);
|
|
ret = nvt_read_partitions((ulong)p_mem->p_data, p_mem->len, PartitionOffset, id, pEmb[id].EmbType);
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE
|
|
nvt_display_draw(DISP_DRAW_UPDATING_BAR);
|
|
#endif
|
|
break;
|
|
case EMBTYPE_UBOOT:
|
|
printf("%s Read: uboot %s\r\n", ANSI_COLOR_YELLOW, ANSI_COLOR_RESET);
|
|
ret = nvt_read_partitions((ulong)p_mem->p_data, p_mem->len, PartitionOffset, id, pEmb[id].EmbType);
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE
|
|
nvt_display_draw(DISP_DRAW_UPDATING_BAR);
|
|
#endif
|
|
break;
|
|
case EMBTYPE_ATF:
|
|
printf("%s Read: ATF %s\r\n", ANSI_COLOR_YELLOW, ANSI_COLOR_RESET);
|
|
ret = nvt_read_partitions((ulong)p_mem->p_data, p_mem->len, PartitionOffset, id, pEmb[id].EmbType);
|
|
nvt_read_user_partition((ulong)p_mem->p_data, p_mem->len, PartitionOffset, PartitionSize, id, &pEmb[id]);
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE
|
|
nvt_display_draw(DISP_DRAW_UPDATING_BAR);
|
|
#endif
|
|
break;
|
|
case EMBTYPE_APP:
|
|
printf("%s Read: App partition %u %s\r\n", ANSI_COLOR_YELLOW, pEmb[id].OrderIdx, ANSI_COLOR_RESET);
|
|
ret = nvt_read_fs_partition((ulong)p_mem->p_data, p_mem->len, PartitionOffset, PartitionSize, id, &pEmb[id]);
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE
|
|
nvt_display_draw(DISP_DRAW_UPDATING_BAR);
|
|
#endif
|
|
break;
|
|
case EMBTYPE_LINUX:
|
|
printf("%s Read: linux %s\r\n", ANSI_COLOR_YELLOW, ANSI_COLOR_RESET);
|
|
ret = nvt_read_partitions((ulong)p_mem->p_data, p_mem->len, PartitionOffset, id, pEmb[id].EmbType);
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE
|
|
nvt_display_draw(DISP_DRAW_UPDATING_BAR);
|
|
#endif
|
|
break;
|
|
case EMBTYPE_ROOTFS:
|
|
printf("%s Read: rootfs%u %s\r\n", ANSI_COLOR_YELLOW, pEmb[id].OrderIdx, ANSI_COLOR_RESET);
|
|
ret = nvt_read_fs_partition((ulong)p_mem->p_data, p_mem->len, PartitionOffset, PartitionSize, id, &pEmb[id]);
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE
|
|
nvt_display_draw(DISP_DRAW_UPDATING_BAR);
|
|
#endif
|
|
break;
|
|
case EMBTYPE_ROOTFSL:
|
|
printf("%s Read: rootfs%u %s\r\n", ANSI_COLOR_YELLOW, pEmb[id].OrderIdx, ANSI_COLOR_RESET);
|
|
ret = nvt_read_rootfsl_partition((ulong)p_mem->p_data, p_mem->len, PartitionOffset, PartitionSize, id, &pEmb[id]);
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE
|
|
nvt_display_draw(DISP_DRAW_UPDATING_BAR);
|
|
#endif
|
|
break;
|
|
case EMBTYPE_RTOS:
|
|
printf("%s Read: rtos %s\r\n", ANSI_COLOR_YELLOW, ANSI_COLOR_RESET);
|
|
ret = nvt_read_partitions((ulong)p_mem->p_data, p_mem->len, PartitionOffset, id, pEmb[id].EmbType);
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE
|
|
nvt_display_draw(DISP_DRAW_UPDATING_BAR);
|
|
#endif
|
|
break;
|
|
case EMBTYPE_TEEOS:
|
|
printf("%s Read: tee os %s\r\n", ANSI_COLOR_YELLOW, ANSI_COLOR_RESET);
|
|
ret = nvt_read_partitions((ulong)p_mem->p_data, p_mem->len, PartitionOffset, id, pEmb[id].EmbType);
|
|
nvt_read_user_partition((ulong)p_mem->p_data, p_mem->len, PartitionOffset, PartitionSize, id, &pEmb[id]);
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE
|
|
nvt_display_draw(DISP_DRAW_UPDATING_BAR);
|
|
#endif
|
|
break;
|
|
case EMBTYPE_AI:
|
|
printf("%s Read: ai %s\r\n", ANSI_COLOR_YELLOW, ANSI_COLOR_RESET);
|
|
ret = nvt_read_partitions((ulong)p_mem->p_data, p_mem->len, PartitionOffset, id, pEmb[id].EmbType);
|
|
nvt_read_user_partition((ulong)p_mem->p_data, p_mem->len, PartitionOffset, PartitionSize, id, &pEmb[id]);
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE
|
|
nvt_display_draw(DISP_DRAW_UPDATING_BAR);
|
|
#endif
|
|
break;
|
|
case EMBTYPE_USER:
|
|
printf("%s Read: user partition %u %s\r\n", ANSI_COLOR_YELLOW, pEmb[id].OrderIdx, ANSI_COLOR_RESET);
|
|
nvt_read_user_partition((ulong)p_mem->p_data, p_mem->len, PartitionOffset, PartitionSize, id, &pEmb[id]);
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE
|
|
nvt_display_draw(DISP_DRAW_UPDATING_BAR);
|
|
#endif
|
|
break;
|
|
case EMBTYPE_USERRAW:
|
|
printf("%s Read: user raw partition %u %s\r\n", ANSI_COLOR_YELLOW, pEmb[id].OrderIdx, ANSI_COLOR_RESET);
|
|
ret = nvt_read_partitions((ulong)p_mem->p_data, p_mem->len, PartitionOffset, id, pEmb[id].EmbType);
|
|
nvt_read_user_partition((ulong)p_mem->p_data, p_mem->len, PartitionOffset, PartitionSize, id, &pEmb[id]);
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE
|
|
nvt_display_draw(DISP_DRAW_UPDATING_BAR);
|
|
#endif
|
|
break;
|
|
default:
|
|
printf("%s Read: skip partition %d, embtype=%d %s\r\n", ANSI_COLOR_YELLOW, id, pEmb[id].EmbType, ANSI_COLOR_RESET);
|
|
break;
|
|
}
|
|
|
|
#endif /* CONFIG_NVT_LINUX_SPINAND_BOOT || CONFIG_NVT_LINUX_SPINOR_BOOT || CONFIG_NVT_LINUX_EMMC_BOOT */
|
|
return ret;
|
|
}
|
|
|
|
static int nvt_getfdt_emb_addr_size(ulong addr, u32 *fdt_emb_addr, u32 *fdt_emb_len)
|
|
{
|
|
const char *ptr = NULL;
|
|
const struct fdt_property* fdt_property = NULL;
|
|
int nodeoffset, nextoffset;
|
|
|
|
#if defined(CONFIG_NVT_IVOT_EMMC)
|
|
char path[128] = {0};
|
|
#if (defined(CONFIG_TARGET_NA51090) || defined(CONFIG_TARGET_NA51090_A64))
|
|
sprintf(path, "/mmc@%x", IOADDR_SDIO2_REG_BASE);
|
|
#else
|
|
sprintf(path, "/mmc@%x", IOADDR_SDIO3_REG_BASE);
|
|
#endif
|
|
nodeoffset = fdt_path_offset((const void*)addr, path);
|
|
#elif defined(CONFIG_NVT_SPI_NOR)
|
|
nodeoffset = fdt_path_offset((const void*)addr, "/nor");
|
|
#else
|
|
nodeoffset = fdt_path_offset((const void*)addr, "/nand");
|
|
#endif
|
|
nextoffset = fdt_first_subnode((const void*)addr, nodeoffset);
|
|
if (nextoffset < 0 || nodeoffset < 0) {
|
|
*fdt_emb_addr = 0;
|
|
return -1;
|
|
}
|
|
*fdt_emb_addr = addr + nextoffset;
|
|
nodeoffset = nextoffset;
|
|
while(strcmp(ptr, "nvtpack") != 0) {
|
|
nextoffset = fdt_next_node((const void*)addr, nodeoffset, NULL);
|
|
if (nextoffset < 0) {
|
|
return -1;
|
|
}
|
|
ptr = fdt_get_name((const void*)addr, nextoffset, NULL);
|
|
nodeoffset = nextoffset;
|
|
}
|
|
nextoffset = fdt_first_property_offset((const void*)addr, nodeoffset);
|
|
nodeoffset = nextoffset;
|
|
if (nextoffset < 0) {
|
|
return -1;
|
|
}
|
|
while(nextoffset >= 0) {
|
|
nextoffset = fdt_next_property_offset((const void*)addr, nodeoffset);
|
|
fdt_property = fdt_get_property_by_offset((const void*)addr, nodeoffset, NULL);
|
|
nodeoffset = nextoffset;
|
|
}
|
|
|
|
if (fdt_emb_len != NULL)
|
|
*fdt_emb_len = (ulong)fdt_property->data + strlen(fdt_property->data) - *fdt_emb_addr;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int nvt_checkfdt_part_is_match(const void *fdt_old, const void *fdt_new)
|
|
{
|
|
int i, len;
|
|
const void *fdt[2] = {fdt_old, fdt_new};
|
|
const char *name[2] = {0};
|
|
unsigned long long ofs[2] = {0};
|
|
unsigned long long size[2] = {0};
|
|
int nodeoffset[2] = {0};
|
|
#if defined(CONFIG_NVT_IVOT_EMMC)
|
|
char path[128] = {0};
|
|
#endif
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
#if defined(CONFIG_NVT_IVOT_EMMC)
|
|
#if (defined(CONFIG_TARGET_NA51090) || defined(CONFIG_TARGET_NA51090_A64))
|
|
sprintf(path, "/mmc@%x", IOADDR_SDIO2_REG_BASE);
|
|
#else
|
|
sprintf(path, "/mmc@%x", IOADDR_SDIO3_REG_BASE);
|
|
#endif
|
|
nodeoffset[i] = fdt_path_offset((const void*)fdt[i], path);
|
|
#elif defined(CONFIG_NVT_SPI_NOR)
|
|
nodeoffset[i] = fdt_path_offset((const void*)fdt[i], "/nor");
|
|
#else
|
|
nodeoffset[i] = fdt_path_offset((const void*)fdt[i], "/nand");
|
|
#endif
|
|
nodeoffset[i] = fdt_first_subnode((const void*)fdt[i], nodeoffset[i]);
|
|
if (nodeoffset[i] < 0 || nodeoffset[i] < 0) {
|
|
printf(ANSI_COLOR_RED "cannot find /mmc@f0510000 or /nor or /nand from fdt.\r\n");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
while (nodeoffset[0] >= 0 || nodeoffset[1] >= 0) {
|
|
//get next nodes of partition_
|
|
for (i = 0; i < 2; i++) {
|
|
ofs[i] = 0;
|
|
size[i] = 0;
|
|
while(nodeoffset[i] >= 0) {
|
|
unsigned long long *nodep;
|
|
name[i] = fdt_get_name(fdt[i], nodeoffset[i], NULL);
|
|
if (strncmp(name[i], "partition_", 10) == 0) {
|
|
nodep = (unsigned long long *)fdt_getprop(fdt[i], nodeoffset[i], "reg", &len);
|
|
if (nodep == NULL || len != sizeof(unsigned long long)*2) {
|
|
printf(ANSI_COLOR_RED "unable to get 'reg' form %s\r\n", name[i]);
|
|
return -1;
|
|
}
|
|
ofs[i] = be64_to_cpu(nodep[0]);
|
|
size[i] = be64_to_cpu(nodep[1]);
|
|
nodeoffset[i] = fdt_next_subnode(fdt[i], nodeoffset[i]);
|
|
break;
|
|
}
|
|
nodeoffset[i] = fdt_next_subnode(fdt[i], nodeoffset[i]);
|
|
name[i] = NULL; //clean name for indicate if partition_xxx has found
|
|
}
|
|
}
|
|
if (name[0] == NULL && name[1] == NULL) {
|
|
break;
|
|
}
|
|
if (strcmp(name[0], name[1]) != 0) {
|
|
printf(ANSI_COLOR_RED "partition name not matched old:%s new:%s\r\n", name[0], name[1]);
|
|
return -1;
|
|
}
|
|
if (ofs[0] != ofs[1]) {
|
|
printf(ANSI_COLOR_RED "%s offset not matched old:%llx new:%llx\r\n", name[0], ofs[0], ofs[1]);
|
|
return -1;
|
|
}
|
|
if (size[0] != size[1]) {
|
|
printf(ANSI_COLOR_RED "%s size not matched old:%llx new:%llx\r\n", name[0], size[0], size[1]);
|
|
return -1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int nvt_process_all_in_one(ulong addr, unsigned int size, int firm_upd_firm)
|
|
{
|
|
u32 i;
|
|
int ret = 0;
|
|
unsigned char md5_output_orig[16] = {0};
|
|
unsigned char md5_output_cur[16] = {0};
|
|
u32 need_chk_all_partition_exist = 0;
|
|
NVTPACK_VERIFY_OUTPUT np_verify = {0};
|
|
NVTPACK_GET_PARTITION_INPUT np_get_input;
|
|
NVTPACK_ENUM_PARTITION_INPUT np_enum_input;
|
|
NVTPACK_MEM mem_in = {(void*)addr, (unsigned int)size};
|
|
NVTPACK_MEM mem_out = {0};
|
|
|
|
memset(&np_get_input, 0, sizeof(np_get_input));
|
|
memset(&np_enum_input, 0, sizeof(np_enum_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;
|
|
}
|
|
|
|
//check if modelext exists.
|
|
EMB_PARTITION* pEmbNew = emb_partition_info_data_new;
|
|
u32 emb_addr_new = 0;
|
|
u32 emb_size_new = 0;
|
|
np_get_input.id = 1; // modelext must always put in partition[1]
|
|
np_get_input.mem = mem_in;
|
|
if(nvtpack_get_partition(&np_get_input,&mem_out) == NVTPACK_ER_SUCCESS)
|
|
{
|
|
if(nvt_check_isfdt((ulong)mem_out.p_data) != 0) {
|
|
printf("partition[1] is not fdt.\r\n");
|
|
return -1;
|
|
}
|
|
|
|
/* extract new partition from new modelext */
|
|
ret = nvt_getfdt_emb_addr_size((ulong)mem_out.p_data, &emb_addr_new, &emb_size_new);
|
|
if(ret < 0) {
|
|
printf("failed to get new partition address and size.\r\n");
|
|
return -1;
|
|
}
|
|
|
|
ret = nvt_getfdt_emb((ulong)mem_out.p_data, pEmbNew);
|
|
if(ret < 0) {
|
|
printf("failed to get new partition table.\r\n");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
// get current partition in embbed storage
|
|
EMB_PARTITION* pEmbCurr = emb_partition_info_data_curr;
|
|
u32 emb_addr_curr = 0;
|
|
u32 emb_size_curr = 0;
|
|
if (nvt_chk_mtd_fdt_is_null()) {
|
|
printf("%s modelext is empty %s\r\n", ANSI_COLOR_RED, ANSI_COLOR_RESET);
|
|
need_chk_all_partition_exist = 1;
|
|
} else if (nvt_check_isfdt((ulong)nvt_fdt_buffer) == 0) {
|
|
//To do current modelext init.
|
|
ret = nvt_fdt_init(true);
|
|
if (ret < 0)
|
|
printf("fdt init fail\n");
|
|
|
|
ret = nvt_getfdt_emb_addr_size((ulong)nvt_fdt_buffer, &emb_addr_curr, &emb_size_curr);
|
|
if(ret < 0) {
|
|
printf("failed to get new partition resource.\r\n");
|
|
return -1;
|
|
}
|
|
|
|
ret = nvt_getfdt_emb((ulong)nvt_fdt_buffer, pEmbCurr);
|
|
if(ret < 0) {
|
|
printf("failed to get current partition resource.\r\n");
|
|
return -1;
|
|
}
|
|
// check if partition changes.
|
|
if(emb_size_new != 0 && nvt_checkfdt_part_is_match(nvt_fdt_buffer, mem_out.p_data) != 0) {
|
|
//must be fully all-in-one-bin
|
|
printf("%s detected partition changed. %s\r\n", ANSI_COLOR_RED, ANSI_COLOR_RESET);
|
|
debug("%s fdt in mtd: 0x%08x@0x%08x fdt in all-in-one:0x%08x@0x%08x %s\r\n",
|
|
ANSI_COLOR_RED,
|
|
emb_size_curr,
|
|
emb_addr_curr,
|
|
emb_size_new,
|
|
emb_addr_new,
|
|
ANSI_COLOR_RESET);
|
|
need_chk_all_partition_exist = 1;
|
|
} else {
|
|
printf("%s Partition is not changed %s\n", ANSI_COLOR_YELLOW, ANSI_COLOR_RESET);
|
|
}
|
|
} else {
|
|
if (emb_size_new == 0) {
|
|
//also pEmbCurr is NULL
|
|
printf("%s FDT mtd partition doesn't exist in neither embedded nor all-in-one %s\r\n", ANSI_COLOR_RED, ANSI_COLOR_RESET);
|
|
return -1;
|
|
} else {
|
|
//the first burn, must be fully all-in-one-bin
|
|
printf("%s detected partition changed. %s\r\n", ANSI_COLOR_RED, ANSI_COLOR_RESET);
|
|
need_chk_all_partition_exist = 1;
|
|
}
|
|
}
|
|
//read fdt from loader to get fdt info
|
|
//need get some fdt information, like nvt_memory_cfg nsmem in nvt_on_partition_enum_sanity
|
|
// when run the nvt_fdt_init(false); the nvt_fdt_buffer will become new fdt.
|
|
ret = nvt_fdt_init(false);
|
|
if(ret < 0)
|
|
{
|
|
printf("fdt init fail\n");
|
|
return ret;
|
|
}
|
|
|
|
//check all-in-one firmware sanity
|
|
EMB_PARTITION* pEmb = (emb_size_new != 0)? pEmbNew : pEmbCurr;
|
|
np_enum_input.mem = mem_in;
|
|
np_enum_input.p_user_data = pEmb;
|
|
np_enum_input.fp_enum = nvt_on_partition_enum_sanity;
|
|
if(nvtpack_enum_partition(&np_enum_input) != NVTPACK_ER_SUCCESS)
|
|
{
|
|
printf("failed sanity.\r\n");
|
|
return -1;
|
|
} else {
|
|
int TotalRes = 0;
|
|
NVTPACK_MEM *p_in = &np_enum_input.mem;
|
|
NVTPACK_FW_HDR2 *pFw = (NVTPACK_FW_HDR2 *)p_in->p_data;
|
|
|
|
TotalRes = pFw->TotalRes;
|
|
printf("nvt_process_all_in_one: TotalRes = %d\r\n", TotalRes);
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE
|
|
nvt_display_config(DISP_CFG_TOTAL_DRAWING_BAR, TotalRes);
|
|
//nvt_display_draw(DISP_DRAW_EXTERNAL_FRAME);
|
|
#endif
|
|
}
|
|
|
|
if(need_chk_all_partition_exist)
|
|
{
|
|
for(i=1; i<EMB_PARTITION_INFO_COUNT; i++)
|
|
{
|
|
if(pEmbNew[i].PartitionSize!=0 && (pEmbNew[i].OrderIdx==0 || pEmbNew[i].EmbType==EMBTYPE_MBR))
|
|
{
|
|
switch(pEmbNew[i].EmbType)
|
|
{
|
|
case EMBTYPE_MBR:
|
|
case EMBTYPE_FDT:
|
|
case EMBTYPE_UITRON:
|
|
case EMBTYPE_ECOS:
|
|
case EMBTYPE_UBOOT:
|
|
case EMBTYPE_ATF:
|
|
//case EMBTYPE_DSP:
|
|
case EMBTYPE_LINUX:
|
|
case EMBTYPE_ROOTFS:
|
|
case EMBTYPE_RTOS:
|
|
case EMBTYPE_APP:
|
|
case EMBTYPE_TEEOS:
|
|
case EMBTYPE_AI:
|
|
{
|
|
//check this type exist in all-in-one
|
|
np_get_input.id = i;
|
|
np_get_input.mem = mem_in;
|
|
if(nvtpack_check_partition(pEmbNew[i], &np_get_input,&mem_out) != NVTPACK_ER_SUCCESS)
|
|
{
|
|
printf("partition changed, need partition[%d]\n",i);
|
|
return -1;
|
|
}
|
|
}break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* partition table env init */
|
|
ret = nvt_part_config(NULL, pEmb);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
/*
|
|
* start to update each partition of all-in-one
|
|
*/
|
|
|
|
//multi-bin
|
|
np_enum_input.mem = mem_in;
|
|
np_enum_input.p_user_data = pEmb;
|
|
np_enum_input.fp_enum = nvt_on_partition_enum_update;
|
|
|
|
if(nvtpack_enum_partition(&np_enum_input) != NVTPACK_ER_SUCCESS)
|
|
{
|
|
printf("failed to run nvt_update_partitions.\r\n");
|
|
return -1;
|
|
}
|
|
/* To calculate original buffer the all-in-one image md5 sum */
|
|
md5_wd((unsigned char *) addr, size, md5_output_orig, CHUNKSZ_MD5);
|
|
|
|
/*
|
|
* Read back updated image from mtd to check if valid or not
|
|
*/
|
|
/*if (firm_upd_firm)
|
|
nvt_disable_mem_protect();*/
|
|
|
|
//multi-bin
|
|
np_enum_input.mem = mem_in;
|
|
np_enum_input.p_user_data = pEmb;
|
|
np_enum_input.fp_enum = nvt_on_partition_enum_mtd_readback;
|
|
if(nvtpack_enum_partition(&np_enum_input) != NVTPACK_ER_SUCCESS) {
|
|
printf("failed to run nvt_read_partitions.\r\n");
|
|
return -1;
|
|
}
|
|
|
|
//check all-in-one firmware sanity
|
|
np_enum_input.mem = mem_in;
|
|
np_enum_input.p_user_data = pEmb;
|
|
np_enum_input.fp_enum = nvt_on_partition_enum_sanity;
|
|
|
|
if(nvtpack_enum_partition(&np_enum_input) != NVTPACK_ER_SUCCESS)
|
|
{
|
|
printf("failed sanity.\r\n");
|
|
#ifndef CONFIG_NVT_SPI_NONE
|
|
ret = nvt_flash_mark_bad();
|
|
if (ret)
|
|
printf("flash mark bad process failed\n");
|
|
#endif
|
|
return -1;
|
|
} else {
|
|
printf("%s Read back check sanity successfully. %s\r\n", ANSI_COLOR_YELLOW, ANSI_COLOR_RESET);
|
|
}
|
|
|
|
/* To calculate the all-in-one image md5 sum after read back */
|
|
md5_wd((unsigned char *) addr, size, md5_output_cur, CHUNKSZ_MD5);
|
|
if (memcmp(md5_output_orig, md5_output_cur, sizeof(md5_output_cur)) != 0) {
|
|
printf("%s All-in-one image MD5 sum is not match %s\n", ANSI_COLOR_RED, ANSI_COLOR_RESET);
|
|
#ifndef CONFIG_NVT_SPI_NONE
|
|
ret = nvt_flash_mark_bad();
|
|
if (ret)
|
|
printf("flash mark bad process failed\n");
|
|
#endif
|
|
return -1;
|
|
} else {
|
|
printf("%s All-in-one image MD5 sum is match %s\n", ANSI_COLOR_YELLOW, ANSI_COLOR_RESET);
|
|
}
|
|
|
|
if(emb_size_new!=0)
|
|
{
|
|
int ret = 0;
|
|
//reload new modelext but must keep loader information
|
|
printf("Reload new modelext partition after updating\r\n");
|
|
ret = nvt_fdt_init(true);
|
|
if (ret < 0)
|
|
printf("modelext init fail\n");
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* This function can be used to do rootfs format
|
|
* Two conditions will do format:
|
|
* iTron cmd: key restore_rootfs
|
|
* Linux: uctrl usys -rootfs_broken => Send event to itron, itron can decide what to do
|
|
*/
|
|
int nvt_process_rootfs_format(void)
|
|
{
|
|
EMB_PARTITION *p_emb_partition = NULL;
|
|
int ret = 0;
|
|
loff_t part_off=0, part_size=0;
|
|
char command[128];
|
|
unsigned long val = 0;
|
|
|
|
memset(command, 0, sizeof(command));
|
|
/* get partition table */
|
|
ret = nvt_getfdt_emb((ulong)nvt_fdt_buffer, p_emb_partition);
|
|
if (ret < 0) {
|
|
printf("FDT: emb_partition setting is null\n");
|
|
goto err_fmt_rootfs;
|
|
}
|
|
|
|
/* partition table env init */
|
|
ret = nvt_part_config(NULL, p_emb_partition);
|
|
if (ret < 0)
|
|
goto err_fmt_rootfs;
|
|
|
|
/* Check if rootfs1 is existed */
|
|
ret = get_part("rootfs1", &part_off, &part_size);
|
|
if (ret < 0)
|
|
goto err_fmt_rootfs;
|
|
|
|
printf("Starting to format R/W rootfs partition\n");
|
|
sprintf(command, "nand erase.part rootfs1");
|
|
run_command(command, 0);
|
|
|
|
#if defined(CONFIG_NVT_UBIFS_SUPPORT)
|
|
sprintf(command, "ubi part rootfs1");
|
|
run_command(command, 0);
|
|
|
|
sprintf(command, "ubi create rootfs1");
|
|
run_command(command, 0);
|
|
#endif
|
|
|
|
val = (nvt_readl((ulong)nvt_shminfo_comm_uboot_boot_func) & ~COMM_UBOOT_BOOT_FUNC_BOOT_DONE_MASK) | COMM_UBOOT_BOOT_FUNC_BOOT_DONE;
|
|
nvt_writel(val, (ulong)nvt_shminfo_comm_uboot_boot_func);
|
|
flush_dcache_all();
|
|
while(1) {
|
|
// Waiting for itron trigger reboot.
|
|
printf(".");
|
|
mdelay(1000);
|
|
}
|
|
|
|
err_fmt_rootfs:
|
|
val = (nvt_readl((ulong)nvt_shminfo_comm_uboot_boot_func) & ~COMM_UBOOT_BOOT_FUNC_BOOT_DONE_MASK) | COMM_UBOOT_BOOT_FUNC_BOOT_NG;
|
|
nvt_writel(val, (ulong)nvt_shminfo_comm_uboot_boot_func);
|
|
flush_dcache_all();
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* This function can be used to do system recovery in emmc boot mode
|
|
* Below condition will do system recovery:
|
|
* Loader send event
|
|
*/
|
|
int nvt_process_sys_recovery(void)
|
|
{
|
|
int ret = 0;
|
|
|
|
#if defined(CONFIG_NVT_IVOT_EMMC_T)
|
|
char dev_part_str[10];
|
|
loff_t size = 0;
|
|
u32 i;
|
|
ulong addr = 0;
|
|
MODELEXT_HEADER* p_resource_curr = NULL;
|
|
EMB_PARTITION* pEmbCurr = NULL;
|
|
NVTPACK_GET_PARTITION_INPUT np_get_input;
|
|
|
|
memset(&np_get_input, 0, sizeof(np_get_input));
|
|
|
|
printf("%sStarting to do EMMC boot recovery %s\r\n", ANSI_COLOR_YELLOW, ANSI_COLOR_RESET);
|
|
/* Switch to emmc bus partition 3 (cache partition) */
|
|
|
|
sprintf(dev_part_str, "%d:3", CONFIG_NVT_IVOT_EMMC);
|
|
if (fs_set_blk_dev("mmc", dev_part_str, FS_TYPE_FAT)) {
|
|
return ERR_NVT_UPDATE_OPENFAILED;
|
|
} else {
|
|
if (!fs_exists(get_nvt_bin_name(NVT_BIN_NAME_TYPE_RECOVERY_FW))) {
|
|
return ERR_NVT_UPDATE_NO_NEED;
|
|
}
|
|
}
|
|
if (fs_set_blk_dev("mmc", dev_part_str, FS_TYPE_FAT))
|
|
return ERR_NVT_UPDATE_OPENFAILED;
|
|
else {
|
|
ret = fs_read(get_nvt_bin_name(NVT_BIN_NAME_TYPE_RECOVERY_FW), (ulong)CONFIG_NVT_RUNFW_SDRAM_BASE, 0, 0, &size);
|
|
if (size <= 0 || ret < 0) {
|
|
printf("Read %s at 0x%x failed ret=%d\n", get_nvt_bin_name(NVT_BIN_NAME_TYPE_RECOVERY_FW), CONFIG_NVT_RUNFW_SDRAM_BASE, size);
|
|
return ERR_NVT_UPDATE_READ_FAILED;
|
|
} else {
|
|
printf("Read %s at 0x%x successfully, size=%d\n", get_nvt_bin_name(NVT_BIN_NAME_TYPE_RECOVERY_FW), CONFIG_NVT_RUNFW_SDRAM_BASE, size);
|
|
NVTPACK_MEM mem_in = {(void*)CONFIG_NVT_RUNFW_SDRAM_BASE, (unsigned int)size};
|
|
NVTPACK_MEM mem_out = {0};
|
|
pEmbCurr = (EMB_PARTITION*)modelext_get_cfg((unsigned char*)CONFIG_SMEM_SDRAM_BASE,MODELEXT_TYPE_EMB_PARTITION,&p_resource_curr);
|
|
if(pEmbCurr==NULL) {
|
|
printf("failed to get current partition resource.\r\n");
|
|
return -1;
|
|
}
|
|
for(i=1; i<EMB_PARTITION_INFO_COUNT; i++)
|
|
{
|
|
if(pEmbCurr[i].PartitionSize!=0 && (pEmbCurr[i].OrderIdx==0 || pEmbCurr[i].EmbType==EMBTYPE_MBR || pEmbCurr[i].EmbType==EMBTYPE_DSP))
|
|
{
|
|
switch(pEmbCurr[i].EmbType)
|
|
{
|
|
case EMBTYPE_MBR:
|
|
case EMBTYPE_FDT:
|
|
case EMBTYPE_UITRON:
|
|
case EMBTYPE_ATF:
|
|
case EMBTYPE_UBOOT:
|
|
#if defined(CONFIG_DSP1_FREERTOS) || defined(CONFIG_DSP2_FREERTOS)
|
|
case EMBTYPE_DSP:
|
|
#endif
|
|
case EMBTYPE_LINUX:
|
|
case EMBTYPE_ROOTFS:
|
|
case EMBTYPE_RTOS:
|
|
case EMBTYPE_TEEOS:
|
|
case EMBTYPE_AI:
|
|
{
|
|
//check this type exist in all-in-one
|
|
np_get_input.id = i;
|
|
np_get_input.mem = mem_in;
|
|
if(nvtpack_check_partition(pEmbCurr[i], &np_get_input,&mem_out) != NVTPACK_ER_SUCCESS)
|
|
{
|
|
printf("Recovery procedure: need partition[%d]\n",i);
|
|
return -1;
|
|
}
|
|
}break;
|
|
}
|
|
}
|
|
}
|
|
ret = nvt_process_all_in_one((ulong)CONFIG_NVT_RUNFW_SDRAM_BASE ,size, 0);
|
|
if (ret < 0)
|
|
return ERR_NVT_UPDATE_FAILED;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
|
|
int nvt_fw_update(bool firm_upd_firm)
|
|
{
|
|
int ret = 0, retry = 0;
|
|
SHMINFO *p_shminfo;
|
|
loff_t size = 0;
|
|
char command[128];
|
|
|
|
p_shminfo = (SHMINFO *)CONFIG_SMEM_SDRAM_BASE;
|
|
if (strncmp(p_shminfo->boot.LdInfo_1, "LD_NVT", 6) != 0) {
|
|
printf("can't get right bin info in %s \n", __func__);
|
|
return ERR_NVT_UPDATE_FAILED;
|
|
}
|
|
|
|
if (firm_upd_firm) {
|
|
unsigned long firm_addr = nvt_readl((ulong)nvt_shminfo_comm_fw_update_addr);
|
|
unsigned long firm_size = nvt_readl((ulong)nvt_shminfo_comm_fw_update_len);
|
|
|
|
printf("%s\tfirmware image at: 0x%08lx@0x%08lx %s\r\n", ANSI_COLOR_YELLOW, firm_size, firm_addr, ANSI_COLOR_RESET);
|
|
ret = nvt_process_all_in_one(firm_addr, firm_size, firm_upd_firm);
|
|
if (ret < 0)
|
|
return ERR_NVT_UPDATE_FAILED;
|
|
} else if (p_shminfo->boot.LdCtrl2 & LDCF_BOOT_FLASH) {
|
|
return ERR_NVT_UPDATE_NO_NEED;
|
|
} else {
|
|
|
|
/*added for emmc upgrade by greg*/
|
|
extern struct mmc *init_mmc_device(int dev, bool force_init);
|
|
struct mmc *mmc;
|
|
mmc = init_mmc_device(curr_device, false);
|
|
if (!mmc) {
|
|
printf("Get eMMc device failed\n\r");
|
|
return ERR_NVT_UPDATE_OPENFAILED;
|
|
}
|
|
|
|
typedef int (*set_blk_dev_cb)(void);
|
|
set_blk_dev_cb nvt_fs_set_blk_dev_cb = NULL;
|
|
|
|
if(nvt_fs_set_blk_dev() == 0 && fs_exists(get_nvt_bin_name(NVT_BIN_NAME_TYPE_FW))){
|
|
printf("***found fw bin in sd card******\n");
|
|
nvt_fs_set_blk_dev_cb = nvt_fs_set_blk_dev;
|
|
}
|
|
else if(nvt_fs_set_blk_dev_emmc() == 0 && fs_exists(get_nvt_bin_name(NVT_BIN_NAME_TYPE_FW))){
|
|
|
|
printf("***found fw bin in emmc*******\n");
|
|
nvt_fs_set_blk_dev_cb = nvt_fs_set_blk_dev_emmc;
|
|
}
|
|
else{
|
|
return ERR_NVT_UPDATE_OPENFAILED;
|
|
}
|
|
|
|
if (nvt_fs_set_blk_dev_cb() || fs_size(get_nvt_bin_name(NVT_BIN_NAME_TYPE_FW), &size) < 0) {
|
|
return ERR_NVT_UPDATE_NO_NEED;
|
|
}
|
|
|
|
|
|
while (retry < UPDATE_ALL_IN_ONE_RETRY_TIMES) {
|
|
if (nvt_fs_set_blk_dev_cb())
|
|
return ERR_NVT_UPDATE_OPENFAILED;
|
|
else {
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE //uboot config
|
|
nvt_display_init();
|
|
#endif
|
|
|
|
ulong fdt_addr = nvt_readl((ulong)nvt_shminfo_boot_fdt_addr);
|
|
ulong fdt_size = fdt_totalsize(fdt_addr);
|
|
/* To check if A.bin is larger than all-in-one temp buffer size */
|
|
if (size > CONFIG_NVT_ALL_IN_ONE_IMG_SIZE) {
|
|
printf("%sYour image size %lld is larger than all-in-one size with %d %s\r\n", ANSI_COLOR_RED, size, CONFIG_NVT_ALL_IN_ONE_IMG_SIZE, ANSI_COLOR_RESET);
|
|
return ERR_NVT_UPDATE_READ_FAILED;
|
|
}
|
|
/* To check if all-in-one buffer is overlapped with mem-tbl's fdt */
|
|
if (fdt_addr + fdt_size > CONFIG_NVT_RUNFW_SDRAM_BASE) {
|
|
printf("%s CONFIG_NVT_RUNFW_SDRAM_BASE (0x%lX) is overlapped with fdt(0x%lX-0x%lX), check CONFIG_NVT_ALL_IN_ONE_IMG_SIZE%s\r\n",
|
|
ANSI_COLOR_RED, CONFIG_NVT_RUNFW_SDRAM_BASE, fdt_addr, fdt_addr + fdt_size, ANSI_COLOR_RESET);
|
|
return ERR_NVT_UPDATE_READ_FAILED;
|
|
}
|
|
/**
|
|
* To check if all-in-one buffer is overlapped with mem-tbl's shmem
|
|
* DO NOT use static-check (such as #if), otherwise it may cause compiler error for non-all-in-one vendor.
|
|
*/
|
|
if (CONFIG_SMEM_SDRAM_BASE + CONFIG_SMEM_SDRAM_SIZE > CONFIG_NVT_RUNFW_SDRAM_BASE) {
|
|
printf("%s CONFIG_NVT_RUNFW_SDRAM_BASE (0x%lX) is overlapped with shmem(0x%lX-0x%lX), check CONFIG_NVT_ALL_IN_ONE_IMG_SIZE%s\r\n",
|
|
ANSI_COLOR_RED, CONFIG_NVT_RUNFW_SDRAM_BASE, CONFIG_SMEM_SDRAM_BASE, CONFIG_SMEM_SDRAM_BASE + CONFIG_SMEM_SDRAM_SIZE, ANSI_COLOR_RESET);
|
|
return ERR_NVT_UPDATE_READ_FAILED;
|
|
}
|
|
|
|
ret = fs_read(get_nvt_bin_name(NVT_BIN_NAME_TYPE_FW), (ulong)CONFIG_NVT_RUNFW_SDRAM_BASE, 0, 0, &size);
|
|
if (size <= 0 || ret < 0) {
|
|
printf("Read %s at 0x%x failed ret=%lld\n", get_nvt_bin_name(NVT_BIN_NAME_TYPE_FW), CONFIG_NVT_RUNFW_SDRAM_BASE, size);
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE //uboot config
|
|
nvt_display_draw(DISP_DRAW_UPDATEFW_FAILED);
|
|
#endif
|
|
return ERR_NVT_UPDATE_READ_FAILED;
|
|
} else {
|
|
printf("Read %s at 0x%x successfully, size=%lld\n", get_nvt_bin_name(NVT_BIN_NAME_TYPE_FW), CONFIG_NVT_RUNFW_SDRAM_BASE, size);
|
|
ret = nvt_process_all_in_one((ulong)CONFIG_NVT_RUNFW_SDRAM_BASE ,size, 0);
|
|
if (ret < 0) {
|
|
retry++;
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE //uboot config
|
|
if (retry < UPDATE_ALL_IN_ONE_RETRY_TIMES) {
|
|
//nvt_display_draw(DISP_DRAW_UPDATEFW_FAILED_AND_RETRY);
|
|
//mdelay(1500);
|
|
nvt_display_draw(DISP_DRAW_UPDATEFW_AGAIN);
|
|
}
|
|
#endif
|
|
} else {
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE //uboot config
|
|
nvt_display_draw(DISP_DRAW_UPDATEFW_OK);
|
|
#endif
|
|
/* This flag is for the first boot after update A.bin finished. */
|
|
p_shminfo->boot.LdCtrl2 &= ~LDCF_BOOT_CARD;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (retry >= UPDATE_ALL_IN_ONE_RETRY_TIMES) {
|
|
#ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE //uboot config
|
|
nvt_display_draw(DISP_DRAW_UPDATEFW_FAILED);
|
|
#endif
|
|
return ERR_NVT_UPDATE_FAILED;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void sf_display_lcd_bl(UINT32 vlaue)
|
|
{
|
|
g_LcdBl = vlaue;
|
|
}
|
|
|
|
UINT32 sf_get_display_lcd_bl(void)
|
|
{
|
|
return g_LcdBl;
|
|
} |