Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Input: iqs5xx - simplify parsing of firmware blob

Do not define or use iqs5xx_ihex_rec structure: the original code was
using just a couple of fields in it and instead used it to calculate
offset to record data. The data field was actually reserving space for
checksum.

Instead iterate through fields and advance pointer explicitly.

Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

+22 -23
+22 -23
drivers/input/touchscreen/iqs5xx.c
··· 73 73 #define IQS5XX_CSTM_LEN (IQS5XX_PMAP_END + 1 - IQS5XX_CSTM) 74 74 #define IQS5XX_PMAP_LEN (IQS5XX_PMAP_END + 1 - IQS5XX_CHKSM) 75 75 76 - #define IQS5XX_REC_HDR_LEN 4 77 - #define IQS5XX_REC_LEN_MAX 255 76 + /* Length of firmware header in hexadecimal characters */ 77 + #define IQS5XX_REC_HDR_LEN_HEX (1 /* start */ + 2 /* size */ + \ 78 + 4 /* addr */ + 2 /* type */) 79 + #define IQS5XX_REC_HDR_SIZE 4 /* size + addr (2 bytes) + type, in bytes*/ 80 + #define IQS5XX_REC_DATA_SIZE 255 /* maximum size of the data portion */ 78 81 #define IQS5XX_REC_TYPE_DATA 0x00 79 82 #define IQS5XX_REC_TYPE_EOF 0x01 80 83 ··· 99 96 u8 major_ver; 100 97 u8 minor_ver; 101 98 u8 bl_status; 102 - } __packed; 103 - 104 - struct iqs5xx_ihex_rec { 105 - char start; 106 - char len[2]; 107 - char addr[4]; 108 - char type[2]; 109 - char data[2]; 110 99 } __packed; 111 100 112 101 struct iqs5xx_touch_data { ··· 692 697 static int iqs5xx_fw_file_parse(struct i2c_client *client, 693 698 const char *fw_file, u8 *pmap) 694 699 { 695 - struct iqs5xx_ihex_rec *rec; 696 700 size_t pos = 0; 697 701 int error, i; 698 702 u16 rec_num = 1; 699 703 u16 rec_addr; 700 704 u8 rec_len, rec_type, rec_chksm, chksm; 701 - u8 rec_hdr[IQS5XX_REC_HDR_LEN]; 702 - u8 rec_data[IQS5XX_REC_LEN_MAX]; 705 + u8 rec_hdr[IQS5XX_REC_HDR_SIZE]; 706 + u8 rec_data[IQS5XX_REC_DATA_SIZE]; 703 707 704 708 /* 705 709 * Firmware exported from the vendor's configuration tool deviates from ··· 718 724 } 719 725 720 726 do { 721 - if (pos + sizeof(*rec) > fw->size) { 727 + if (pos + IQS5XX_REC_HDR_LEN_HEX > fw->size) { 722 728 dev_err(&client->dev, "Insufficient firmware size\n"); 723 729 return -EINVAL; 724 730 } 725 - rec = (struct iqs5xx_ihex_rec *)(fw->data + pos); 726 - pos += sizeof(*rec); 727 731 728 - if (rec->start != ':') { 732 + if (fw->data[pos] != ':') { 729 733 dev_err(&client->dev, "Invalid start at record %u\n", 730 734 rec_num); 731 735 return -EINVAL; 732 736 } 733 737 734 - error = hex2bin(rec_hdr, rec->len, sizeof(rec_hdr)); 738 + /* Convert all 3 fields (length, address, and type) in one go */ 739 + error = hex2bin(rec_hdr, &fw->data[pos + 1], sizeof(rec_hdr)); 735 740 if (error) { 736 741 dev_err(&client->dev, "Invalid header at record %u\n", 737 742 rec_num); 738 743 return error; 739 744 } 745 + pos += IQS5XX_REC_HDR_LEN_HEX; 740 746 741 747 rec_len = *rec_hdr; 742 748 rec_addr = get_unaligned_be16(rec_hdr + sizeof(rec_len)); 743 749 rec_type = *(rec_hdr + sizeof(rec_len) + sizeof(rec_addr)); 744 750 745 - if (pos + rec_len * 2 > fw->size) { 751 + /* 752 + * Check if we have enough data for the data portion of the 753 + * record, as well as the checksum byte. Everything is doubled 754 + * because data is in ASCII HEX and not binary format. 755 + */ 756 + if (pos + (rec_len + sizeof(rec_chksm)) * 2 > fw->size) { 746 757 dev_err(&client->dev, "Insufficient firmware size\n"); 747 758 return -EINVAL; 748 759 } 749 - pos += (rec_len * 2); 750 760 751 - error = hex2bin(rec_data, rec->data, rec_len); 761 + error = hex2bin(rec_data, &fw->data[pos], rec_len); 752 762 if (error) { 753 763 dev_err(&client->dev, "Invalid data at record %u\n", 754 764 rec_num); 755 765 return error; 756 766 } 767 + pos += rec_len * 2; 757 768 758 - error = hex2bin(&rec_chksm, 759 - rec->data + rec_len * 2, sizeof(rec_chksm)); 769 + error = hex2bin(&rec_chksm, &fw->data[pos], sizeof(rec_chksm)); 760 770 if (error) { 761 771 dev_err(&client->dev, "Invalid checksum at record %u\n", 762 772 rec_num); 763 773 return error; 764 774 } 775 + pos += 2; 765 776 766 777 chksm = 0; 767 778 for (i = 0; i < sizeof(rec_hdr); i++)