[U-Boot] [RFC PATCH 1/2] fpga: xilinx: zynq: Add support to decrypt images

Michal Simek michal.simek at xilinx.com
Wed Apr 4 10:56:47 UTC 2018


On 2.4.2018 08:15, Siva Durga Prasad Paladugu wrote:
> This patch adds support to decrypt an encrypted bitstream
> or image. This zynq aes command can either load decrypted
> image back to DDR or it can load an encrypted bitsream to
> PL directly by decrypting it. The image has to be encrypted
> using xilinx bootgen tool and to get only the encrypted
> image from tool use -split option while invoking bootgen.
> 
> Signed-off-by: Siva Durga Prasad Paladugu <sivadur at xilinx.com>
> ---
>  arch/arm/Kconfig          |   1 +
>  board/xilinx/zynq/Kconfig |  14 ++++
>  drivers/fpga/zynqpl.c     | 158 ++++++++++++++++++++++++++++++++++++++++++++++
>  include/zynqpl.h          |   5 ++
>  4 files changed, 178 insertions(+)
>  create mode 100644 board/xilinx/zynq/Kconfig
> 
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index 068ea1e..e0cd1d8 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -1360,6 +1360,7 @@ source "board/toradex/colibri_pxa270/Kconfig"
>  source "board/vscom/baltos/Kconfig"
>  source "board/woodburn/Kconfig"
>  source "board/work-microwave/work_92105/Kconfig"
> +source "board/xilinx/zynq/Kconfig"
>  source "board/xilinx/zynqmp/Kconfig"
>  source "board/zipitz2/Kconfig"
>  
> diff --git a/board/xilinx/zynq/Kconfig b/board/xilinx/zynq/Kconfig
> new file mode 100644
> index 0000000..f8f8a7f
> --- /dev/null
> +++ b/board/xilinx/zynq/Kconfig
> @@ -0,0 +1,14 @@
> +# Copyright (c) 2018, Xilinx, Inc.
> +#
> +# SPDX-License-Identifier: GPL-2.0
> +
> +if ARCH_ZYNQ
> +
> +config CMD_ZYNQ_AES
> +	bool "Zynq AES"
> +	default y
> +	help
> +	  Decrypts the encrypted image present in source address
> +	  and places the decrypted image at destination address.
> +
> +endif
> diff --git a/drivers/fpga/zynqpl.c b/drivers/fpga/zynqpl.c
> index db9bd12..fcffc2d 100644
> --- a/drivers/fpga/zynqpl.c
> +++ b/drivers/fpga/zynqpl.c
> @@ -18,6 +18,7 @@
>  
>  #define DEVCFG_CTRL_PCFG_PROG_B		0x40000000
>  #define DEVCFG_CTRL_PCFG_AES_EFUSE_MASK	0x00001000
> +#define DEVCFG_CTRL_PCAP_RATE_EN_MASK	0x02000000
>  #define DEVCFG_ISR_FATAL_ERROR_MASK	0x00740040
>  #define DEVCFG_ISR_ERROR_FLAGS_MASK	0x00340840
>  #define DEVCFG_ISR_RX_FIFO_OV		0x00040000
> @@ -498,3 +499,160 @@ struct xilinx_fpga_op zynq_op = {
>  	.loadfs = zynq_loadfs,
>  #endif
>  };
> +
> +#ifdef CONFIG_CMD_ZYNQ_AES
> +/*
> + * Load the encrypted image from src addr and decrypt the image and
> + * place it back the decrypted image into dstaddr.
> + */
> +int zynq_decrypt_load(u32 srcaddr, u32 srclen, u32 dstaddr, u32 dstlen,
> +		      u8 bstype)
> +{
> +	u32 isr_status, ts;
> +
> +	if ((srcaddr < SZ_1M) || (dstaddr < SZ_1M)) {
> +		printf("%s: src and dst addr should be > 1M\n",
> +		       __func__);
> +		return FPGA_FAIL;
> +	}
> +
> +	if (zynq_dma_xfer_init(bstype)) {
> +		printf("%s: zynq_dma_xfer_init FAIL\n", __func__);
> +		return FPGA_FAIL;
> +	}
> +
> +	writel((readl(&devcfg_base->ctrl) | DEVCFG_CTRL_PCAP_RATE_EN_MASK),
> +	       &devcfg_base->ctrl);
> +
> +	debug("%s: Source = 0x%08X\n", __func__, (u32)srcaddr);
> +	debug("%s: Size = %zu\n", __func__, srclen);
> +
> +	/* flush(clean & invalidate) d-cache range buf */
> +	flush_dcache_range((u32)srcaddr, (u32)srcaddr +
> +			roundup(srclen << 2, ARCH_DMA_MINALIGN));
> +	/*
> +	 * Flush destination address range only if image is not
> +	 * bitstream.
> +	 */
> +	if (bstype == BIT_NONE)
> +		flush_dcache_range((u32)dstaddr, (u32)dstaddr +
> +				roundup(dstlen << 2, ARCH_DMA_MINALIGN));
> +
> +	if (zynq_dma_transfer(srcaddr | 1, srclen, dstaddr | 1, dstlen))
> +		return FPGA_FAIL;
> +
> +	if (bstype == BIT_FULL) {
> +		isr_status = readl(&devcfg_base->int_sts);
> +		/* Check FPGA configuration completion */
> +		ts = get_timer(0);
> +		while (!(isr_status & DEVCFG_ISR_PCFG_DONE)) {
> +			if (get_timer(ts) > CONFIG_SYS_FPGA_WAIT) {
> +				printf("%s: Timeout wait for FPGA to config\n",
> +				       __func__);
> +				return FPGA_FAIL;
> +			}
> +			isr_status = readl(&devcfg_base->int_sts);
> +		}
> +
> +		printf("%s: FPGA config done\n", __func__);
> +
> +		if (bstype != BIT_PARTIAL)
> +			zynq_slcr_devcfg_enable();
> +	}
> +
> +	return FPGA_SUCCESS;
> +}
> +
> +static int do_zynq_decrypt_image(cmd_tbl_t *cmdtp, int flag, int argc,
> +				 char * const argv[])
> +{
> +	char *endp;
> +	u32 srcaddr;
> +	u32 srclen;
> +	u32 dstaddr;
> +	u32 dstlen;
> +	u8 imgtype = BIT_NONE;
> +	int status;
> +	u8 i = 1;
> +
> +	if (argc < 4 && argc > 5)
> +		goto usage;
> +
> +	if (argc == 4) {
> +		if (!strcmp("load", argv[i]))
> +			imgtype = BIT_FULL;
> +		else if (!strcmp("loadp", argv[i]))
> +			imgtype = BIT_PARTIAL;
> +		else
> +			goto usage;
> +		i++;
> +	}
> +
> +	srcaddr = simple_strtoul(argv[i], &endp, 16);
> +	if (*argv[i++] == 0 || *endp != 0)
> +		goto usage;
> +	srclen = simple_strtoul(argv[i], &endp, 16);
> +	if (*argv[i++] == 0 || *endp != 0)
> +		goto usage;
> +	if (argc == 4) {
> +		dstaddr = 0xFFFFFFFF;
> +		dstlen = srclen;
> +	} else {
> +		dstaddr = simple_strtoul(argv[i], &endp, 16);
> +		if (*argv[i++] == 0 || *endp != 0)
> +			goto usage;
> +		dstlen = simple_strtoul(argv[i], &endp, 16);
> +		if (*argv[i++] == 0 || *endp != 0)
> +			goto usage;
> +	}
> +
> +	/*
> +	 * If the image is not bitstream but destination address is
> +	 * 0xFFFFFFFF
> +	 */
> +	if (imgtype == BIT_NONE && dstaddr == 0xFFFFFFFF) {
> +		printf("ERR:use zynqaes load/loadp encrypted bitstream\n");
> +		goto usage;
> +	}
> +
> +	/*
> +	 * Roundup source and destination lengths to
> +	 * word size
> +	 */
> +	if (srclen % 4)
> +		srclen = roundup(srclen, 4);
> +	if (dstlen % 4)
> +		dstlen = roundup(dstlen, 4);
> +
> +	status = zynq_decrypt_load(srcaddr, srclen >> 2, dstaddr, dstlen >> 2,
> +				   imgtype);
> +	if (status != 0)
> +		return -1;
> +
> +	return 0;
> +
> +usage:
> +	return CMD_RET_USAGE;
> +}
> +
> +#ifdef CONFIG_SYS_LONGHELP
> +static char zynqaes_help_text[] =
> +"zynqaes [operation type] <srcaddr> <srclen> <dstaddr> <dstlen>  -\n"
> +"Decrypts the encrypted image present in source address\n"
> +"and places the decrypted image at destination address\n"
> +"zynqaes operations:\n"
> +"   zynqaes <srcaddr> <srclen> <dstaddr> <dstlen>\n"
> +"   zynqaes load <srcaddr> <srclen>\n"
> +"   zynqaes loadp <srcaddr> <srclen>\n"
> +"if operation type is load or loadp, it loads the encrypted\n"
> +"full or partial bitstream on to PL respectively. If no valid\n"
> +"operation type specified then it loads decrypted image back\n"
> +"to memory and it doesn't support loading PL bistsream\n";
> +#endif
> +
> +U_BOOT_CMD(
> +		zynqaes,        5,      0,      do_zynq_decrypt_image,
> +		"Zynq AES decryption ", zynqaes_help_text
> +	  );
> +
> +#endif

Please move this to board/xilinx/zynq/cmds.c introduced in 2/2.

It should follow the same style as we started to use in zynqmp.

It means zynq rsa ...
and zynq aes ...
etc.


> diff --git a/include/zynqpl.h b/include/zynqpl.h
> index 5a34a17..0dd4cf9 100644
> --- a/include/zynqpl.h
> +++ b/include/zynqpl.h
> @@ -12,6 +12,11 @@
>  
>  #include <xilinx.h>
>  
> +#ifdef CONFIG_CMD_ZYNQ_AES
> +int zynq_decrypt_load(u32 srcaddr, u32 dstaddr, u32 srclen, u32 dstlen,
> +			     u8 bstype);


Align this one to match checkpatch strict.

M



> +#endif
> +
>  #if defined(CONFIG_FPGA_ZYNQPL)
>  extern struct xilinx_fpga_op zynq_op;
>  # define FPGA_ZYNQPL_OPS	&zynq_op
> 



More information about the U-Boot mailing list