Commit 2be7256f authored by Dmitry Torokhov's avatar Dmitry Torokhov

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: default avatarkbuild test robot <fengguang.wu@intel.com>
Reviewed-by: default avatarDudley Du <dudl@cypress.com>
Tested-by: default avatarDudley Du <dudl@cypress.com>
Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
parent 7b2171d7
...@@ -319,7 +319,7 @@ struct gen5_bl_initiate_cmd_data { ...@@ -319,7 +319,7 @@ struct gen5_bl_initiate_cmd_data {
struct gen5_bl_metadata_row_params { struct gen5_bl_metadata_row_params {
__le16 size; __le16 size;
__le16 maximun_size; __le16 maximum_size;
__le32 app_start; __le32 app_start;
__le16 app_len; __le16 app_len;
__le16 app_crc; __le16 app_crc;
...@@ -1192,67 +1192,68 @@ static int cyapa_gen5_bl_enter(struct cyapa *cyapa) ...@@ -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) static int cyapa_gen5_check_fw(struct cyapa *cyapa, const struct firmware *fw)
{ {
struct device *dev = &cyapa->client->dev; struct device *dev = &cyapa->client->dev;
struct gen5_bl_metadata_row_params metadata; const struct cyapa_tsg_bin_image *image = (const void *)fw->data;
struct cyapa_tsg_bin_image *image; const struct cyapa_tsg_bin_image_data_record *app_integrity;
int flash_records_count; const struct gen5_bl_metadata_row_params *metadata;
u16 app_crc = 0; size_t flash_records_count;
u16 app_integrity_crc = 0; u32 fw_app_start, fw_upgrade_start;
u16 row_num; u16 fw_app_len, fw_upgrade_len;
u8 *data; u16 app_crc;
u16 app_integrity_crc;
int record_index; int record_index;
int i; int i;
image = (struct cyapa_tsg_bin_image *)fw->data;
flash_records_count = (fw->size - flash_records_count = (fw->size -
sizeof(struct cyapa_tsg_bin_image_head)) / sizeof(struct cyapa_tsg_bin_image_head)) /
sizeof(struct cyapa_tsg_bin_image_data_record); sizeof(struct cyapa_tsg_bin_image_data_record);
/* APP_INTEGRITY row is always the last row block, /*
* and the row id must be 0x01ff */ * APP_INTEGRITY row is always the last row block,
row_num = get_unaligned_be16( * and the row id must be 0x01ff.
&image->records[flash_records_count - 1].row_number); */
if (image->records[flash_records_count - 1].flash_array_id != 0x00 && app_integrity = &image->records[flash_records_count - 1];
row_num != 0x01ff) {
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__); dev_err(dev, "%s: invalid app_integrity data.\n", __func__);
return -EINVAL; return -EINVAL;
} }
data = image->records[flash_records_count - 1].record_data;
metadata = (const void *)app_integrity->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;
}
/* Verify app_integrity crc */ /* Verify app_integrity crc */
app_integrity_crc = crc_itu_t(0xffff, data, app_integrity_crc = crc_itu_t(0xffff, app_integrity->record_data,
CYAPA_TSG_APP_INTEGRITY_SIZE); CYAPA_TSG_APP_INTEGRITY_SIZE);
if (app_integrity_crc != metadata.metadata_crc) { if (app_integrity_crc != get_unaligned_le16(&metadata->metadata_crc)) {
dev_err(dev, "%s: invalid app_integrity crc.\n", __func__); dev_err(dev, "%s: invalid app_integrity crc.\n", __func__);
return -EINVAL; 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 * 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; CYAPA_TSG_IMG_START_ROW_NUM;
data = (u8 *)&image->records[record_index].record_data; app_crc = 0xffffU;
app_crc = crc_itu_t(0xffff, data, CYAPA_TSG_FW_ROW_SIZE); for (i = 0; i < fw_app_len / CYAPA_TSG_FW_ROW_SIZE; i++) {
for (i = 1; i < (metadata.app_len / CYAPA_TSG_FW_ROW_SIZE); i++) { const u8 *data = image->records[record_index + i].record_data;
data = (u8 *)&image->records[++record_index].record_data;
app_crc = crc_itu_t(app_crc, data, CYAPA_TSG_FW_ROW_SIZE); 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__); dev_err(dev, "%s: invalid firmware app crc check.\n", __func__);
return -EINVAL; return -EINVAL;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment