| From 1e390eb9365008a5f3713e390ffe4484f078468c Mon Sep 17 00:00:00 2001 |
| From: Jason Gunthorpe <jgunthorpe@obsidianresearch.com> |
| Date: Wed, 1 Feb 2017 12:48:43 -0700 |
| Subject: [PATCH 042/103] fpga zynq: Check the bitstream for validity |
| |
| There is no sense in sending a bitstream we know will not work, and |
| with the variety of options for bitstream generation in Xilinx tools |
| it is not terribly clear what the correct input should be. |
| |
| This is particularly important for Zynq since auto-correction was |
| removed from the driver and the Zynq hardware only accepts a bitstream |
| format that is different from what the Xilinx tools typically produce. |
| |
| Worse, the hardware provides no indication why the bitstream fails, |
| it simply times out if the input is wrong. |
| |
| The best option here is to have the kernel print a message informing |
| the user they are using a malformed bistream and programming failure |
| isn't for any of the myriad of other reasons. |
| |
| Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com> |
| Acked-by: Moritz Fischer <moritz.fischer@ettus.com> |
| Acked-by: Alan Tull <atull@opensource.altera.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/fpga/zynq-fpga.c | 21 +++++++++++++++++++++ |
| 1 file changed, 21 insertions(+) |
| |
| --- a/drivers/fpga/zynq-fpga.c |
| +++ b/drivers/fpga/zynq-fpga.c |
| @@ -161,6 +161,19 @@ static irqreturn_t zynq_fpga_isr(int irq |
| return IRQ_HANDLED; |
| } |
| |
| +/* Sanity check the proposed bitstream. It must start with the sync word in |
| + * the correct byte order, and be dword aligned. The input is a Xilinx .bin |
| + * file with every 32 bit quantity swapped. |
| + */ |
| +static bool zynq_fpga_has_sync(const u8 *buf, size_t count) |
| +{ |
| + for (; count >= 4; buf += 4, count -= 4) |
| + if (buf[0] == 0x66 && buf[1] == 0x55 && buf[2] == 0x99 && |
| + buf[3] == 0xaa) |
| + return true; |
| + return false; |
| +} |
| + |
| static int zynq_fpga_ops_write_init(struct fpga_manager *mgr, |
| struct fpga_image_info *info, |
| const char *buf, size_t count) |
| @@ -177,6 +190,13 @@ static int zynq_fpga_ops_write_init(stru |
| |
| /* don't globally reset PL if we're doing partial reconfig */ |
| if (!(info->flags & FPGA_MGR_PARTIAL_RECONFIG)) { |
| + if (!zynq_fpga_has_sync(buf, count)) { |
| + dev_err(&mgr->dev, |
| + "Invalid bitstream, could not find a sync word. Bitstream must be a byte swapped .bin file\n"); |
| + err = -EINVAL; |
| + goto out_err; |
| + } |
| + |
| /* assert AXI interface resets */ |
| regmap_write(priv->slcr, SLCR_FPGA_RST_CTRL_OFFSET, |
| FPGA_RST_ALL_MASK); |
| @@ -410,6 +430,7 @@ static enum fpga_mgr_states zynq_fpga_op |
| } |
| |
| static const struct fpga_manager_ops zynq_fpga_ops = { |
| + .initial_header_size = 128, |
| .state = zynq_fpga_ops_state, |
| .write_init = zynq_fpga_ops_write_init, |
| .write = zynq_fpga_ops_write, |