From mboxrd@z Thu Jan 1 00:00:00 1970 From: stefan at herbrechtsmeier.net Date: Fri, 8 Jun 2018 13:58:41 +0200 Subject: [U-Boot] [RFC PATCH] fpga: zynq: Add encrypted bitstream support with auto detect Message-ID: <1528459121-23036-1-git-send-email-stefan@herbrechtsmeier.net> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de From: Stefan Herbrechtsmeier Signed-off-by: Stefan Herbrechtsmeier --- 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@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