add spienc feature
This commit is contained in:
parent
b3676b7ab2
commit
5975e8c040
@ -87,6 +87,10 @@ static int do_upgrade_detect(struct cmd_tbl *cmdtp, int flag, int argc,
|
|||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
#if CONFIG_ARTINCHIP_SID_BURN_SPIENC_KEY_CMD
|
||||||
|
run_command("efuse_spienc", 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
env_set("upg_type", "");
|
env_set("upg_type", "");
|
||||||
if (check_usb_upg()) {
|
if (check_usb_upg()) {
|
||||||
aic_upg_flag_clear();
|
aic_upg_flag_clear();
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
obj-y += d211.o
|
obj-y += d211.o
|
||||||
obj-y += env_location.o
|
obj-y += env_location.o
|
||||||
obj-y += efuse_cmd.o
|
obj-y += efuse_cmd.o
|
||||||
|
obj-$(CONFIG_ARTINCHIP_SID_BURN_SPIENC_KEY_CMD) += efuse_burn_spienc_key_cmd.o
|
||||||
obj-$(CONFIG_AICUPG_ARTINCHIP) += usb_device_check.o
|
obj-$(CONFIG_AICUPG_ARTINCHIP) += usb_device_check.o
|
||||||
obj-$(CONFIG_UPDATE_UDISK_FATFS_ARTINCHIP) += usb_host_check.o
|
obj-$(CONFIG_UPDATE_UDISK_FATFS_ARTINCHIP) += usb_host_check.o
|
||||||
obj-$(CONFIG_$(SPL_TPL_)ENV_IS_IN_MMC) += mmc_env.o
|
obj-$(CONFIG_$(SPL_TPL_)ENV_IS_IN_MMC) += mmc_env.o
|
||||||
|
|||||||
@ -0,0 +1,471 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2022-2025 ArtInChip Technology Co., Ltd
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <common.h>
|
||||||
|
#include <command.h>
|
||||||
|
#include <console.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <dm.h>
|
||||||
|
#include <misc.h>
|
||||||
|
#include <asm/io.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include "spi_aes_key.h"
|
||||||
|
|
||||||
|
#ifndef CONFIG_SPL_BUILD
|
||||||
|
|
||||||
|
static struct udevice *efuse_dev;
|
||||||
|
static struct udevice *get_efuse_device(void)
|
||||||
|
{
|
||||||
|
struct udevice *dev = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (efuse_dev)
|
||||||
|
return efuse_dev;
|
||||||
|
|
||||||
|
ret = uclass_first_device_err(UCLASS_MISC, &dev);
|
||||||
|
if (ret) {
|
||||||
|
pr_err("Get UCLASS_MISC device failed.\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (device_is_compatible(dev, "artinchip,aic-sid-v1.0"))
|
||||||
|
break;
|
||||||
|
ret = uclass_next_device_err(&dev);
|
||||||
|
} while (dev);
|
||||||
|
|
||||||
|
efuse_dev = dev;
|
||||||
|
return efuse_dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hexdump(const u8 *buf, uint len)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
if (i && (i % 16) == 0)
|
||||||
|
printf("\n");
|
||||||
|
if ((i % 16) == 0)
|
||||||
|
printf("0x%08lx : ", (unsigned long)&buf[i]);
|
||||||
|
printf("%02x ", buf[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int write_efuse(char *msg, u32 offset, const void *val, u32 size)
|
||||||
|
{
|
||||||
|
#if CONFIG_ARTINCHIP_SID_BURN_SIMULATED
|
||||||
|
printf("eFuse %s:\n", msg);
|
||||||
|
hexdump((unsigned char *)val, size);
|
||||||
|
return size;
|
||||||
|
#else
|
||||||
|
struct udevice *dev = NULL;
|
||||||
|
int wrcnt;
|
||||||
|
|
||||||
|
dev = get_efuse_device();
|
||||||
|
if (!dev) {
|
||||||
|
pr_err("Failed to get efuse device.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
wrcnt = misc_write(dev, offset, val, size);
|
||||||
|
if (wrcnt != size) {
|
||||||
|
pr_err("Failed to write eFuse.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static int read_efuse(u32 offset, void *val, u32 size)
|
||||||
|
{
|
||||||
|
struct udevice *dev = NULL;
|
||||||
|
int rdcnt;
|
||||||
|
|
||||||
|
dev = get_efuse_device();
|
||||||
|
if (!dev) {
|
||||||
|
pr_err("Failed to get efuse device.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rdcnt = misc_read(dev, offset, val, size);
|
||||||
|
if (rdcnt != size) {
|
||||||
|
pr_err("Failed to read eFuse.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int burn_brom_spienc_bit(void)
|
||||||
|
{
|
||||||
|
u32 offset = 0xFFFF, val;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
offset = 0x38;
|
||||||
|
val = 0;
|
||||||
|
val |= (1 << 16); // Secure boot bit for brom
|
||||||
|
val |= (1 << 19); // SPIENC boot bit for brom
|
||||||
|
|
||||||
|
ret = write_efuse("brom enable spienc secure bit", offset, (const void *)&val, 4);
|
||||||
|
if (ret <= 0) {
|
||||||
|
printf("Write BROM SPIENC bit error\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int check_brom_spienc_bit(void)
|
||||||
|
{
|
||||||
|
u32 offset = 0xFFFF, val, mskval = 0;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
offset = 0x38;
|
||||||
|
mskval = 0;
|
||||||
|
mskval |= (1 << 16); // Secure boot bit for brom
|
||||||
|
mskval |= (1 << 19); // SPIENC boot bit for brom
|
||||||
|
|
||||||
|
ret = read_efuse(offset, (void *)&val, 4);
|
||||||
|
if (ret <= 0) {
|
||||||
|
printf("Read secure bit efuse error.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((val & mskval) == mskval) {
|
||||||
|
printf("BROM SPIENC is ENABLED\n");
|
||||||
|
} else {
|
||||||
|
printf("BROM SPIENC is NOT enabled\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int burn_jtag_lock_bit(void)
|
||||||
|
{
|
||||||
|
u32 offset = 0xFFFF, val;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
offset = 0x38;
|
||||||
|
val = 0;
|
||||||
|
val |= (1 << 0); // JTAG LOCK
|
||||||
|
|
||||||
|
ret = write_efuse("jtag lock bit", offset, (const void *)&val, 4);
|
||||||
|
if (ret <= 0) {
|
||||||
|
printf("Write JTAG LOCK bit error\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int check_jtag_lock_bit(void)
|
||||||
|
{
|
||||||
|
u32 offset = 0xFFFF, val, mskval = 0;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
offset = 0x38;
|
||||||
|
mskval = 0;
|
||||||
|
mskval |= (1 << 0); // JTAG LOCK
|
||||||
|
|
||||||
|
ret = read_efuse(offset, (void *)&val, 4);
|
||||||
|
if (ret <= 0) {
|
||||||
|
printf("Read secure bit efuse error.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((val & mskval) == mskval) {
|
||||||
|
printf("JTAG LOCK is ENABLED\n");
|
||||||
|
} else {
|
||||||
|
printf("JTAG LOCK is NOT enabled\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int burn_spienc_key(void)
|
||||||
|
{
|
||||||
|
u32 offset = 0xFFFF;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
offset = 0xA0;
|
||||||
|
|
||||||
|
ret = write_efuse("spi_aes.key", offset, (const void *)spi_aes_key, spi_aes_key_len);
|
||||||
|
if (ret <= 0) {
|
||||||
|
printf("Write SPI ENC AES key error.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int check_spienc_key(void)
|
||||||
|
{
|
||||||
|
u32 offset = 0xFFFF;
|
||||||
|
u8 data[256];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
offset = 0xA0;
|
||||||
|
|
||||||
|
ret = read_efuse(offset, (void *)data, 16);
|
||||||
|
if (ret <= 0) {
|
||||||
|
printf("Read efuse error.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("SPI ENC KEY:\n");
|
||||||
|
hexdump(data, 16);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int burn_spienc_nonce(void)
|
||||||
|
{
|
||||||
|
u32 offset;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
offset = 0xB0;
|
||||||
|
ret = write_efuse("spi_nonce.key", offset, (const void *)spi_nonce_key,
|
||||||
|
spi_nonce_key_len);
|
||||||
|
if (ret <= 0) {
|
||||||
|
printf("Write SPI ENC NONCE key error.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int check_spienc_nonce(void)
|
||||||
|
{
|
||||||
|
u32 offset;
|
||||||
|
u8 data[256];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
offset = 0xB0;
|
||||||
|
ret = read_efuse(offset, (void *)data, 8);
|
||||||
|
if (ret <= 0) {
|
||||||
|
printf("Read efuse error.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("SPI ENC NONCE:\n");
|
||||||
|
hexdump(data, 8);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int burn_spienc_rotpk(void)
|
||||||
|
{
|
||||||
|
u32 offset = 0xFFFF;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
offset = 0x40;
|
||||||
|
ret = write_efuse("rotpk.bin", offset, (const void *)rotpk_bin,
|
||||||
|
rotpk_bin_len);
|
||||||
|
if (ret <= 0) {
|
||||||
|
printf("Write SPI ENC ROTPK error.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int check_spienc_rotpk(void)
|
||||||
|
{
|
||||||
|
u32 offset = 0xFFFF;
|
||||||
|
u8 data[256];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
offset = 0x40;
|
||||||
|
ret = read_efuse(offset, (void *)data, 16);
|
||||||
|
if (ret <= 0) {
|
||||||
|
printf("Read efuse error.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("ROTPK:\n");
|
||||||
|
hexdump(data, 16);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int burn_spienc_key_read_write_disable_bits(void)
|
||||||
|
{
|
||||||
|
u32 offset, val;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
// SPIENC KEY and NONCE
|
||||||
|
offset = 0x4;
|
||||||
|
val = 0;
|
||||||
|
val = 0x00003F00; // SPIENC Key and Nonce Read disable
|
||||||
|
ret = write_efuse("spienc key/nonce r dis", offset, (const void *)&val,
|
||||||
|
4);
|
||||||
|
if (ret <= 0) {
|
||||||
|
printf("Write r/w disable bit efuse error.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ROTPK
|
||||||
|
offset = 0x8;
|
||||||
|
val = 0;
|
||||||
|
val = 0x000F0000; // ROTPK Write disable
|
||||||
|
ret = write_efuse("rotpk w dis", offset, (const void *)&val, 4);
|
||||||
|
if (ret <= 0) {
|
||||||
|
printf("Write r/w disable bit efuse error.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// SPIENC KEY and NONCE
|
||||||
|
offset = 0xC;
|
||||||
|
val = 0;
|
||||||
|
val = 0x00003F00; // SPIENC Key Write disable
|
||||||
|
ret = write_efuse("spienc key/nonce w dis", offset, (const void *)&val,
|
||||||
|
4);
|
||||||
|
if (ret <= 0) {
|
||||||
|
printf("Write r/w disable bit efuse error.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int check_spienc_key_read_write_disable_bits(void)
|
||||||
|
{
|
||||||
|
u32 offset, val, mskval;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
offset = 0x4;
|
||||||
|
mskval = 0x00003F00;
|
||||||
|
ret = read_efuse(offset, (void *)&val, 4);
|
||||||
|
if (ret <= 0) {
|
||||||
|
printf("Read read disable bit efuse error.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((val & mskval) == mskval)
|
||||||
|
printf("SPI ENC Key is read DISABLED\n");
|
||||||
|
else
|
||||||
|
printf("SPI ENC Key is NOT read disabled\n");
|
||||||
|
|
||||||
|
offset = 0x8;
|
||||||
|
mskval = 0x000F0000;
|
||||||
|
ret = read_efuse(offset, (void *)&val, 4);
|
||||||
|
if (ret <= 0) {
|
||||||
|
printf("Read write disable bit efuse error.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((val & mskval) == mskval)
|
||||||
|
printf("SPI ENC ROTPK is write DISABLED\n");
|
||||||
|
else
|
||||||
|
printf("SPI ENC ROTPK is NOT write disabled\n");
|
||||||
|
|
||||||
|
offset = 0xC;
|
||||||
|
mskval = 0x00003F00;
|
||||||
|
ret = read_efuse(offset, (void *)&val, 4);
|
||||||
|
if (ret <= 0) {
|
||||||
|
printf("Read write disable bit efuse error.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((val & mskval) == mskval)
|
||||||
|
printf("SPI ENC Key is write DISABLED\n");
|
||||||
|
else
|
||||||
|
printf("SPI ENC Key is NOT write disabled\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmd_efuse_do_spienc(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = burn_brom_spienc_bit();
|
||||||
|
if (ret) {
|
||||||
|
printf("Error\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = burn_spienc_key();
|
||||||
|
if (ret) {
|
||||||
|
printf("Error\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = burn_spienc_nonce();
|
||||||
|
if (ret) {
|
||||||
|
printf("Error\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = burn_spienc_rotpk();
|
||||||
|
if (ret) {
|
||||||
|
printf("Error\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = burn_spienc_key_read_write_disable_bits();
|
||||||
|
if (ret) {
|
||||||
|
printf("Error\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = burn_jtag_lock_bit();
|
||||||
|
if (ret) {
|
||||||
|
printf("Error\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = check_brom_spienc_bit();
|
||||||
|
if (ret) {
|
||||||
|
printf("Error\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = check_jtag_lock_bit();
|
||||||
|
if (ret) {
|
||||||
|
printf("Error\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ret = check_spienc_key();
|
||||||
|
if (ret) {
|
||||||
|
printf("Error\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = check_spienc_nonce();
|
||||||
|
if (ret) {
|
||||||
|
printf("Error\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = check_spienc_rotpk();
|
||||||
|
if (ret) {
|
||||||
|
printf("Error\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = check_spienc_key_read_write_disable_bits();
|
||||||
|
if (ret) {
|
||||||
|
printf("Error\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
printf("Write SPI ENC eFuse done.\n");
|
||||||
|
#if CONFIG_ARTINCHIP_SID_BURN_SIMULATED
|
||||||
|
printf("WARNING: This is a dry run to check the eFuse content, key is not burn to eFuse yet.\n");
|
||||||
|
#endif
|
||||||
|
#if !CONFIG_ARTINCHIP_SID_CONTINUE_BOOT_BURN_AFTER
|
||||||
|
while (1)
|
||||||
|
continue;
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
U_BOOT_CMD(efuse_spienc, 1, 1, cmd_efuse_do_spienc,
|
||||||
|
"ArtInChip eFuse burn spienc command", "");
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -227,6 +227,37 @@ static int do_mtd_list(struct cmd_tbl *cmdtp, int flag, int argc,
|
|||||||
return CMD_RET_SUCCESS;
|
return CMD_RET_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARTINCHIP_SPIENC
|
||||||
|
#include <misc.h>
|
||||||
|
#include <artinchip/aic_spienc.h>
|
||||||
|
static int do_mtd_bypass(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||||
|
char *const argv[])
|
||||||
|
{
|
||||||
|
struct udevice *dev = NULL;
|
||||||
|
unsigned long status;
|
||||||
|
|
||||||
|
if (argc < 2)
|
||||||
|
return CMD_RET_USAGE;
|
||||||
|
|
||||||
|
status = hextoul(argv[1], NULL);
|
||||||
|
|
||||||
|
uclass_first_device_err(UCLASS_MISC, &dev);
|
||||||
|
do {
|
||||||
|
if (device_is_compatible(dev, "artinchip,aic-spienc-v1.0"))
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
dev = NULL;
|
||||||
|
uclass_next_device_err(&dev);
|
||||||
|
} while (dev);
|
||||||
|
|
||||||
|
if (dev) {
|
||||||
|
return misc_ioctl(dev, AIC_SPIENC_IOCTL_BYPASS, (void *)status);
|
||||||
|
} else {
|
||||||
|
return CMD_RET_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int mtd_special_write_oob(struct mtd_info *mtd, u64 off,
|
static int mtd_special_write_oob(struct mtd_info *mtd, u64 off,
|
||||||
struct mtd_oob_ops *io_op,
|
struct mtd_oob_ops *io_op,
|
||||||
bool write_empty_pages, bool woob)
|
bool write_empty_pages, bool woob)
|
||||||
@ -586,6 +617,9 @@ static int mtd_name_complete(int argc, char *const argv[], char last_char,
|
|||||||
static char mtd_help_text[] =
|
static char mtd_help_text[] =
|
||||||
"- generic operations on memory technology devices\n\n"
|
"- generic operations on memory technology devices\n\n"
|
||||||
"mtd list\n"
|
"mtd list\n"
|
||||||
|
#ifdef CONFIG_ARTINCHIP_SPIENC
|
||||||
|
"mtd bypass <status>\n"
|
||||||
|
#endif
|
||||||
"mtd read[.raw][.oob] <name> <addr> [<off> [<size>]]\n"
|
"mtd read[.raw][.oob] <name> <addr> [<off> [<size>]]\n"
|
||||||
"mtd dump[.raw][.oob] <name> [<off> [<size>]]\n"
|
"mtd dump[.raw][.oob] <name> [<off> [<size>]]\n"
|
||||||
"mtd write[.raw][.oob][.dontskipff] <name> <addr> [<off> [<size>]]\n"
|
"mtd write[.raw][.oob][.dontskipff] <name> <addr> [<off> [<size>]]\n"
|
||||||
@ -596,6 +630,9 @@ static char mtd_help_text[] =
|
|||||||
"mtd mark <name> [<off>\n"
|
"mtd mark <name> [<off>\n"
|
||||||
"\n"
|
"\n"
|
||||||
"With:\n"
|
"With:\n"
|
||||||
|
#ifdef CONFIG_ARTINCHIP_SPIENC
|
||||||
|
"\t<status>: 1;bypass spienc, 0;enable spienc\n"
|
||||||
|
#endif
|
||||||
"\t<name>: NAND partition/chip name (or corresponding DM device name or OF path)\n"
|
"\t<name>: NAND partition/chip name (or corresponding DM device name or OF path)\n"
|
||||||
"\t<addr>: user address from/to which data will be retrieved/stored\n"
|
"\t<addr>: user address from/to which data will be retrieved/stored\n"
|
||||||
"\t<off>: offset in <name> in bytes (default: start of the part)\n"
|
"\t<off>: offset in <name> in bytes (default: start of the part)\n"
|
||||||
@ -610,6 +647,10 @@ static char mtd_help_text[] =
|
|||||||
|
|
||||||
U_BOOT_CMD_WITH_SUBCMDS(mtd, "MTD utils", mtd_help_text,
|
U_BOOT_CMD_WITH_SUBCMDS(mtd, "MTD utils", mtd_help_text,
|
||||||
U_BOOT_SUBCMD_MKENT(list, 1, 1, do_mtd_list),
|
U_BOOT_SUBCMD_MKENT(list, 1, 1, do_mtd_list),
|
||||||
|
#ifdef CONFIG_ARTINCHIP_SPIENC
|
||||||
|
U_BOOT_SUBCMD_MKENT_COMPLETE(bypass, 2, 0, do_mtd_bypass,
|
||||||
|
mtd_name_complete),
|
||||||
|
#endif
|
||||||
U_BOOT_SUBCMD_MKENT_COMPLETE(read, 5, 0, do_mtd_io,
|
U_BOOT_SUBCMD_MKENT_COMPLETE(read, 5, 0, do_mtd_io,
|
||||||
mtd_name_complete),
|
mtd_name_complete),
|
||||||
U_BOOT_SUBCMD_MKENT_COMPLETE(write, 5, 0, do_mtd_io,
|
U_BOOT_SUBCMD_MKENT_COMPLETE(write, 5, 0, do_mtd_io,
|
||||||
|
|||||||
@ -27,10 +27,16 @@ config AICUPG_FORCE_USBUPG_SUPPORT
|
|||||||
bool "Force USB upgrading check during boot"
|
bool "Force USB upgrading check during boot"
|
||||||
default n
|
default n
|
||||||
|
|
||||||
|
config AICUPG_FIRMWARE_SECURITY
|
||||||
|
bool "Secure transfer firmware and burn"
|
||||||
|
default n
|
||||||
|
depends on ARTINCHIP_SPIENC
|
||||||
|
|
||||||
config AICUPG_LOG_BUFFER_SUPPORT
|
config AICUPG_LOG_BUFFER_SUPPORT
|
||||||
bool "Support to get log buffer from device"
|
bool "Support to get log buffer from device"
|
||||||
default y
|
default y
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if AICUPG_LOG_BUFFER_SUPPORT
|
if AICUPG_LOG_BUFFER_SUPPORT
|
||||||
config AICUPG_LOG_BUFFER_ADDR
|
config AICUPG_LOG_BUFFER_ADDR
|
||||||
hex "Log buffer start address"
|
hex "Log buffer start address"
|
||||||
|
|||||||
@ -10,7 +10,19 @@ obj-$(CONFIG_AICUPG_NAND_ARTINCHIP) += nand_fwc.o
|
|||||||
obj-$(CONFIG_AICUPG_NOR_ARTINCHIP) += nor_fwc.o
|
obj-$(CONFIG_AICUPG_NOR_ARTINCHIP) += nor_fwc.o
|
||||||
obj-$(CONFIG_AICUPG_MMC_ARTINCHIP) += mmc_fwc.o
|
obj-$(CONFIG_AICUPG_MMC_ARTINCHIP) += mmc_fwc.o
|
||||||
|
|
||||||
|
ifneq ($(wildcard $(srctree)/drivers/aicupg/libfirmware_security.a),)
|
||||||
|
$(shell cp $(srctree)/drivers/aicupg/libfirmware_security.a $(obj)/libfirmware_security.a)
|
||||||
|
obj-$(CONFIG_AICUPG_FIRMWARE_SECURITY) += libfirmware_security.a
|
||||||
|
else
|
||||||
|
quiet_cmd_ar = AR $@
|
||||||
|
cmd_ar = $(AR) crs $@ $^
|
||||||
|
|
||||||
|
$(obj)/libfirmware_security.a: $(obj)/firmware_security.o
|
||||||
|
$(Q)$(AR) crs $@ $^
|
||||||
|
|
||||||
|
obj-$(CONFIG_AICUPG_FIRMWARE_SECURITY) += libfirmware_security.a
|
||||||
|
endif
|
||||||
|
|
||||||
ifdef CONFIG_TARGET_D211
|
ifdef CONFIG_TARGET_D211
|
||||||
obj-$(CONFIG_AICUPG_NAND_ARTINCHIP) += nand_fwc_spl.o
|
obj-$(CONFIG_AICUPG_NAND_ARTINCHIP) += nand_fwc_spl.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|||||||
@ -15,6 +15,7 @@
|
|||||||
#include "nand_fwc_priv.h"
|
#include "nand_fwc_priv.h"
|
||||||
#include "upg_internal.h"
|
#include "upg_internal.h"
|
||||||
#include "nand_fwc_spl.h"
|
#include "nand_fwc_spl.h"
|
||||||
|
#include <artinchip/firmware_security.h>
|
||||||
|
|
||||||
#ifdef CONFIG_NAND_BBT_MANAGE
|
#ifdef CONFIG_NAND_BBT_MANAGE
|
||||||
#include <linux/mtd/spinand.h>
|
#include <linux/mtd/spinand.h>
|
||||||
@ -938,6 +939,10 @@ void nand_fwc_start(struct fwc_info *fwc)
|
|||||||
memset(priv, 0, sizeof(struct aicupg_nand_priv));
|
memset(priv, 0, sizeof(struct aicupg_nand_priv));
|
||||||
fwc->priv = priv;
|
fwc->priv = priv;
|
||||||
|
|
||||||
|
#ifdef CONFIG_AICUPG_FIRMWARE_SECURITY
|
||||||
|
firmware_security_init();
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the meta.name contains the "image" string, the program is going to
|
* If the meta.name contains the "image" string, the program is going to
|
||||||
* write data to the partition, otherwise the the program is going to read
|
* write data to the partition, otherwise the the program is going to read
|
||||||
@ -961,6 +966,7 @@ void nand_fwc_start(struct fwc_info *fwc)
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
fwc->block_size = mtd->writesize;
|
fwc->block_size = mtd->writesize;
|
||||||
|
|
||||||
if (strstr(fwc->meta.name, "target.spl")) {
|
if (strstr(fwc->meta.name, "target.spl")) {
|
||||||
ret = nand_fwc_spl_prepare(fwc);
|
ret = nand_fwc_spl_prepare(fwc);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@ -1059,11 +1065,25 @@ static s32 nand_fwc_mtd_writer(struct fwc_info *fwc, u8 *buf, s32 len)
|
|||||||
if (!priv)
|
if (!priv)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if ((fwc->meta.size - fwc->trans_size) < len)
|
||||||
|
calc_len = fwc->meta.size - fwc->trans_size;
|
||||||
|
else
|
||||||
|
calc_len = len;
|
||||||
|
|
||||||
|
fwc->calc_partition_crc = crc32(fwc->calc_partition_crc, buf, calc_len);
|
||||||
|
|
||||||
|
#ifdef CONFIG_AICUPG_FIRMWARE_SECURITY
|
||||||
|
firmware_security_decrypt(buf, len);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_AICUPG_SINGLE_TRANS_BURN_CRC32_VERIFY
|
||||||
rdbuf = malloc(len);
|
rdbuf = malloc(len);
|
||||||
if (!rdbuf) {
|
if (!rdbuf) {
|
||||||
pr_err("Error: malloc buffer failed.\n");
|
pr_err("Error: malloc buffer failed.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
for (i = 0; i < MAX_DUPLICATED_PART; i++) {
|
for (i = 0; i < MAX_DUPLICATED_PART; i++) {
|
||||||
mtd = priv->mtds[i];
|
mtd = priv->mtds[i];
|
||||||
if (!mtd)
|
if (!mtd)
|
||||||
@ -1088,41 +1108,35 @@ static s32 nand_fwc_mtd_writer(struct fwc_info *fwc, u8 *buf, s32 len)
|
|||||||
pr_err("Write mtd %s error.\n", mtd->name);
|
pr_err("Write mtd %s error.\n", mtd->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#ifdef CONFIG_AICUPG_SINGLE_TRANS_BURN_CRC32_VERIFY
|
||||||
// Read data to calc crc
|
// Read data to calc crc
|
||||||
ret = mtd_read(mtd, offs, mtd->writesize, &retlen,
|
ret = mtd_read(mtd, offs, mtd->writesize, &retlen,
|
||||||
buf_to_read);
|
buf_to_read);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pr_err("Write mtd %s error.\n", mtd->name);
|
pr_err("Read mtd %s error.\n", mtd->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
buf_to_read += retlen;
|
||||||
|
#endif
|
||||||
/* Update for next write */
|
/* Update for next write */
|
||||||
buf_to_write += retlen;
|
buf_to_write += retlen;
|
||||||
buf_to_read += retlen;
|
|
||||||
priv->offs[i] = offs + retlen;
|
priv->offs[i] = offs + retlen;
|
||||||
offs = priv->offs[i];
|
offs = priv->offs[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((fwc->meta.size - fwc->trans_size) < len)
|
|
||||||
calc_len = fwc->meta.size - fwc->trans_size;
|
|
||||||
else
|
|
||||||
calc_len = len;
|
|
||||||
|
|
||||||
fwc->calc_partition_crc = crc32(fwc->calc_partition_crc,
|
|
||||||
rdbuf, calc_len);
|
|
||||||
#ifdef CONFIG_AICUPG_SINGLE_TRANS_BURN_CRC32_VERIFY
|
#ifdef CONFIG_AICUPG_SINGLE_TRANS_BURN_CRC32_VERIFY
|
||||||
fwc->calc_trans_crc = crc32(fwc->calc_trans_crc, buf, calc_len);
|
fwc->calc_trans_crc = crc32(fwc->calc_trans_crc, buf, calc_len);
|
||||||
if (fwc->calc_trans_crc != fwc->calc_partition_crc) {
|
if (crc32(0, buf, calc_len) != crc32(0, rdbuf, calc_len)) {
|
||||||
pr_err("calc_len:%d\n", calc_len);
|
pr_err("calc_len:%d\n", calc_len);
|
||||||
pr_err("crc err at trans len %u\n", fwc->trans_size);
|
pr_err("crc err at trans len %u\n", fwc->trans_size);
|
||||||
pr_err("trans crc:0x%x, partition crc:0x%x\n",
|
|
||||||
fwc->calc_trans_crc, fwc->calc_partition_crc);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
debug("%s, data len %d, trans len %d, calc len %d\n", __func__, len,
|
debug("%s, data len %d, trans len %d, calc len %d\n", __func__, len,
|
||||||
fwc->trans_size, calc_len);
|
fwc->trans_size, calc_len);
|
||||||
|
|
||||||
free(rdbuf);
|
if (rdbuf)
|
||||||
|
free(rdbuf);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1130,11 +1144,23 @@ static s32 nand_fwc_ubi_writer(struct fwc_info *fwc, u8 *buf, s32 len)
|
|||||||
{
|
{
|
||||||
struct aicupg_nand_priv *priv;
|
struct aicupg_nand_priv *priv;
|
||||||
struct ubi_volume *vol;
|
struct ubi_volume *vol;
|
||||||
s32 ret, i;
|
s32 calc_len, ret, i;
|
||||||
|
|
||||||
priv = (struct aicupg_nand_priv *)fwc->priv;
|
priv = (struct aicupg_nand_priv *)fwc->priv;
|
||||||
if (!priv)
|
if (!priv)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if ((fwc->meta.size - fwc->trans_size) < len)
|
||||||
|
calc_len = fwc->meta.size - fwc->trans_size;
|
||||||
|
else
|
||||||
|
calc_len = len;
|
||||||
|
|
||||||
|
fwc->calc_partition_crc = crc32(fwc->calc_partition_crc, buf, calc_len);
|
||||||
|
|
||||||
|
#ifdef CONFIG_AICUPG_FIRMWARE_SECURITY
|
||||||
|
firmware_security_decrypt(buf, len);
|
||||||
|
#endif
|
||||||
|
|
||||||
for (i = 0; i < MAX_DUPLICATED_PART; i++) {
|
for (i = 0; i < MAX_DUPLICATED_PART; i++) {
|
||||||
if (!priv->vols[i])
|
if (!priv->vols[i])
|
||||||
continue;
|
continue;
|
||||||
@ -1146,7 +1172,6 @@ static s32 nand_fwc_ubi_writer(struct fwc_info *fwc, u8 *buf, s32 len)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fwc->calc_partition_crc = fwc->meta.crc; /* TODO: need to calc CRC */
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -17,6 +17,7 @@
|
|||||||
#include "nand_fwc_spl.h"
|
#include "nand_fwc_spl.h"
|
||||||
#include "spi_enc_spl.h"
|
#include "spi_enc_spl.h"
|
||||||
#include <u-boot/crc.h>
|
#include <u-boot/crc.h>
|
||||||
|
#include <artinchip/firmware_security.h>
|
||||||
|
|
||||||
struct aicupg_nand_spl {
|
struct aicupg_nand_spl {
|
||||||
struct mtd_info *mtd;
|
struct mtd_info *mtd;
|
||||||
@ -419,20 +420,32 @@ static s32 nand_fwc_spl_program(struct fwc_info *fwc,
|
|||||||
u32 data_size, blkidx, blkcnt, pa, pgidx, slice_size;
|
u32 data_size, blkidx, blkcnt, pa, pgidx, slice_size;
|
||||||
size_t retlen;
|
size_t retlen;
|
||||||
loff_t offs;
|
loff_t offs;
|
||||||
s32 ret = -1, i, calc_len;
|
s32 ret = -1, i;
|
||||||
u32 trans_crc;
|
|
||||||
u32 partition_crc;
|
|
||||||
u32 trans_size;
|
u32 trans_size;
|
||||||
u32 page_per_blk;
|
u32 page_per_blk;
|
||||||
|
|
||||||
|
fwc->calc_partition_crc = crc32(fwc->calc_partition_crc, spl->image_buf, fwc->meta.size);
|
||||||
|
#ifdef CONFIG_AICUPG_FIRMWARE_SECURITY
|
||||||
|
firmware_security_decrypt(spl->image_buf, spl->rx_size);
|
||||||
|
#endif
|
||||||
|
|
||||||
pt = malloc(PAGE_TABLE_USE_SIZE);
|
pt = malloc(PAGE_TABLE_USE_SIZE);
|
||||||
page_data = malloc(PAGE_MAX_SIZE);
|
page_data = malloc(PAGE_MAX_SIZE);
|
||||||
rd_page_data = malloc(PAGE_MAX_SIZE);
|
if (!page_data) {
|
||||||
if (!page_data || !rd_page_data || !pt) {
|
pr_err("malloc page_data failed.\n");
|
||||||
ret = -1;
|
ret = -ENOMEM;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_AICUPG_SINGLE_TRANS_BURN_CRC32_VERIFY
|
||||||
|
rd_page_data = malloc(PAGE_MAX_SIZE);
|
||||||
|
if (!rd_page_data || !pt) {
|
||||||
|
pr_err("malloc rd_page_data failed.\n");
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ret = spl_build_page_table(spl, pt);
|
ret = spl_build_page_table(spl, pt);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pr_err("Generate page table failed.\n");
|
pr_err("Generate page table failed.\n");
|
||||||
@ -482,8 +495,6 @@ static s32 nand_fwc_spl_program(struct fwc_info *fwc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Write image data to page */
|
/* Write image data to page */
|
||||||
trans_crc = 0;
|
|
||||||
partition_crc = 0;
|
|
||||||
trans_size = 0;
|
trans_size = 0;
|
||||||
p = spl->image_buf;
|
p = spl->image_buf;
|
||||||
end = p + spl->buf_size;
|
end = p + spl->buf_size;
|
||||||
@ -512,6 +523,7 @@ static s32 nand_fwc_spl_program(struct fwc_info *fwc,
|
|||||||
ret = -1;
|
ret = -1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
#ifdef CONFIG_AICUPG_SINGLE_TRANS_BURN_CRC32_VERIFY
|
||||||
// Read data to calc crc
|
// Read data to calc crc
|
||||||
ret = mtd_read(spl->mtd, offs, slice_size, &retlen,
|
ret = mtd_read(spl->mtd, offs, slice_size, &retlen,
|
||||||
rd_page_data);
|
rd_page_data);
|
||||||
@ -521,19 +533,9 @@ static s32 nand_fwc_spl_program(struct fwc_info *fwc,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((trans_size + data_size) > fwc->meta.size)
|
if (crc32(0, page_data, slice_size) != crc32(0, rd_page_data, slice_size)) {
|
||||||
calc_len = fwc->meta.size % slice_size;
|
pr_err("calc_len:%d\n", slice_size);
|
||||||
else
|
|
||||||
calc_len = slice_size;
|
|
||||||
|
|
||||||
partition_crc = crc32(partition_crc, rd_page_data, calc_len);
|
|
||||||
#ifdef CONFIG_AICUPG_SINGLE_TRANS_BURN_CRC32_VERIFY
|
|
||||||
trans_crc = crc32(trans_crc, page_data, calc_len);
|
|
||||||
if (trans_crc != partition_crc) {
|
|
||||||
pr_err("calc_len:%d\n", calc_len);
|
|
||||||
pr_err("crc err at trans len %u\n", trans_size);
|
pr_err("crc err at trans len %u\n", trans_size);
|
||||||
pr_err("trans crc:0x%x, partition crc:0x%x\n",
|
|
||||||
trans_crc, partition_crc);
|
|
||||||
ret = -1;
|
ret = -1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -541,8 +543,6 @@ static s32 nand_fwc_spl_program(struct fwc_info *fwc,
|
|||||||
trans_size += data_size;
|
trans_size += data_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
fwc->calc_partition_crc = partition_crc;
|
|
||||||
fwc->calc_trans_crc = trans_crc;
|
|
||||||
out:
|
out:
|
||||||
if (page_data)
|
if (page_data)
|
||||||
free(page_data);
|
free(page_data);
|
||||||
|
|||||||
@ -13,6 +13,7 @@
|
|||||||
#include <dm/device-internal.h>
|
#include <dm/device-internal.h>
|
||||||
#include <mtd.h>
|
#include <mtd.h>
|
||||||
#include <artinchip/aic_spienc.h>
|
#include <artinchip/aic_spienc.h>
|
||||||
|
#include <artinchip/firmware_security.h>
|
||||||
|
|
||||||
#include "spi_enc_spl.h"
|
#include "spi_enc_spl.h"
|
||||||
|
|
||||||
@ -208,6 +209,9 @@ void nor_fwc_start(struct fwc_info *fwc)
|
|||||||
#endif
|
#endif
|
||||||
fwc->block_size = mtd->writesize;
|
fwc->block_size = mtd->writesize;
|
||||||
debug("%s, FWC name %s\n", __func__, fwc->meta.name);
|
debug("%s, FWC name %s\n", __func__, fwc->meta.name);
|
||||||
|
#ifdef CONFIG_AICUPG_FIRMWARE_SECURITY
|
||||||
|
firmware_security_init();
|
||||||
|
#endif
|
||||||
return;
|
return;
|
||||||
err:
|
err:
|
||||||
pr_err("error:free(priv)\n");
|
pr_err("error:free(priv)\n");
|
||||||
@ -235,6 +239,17 @@ s32 nor_fwc_data_write(struct fwc_info *fwc, u8 *buf, s32 len)
|
|||||||
if (!priv)
|
if (!priv)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if ((fwc->meta.size - fwc->trans_size) < len)
|
||||||
|
calc_len = fwc->meta.size - fwc->trans_size;
|
||||||
|
else
|
||||||
|
calc_len = len;
|
||||||
|
|
||||||
|
fwc->calc_partition_crc = crc32(fwc->calc_partition_crc, buf, calc_len);
|
||||||
|
|
||||||
|
#ifdef CONFIG_AICUPG_FIRMWARE_SECURITY
|
||||||
|
firmware_security_decrypt(buf, len);
|
||||||
|
#endif
|
||||||
|
|
||||||
for (i = 0; i < MAX_DUPLICATED_PART; i++) {
|
for (i = 0; i < MAX_DUPLICATED_PART; i++) {
|
||||||
mtd = priv->mtds[i];
|
mtd = priv->mtds[i];
|
||||||
if (!mtd)
|
if (!mtd)
|
||||||
@ -299,19 +314,10 @@ s32 nor_fwc_data_write(struct fwc_info *fwc, u8 *buf, s32 len)
|
|||||||
priv->offs[i] = offset + retlen;
|
priv->offs[i] = offset + retlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((fwc->meta.size - fwc->trans_size) < len)
|
|
||||||
calc_len = fwc->meta.size - fwc->trans_size;
|
|
||||||
else
|
|
||||||
calc_len = len;
|
|
||||||
|
|
||||||
fwc->calc_partition_crc = crc32(fwc->calc_partition_crc, rdbuf, calc_len);
|
|
||||||
#ifdef CONFIG_AICUPG_SINGLE_TRANS_BURN_CRC32_VERIFY
|
#ifdef CONFIG_AICUPG_SINGLE_TRANS_BURN_CRC32_VERIFY
|
||||||
fwc->calc_trans_crc = crc32(fwc->calc_trans_crc, buf, calc_len);
|
if (crc32(0, buf, calc_len) != crc32(0, rdbuf, calc_len)) {
|
||||||
if (fwc->calc_trans_crc != fwc->calc_partition_crc) {
|
|
||||||
pr_err("calc_len:%d\n", calc_len);
|
pr_err("calc_len:%d\n", calc_len);
|
||||||
pr_err("crc err at trans len %u\n", fwc->trans_size);
|
pr_err("crc err at trans len %u\n", fwc->trans_size);
|
||||||
pr_err("trans crc:0x%x, partition crc:0x%x\n",
|
|
||||||
fwc->calc_trans_crc, fwc->calc_partition_crc);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
fwc->trans_size += len;
|
fwc->trans_size += len;
|
||||||
|
|||||||
@ -61,6 +61,25 @@ config ARTINCHIP_SID
|
|||||||
help
|
help
|
||||||
Enable support for ArtInChip eFuse read/write.
|
Enable support for ArtInChip eFuse read/write.
|
||||||
|
|
||||||
|
config ARTINCHIP_SID_BURN_SPIENC_KEY_CMD
|
||||||
|
bool "Enable SID(eFuse) burn spienc key command"
|
||||||
|
depends on ARTINCHIP_SID
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Burn spienc related eFuse.
|
||||||
|
|
||||||
|
if ARTINCHIP_SID_BURN_SPIENC_KEY_CMD
|
||||||
|
|
||||||
|
config ARTINCHIP_SID_BURN_SIMULATED
|
||||||
|
bool "Enable SID(eFuse) simulated burning"
|
||||||
|
default n
|
||||||
|
|
||||||
|
config ARTINCHIP_SID_CONTINUE_BOOT_BURN_AFTER
|
||||||
|
bool "Enable SID(eFuse) continue to boot after burning"
|
||||||
|
default n
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
config ARTINCHIP_SYSCFG
|
config ARTINCHIP_SYSCFG
|
||||||
bool "Syscfg driver for ArtInChip SoC"
|
bool "Syscfg driver for ArtInChip SoC"
|
||||||
depends on MISC
|
depends on MISC
|
||||||
|
|||||||
14
source/uboot-2021.10/include/artinchip/firmware_security.h
Normal file
14
source/uboot-2021.10/include/artinchip/firmware_security.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025, ArtInChip Technology Co., Ltd
|
||||||
|
*/
|
||||||
|
#ifndef __FIRMWARE_SECURITY_H_
|
||||||
|
#define __FIRMWARE_SECURITY_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
int firmware_security_init(void);
|
||||||
|
void firmware_security_decrypt(uint8_t *buf, unsigned int length);
|
||||||
|
|
||||||
|
#endif // __FIRMWARE_SECURITY_H_
|
||||||
Binary file not shown.
BIN
target/d211/common/libfirmware_security.a
Normal file
BIN
target/d211/common/libfirmware_security.a
Normal file
Binary file not shown.
3
target/d211/demo88_nand/keys/.gitignore
vendored
Normal file
3
target/d211/demo88_nand/keys/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
rotpk*
|
||||||
|
*.h
|
||||||
|
*.pem
|
||||||
31
target/d211/demo88_nand/keys/gen_spienc_key.sh
Executable file
31
target/d211/demo88_nand/keys/gen_spienc_key.sh
Executable file
@ -0,0 +1,31 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Copyright (c) 2022-2025, ArtInChip Technology Co., Ltd
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
# Authors: Xiong Hao <hao.xiong@artinchip.com>
|
||||||
|
#
|
||||||
|
|
||||||
|
if [ ! -f "rsa_private_key.der" ] || [ ! -f "rsa_public_key.der" ];then
|
||||||
|
openssl genrsa -out rsa_private_key.pem 2048
|
||||||
|
openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
|
||||||
|
openssl base64 -d -in rsa_public_key.pem -out rsa_public_key.der
|
||||||
|
openssl base64 -d -in rsa_private_key.pem -out rsa_private_key.der
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "set_aes_key.txt" ] || [ ! -f "set_nonce.txt" ];then
|
||||||
|
openssl rand -hex 16 > set_aes_key.txt
|
||||||
|
openssl rand -hex 8 > set_nonce.txt
|
||||||
|
fi
|
||||||
|
|
||||||
|
openssl dgst -md5 -binary -out rotpk.bin rsa_public_key.der
|
||||||
|
|
||||||
|
xxd -p -r set_aes_key.txt > spi_aes.key
|
||||||
|
xxd -p -r set_nonce.txt > spi_nonce.key
|
||||||
|
xxd -c 16 -i spi_aes.key > spi_aes_key.h
|
||||||
|
xxd -c 16 -i spi_nonce.key >> spi_aes_key.h
|
||||||
|
xxd -c 16 -i rotpk.bin >> spi_aes_key.h
|
||||||
|
|
||||||
|
cp spi_aes_key.h ../../../../source/uboot-2021.10/board/artinchip/d211/spi_aes_key.h
|
||||||
|
cp ../../common/libfirmware_security.a ../../../../source/uboot-2021.10/drivers/aicupg/libfirmware_security.a
|
||||||
1
target/d211/demo88_nand/keys/set_aes_key.txt
Normal file
1
target/d211/demo88_nand/keys/set_aes_key.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
00000000000000000000000000000000
|
||||||
1
target/d211/demo88_nand/keys/set_nonce.txt
Normal file
1
target/d211/demo88_nand/keys/set_nonce.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
0000000000000000
|
||||||
BIN
tools/scripts/firmware_security_encrypt
Executable file
BIN
tools/scripts/firmware_security_encrypt
Executable file
Binary file not shown.
BIN
tools/scripts/firmware_security_encrypt.exe
Executable file
BIN
tools/scripts/firmware_security_encrypt.exe
Executable file
Binary file not shown.
@ -12,6 +12,7 @@ import math
|
|||||||
import zlib
|
import zlib
|
||||||
import json
|
import json
|
||||||
import struct
|
import struct
|
||||||
|
import shutil
|
||||||
import argparse
|
import argparse
|
||||||
import platform
|
import platform
|
||||||
import subprocess
|
import subprocess
|
||||||
@ -1105,6 +1106,10 @@ def aic_boot_create_image_v2(cfg, keydir, datadir):
|
|||||||
else:
|
else:
|
||||||
signature_bytes = aic_boot_gen_signature_bytes(cfg, bootimg)
|
signature_bytes = aic_boot_gen_signature_bytes(cfg, bootimg)
|
||||||
bootimg = bootimg + signature_bytes
|
bootimg = bootimg + signature_bytes
|
||||||
|
if aic_boot_with_ext_loader(cfg):
|
||||||
|
padlen = round_up(len(bootimg), META_ALIGNED_SIZE) - len(bootimg)
|
||||||
|
if padlen > 0:
|
||||||
|
bootimg += bytearray(padlen)
|
||||||
return bootimg
|
return bootimg
|
||||||
|
|
||||||
# Secure boot is not enabled, always add md5 result to the end
|
# Secure boot is not enabled, always add md5 result to the end
|
||||||
@ -1175,6 +1180,58 @@ def spienc_create_image(imgcfg, script_dir):
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def get_align_file(filename, alignsize):
|
||||||
|
if os.path.exists(filename) is False:
|
||||||
|
print("File {} is not exist".format(filename))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
filesize = os.path.getsize(filename)
|
||||||
|
padlen = (alignsize - (filesize % alignsize)) % alignsize
|
||||||
|
|
||||||
|
alignfile = filename + '.align'
|
||||||
|
shutil.copyfile(filename, alignfile)
|
||||||
|
|
||||||
|
if padlen == 0:
|
||||||
|
return alignfile
|
||||||
|
|
||||||
|
with open(alignfile, "ab") as f:
|
||||||
|
f.write(bytearray(padlen))
|
||||||
|
|
||||||
|
return alignfile
|
||||||
|
|
||||||
|
|
||||||
|
def data_crypt_create_image(imgcfg, script_dir):
|
||||||
|
keypath = get_file_path(imgcfg["key"], imgcfg["keydir"])
|
||||||
|
if keypath is None:
|
||||||
|
keypath = get_file_path(imgcfg["key"], imgcfg["datadir"])
|
||||||
|
|
||||||
|
mkcmd = os.path.join(script_dir, "firmware_security_encrypt")
|
||||||
|
if os.path.exists(mkcmd) is False:
|
||||||
|
mkcmd = "firmware_security_encrypt"
|
||||||
|
if sys.platform == "win32":
|
||||||
|
mkcmd += ".exe"
|
||||||
|
cmd = [mkcmd]
|
||||||
|
cmd.append("--key")
|
||||||
|
cmd.append("{}".format(keypath))
|
||||||
|
if "nonce" in imgcfg:
|
||||||
|
noncepath = get_file_path(imgcfg["nonce"], imgcfg["keydir"])
|
||||||
|
if noncepath is None:
|
||||||
|
noncepath = get_file_path(imgcfg["nonce"], imgcfg["datadir"])
|
||||||
|
cmd.append("--nonce")
|
||||||
|
cmd.append("{}".format(noncepath))
|
||||||
|
if "tweak" in imgcfg:
|
||||||
|
cmd.append("--tweak")
|
||||||
|
cmd.append("{}".format(imgcfg["tweak"]))
|
||||||
|
cmd.append("--infile")
|
||||||
|
cmd.append("{}".format(get_align_file(imgcfg["input"], 16)))
|
||||||
|
cmd.append("--outfile")
|
||||||
|
cmd.append("{}".format(imgcfg["output"]))
|
||||||
|
ret = subprocess.run(cmd, stdout=subprocess.PIPE)
|
||||||
|
if ret.returncode != 0:
|
||||||
|
print(ret.stdout.decode("utf-8"))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
def concatenate_create_image(outname, flist, datadir):
|
def concatenate_create_image(outname, flist, datadir):
|
||||||
with open(outname, "wb") as fout:
|
with open(outname, "wb") as fout:
|
||||||
for fn in flist:
|
for fn in flist:
|
||||||
@ -1775,6 +1832,7 @@ def img_write_fwc_file_to_binfile(binfile, cfg, datadir):
|
|||||||
start_block = 0
|
start_block = 0
|
||||||
last_block = 0
|
last_block = 0
|
||||||
used_block = 0
|
used_block = 0
|
||||||
|
total_block = 0
|
||||||
|
|
||||||
if VERBOSE:
|
if VERBOSE:
|
||||||
print("\tPacking file data:")
|
print("\tPacking file data:")
|
||||||
@ -1807,7 +1865,16 @@ def img_write_fwc_file_to_binfile(binfile, cfg, datadir):
|
|||||||
used_block = filesize // block_size // 1024 + 1
|
used_block = filesize // block_size // 1024 + 1
|
||||||
else:
|
else:
|
||||||
used_block = filesize // block_size // 1024
|
used_block = filesize // block_size // 1024
|
||||||
last_block = start_block + used_block - 1
|
total_block = (part_size // block_size // 1024)
|
||||||
|
if (total_block - used_block) <= (total_block // 50):
|
||||||
|
print("\t\tPart {} reserved blocks are less than 2%, \
|
||||||
|
bad blocks may cause burning failures".format(part_name))
|
||||||
|
|
||||||
|
last_block = start_block + total_block - 1
|
||||||
|
if last_block < (start_block + used_block - 1):
|
||||||
|
print("\t\tFile {} exceeds the part {} size".format(path, part_name))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
elif cfg["image"]["info"]["media"]["type"] == "spi-nor":
|
elif cfg["image"]["info"]["media"]["type"] == "spi-nor":
|
||||||
block_size = 64
|
block_size = 64
|
||||||
start_block = part_offset // block_size // 1024
|
start_block = part_offset // block_size // 1024
|
||||||
@ -2338,6 +2405,60 @@ def firmware_component_preproc_spienc(cfg, datadir, keydir, bindir):
|
|||||||
spienc_create_image(imgcfg, bindir)
|
spienc_create_image(imgcfg, bindir)
|
||||||
|
|
||||||
|
|
||||||
|
def firmware_component_preproc_data_crypt(cfg, datadir, keydir, bindir):
|
||||||
|
preproc_cfg = get_pre_process_cfg(cfg)
|
||||||
|
imgnames = preproc_cfg["data_crypt"].keys()
|
||||||
|
for name in imgnames:
|
||||||
|
imgcfg = preproc_cfg["data_crypt"][name]
|
||||||
|
imgcfg["keydir"] = keydir
|
||||||
|
imgcfg["datadir"] = datadir
|
||||||
|
inname = datadir + imgcfg["file"]
|
||||||
|
outname = datadir + name
|
||||||
|
imgcfg["input"] = inname
|
||||||
|
imgcfg["output"] = outname
|
||||||
|
|
||||||
|
imglist = []
|
||||||
|
if cfg["image"]["info"]["media"]["type"] == "spi-nand":
|
||||||
|
imglist = []
|
||||||
|
orglist = cfg["image"]["info"]["media"]["array_organization"]
|
||||||
|
for item in orglist:
|
||||||
|
paramstr = "_page_{}_block_{}".format(item["page"], item["block"])
|
||||||
|
paramstr = paramstr.lower()
|
||||||
|
status_ok = True
|
||||||
|
if not inname.endswith(".ubi") and not inname.endswith(".ubifs"):
|
||||||
|
continue
|
||||||
|
|
||||||
|
if inname.find("*") <= 0:
|
||||||
|
# No need to check
|
||||||
|
continue
|
||||||
|
|
||||||
|
imgcfg["output"] = outname.replace("*", paramstr)
|
||||||
|
imgcfg["input"] = inname.replace("*", paramstr)
|
||||||
|
imgcfg["input"] = get_file_path(imgcfg["input"], datadir)
|
||||||
|
if imgcfg["input"] is None:
|
||||||
|
status_ok = False
|
||||||
|
print("{} is not found".format(inname))
|
||||||
|
continue
|
||||||
|
|
||||||
|
if status_ok:
|
||||||
|
imglist.append(paramstr)
|
||||||
|
|
||||||
|
if len(imglist) > 0:
|
||||||
|
for img in imglist:
|
||||||
|
imgcfg["input"] = inname.replace("*", paramstr)
|
||||||
|
imgcfg["output"] = outname.replace("*", paramstr)
|
||||||
|
if get_file_path(imgcfg["input"], datadir):
|
||||||
|
if VERBOSE:
|
||||||
|
print("\tCreating {} ...".format(imgcfg["output"]))
|
||||||
|
data_crypt_create_image(imgcfg, bindir)
|
||||||
|
else:
|
||||||
|
print("{} is not found".format(imgcfg["input"]))
|
||||||
|
else:
|
||||||
|
if VERBOSE:
|
||||||
|
print("\tCreating {} ...".format(outname))
|
||||||
|
data_crypt_create_image(imgcfg, bindir)
|
||||||
|
|
||||||
|
|
||||||
def firmware_component_preproc_concatenate(cfg, datadir, keydir, bindir):
|
def firmware_component_preproc_concatenate(cfg, datadir, keydir, bindir):
|
||||||
preproc_cfg = get_pre_process_cfg(cfg)
|
preproc_cfg = get_pre_process_cfg(cfg)
|
||||||
imgnames = preproc_cfg["concatenate"].keys()
|
imgnames = preproc_cfg["concatenate"].keys()
|
||||||
@ -2385,10 +2506,12 @@ def firmware_component_preproc(cfg, datadir, keydir, bindir):
|
|||||||
firmware_component_preproc_aicboot(cfg, datadir, keydir, bindir)
|
firmware_component_preproc_aicboot(cfg, datadir, keydir, bindir)
|
||||||
if "aicimage" in preproc_cfg:
|
if "aicimage" in preproc_cfg:
|
||||||
firmware_component_preproc_aicimage(cfg, datadir, keydir, bindir)
|
firmware_component_preproc_aicimage(cfg, datadir, keydir, bindir)
|
||||||
if "spienc" in preproc_cfg:
|
|
||||||
firmware_component_preproc_spienc(cfg, datadir, keydir, bindir)
|
|
||||||
if "concatenate" in preproc_cfg:
|
if "concatenate" in preproc_cfg:
|
||||||
firmware_component_preproc_concatenate(cfg, datadir, keydir, bindir)
|
firmware_component_preproc_concatenate(cfg, datadir, keydir, bindir)
|
||||||
|
if "spienc" in preproc_cfg:
|
||||||
|
firmware_component_preproc_spienc(cfg, datadir, keydir, bindir)
|
||||||
|
if "data_crypt" in preproc_cfg:
|
||||||
|
firmware_component_preproc_data_crypt(cfg, datadir, keydir, bindir)
|
||||||
|
|
||||||
|
|
||||||
def generate_bootcfg(bcfgfile, cfg):
|
def generate_bootcfg(bcfgfile, cfg):
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user