[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