diff options
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/fw/uefi.c')
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/fw/uefi.c | 62 |
1 files changed, 45 insertions, 17 deletions
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"); |