From 2be7256fe7f428a5627c368d6f32f4004df63df9 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 19 Jan 2015 15:59:31 -0800 Subject: [PATCH] Input: cyapa - fix endianness issues in gen5 firmware update support 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 Reviewed-by: Dudley Du Tested-by: Dudley Du Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/cyapa_gen5.c | 79 ++++++++++++++++---------------- 1 file changed, 40 insertions(+), 39 deletions(-) diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c index ced2a2c641cc..9a4a422afc2a 100644 --- a/drivers/input/mouse/cyapa_gen5.c +++ b/drivers/input/mouse/cyapa_gen5.c @@ -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; } -- 2.20.1