Input: cyapa - fix endianness issues in gen5 firmware update support
authorDmitry Torokhov <dmitry.torokhov@gmail.com>
Mon, 19 Jan 2015 23:59:31 +0000 (15:59 -0800)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Thu, 22 Jan 2015 15:57:36 +0000 (07:57 -0800)
gen5_bl_metadata_row_params structure has its fields specified with
explicit endianness, so we should not be trying to convert to native CPU
endianness when filling the structure.

Also fix firmware validation checks and misspelled field in
gen5_bl_metadata_row_params.

Reported-by: kbuild test robot <fengguang.wu@intel.com>
Reviewed-by: Dudley Du <dudl@cypress.com>
Tested-by: Dudley Du <dudl@cypress.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
drivers/input/mouse/cyapa_gen5.c

index ced2a2c..9a4a422 100644 (file)
@@ -319,7 +319,7 @@ struct gen5_bl_initiate_cmd_data {
 
 struct gen5_bl_metadata_row_params {
        __le16 size;
-       __le16 maximun_size;
+       __le16 maximum_size;
        __le32 app_start;
        __le16 app_len;
        __le16 app_crc;
@@ -1192,67 +1192,68 @@ static int cyapa_gen5_bl_enter(struct cyapa *cyapa)
 static int cyapa_gen5_check_fw(struct cyapa *cyapa, const struct firmware *fw)
 {
        struct device *dev = &cyapa->client->dev;
-       struct gen5_bl_metadata_row_params metadata;
-       struct cyapa_tsg_bin_image *image;
-       int flash_records_count;
-       u16 app_crc = 0;
-       u16 app_integrity_crc = 0;
-       u16 row_num;
-       u8 *data;
+       const struct cyapa_tsg_bin_image *image = (const void *)fw->data;
+       const struct cyapa_tsg_bin_image_data_record *app_integrity;
+       const struct gen5_bl_metadata_row_params *metadata;
+       size_t flash_records_count;
+       u32 fw_app_start, fw_upgrade_start;
+       u16 fw_app_len, fw_upgrade_len;
+       u16 app_crc;
+       u16 app_integrity_crc;
        int record_index;
        int i;
 
-       image = (struct cyapa_tsg_bin_image *)fw->data;
        flash_records_count = (fw->size -
                        sizeof(struct cyapa_tsg_bin_image_head)) /
                        sizeof(struct cyapa_tsg_bin_image_data_record);
 
-       /* APP_INTEGRITY row is always the last row block,
-        * and the row id must be 0x01ff */
-       row_num = get_unaligned_be16(
-                       &image->records[flash_records_count - 1].row_number);
-       if (image->records[flash_records_count - 1].flash_array_id != 0x00 &&
-                       row_num != 0x01ff) {
+       /*
+        * APP_INTEGRITY row is always the last row block,
+        * and the row id must be 0x01ff.
+        */
+       app_integrity = &image->records[flash_records_count - 1];
+
+       if (app_integrity->flash_array_id != 0x00 ||
+           get_unaligned_be16(&app_integrity->row_number) != 0x01ff) {
                dev_err(dev, "%s: invalid app_integrity data.\n", __func__);
                return -EINVAL;
        }
-       data = image->records[flash_records_count - 1].record_data;
-
-       metadata.app_start = get_unaligned_le32(&data[4]);
-       metadata.app_len = get_unaligned_le16(&data[8]);
-       metadata.app_crc = get_unaligned_le16(&data[10]);
-       metadata.upgrade_start = get_unaligned_le32(&data[16]);
-       metadata.upgrade_len  = get_unaligned_le16(&data[20]);
-       metadata.metadata_crc = get_unaligned_le16(&data[60]);
-
-       if ((metadata.app_start + metadata.app_len +
-               metadata.upgrade_start + metadata.upgrade_len) %
-                       CYAPA_TSG_FW_ROW_SIZE) {
-               dev_err(dev, "%s: invalid image alignment.\n", __func__);
-               return -EINVAL;
-       }
+
+       metadata = (const void *)app_integrity->record_data;
 
        /* Verify app_integrity crc */
-       app_integrity_crc = crc_itu_t(0xffff, data,
-                       CYAPA_TSG_APP_INTEGRITY_SIZE);
-       if (app_integrity_crc != metadata.metadata_crc) {
+       app_integrity_crc = crc_itu_t(0xffff, app_integrity->record_data,
+                                     CYAPA_TSG_APP_INTEGRITY_SIZE);
+       if (app_integrity_crc != get_unaligned_le16(&metadata->metadata_crc)) {
                dev_err(dev, "%s: invalid app_integrity crc.\n", __func__);
                return -EINVAL;
        }
 
+       fw_app_start = get_unaligned_le32(&metadata->app_start);
+       fw_app_len = get_unaligned_le16(&metadata->app_len);
+       fw_upgrade_start = get_unaligned_le32(&metadata->upgrade_start);
+       fw_upgrade_len = get_unaligned_le16(&metadata->upgrade_len);
+
+       if (fw_app_start % CYAPA_TSG_FW_ROW_SIZE ||
+           fw_app_len % CYAPA_TSG_FW_ROW_SIZE ||
+           fw_upgrade_start % CYAPA_TSG_FW_ROW_SIZE ||
+           fw_upgrade_len % CYAPA_TSG_FW_ROW_SIZE) {
+               dev_err(dev, "%s: invalid image alignment.\n", __func__);
+               return -EINVAL;
+       }
+
        /*
         * Verify application image CRC
         */
-       record_index = metadata.app_start / CYAPA_TSG_FW_ROW_SIZE -
+       record_index = fw_app_start / CYAPA_TSG_FW_ROW_SIZE -
                                CYAPA_TSG_IMG_START_ROW_NUM;
-       data = (u8 *)&image->records[record_index].record_data;
-       app_crc = crc_itu_t(0xffff, data, CYAPA_TSG_FW_ROW_SIZE);
-       for (i = 1; i < (metadata.app_len / CYAPA_TSG_FW_ROW_SIZE); i++) {
-               data = (u8 *)&image->records[++record_index].record_data;
+       app_crc = 0xffffU;
+       for (i = 0; i < fw_app_len / CYAPA_TSG_FW_ROW_SIZE; i++) {
+               const u8 *data = image->records[record_index + i].record_data;
                app_crc = crc_itu_t(app_crc, data, CYAPA_TSG_FW_ROW_SIZE);
        }
 
-       if (app_crc != metadata.app_crc) {
+       if (app_crc != get_unaligned_le16(&metadata->app_crc)) {
                dev_err(dev, "%s: invalid firmware app crc check.\n", __func__);
                return -EINVAL;
        }