aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c101
1 files changed, 63 insertions, 38 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 3368cfd25a99..22c0149e5d4a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -1806,12 +1806,21 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,
1806 const u8 *data; 1806 const u8 *data;
1807 int wanted_alternative = iwlagn_wanted_ucode_alternative, tmp; 1807 int wanted_alternative = iwlagn_wanted_ucode_alternative, tmp;
1808 u64 alternatives; 1808 u64 alternatives;
1809 u32 tlv_len;
1810 enum iwl_ucode_tlv_type tlv_type;
1811 const u8 *tlv_data;
1812 int ret = 0;
1809 1813
1810 if (len < sizeof(*ucode)) 1814 if (len < sizeof(*ucode)) {
1815 IWL_ERR(priv, "uCode has invalid length: %zd\n", len);
1811 return -EINVAL; 1816 return -EINVAL;
1817 }
1812 1818
1813 if (ucode->magic != cpu_to_le32(IWL_TLV_UCODE_MAGIC)) 1819 if (ucode->magic != cpu_to_le32(IWL_TLV_UCODE_MAGIC)) {
1820 IWL_ERR(priv, "invalid uCode magic: 0X%x\n",
1821 le32_to_cpu(ucode->magic));
1814 return -EINVAL; 1822 return -EINVAL;
1823 }
1815 1824
1816 /* 1825 /*
1817 * Check which alternatives are present, and "downgrade" 1826 * Check which alternatives are present, and "downgrade"
@@ -1836,11 +1845,9 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,
1836 1845
1837 len -= sizeof(*ucode); 1846 len -= sizeof(*ucode);
1838 1847
1839 while (len >= sizeof(*tlv)) { 1848 while (len >= sizeof(*tlv) && !ret) {
1840 u32 tlv_len;
1841 enum iwl_ucode_tlv_type tlv_type;
1842 u16 tlv_alt; 1849 u16 tlv_alt;
1843 const u8 *tlv_data; 1850 u32 fixed_tlv_size = 4;
1844 1851
1845 len -= sizeof(*tlv); 1852 len -= sizeof(*tlv);
1846 tlv = (void *)data; 1853 tlv = (void *)data;
@@ -1850,8 +1857,11 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,
1850 tlv_alt = le16_to_cpu(tlv->alternative); 1857 tlv_alt = le16_to_cpu(tlv->alternative);
1851 tlv_data = tlv->data; 1858 tlv_data = tlv->data;
1852 1859
1853 if (len < tlv_len) 1860 if (len < tlv_len) {
1861 IWL_ERR(priv, "invalid TLV len: %zd/%u\n",
1862 len, tlv_len);
1854 return -EINVAL; 1863 return -EINVAL;
1864 }
1855 len -= ALIGN(tlv_len, 4); 1865 len -= ALIGN(tlv_len, 4);
1856 data += sizeof(*tlv) + ALIGN(tlv_len, 4); 1866 data += sizeof(*tlv) + ALIGN(tlv_len, 4);
1857 1867
@@ -1885,56 +1895,71 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,
1885 pieces->boot_size = tlv_len; 1895 pieces->boot_size = tlv_len;
1886 break; 1896 break;
1887 case IWL_UCODE_TLV_PROBE_MAX_LEN: 1897 case IWL_UCODE_TLV_PROBE_MAX_LEN:
1888 if (tlv_len != 4) 1898 if (tlv_len != fixed_tlv_size)
1889 return -EINVAL; 1899 ret = -EINVAL;
1890 capa->max_probe_length = 1900 else
1891 le32_to_cpup((__le32 *)tlv_data); 1901 capa->max_probe_length =
1902 le32_to_cpup((__le32 *)tlv_data);
1892 break; 1903 break;
1893 case IWL_UCODE_TLV_INIT_EVTLOG_PTR: 1904 case IWL_UCODE_TLV_INIT_EVTLOG_PTR:
1894 if (tlv_len != 4) 1905 if (tlv_len != fixed_tlv_size)
1895 return -EINVAL; 1906 ret = -EINVAL;
1896 pieces->init_evtlog_ptr = 1907 else
1897 le32_to_cpup((__le32 *)tlv_data); 1908 pieces->init_evtlog_ptr =
1909 le32_to_cpup((__le32 *)tlv_data);
1898 break; 1910 break;
1899 case IWL_UCODE_TLV_INIT_EVTLOG_SIZE: 1911 case IWL_UCODE_TLV_INIT_EVTLOG_SIZE:
1900 if (tlv_len != 4) 1912 if (tlv_len != fixed_tlv_size)
1901 return -EINVAL; 1913 ret = -EINVAL;
1902 pieces->init_evtlog_size = 1914 else
1903 le32_to_cpup((__le32 *)tlv_data); 1915 pieces->init_evtlog_size =
1916 le32_to_cpup((__le32 *)tlv_data);
1904 break; 1917 break;
1905 case IWL_UCODE_TLV_INIT_ERRLOG_PTR: 1918 case IWL_UCODE_TLV_INIT_ERRLOG_PTR:
1906 if (tlv_len != 4) 1919 if (tlv_len != fixed_tlv_size)
1907 return -EINVAL; 1920 ret = -EINVAL;
1908 pieces->init_errlog_ptr = 1921 else
1909 le32_to_cpup((__le32 *)tlv_data); 1922 pieces->init_errlog_ptr =
1923 le32_to_cpup((__le32 *)tlv_data);
1910 break; 1924 break;
1911 case IWL_UCODE_TLV_RUNT_EVTLOG_PTR: 1925 case IWL_UCODE_TLV_RUNT_EVTLOG_PTR:
1912 if (tlv_len != 4) 1926 if (tlv_len != fixed_tlv_size)
1913 return -EINVAL; 1927 ret = -EINVAL;
1914 pieces->inst_evtlog_ptr = 1928 else
1915 le32_to_cpup((__le32 *)tlv_data); 1929 pieces->inst_evtlog_ptr =
1930 le32_to_cpup((__le32 *)tlv_data);
1916 break; 1931 break;
1917 case IWL_UCODE_TLV_RUNT_EVTLOG_SIZE: 1932 case IWL_UCODE_TLV_RUNT_EVTLOG_SIZE:
1918 if (tlv_len != 4) 1933 if (tlv_len != fixed_tlv_size)
1919 return -EINVAL; 1934 ret = -EINVAL;
1920 pieces->inst_evtlog_size = 1935 else
1921 le32_to_cpup((__le32 *)tlv_data); 1936 pieces->inst_evtlog_size =
1937 le32_to_cpup((__le32 *)tlv_data);
1922 break; 1938 break;
1923 case IWL_UCODE_TLV_RUNT_ERRLOG_PTR: 1939 case IWL_UCODE_TLV_RUNT_ERRLOG_PTR:
1924 if (tlv_len != 4) 1940 if (tlv_len != fixed_tlv_size)
1925 return -EINVAL; 1941 ret = -EINVAL;
1926 pieces->inst_errlog_ptr = 1942 else
1927 le32_to_cpup((__le32 *)tlv_data); 1943 pieces->inst_errlog_ptr =
1944 le32_to_cpup((__le32 *)tlv_data);
1928 break; 1945 break;
1929 default: 1946 default:
1947 IWL_WARN(priv, "unknown TLV: %d\n", tlv_type);
1930 break; 1948 break;
1931 } 1949 }
1932 } 1950 }
1933 1951
1934 if (len) 1952 if (len) {
1935 return -EINVAL; 1953 IWL_ERR(priv, "invalid TLV after parsing: %zd\n", len);
1954 iwl_print_hex_dump(priv, IWL_DL_FW, (u8 *)data, len);
1955 ret = -EINVAL;
1956 } else if (ret) {
1957 IWL_ERR(priv, "TLV %d has invalid size: %u\n",
1958 tlv_type, tlv_len);
1959 iwl_print_hex_dump(priv, IWL_DL_FW, (u8 *)tlv_data, tlv_len);
1960 }
1936 1961
1937 return 0; 1962 return ret;
1938} 1963}
1939 1964
1940/** 1965/**