struct gen5_bl_metadata_row_params {
__le16 size;
- __le16 maximun_size;
+ __le16 maximum_size;
__le32 app_start;
__le16 app_len;
__le16 app_crc;
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;
}