diff options
Diffstat (limited to 'drivers/staging/gs_fpgaboot')
-rw-r--r-- | drivers/staging/gs_fpgaboot/gs_fpgaboot.c | 90 | ||||
-rw-r--r-- | drivers/staging/gs_fpgaboot/gs_fpgaboot.h | 2 | ||||
-rw-r--r-- | drivers/staging/gs_fpgaboot/io.c | 4 |
3 files changed, 59 insertions, 37 deletions
diff --git a/drivers/staging/gs_fpgaboot/gs_fpgaboot.c b/drivers/staging/gs_fpgaboot/gs_fpgaboot.c index 19b550fff04b..bcbdc7340b55 100644 --- a/drivers/staging/gs_fpgaboot/gs_fpgaboot.c +++ b/drivers/staging/gs_fpgaboot/gs_fpgaboot.c @@ -23,6 +23,7 @@ #include <linux/delay.h> #include <linux/io.h> #include <linux/firmware.h> +#include <asm/unaligned.h> #include "gs_fpgaboot.h" #include "io.h" @@ -41,16 +42,16 @@ static char *file = "xlinx_fpga_firmware.bit"; module_param(file, charp, 0444); MODULE_PARM_DESC(file, "Xilinx FPGA firmware file."); -static void read_bitstream(char *bitdata, char *buf, int *offset, int rdsize) +static void read_bitstream(u8 *bitdata, u8 *buf, int *offset, int rdsize) { memcpy(buf, bitdata + *offset, rdsize); *offset += rdsize; } -static void readinfo_bitstream(char *bitdata, char *buf, int *offset) +static int readinfo_bitstream(u8 *bitdata, u8 *buf, int size, int *offset) { - char tbuf[64]; - s32 len; + u8 tbuf[2]; + u16 len; /* read section char */ read_bitstream(bitdata, tbuf, offset, 1); @@ -58,18 +59,24 @@ static void readinfo_bitstream(char *bitdata, char *buf, int *offset) /* read length */ read_bitstream(bitdata, tbuf, offset, 2); - len = tbuf[0] << 8 | tbuf[1]; + len = get_unaligned_be16(tbuf); + if (len >= size) { + pr_err("error: readinfo buffer too small\n"); + return -EINVAL; + } read_bitstream(bitdata, buf, offset, len); buf[len] = '\0'; + + return 0; } /* * read bitdata length */ -static int readlength_bitstream(char *bitdata, int *lendata, int *offset) +static int readlength_bitstream(u8 *bitdata, int *lendata, int *offset) { - char tbuf[64]; + u8 tbuf[4]; /* read section char */ read_bitstream(bitdata, tbuf, offset, 1); @@ -77,14 +84,13 @@ static int readlength_bitstream(char *bitdata, int *lendata, int *offset) /* make sure it is section 'e' */ if (tbuf[0] != 'e') { pr_err("error: length section is not 'e', but %c\n", tbuf[0]); - return -1; + return -EINVAL; } /* read 4bytes length */ read_bitstream(bitdata, tbuf, offset, 4); - *lendata = tbuf[0] << 24 | tbuf[1] << 16 | - tbuf[2] << 8 | tbuf[3]; + *lendata = get_unaligned_be32(tbuf); return 0; } @@ -92,16 +98,16 @@ static int readlength_bitstream(char *bitdata, int *lendata, int *offset) /* * read first 13 bytes to check bitstream magic number */ -static int readmagic_bitstream(char *bitdata, int *offset) +static int readmagic_bitstream(u8 *bitdata, int *offset) { - char buf[13]; + u8 buf[13]; int r; read_bitstream(bitdata, buf, offset, 13); r = memcmp(buf, bits_magic, 13); if (r) { pr_err("error: corrupted header"); - return -1; + return -EINVAL; } pr_info("bitstream file magic number Ok\n"); @@ -113,7 +119,7 @@ static int readmagic_bitstream(char *bitdata, int *offset) /* * NOTE: supports only bitstream format */ -static enum fmt_image get_imageformat(struct fpgaimage *fimage) +static enum fmt_image get_imageformat(void) { return f_bit; } @@ -127,38 +133,58 @@ static void gs_print_header(struct fpgaimage *fimage) pr_info("lendata: %d\n", fimage->lendata); } -static void gs_read_bitstream(struct fpgaimage *fimage) +static int gs_read_bitstream(struct fpgaimage *fimage) { - char *bitdata; + u8 *bitdata; int offset; + int err; offset = 0; - bitdata = (char *)fimage->fw_entry->data; + bitdata = (u8 *)fimage->fw_entry->data; + + err = readmagic_bitstream(bitdata, &offset); + if (err) + return err; + + err = readinfo_bitstream(bitdata, fimage->filename, MAX_STR, &offset); + if (err) + return err; + err = readinfo_bitstream(bitdata, fimage->part, MAX_STR, &offset); + if (err) + return err; + err = readinfo_bitstream(bitdata, fimage->date, MAX_STR, &offset); + if (err) + return err; + err = readinfo_bitstream(bitdata, fimage->time, MAX_STR, &offset); + if (err) + return err; - readmagic_bitstream(bitdata, &offset); - readinfo_bitstream(bitdata, fimage->filename, &offset); - readinfo_bitstream(bitdata, fimage->part, &offset); - readinfo_bitstream(bitdata, fimage->date, &offset); - readinfo_bitstream(bitdata, fimage->time, &offset); - readlength_bitstream(bitdata, &fimage->lendata, &offset); + err = readlength_bitstream(bitdata, &fimage->lendata, &offset); + if (err) + return err; fimage->fpgadata = bitdata + offset; + + return 0; } static int gs_read_image(struct fpgaimage *fimage) { int img_fmt; + int err; - img_fmt = get_imageformat(fimage); + img_fmt = get_imageformat(); switch (img_fmt) { case f_bit: pr_info("image is bitstream format\n"); - gs_read_bitstream(fimage); + err = gs_read_bitstream(fimage); + if (err) + return err; break; default: pr_err("unsupported fpga image format\n"); - return -1; + return -EINVAL; } gs_print_header(fimage); @@ -183,11 +209,11 @@ static int gs_load_image(struct fpgaimage *fimage, char *fw_file) static int gs_download_image(struct fpgaimage *fimage, enum wbus bus_bytes) { - char *bitdata; + u8 *bitdata; int size, i, cnt; cnt = 0; - bitdata = (char *)fimage->fpgadata; + bitdata = (u8 *)fimage->fpgadata; size = fimage->lendata; #ifdef DEBUG_FPGA @@ -197,7 +223,7 @@ static int gs_download_image(struct fpgaimage *fimage, enum wbus bus_bytes) if (!xl_supported_prog_bus_width(bus_bytes)) { pr_err("unsupported program bus width %d\n", bus_bytes); - return -1; + return -EINVAL; } /* Bring csi_b, rdwr_b Low and program_b High */ @@ -224,7 +250,7 @@ static int gs_download_image(struct fpgaimage *fimage, enum wbus bus_bytes) /* Check INIT_B */ if (xl_get_init_b() == 0) { pr_err("init_b 0\n"); - return -1; + return -EIO; } while (xl_get_done_b() == 0) { @@ -236,7 +262,7 @@ static int gs_download_image(struct fpgaimage *fimage, enum wbus bus_bytes) if (cnt > MAX_WAIT_DONE) { pr_err("fpga download fail\n"); - return -1; + return -EIO; } pr_info("download fpgaimage\n"); @@ -325,7 +351,7 @@ err_out2: err_out1: kfree(fimage); - return -1; + return err; } static int __init gs_fpgaboot_init(void) diff --git a/drivers/staging/gs_fpgaboot/gs_fpgaboot.h b/drivers/staging/gs_fpgaboot/gs_fpgaboot.h index cd1eb2c4c940..986e841f6b5e 100644 --- a/drivers/staging/gs_fpgaboot/gs_fpgaboot.h +++ b/drivers/staging/gs_fpgaboot/gs_fpgaboot.h @@ -47,5 +47,5 @@ struct fpgaimage { char date[MAX_STR]; char time[MAX_STR]; int lendata; - char *fpgadata; + u8 *fpgadata; }; diff --git a/drivers/staging/gs_fpgaboot/io.c b/drivers/staging/gs_fpgaboot/io.c index c9391198fbfb..83a13ca7259a 100644 --- a/drivers/staging/gs_fpgaboot/io.c +++ b/drivers/staging/gs_fpgaboot/io.c @@ -9,10 +9,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <linux/kernel.h> |