aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/r8169.c36
1 files changed, 35 insertions, 1 deletions
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 8fc9af246944..7074989d5f75 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -1754,18 +1754,52 @@ static void rtl_writephy_batch(struct rtl8169_private *tp,
1754#define PHY_DELAY_MS 0xe0000000 1754#define PHY_DELAY_MS 0xe0000000
1755#define PHY_WRITE_ERI_WORD 0xf0000000 1755#define PHY_WRITE_ERI_WORD 0xf0000000
1756 1756
1757struct fw_info {
1758 u32 magic;
1759 char version[RTL_VER_SIZE];
1760 __le32 fw_start;
1761 __le32 fw_len;
1762 u8 chksum;
1763} __packed;
1764
1757#define FW_OPCODE_SIZE sizeof(typeof(*((struct rtl_fw_phy_action *)0)->code)) 1765#define FW_OPCODE_SIZE sizeof(typeof(*((struct rtl_fw_phy_action *)0)->code))
1758 1766
1759static bool rtl_fw_format_ok(struct rtl8169_private *tp, struct rtl_fw *rtl_fw) 1767static bool rtl_fw_format_ok(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
1760{ 1768{
1761 const struct firmware *fw = rtl_fw->fw; 1769 const struct firmware *fw = rtl_fw->fw;
1770 struct fw_info *fw_info = (struct fw_info *)fw->data;
1762 struct rtl_fw_phy_action *pa = &rtl_fw->phy_action; 1771 struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
1763 char *version = rtl_fw->version; 1772 char *version = rtl_fw->version;
1764 bool rc = false; 1773 bool rc = false;
1765 1774
1766 if (fw->size < FW_OPCODE_SIZE) 1775 if (fw->size < FW_OPCODE_SIZE)
1767 goto out; 1776 goto out;
1768 else { 1777
1778 if (!fw_info->magic) {
1779 size_t i, size, start;
1780 u8 checksum = 0;
1781
1782 if (fw->size < sizeof(*fw_info))
1783 goto out;
1784
1785 for (i = 0; i < fw->size; i++)
1786 checksum += fw->data[i];
1787 if (checksum != 0)
1788 goto out;
1789
1790 start = le32_to_cpu(fw_info->fw_start);
1791 if (start > fw->size)
1792 goto out;
1793
1794 size = le32_to_cpu(fw_info->fw_len);
1795 if (size > (fw->size - start) / FW_OPCODE_SIZE)
1796 goto out;
1797
1798 memcpy(version, fw_info->version, RTL_VER_SIZE);
1799
1800 pa->code = (__le32 *)(fw->data + start);
1801 pa->size = size;
1802 } else {
1769 if (fw->size % FW_OPCODE_SIZE) 1803 if (fw->size % FW_OPCODE_SIZE)
1770 goto out; 1804 goto out;
1771 1805