[U-Boot] [RFC PATCH] fpga: zynq: Add encrypted bitstream support with auto detect

stefan at herbrechtsmeier.net stefan at herbrechtsmeier.net
Fri Jun 8 11:58:41 UTC 2018


From: Stefan Herbrechtsmeier <stefan.herbrechtsmeier at weidmueller.com>

Signed-off-by: Stefan Herbrechtsmeier <stefan.herbrechtsmeier at weidmueller.com>

---

 drivers/fpga/zynqpl.c | 73 ++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 57 insertions(+), 16 deletions(-)

diff --git a/drivers/fpga/zynqpl.c b/drivers/fpga/zynqpl.c
index fd37d18..6622750 100644
--- a/drivers/fpga/zynqpl.c
+++ b/drivers/fpga/zynqpl.c
@@ -17,6 +17,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
@@ -38,18 +39,16 @@
 #define CONFIG_SYS_FPGA_PROG_TIME	(CONFIG_SYS_HZ * 4) /* 4 s */
 #endif
 
+#define NOP_WORD	0x20000000
+#define CTRL0_WORD	0x3000a001
+#define MASK_WORD	0x3000c001
 #define DUMMY_WORD	0xffffffff
 
+#define CTRL0_DEC_MASK	BIT(6)
+
 /* Xilinx binary format header */
+#define MAX_DUMMY_WORD_COUNT	8
 static const u32 bin_format[] = {
-	DUMMY_WORD, /* Dummy words */
-	DUMMY_WORD,
-	DUMMY_WORD,
-	DUMMY_WORD,
-	DUMMY_WORD,
-	DUMMY_WORD,
-	DUMMY_WORD,
-	DUMMY_WORD,
 	0x000000bb, /* Sync word */
 	0x11220044, /* Sync word */
 	DUMMY_WORD,
@@ -85,7 +84,23 @@ static u32 load_word(const void *buf, u32 swap)
 	return word;
 }
 
-static u32 check_header(const void *buf)
+static void *skip_dummy_words(const void *buf)
+{
+	u32 *test = (u32 *)buf;
+	u32 i;
+
+	for (i = 0; i < MAX_DUMMY_WORD_COUNT; i++) {
+		if (load_word(&test[i], SWAP_NO) != DUMMY_WORD) {
+			debug("%s: Found no dummy word at position %d/%x\n",
+			      __func__, i, (u32)&test[i]);
+			return &test[i];
+		}
+	}
+
+	return &test[i];
+}
+
+static u32 check_header(const void *buf, bool *encrypted)
 {
 	u32 i, pattern;
 	int swap = SWAP_NO;
@@ -93,6 +108,8 @@ static u32 check_header(const void *buf)
 
 	debug("%s: Let's check bitstream header\n", __func__);
 
+	test = (u32 *)skip_dummy_words(buf);
+
 	/* Checking that passing bin is not a bitstream */
 	for (i = 0; i < ARRAY_SIZE(bin_format); i++) {
 		pattern = load_word(&test[i], swap);
@@ -112,18 +129,34 @@ static u32 check_header(const void *buf)
 
 		debug("%s: %d/%x: pattern %x/%x bin_format\n", __func__, i,
 		      (u32)&test[i], pattern, bin_format[i]);
+
 		if (pattern != bin_format[i]) {
 			debug("%s: Bitstream is not recognized\n", __func__);
 			return 0;
 		}
 	}
-	debug("%s: Found bitstream header at %x %s swapinng\n", __func__,
-	      (u32)buf, swap == SWAP_NO ? "without" : "with");
+
+	test = &test[i];
+
+	/* Checking if passing bin is an encrypted bitstream */
+	if ((load_word(&test[0], swap) == NOP_WORD) &&
+	    (load_word(&test[1], swap) == MASK_WORD) &&
+	    (load_word(&test[2], swap) & CTRL0_DEC_MASK) &&
+	    (load_word(&test[3], swap) == CTRL0_WORD) &&
+	    (load_word(&test[4], swap) & CTRL0_DEC_MASK) &&
+	    (load_word(&test[5], swap) == NOP_WORD))
+		*encrypted = true;
+	else
+		*encrypted = false;
+
+	debug("%s: Found %sencrypted bitstream header at %x %s swapping\n",
+	      __func__, *encrypted ? "" : "un", (u32)buf,
+	      swap == SWAP_NO ? "without" : "with");
 
 	return swap;
 }
 
-static void *check_data(u8 *buf, size_t bsize, u32 *swap)
+static void *check_data(u8 *buf, size_t bsize, u32 *swap, bool *encrypted)
 {
 	u32 word, p = 0; /* possition */
 
@@ -136,7 +169,7 @@ static void *check_data(u8 *buf, size_t bsize, u32 *swap)
 		if (word == DUMMY_WORD) {
 			debug("%s: Found dummy word at position %x/%x\n",
 			      __func__, p, (u32)&buf[p]);
-			*swap = check_header(&buf[p]);
+			*swap = check_header(&buf[p], encrypted);
 			if (*swap) {
 				/* FIXME add full bitstream checking here */
 				return &buf[p];
@@ -191,7 +224,7 @@ static int zynq_dma_transfer(u32 srcbuf, u32 srclen, u32 dstbuf, u32 dstlen)
 	return FPGA_SUCCESS;
 }
 
-static int zynq_dma_xfer_init(bitstream_type bstype)
+static int zynq_dma_xfer_init(bitstream_type bstype, bool encrypted)
 {
 	u32 status, control, isr_status;
 	unsigned long ts;
@@ -291,6 +324,13 @@ static int zynq_dma_xfer_init(bitstream_type bstype)
 		writel(DEVCFG_STATUS_DMA_DONE_CNT_MASK, &devcfg_base->status);
 	}
 
+	control = readl(&devcfg_base->ctrl);
+	if (encrypted)
+		control |= DEVCFG_CTRL_PCAP_RATE_EN_MASK;
+	else
+		control &= ~DEVCFG_CTRL_PCAP_RATE_EN_MASK;
+	writel(control, &devcfg_base->ctrl);
+
 	return FPGA_SUCCESS;
 }
 
@@ -336,10 +376,11 @@ static int zynq_validate_bitstream(xilinx_desc *desc, const void *buf,
 				   size_t bsize, u32 blocksize, u32 *swap,
 				   bitstream_type *bstype)
 {
+	bool encrypted = false;
 	u32 *buf_start;
 	u32 diff;
 
-	buf_start = check_data((u8 *)buf, blocksize, swap);
+	buf_start = check_data((u8 *)buf, blocksize, swap, &encrypted);
 
 	if (!buf_start)
 		return FPGA_FAIL;
@@ -358,7 +399,7 @@ static int zynq_validate_bitstream(xilinx_desc *desc, const void *buf,
 		return FPGA_FAIL;
 	}
 
-	if (zynq_dma_xfer_init(*bstype))
+	if (zynq_dma_xfer_init(*bstype, encrypted))
 		return FPGA_FAIL;
 
 	return 0;
-- 
2.7.4



More information about the U-Boot mailing list