diff options
author | Francois Romieu <romieu@fr.zoreil.com> | 2011-06-17 11:16:24 -0400 |
---|---|---|
committer | Francois Romieu <romieu@fr.zoreil.com> | 2011-06-18 05:34:32 -0400 |
commit | 1c361efb226d609a07403057a71557faf500b17a (patch) | |
tree | ff97f697d1634e160d76cf225ae52dceff55bcdb /drivers/net/r8169.c | |
parent | b6ffd97f5bcfd12df88ece6bc6df7a761ac5a049 (diff) |
r8169: explicit firmware format check.
Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
Diffstat (limited to 'drivers/net/r8169.c')
-rw-r--r-- | drivers/net/r8169.c | 62 |
1 files changed, 49 insertions, 13 deletions
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 3eeefe4b49e0..8fc9af246944 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c | |||
@@ -669,6 +669,15 @@ struct rtl8169_private { | |||
669 | 669 | ||
670 | struct rtl_fw { | 670 | struct rtl_fw { |
671 | const struct firmware *fw; | 671 | const struct firmware *fw; |
672 | |||
673 | #define RTL_VER_SIZE 32 | ||
674 | |||
675 | char version[RTL_VER_SIZE]; | ||
676 | |||
677 | struct rtl_fw_phy_action { | ||
678 | __le32 *code; | ||
679 | size_t size; | ||
680 | } phy_action; | ||
672 | } *rtl_fw; | 681 | } *rtl_fw; |
673 | #define RTL_FIRMWARE_UNKNOWN ERR_PTR(-EAGAIN); | 682 | #define RTL_FIRMWARE_UNKNOWN ERR_PTR(-EAGAIN); |
674 | }; | 683 | }; |
@@ -1229,8 +1238,9 @@ static void rtl8169_get_drvinfo(struct net_device *dev, | |||
1229 | strcpy(info->driver, MODULENAME); | 1238 | strcpy(info->driver, MODULENAME); |
1230 | strcpy(info->version, RTL8169_VERSION); | 1239 | strcpy(info->version, RTL8169_VERSION); |
1231 | strcpy(info->bus_info, pci_name(tp->pci_dev)); | 1240 | strcpy(info->bus_info, pci_name(tp->pci_dev)); |
1232 | strncpy(info->fw_version, IS_ERR_OR_NULL(rtl_fw) ? "N/A" : | 1241 | BUILD_BUG_ON(sizeof(info->fw_version) < sizeof(rtl_fw->version)); |
1233 | rtl_lookup_firmware_name(tp), sizeof(info->fw_version) - 1); | 1242 | strcpy(info->fw_version, IS_ERR_OR_NULL(rtl_fw) ? "N/A" : |
1243 | rtl_fw->version); | ||
1234 | } | 1244 | } |
1235 | 1245 | ||
1236 | static int rtl8169_get_regs_len(struct net_device *dev) | 1246 | static int rtl8169_get_regs_len(struct net_device *dev) |
@@ -1744,21 +1754,47 @@ static void rtl_writephy_batch(struct rtl8169_private *tp, | |||
1744 | #define PHY_DELAY_MS 0xe0000000 | 1754 | #define PHY_DELAY_MS 0xe0000000 |
1745 | #define PHY_WRITE_ERI_WORD 0xf0000000 | 1755 | #define PHY_WRITE_ERI_WORD 0xf0000000 |
1746 | 1756 | ||
1747 | static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw) | 1757 | #define FW_OPCODE_SIZE sizeof(typeof(*((struct rtl_fw_phy_action *)0)->code)) |
1758 | |||
1759 | static bool rtl_fw_format_ok(struct rtl8169_private *tp, struct rtl_fw *rtl_fw) | ||
1748 | { | 1760 | { |
1749 | const struct firmware *fw = rtl_fw->fw; | 1761 | const struct firmware *fw = rtl_fw->fw; |
1750 | __le32 *phytable = (__le32 *)fw->data; | 1762 | struct rtl_fw_phy_action *pa = &rtl_fw->phy_action; |
1763 | char *version = rtl_fw->version; | ||
1764 | bool rc = false; | ||
1765 | |||
1766 | if (fw->size < FW_OPCODE_SIZE) | ||
1767 | goto out; | ||
1768 | else { | ||
1769 | if (fw->size % FW_OPCODE_SIZE) | ||
1770 | goto out; | ||
1771 | |||
1772 | strlcpy(version, rtl_lookup_firmware_name(tp), RTL_VER_SIZE); | ||
1773 | |||
1774 | pa->code = (__le32 *)fw->data; | ||
1775 | pa->size = fw->size / FW_OPCODE_SIZE; | ||
1776 | } | ||
1777 | version[RTL_VER_SIZE - 1] = 0; | ||
1778 | |||
1779 | rc = true; | ||
1780 | out: | ||
1781 | return rc; | ||
1782 | } | ||
1783 | |||
1784 | static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw) | ||
1785 | { | ||
1786 | struct rtl_fw_phy_action *pa = &rtl_fw->phy_action; | ||
1751 | struct net_device *dev = tp->dev; | 1787 | struct net_device *dev = tp->dev; |
1752 | size_t index, fw_size = fw->size / sizeof(*phytable); | ||
1753 | u32 predata, count; | 1788 | u32 predata, count; |
1789 | size_t index; | ||
1754 | 1790 | ||
1755 | if (fw->size % sizeof(*phytable)) { | 1791 | if (!rtl_fw_format_ok(tp, rtl_fw)) { |
1756 | netif_err(tp, probe, dev, "odd sized firmware %zd\n", fw->size); | 1792 | netif_err(tp, probe, dev, "invalid firwmare\n"); |
1757 | return; | 1793 | return; |
1758 | } | 1794 | } |
1759 | 1795 | ||
1760 | for (index = 0; index < fw_size; index++) { | 1796 | for (index = 0; index < pa->size; index++) { |
1761 | u32 action = le32_to_cpu(phytable[index]); | 1797 | u32 action = le32_to_cpu(pa->code[index]); |
1762 | u32 regno = (action & 0x0fff0000) >> 16; | 1798 | u32 regno = (action & 0x0fff0000) >> 16; |
1763 | 1799 | ||
1764 | switch(action & 0xf0000000) { | 1800 | switch(action & 0xf0000000) { |
@@ -1780,7 +1816,7 @@ static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw) | |||
1780 | } | 1816 | } |
1781 | break; | 1817 | break; |
1782 | case PHY_READCOUNT_EQ_SKIP: | 1818 | case PHY_READCOUNT_EQ_SKIP: |
1783 | if (index + 2 >= fw_size) { | 1819 | if (index + 2 >= pa->size) { |
1784 | netif_err(tp, probe, tp->dev, | 1820 | netif_err(tp, probe, tp->dev, |
1785 | "Out of range of firmware\n"); | 1821 | "Out of range of firmware\n"); |
1786 | return; | 1822 | return; |
@@ -1789,7 +1825,7 @@ static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw) | |||
1789 | case PHY_COMP_EQ_SKIPN: | 1825 | case PHY_COMP_EQ_SKIPN: |
1790 | case PHY_COMP_NEQ_SKIPN: | 1826 | case PHY_COMP_NEQ_SKIPN: |
1791 | case PHY_SKIPN: | 1827 | case PHY_SKIPN: |
1792 | if (index + 1 + regno >= fw_size) { | 1828 | if (index + 1 + regno >= pa->size) { |
1793 | netif_err(tp, probe, tp->dev, | 1829 | netif_err(tp, probe, tp->dev, |
1794 | "Out of range of firmware\n"); | 1830 | "Out of range of firmware\n"); |
1795 | return; | 1831 | return; |
@@ -1809,8 +1845,8 @@ static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw) | |||
1809 | predata = 0; | 1845 | predata = 0; |
1810 | count = 0; | 1846 | count = 0; |
1811 | 1847 | ||
1812 | for (index = 0; index < fw_size; ) { | 1848 | for (index = 0; index < pa->size; ) { |
1813 | u32 action = le32_to_cpu(phytable[index]); | 1849 | u32 action = le32_to_cpu(pa->code[index]); |
1814 | u32 data = action & 0x0000ffff; | 1850 | u32 data = action & 0x0000ffff; |
1815 | u32 regno = (action & 0x0fff0000) >> 16; | 1851 | u32 regno = (action & 0x0fff0000) >> 16; |
1816 | 1852 | ||