add spienc feature

This commit is contained in:
刘可亮 2025-08-22 16:30:15 +08:00
parent b3676b7ab2
commit 5975e8c040
20 changed files with 809 additions and 51 deletions

View File

@ -87,6 +87,10 @@ static int do_upgrade_detect(struct cmd_tbl *cmdtp, int flag, int argc,
{
int ret = 0;
#if CONFIG_ARTINCHIP_SID_BURN_SPIENC_KEY_CMD
run_command("efuse_spienc", 0);
#endif
env_set("upg_type", "");
if (check_usb_upg()) {
aic_upg_flag_clear();

View File

@ -3,6 +3,7 @@
obj-y += d211.o
obj-y += env_location.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_UPDATE_UDISK_FATFS_ARTINCHIP) += usb_host_check.o
obj-$(CONFIG_$(SPL_TPL_)ENV_IS_IN_MMC) += mmc_env.o

View File

@ -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

View File

@ -227,6 +227,37 @@ static int do_mtd_list(struct cmd_tbl *cmdtp, int flag, int argc,
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,
struct mtd_oob_ops *io_op,
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[] =
"- generic operations on memory technology devices\n\n"
"mtd list\n"
#ifdef CONFIG_ARTINCHIP_SPIENC
"mtd bypass <status>\n"
#endif
"mtd read[.raw][.oob] <name> <addr> [<off> [<size>]]\n"
"mtd dump[.raw][.oob] <name> [<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"
"\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<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"
@ -610,6 +647,10 @@ static char mtd_help_text[] =
U_BOOT_CMD_WITH_SUBCMDS(mtd, "MTD utils", mtd_help_text,
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,
mtd_name_complete),
U_BOOT_SUBCMD_MKENT_COMPLETE(write, 5, 0, do_mtd_io,

View File

@ -27,10 +27,16 @@ config AICUPG_FORCE_USBUPG_SUPPORT
bool "Force USB upgrading check during boot"
default n
config AICUPG_FIRMWARE_SECURITY
bool "Secure transfer firmware and burn"
default n
depends on ARTINCHIP_SPIENC
config AICUPG_LOG_BUFFER_SUPPORT
bool "Support to get log buffer from device"
default y
endif
if AICUPG_LOG_BUFFER_SUPPORT
config AICUPG_LOG_BUFFER_ADDR
hex "Log buffer start address"

View File

@ -10,7 +10,19 @@ obj-$(CONFIG_AICUPG_NAND_ARTINCHIP) += nand_fwc.o
obj-$(CONFIG_AICUPG_NOR_ARTINCHIP) += nor_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
obj-$(CONFIG_AICUPG_NAND_ARTINCHIP) += nand_fwc_spl.o
endif

View File

@ -15,6 +15,7 @@
#include "nand_fwc_priv.h"
#include "upg_internal.h"
#include "nand_fwc_spl.h"
#include <artinchip/firmware_security.h>
#ifdef CONFIG_NAND_BBT_MANAGE
#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));
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
* 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;
}
fwc->block_size = mtd->writesize;
if (strstr(fwc->meta.name, "target.spl")) {
ret = nand_fwc_spl_prepare(fwc);
if (ret) {
@ -1059,11 +1065,25 @@ static s32 nand_fwc_mtd_writer(struct fwc_info *fwc, u8 *buf, s32 len)
if (!priv)
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);
if (!rdbuf) {
pr_err("Error: malloc buffer failed.\n");
return 0;
}
#endif
for (i = 0; i < MAX_DUPLICATED_PART; i++) {
mtd = priv->mtds[i];
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);
return 0;
}
#ifdef CONFIG_AICUPG_SINGLE_TRANS_BURN_CRC32_VERIFY
// Read data to calc crc
ret = mtd_read(mtd, offs, mtd->writesize, &retlen,
buf_to_read);
if (ret) {
pr_err("Write mtd %s error.\n", mtd->name);
pr_err("Read mtd %s error.\n", mtd->name);
return 0;
}
buf_to_read += retlen;
#endif
/* Update for next write */
buf_to_write += retlen;
buf_to_read += retlen;
priv->offs[i] = offs + retlen;
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
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("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
debug("%s, data len %d, trans len %d, calc len %d\n", __func__, len,
fwc->trans_size, calc_len);
free(rdbuf);
if (rdbuf)
free(rdbuf);
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 ubi_volume *vol;
s32 ret, i;
s32 calc_len, ret, i;
priv = (struct aicupg_nand_priv *)fwc->priv;
if (!priv)
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++) {
if (!priv->vols[i])
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;
}

View File

@ -17,6 +17,7 @@
#include "nand_fwc_spl.h"
#include "spi_enc_spl.h"
#include <u-boot/crc.h>
#include <artinchip/firmware_security.h>
struct aicupg_nand_spl {
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;
size_t retlen;
loff_t offs;
s32 ret = -1, i, calc_len;
u32 trans_crc;
u32 partition_crc;
s32 ret = -1, i;
u32 trans_size;
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);
page_data = malloc(PAGE_MAX_SIZE);
rd_page_data = malloc(PAGE_MAX_SIZE);
if (!page_data || !rd_page_data || !pt) {
ret = -1;
if (!page_data) {
pr_err("malloc page_data failed.\n");
ret = -ENOMEM;
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);
if (ret) {
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 */
trans_crc = 0;
partition_crc = 0;
trans_size = 0;
p = spl->image_buf;
end = p + spl->buf_size;
@ -512,6 +523,7 @@ static s32 nand_fwc_spl_program(struct fwc_info *fwc,
ret = -1;
goto out;
}
#ifdef CONFIG_AICUPG_SINGLE_TRANS_BURN_CRC32_VERIFY
// Read data to calc crc
ret = mtd_read(spl->mtd, offs, slice_size, &retlen,
rd_page_data);
@ -521,19 +533,9 @@ static s32 nand_fwc_spl_program(struct fwc_info *fwc,
goto out;
}
if ((trans_size + data_size) > fwc->meta.size)
calc_len = fwc->meta.size % 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);
if (crc32(0, page_data, slice_size) != crc32(0, rd_page_data, slice_size)) {
pr_err("calc_len:%d\n", slice_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;
goto out;
}
@ -541,8 +543,6 @@ static s32 nand_fwc_spl_program(struct fwc_info *fwc,
trans_size += data_size;
}
fwc->calc_partition_crc = partition_crc;
fwc->calc_trans_crc = trans_crc;
out:
if (page_data)
free(page_data);

View File

@ -13,6 +13,7 @@
#include <dm/device-internal.h>
#include <mtd.h>
#include <artinchip/aic_spienc.h>
#include <artinchip/firmware_security.h>
#include "spi_enc_spl.h"
@ -208,6 +209,9 @@ void nor_fwc_start(struct fwc_info *fwc)
#endif
fwc->block_size = mtd->writesize;
debug("%s, FWC name %s\n", __func__, fwc->meta.name);
#ifdef CONFIG_AICUPG_FIRMWARE_SECURITY
firmware_security_init();
#endif
return;
err:
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)
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++) {
mtd = priv->mtds[i];
if (!mtd)
@ -299,19 +314,10 @@ s32 nor_fwc_data_write(struct fwc_info *fwc, u8 *buf, s32 len)
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
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("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
fwc->trans_size += len;

View File

@ -61,6 +61,25 @@ config ARTINCHIP_SID
help
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
bool "Syscfg driver for ArtInChip SoC"
depends on MISC

View 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.

Binary file not shown.

View File

@ -0,0 +1,3 @@
rotpk*
*.h
*.pem

View 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

View File

@ -0,0 +1 @@
00000000000000000000000000000000

View File

@ -0,0 +1 @@
0000000000000000

Binary file not shown.

Binary file not shown.

View File

@ -12,6 +12,7 @@ import math
import zlib
import json
import struct
import shutil
import argparse
import platform
import subprocess
@ -1105,6 +1106,10 @@ def aic_boot_create_image_v2(cfg, keydir, datadir):
else:
signature_bytes = aic_boot_gen_signature_bytes(cfg, bootimg)
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
# 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)
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):
with open(outname, "wb") as fout:
for fn in flist:
@ -1775,6 +1832,7 @@ def img_write_fwc_file_to_binfile(binfile, cfg, datadir):
start_block = 0
last_block = 0
used_block = 0
total_block = 0
if VERBOSE:
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
else:
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":
block_size = 64
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)
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):
preproc_cfg = get_pre_process_cfg(cfg)
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)
if "aicimage" in preproc_cfg:
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:
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):