summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/pnvm.c5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/uefi.c62
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/uefi.h9
3 files changed, 59 insertions, 17 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c
index 82eb32e67a2c..650e4bde9c17 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c
@@ -127,6 +127,11 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
break;
}
+ case IWL_UCODE_TLV_MEM_DESC:
+ if (iwl_uefi_handle_tlv_mem_desc(trans, data, tlv_len,
+ pnvm_data))
+ return -EINVAL;
+ break;
case IWL_UCODE_TLV_PNVM_SKU:
IWL_DEBUG_FW(trans,
"New PNVM section started, stop parsing.\n");
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
index 488b9fb79743..9877988db0d2 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
@@ -17,6 +17,12 @@
0xb2, 0xec, 0xf5, 0xa3, \
0x59, 0x4f, 0x4a, 0xea)
+struct iwl_uefi_pnvm_mem_desc {
+ __le32 addr;
+ __le32 size;
+ const u8 data[];
+} __packed;
+
static void *iwl_uefi_get_variable(efi_char16_t *name, efi_guid_t *guid,
unsigned long *data_size)
{
@@ -70,6 +76,42 @@ void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
return data;
}
+int iwl_uefi_handle_tlv_mem_desc(struct iwl_trans *trans, const u8 *data,
+ u32 tlv_len, struct iwl_pnvm_image *pnvm_data)
+{
+ const struct iwl_uefi_pnvm_mem_desc *desc = (const void *)data;
+ u32 data_len;
+
+ if (tlv_len < sizeof(*desc)) {
+ IWL_DEBUG_FW(trans, "TLV len (%d) is too small\n", tlv_len);
+ return -EINVAL;
+ }
+
+ data_len = tlv_len - sizeof(*desc);
+
+ IWL_DEBUG_FW(trans,
+ "Handle IWL_UCODE_TLV_MEM_DESC, len %d data_len %d\n",
+ tlv_len, data_len);
+
+ if (le32_to_cpu(desc->size) != data_len) {
+ IWL_DEBUG_FW(trans, "invalid mem desc size %d\n", desc->size);
+ return -EINVAL;
+ }
+
+ if (pnvm_data->n_chunks == IPC_DRAM_MAP_ENTRY_NUM_MAX) {
+ IWL_DEBUG_FW(trans, "too many payloads to allocate in DRAM.\n");
+ return -EINVAL;
+ }
+
+ IWL_DEBUG_FW(trans, "Adding data (size %d)\n", data_len);
+
+ pnvm_data->chunks[pnvm_data->n_chunks].data = desc->data;
+ pnvm_data->chunks[pnvm_data->n_chunks].len = data_len;
+ pnvm_data->n_chunks++;
+
+ return 0;
+}
+
static int iwl_uefi_reduce_power_section(struct iwl_trans *trans,
const u8 *data, size_t len,
struct iwl_pnvm_image *pnvm_data)
@@ -97,25 +139,11 @@ static int iwl_uefi_reduce_power_section(struct iwl_trans *trans,
data += sizeof(*tlv);
switch (tlv_type) {
- case IWL_UCODE_TLV_MEM_DESC: {
- IWL_DEBUG_FW(trans,
- "Got IWL_UCODE_TLV_MEM_DESC len %d\n",
- tlv_len);
-
- if (pnvm_data->n_chunks == IPC_DRAM_MAP_ENTRY_NUM_MAX) {
- IWL_DEBUG_FW(trans,
- "too many payloads to allocate in DRAM.\n");
+ case IWL_UCODE_TLV_MEM_DESC:
+ if (iwl_uefi_handle_tlv_mem_desc(trans, data, tlv_len,
+ pnvm_data))
return -EINVAL;
- }
-
- IWL_DEBUG_FW(trans, "Adding data (size %d)\n", tlv_len);
-
- pnvm_data->chunks[pnvm_data->n_chunks].data = data;
- pnvm_data->chunks[pnvm_data->n_chunks].len = tlv_len;
- pnvm_data->n_chunks++;
-
break;
- }
case IWL_UCODE_TLV_PNVM_SKU:
IWL_DEBUG_FW(trans,
"New REDUCE_POWER section started, stop parsing.\n");
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h
index dc7ccf49d92d..1369cc4855c3 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h
@@ -46,6 +46,8 @@ int iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
const u8 *data, size_t len,
struct iwl_pnvm_image *pnvm_data);
void iwl_uefi_get_step_table(struct iwl_trans *trans);
+int iwl_uefi_handle_tlv_mem_desc(struct iwl_trans *trans, const u8 *data,
+ u32 tlv_len, struct iwl_pnvm_image *pnvm_data);
#else /* CONFIG_EFI */
static inline void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
{
@@ -69,6 +71,13 @@ iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len)
static inline void iwl_uefi_get_step_table(struct iwl_trans *trans)
{
}
+
+static inline int
+iwl_uefi_handle_tlv_mem_desc(struct iwl_trans *trans, const u8 *data,
+ u32 tlv_len, struct iwl_pnvm_image *pnvm_data)
+{
+ return 0;
+}
#endif /* CONFIG_EFI */
#if defined(CONFIG_EFI) && defined(CONFIG_ACPI)