summaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/serial/io_ti.c40
1 files changed, 36 insertions, 4 deletions
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index b562665e9fb1..422423671ee4 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -928,6 +928,41 @@ static int ti_cpu_rev(struct edge_ti_manuf_descriptor *desc)
return TI_GET_CPU_REVISION(desc->CpuRev_BoardRev);
}
+static int check_fw_sanity(struct edgeport_serial *serial,
+ const struct firmware *fw)
+{
+ u16 length_total;
+ u8 checksum = 0;
+ int pos;
+ struct device *dev = &serial->serial->interface->dev;
+ struct edgeport_fw_hdr *fw_hdr = (struct edgeport_fw_hdr *)fw->data;
+
+ if (fw->size < sizeof(struct edgeport_fw_hdr)) {
+ dev_err(dev, "incomplete fw header\n");
+ return -EINVAL;
+ }
+
+ length_total = le16_to_cpu(fw_hdr->length) +
+ sizeof(struct edgeport_fw_hdr);
+
+ if (fw->size != length_total) {
+ dev_err(dev, "bad fw size (expected: %u, got: %zu)\n",
+ length_total, fw->size);
+ return -EINVAL;
+ }
+
+ for (pos = sizeof(struct edgeport_fw_hdr); pos < fw->size; ++pos)
+ checksum += fw->data[pos];
+
+ if (checksum != fw_hdr->checksum) {
+ dev_err(dev, "bad fw checksum (expected: 0x%x, got: 0x%x)\n",
+ fw_hdr->checksum, checksum);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
/**
* DownloadTIFirmware - Download run-time operating firmware to the TI5052
*
@@ -946,11 +981,8 @@ static int download_fw(struct edgeport_serial *serial,
int download_new_ver;
struct edgeport_fw_hdr *fw_hdr = (struct edgeport_fw_hdr *)fw->data;
- if (fw->size < sizeof(struct edgeport_fw_hdr)) {
- dev_err(&serial->serial->interface->dev,
- "Incomplete firmware header.\n");
+ if (check_fw_sanity(serial, fw))
return -EINVAL;
- }
/* If on-board version is newer, "fw_version" will be updated below. */
serial->fw_version = (fw_hdr->major_version << 8) +