162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright(c) 2021-2023 Intel Corporation 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include "iwl-drv.h" 762306a36Sopenharmony_ci#include "pnvm.h" 862306a36Sopenharmony_ci#include "iwl-prph.h" 962306a36Sopenharmony_ci#include "iwl-io.h" 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include "fw/uefi.h" 1262306a36Sopenharmony_ci#include "fw/api/alive.h" 1362306a36Sopenharmony_ci#include <linux/efi.h> 1462306a36Sopenharmony_ci#include "fw/runtime.h" 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#define IWL_EFI_VAR_GUID EFI_GUID(0x92daaf2f, 0xc02b, 0x455b, \ 1762306a36Sopenharmony_ci 0xb2, 0xec, 0xf5, 0xa3, \ 1862306a36Sopenharmony_ci 0x59, 0x4f, 0x4a, 0xea) 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_cistruct iwl_uefi_pnvm_mem_desc { 2162306a36Sopenharmony_ci __le32 addr; 2262306a36Sopenharmony_ci __le32 size; 2362306a36Sopenharmony_ci const u8 data[]; 2462306a36Sopenharmony_ci} __packed; 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cistatic void *iwl_uefi_get_variable(efi_char16_t *name, efi_guid_t *guid, 2762306a36Sopenharmony_ci unsigned long *data_size) 2862306a36Sopenharmony_ci{ 2962306a36Sopenharmony_ci efi_status_t status; 3062306a36Sopenharmony_ci void *data; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci if (!data_size) 3362306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE)) 3662306a36Sopenharmony_ci return ERR_PTR(-ENODEV); 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci /* first call with NULL data to get the exact entry size */ 3962306a36Sopenharmony_ci *data_size = 0; 4062306a36Sopenharmony_ci status = efi.get_variable(name, guid, NULL, data_size, NULL); 4162306a36Sopenharmony_ci if (status != EFI_BUFFER_TOO_SMALL || !*data_size) 4262306a36Sopenharmony_ci return ERR_PTR(-EIO); 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci data = kmalloc(*data_size, GFP_KERNEL); 4562306a36Sopenharmony_ci if (!data) 4662306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci status = efi.get_variable(name, guid, NULL, data_size, data); 4962306a36Sopenharmony_ci if (status != EFI_SUCCESS) { 5062306a36Sopenharmony_ci kfree(data); 5162306a36Sopenharmony_ci return ERR_PTR(-ENOENT); 5262306a36Sopenharmony_ci } 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci return data; 5562306a36Sopenharmony_ci} 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_civoid *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len) 5862306a36Sopenharmony_ci{ 5962306a36Sopenharmony_ci unsigned long package_size; 6062306a36Sopenharmony_ci void *data; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci *len = 0; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci data = iwl_uefi_get_variable(IWL_UEFI_OEM_PNVM_NAME, &IWL_EFI_VAR_GUID, 6562306a36Sopenharmony_ci &package_size); 6662306a36Sopenharmony_ci if (IS_ERR(data)) { 6762306a36Sopenharmony_ci IWL_DEBUG_FW(trans, 6862306a36Sopenharmony_ci "PNVM UEFI variable not found 0x%lx (len %lu)\n", 6962306a36Sopenharmony_ci PTR_ERR(data), package_size); 7062306a36Sopenharmony_ci return data; 7162306a36Sopenharmony_ci } 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci IWL_DEBUG_FW(trans, "Read PNVM from UEFI with size %lu\n", package_size); 7462306a36Sopenharmony_ci *len = package_size; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci return data; 7762306a36Sopenharmony_ci} 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ciint iwl_uefi_handle_tlv_mem_desc(struct iwl_trans *trans, const u8 *data, 8062306a36Sopenharmony_ci u32 tlv_len, struct iwl_pnvm_image *pnvm_data) 8162306a36Sopenharmony_ci{ 8262306a36Sopenharmony_ci const struct iwl_uefi_pnvm_mem_desc *desc = (const void *)data; 8362306a36Sopenharmony_ci u32 data_len; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci if (tlv_len < sizeof(*desc)) { 8662306a36Sopenharmony_ci IWL_DEBUG_FW(trans, "TLV len (%d) is too small\n", tlv_len); 8762306a36Sopenharmony_ci return -EINVAL; 8862306a36Sopenharmony_ci } 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci data_len = tlv_len - sizeof(*desc); 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci IWL_DEBUG_FW(trans, 9362306a36Sopenharmony_ci "Handle IWL_UCODE_TLV_MEM_DESC, len %d data_len %d\n", 9462306a36Sopenharmony_ci tlv_len, data_len); 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci if (le32_to_cpu(desc->size) != data_len) { 9762306a36Sopenharmony_ci IWL_DEBUG_FW(trans, "invalid mem desc size %d\n", desc->size); 9862306a36Sopenharmony_ci return -EINVAL; 9962306a36Sopenharmony_ci } 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci if (pnvm_data->n_chunks == IPC_DRAM_MAP_ENTRY_NUM_MAX) { 10262306a36Sopenharmony_ci IWL_DEBUG_FW(trans, "too many payloads to allocate in DRAM.\n"); 10362306a36Sopenharmony_ci return -EINVAL; 10462306a36Sopenharmony_ci } 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci IWL_DEBUG_FW(trans, "Adding data (size %d)\n", data_len); 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci pnvm_data->chunks[pnvm_data->n_chunks].data = desc->data; 10962306a36Sopenharmony_ci pnvm_data->chunks[pnvm_data->n_chunks].len = data_len; 11062306a36Sopenharmony_ci pnvm_data->n_chunks++; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci return 0; 11362306a36Sopenharmony_ci} 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_cistatic int iwl_uefi_reduce_power_section(struct iwl_trans *trans, 11662306a36Sopenharmony_ci const u8 *data, size_t len, 11762306a36Sopenharmony_ci struct iwl_pnvm_image *pnvm_data) 11862306a36Sopenharmony_ci{ 11962306a36Sopenharmony_ci const struct iwl_ucode_tlv *tlv; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci IWL_DEBUG_FW(trans, "Handling REDUCE_POWER section\n"); 12262306a36Sopenharmony_ci memset(pnvm_data, 0, sizeof(*pnvm_data)); 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci while (len >= sizeof(*tlv)) { 12562306a36Sopenharmony_ci u32 tlv_len, tlv_type; 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci len -= sizeof(*tlv); 12862306a36Sopenharmony_ci tlv = (const void *)data; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci tlv_len = le32_to_cpu(tlv->length); 13162306a36Sopenharmony_ci tlv_type = le32_to_cpu(tlv->type); 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci if (len < tlv_len) { 13462306a36Sopenharmony_ci IWL_ERR(trans, "invalid TLV len: %zd/%u\n", 13562306a36Sopenharmony_ci len, tlv_len); 13662306a36Sopenharmony_ci return -EINVAL; 13762306a36Sopenharmony_ci } 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci data += sizeof(*tlv); 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci switch (tlv_type) { 14262306a36Sopenharmony_ci case IWL_UCODE_TLV_MEM_DESC: 14362306a36Sopenharmony_ci if (iwl_uefi_handle_tlv_mem_desc(trans, data, tlv_len, 14462306a36Sopenharmony_ci pnvm_data)) 14562306a36Sopenharmony_ci return -EINVAL; 14662306a36Sopenharmony_ci break; 14762306a36Sopenharmony_ci case IWL_UCODE_TLV_PNVM_SKU: 14862306a36Sopenharmony_ci IWL_DEBUG_FW(trans, 14962306a36Sopenharmony_ci "New REDUCE_POWER section started, stop parsing.\n"); 15062306a36Sopenharmony_ci goto done; 15162306a36Sopenharmony_ci default: 15262306a36Sopenharmony_ci IWL_DEBUG_FW(trans, "Found TLV 0x%0x, len %d\n", 15362306a36Sopenharmony_ci tlv_type, tlv_len); 15462306a36Sopenharmony_ci break; 15562306a36Sopenharmony_ci } 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci len -= ALIGN(tlv_len, 4); 15862306a36Sopenharmony_ci data += ALIGN(tlv_len, 4); 15962306a36Sopenharmony_ci } 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_cidone: 16262306a36Sopenharmony_ci if (!pnvm_data->n_chunks) { 16362306a36Sopenharmony_ci IWL_DEBUG_FW(trans, "Empty REDUCE_POWER, skipping.\n"); 16462306a36Sopenharmony_ci return -ENOENT; 16562306a36Sopenharmony_ci } 16662306a36Sopenharmony_ci return 0; 16762306a36Sopenharmony_ci} 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ciint iwl_uefi_reduce_power_parse(struct iwl_trans *trans, 17062306a36Sopenharmony_ci const u8 *data, size_t len, 17162306a36Sopenharmony_ci struct iwl_pnvm_image *pnvm_data) 17262306a36Sopenharmony_ci{ 17362306a36Sopenharmony_ci const struct iwl_ucode_tlv *tlv; 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci IWL_DEBUG_FW(trans, "Parsing REDUCE_POWER data\n"); 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci while (len >= sizeof(*tlv)) { 17862306a36Sopenharmony_ci u32 tlv_len, tlv_type; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci len -= sizeof(*tlv); 18162306a36Sopenharmony_ci tlv = (const void *)data; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci tlv_len = le32_to_cpu(tlv->length); 18462306a36Sopenharmony_ci tlv_type = le32_to_cpu(tlv->type); 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci if (len < tlv_len) { 18762306a36Sopenharmony_ci IWL_ERR(trans, "invalid TLV len: %zd/%u\n", 18862306a36Sopenharmony_ci len, tlv_len); 18962306a36Sopenharmony_ci return -EINVAL; 19062306a36Sopenharmony_ci } 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci if (tlv_type == IWL_UCODE_TLV_PNVM_SKU) { 19362306a36Sopenharmony_ci const struct iwl_sku_id *sku_id = 19462306a36Sopenharmony_ci (const void *)(data + sizeof(*tlv)); 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci IWL_DEBUG_FW(trans, 19762306a36Sopenharmony_ci "Got IWL_UCODE_TLV_PNVM_SKU len %d\n", 19862306a36Sopenharmony_ci tlv_len); 19962306a36Sopenharmony_ci IWL_DEBUG_FW(trans, "sku_id 0x%0x 0x%0x 0x%0x\n", 20062306a36Sopenharmony_ci le32_to_cpu(sku_id->data[0]), 20162306a36Sopenharmony_ci le32_to_cpu(sku_id->data[1]), 20262306a36Sopenharmony_ci le32_to_cpu(sku_id->data[2])); 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci data += sizeof(*tlv) + ALIGN(tlv_len, 4); 20562306a36Sopenharmony_ci len -= ALIGN(tlv_len, 4); 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci if (trans->sku_id[0] == le32_to_cpu(sku_id->data[0]) && 20862306a36Sopenharmony_ci trans->sku_id[1] == le32_to_cpu(sku_id->data[1]) && 20962306a36Sopenharmony_ci trans->sku_id[2] == le32_to_cpu(sku_id->data[2])) { 21062306a36Sopenharmony_ci int ret = iwl_uefi_reduce_power_section(trans, 21162306a36Sopenharmony_ci data, len, 21262306a36Sopenharmony_ci pnvm_data); 21362306a36Sopenharmony_ci if (!ret) 21462306a36Sopenharmony_ci return 0; 21562306a36Sopenharmony_ci } else { 21662306a36Sopenharmony_ci IWL_DEBUG_FW(trans, "SKU ID didn't match!\n"); 21762306a36Sopenharmony_ci } 21862306a36Sopenharmony_ci } else { 21962306a36Sopenharmony_ci data += sizeof(*tlv) + ALIGN(tlv_len, 4); 22062306a36Sopenharmony_ci len -= ALIGN(tlv_len, 4); 22162306a36Sopenharmony_ci } 22262306a36Sopenharmony_ci } 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci return -ENOENT; 22562306a36Sopenharmony_ci} 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ciu8 *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len) 22862306a36Sopenharmony_ci{ 22962306a36Sopenharmony_ci struct pnvm_sku_package *package; 23062306a36Sopenharmony_ci unsigned long package_size; 23162306a36Sopenharmony_ci u8 *data; 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci package = iwl_uefi_get_variable(IWL_UEFI_REDUCED_POWER_NAME, 23462306a36Sopenharmony_ci &IWL_EFI_VAR_GUID, &package_size); 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci if (IS_ERR(package)) { 23762306a36Sopenharmony_ci IWL_DEBUG_FW(trans, 23862306a36Sopenharmony_ci "Reduced Power UEFI variable not found 0x%lx (len %lu)\n", 23962306a36Sopenharmony_ci PTR_ERR(package), package_size); 24062306a36Sopenharmony_ci return ERR_CAST(package); 24162306a36Sopenharmony_ci } 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci if (package_size < sizeof(*package)) { 24462306a36Sopenharmony_ci IWL_DEBUG_FW(trans, 24562306a36Sopenharmony_ci "Invalid Reduced Power UEFI variable len (%lu)\n", 24662306a36Sopenharmony_ci package_size); 24762306a36Sopenharmony_ci kfree(package); 24862306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 24962306a36Sopenharmony_ci } 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci IWL_DEBUG_FW(trans, "Read reduced power from UEFI with size %lu\n", 25262306a36Sopenharmony_ci package_size); 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci IWL_DEBUG_FW(trans, "rev %d, total_size %d, n_skus %d\n", 25562306a36Sopenharmony_ci package->rev, package->total_size, package->n_skus); 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci *len = package_size - sizeof(*package); 25862306a36Sopenharmony_ci data = kmemdup(package->data, *len, GFP_KERNEL); 25962306a36Sopenharmony_ci if (!data) { 26062306a36Sopenharmony_ci kfree(package); 26162306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 26262306a36Sopenharmony_ci } 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci kfree(package); 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci return data; 26762306a36Sopenharmony_ci} 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_cistatic int iwl_uefi_step_parse(struct uefi_cnv_common_step_data *common_step_data, 27062306a36Sopenharmony_ci struct iwl_trans *trans) 27162306a36Sopenharmony_ci{ 27262306a36Sopenharmony_ci if (common_step_data->revision != 1) 27362306a36Sopenharmony_ci return -EINVAL; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci trans->mbx_addr_0_step = (u32)common_step_data->revision | 27662306a36Sopenharmony_ci (u32)common_step_data->cnvi_eq_channel << 8 | 27762306a36Sopenharmony_ci (u32)common_step_data->cnvr_eq_channel << 16 | 27862306a36Sopenharmony_ci (u32)common_step_data->radio1 << 24; 27962306a36Sopenharmony_ci trans->mbx_addr_1_step = (u32)common_step_data->radio2; 28062306a36Sopenharmony_ci return 0; 28162306a36Sopenharmony_ci} 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_civoid iwl_uefi_get_step_table(struct iwl_trans *trans) 28462306a36Sopenharmony_ci{ 28562306a36Sopenharmony_ci struct uefi_cnv_common_step_data *data; 28662306a36Sopenharmony_ci unsigned long package_size; 28762306a36Sopenharmony_ci int ret; 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) 29062306a36Sopenharmony_ci return; 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci data = iwl_uefi_get_variable(IWL_UEFI_STEP_NAME, &IWL_EFI_VAR_GUID, 29362306a36Sopenharmony_ci &package_size); 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci if (IS_ERR(data)) { 29662306a36Sopenharmony_ci IWL_DEBUG_FW(trans, 29762306a36Sopenharmony_ci "STEP UEFI variable not found 0x%lx\n", 29862306a36Sopenharmony_ci PTR_ERR(data)); 29962306a36Sopenharmony_ci return; 30062306a36Sopenharmony_ci } 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci if (package_size < sizeof(*data)) { 30362306a36Sopenharmony_ci IWL_DEBUG_FW(trans, 30462306a36Sopenharmony_ci "Invalid STEP table UEFI variable len (%lu)\n", 30562306a36Sopenharmony_ci package_size); 30662306a36Sopenharmony_ci kfree(data); 30762306a36Sopenharmony_ci return; 30862306a36Sopenharmony_ci } 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci IWL_DEBUG_FW(trans, "Read STEP from UEFI with size %lu\n", 31162306a36Sopenharmony_ci package_size); 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci ret = iwl_uefi_step_parse(data, trans); 31462306a36Sopenharmony_ci if (ret < 0) 31562306a36Sopenharmony_ci IWL_DEBUG_FW(trans, "Cannot read STEP tables. rev is invalid\n"); 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci kfree(data); 31862306a36Sopenharmony_ci} 31962306a36Sopenharmony_ciIWL_EXPORT_SYMBOL(iwl_uefi_get_step_table); 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci#ifdef CONFIG_ACPI 32262306a36Sopenharmony_cistatic int iwl_uefi_sgom_parse(struct uefi_cnv_wlan_sgom_data *sgom_data, 32362306a36Sopenharmony_ci struct iwl_fw_runtime *fwrt) 32462306a36Sopenharmony_ci{ 32562306a36Sopenharmony_ci int i, j; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci if (sgom_data->revision != 1) 32862306a36Sopenharmony_ci return -EINVAL; 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci memcpy(fwrt->sgom_table.offset_map, sgom_data->offset_map, 33162306a36Sopenharmony_ci sizeof(fwrt->sgom_table.offset_map)); 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci for (i = 0; i < MCC_TO_SAR_OFFSET_TABLE_ROW_SIZE; i++) { 33462306a36Sopenharmony_ci for (j = 0; j < MCC_TO_SAR_OFFSET_TABLE_COL_SIZE; j++) { 33562306a36Sopenharmony_ci /* since each byte is composed of to values, */ 33662306a36Sopenharmony_ci /* one for each letter, */ 33762306a36Sopenharmony_ci /* extract and check each of them separately */ 33862306a36Sopenharmony_ci u8 value = fwrt->sgom_table.offset_map[i][j]; 33962306a36Sopenharmony_ci u8 low = value & 0xF; 34062306a36Sopenharmony_ci u8 high = (value & 0xF0) >> 4; 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci if (high > fwrt->geo_num_profiles) 34362306a36Sopenharmony_ci high = 0; 34462306a36Sopenharmony_ci if (low > fwrt->geo_num_profiles) 34562306a36Sopenharmony_ci low = 0; 34662306a36Sopenharmony_ci fwrt->sgom_table.offset_map[i][j] = (high << 4) | low; 34762306a36Sopenharmony_ci } 34862306a36Sopenharmony_ci } 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci fwrt->sgom_enabled = true; 35162306a36Sopenharmony_ci return 0; 35262306a36Sopenharmony_ci} 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_civoid iwl_uefi_get_sgom_table(struct iwl_trans *trans, 35562306a36Sopenharmony_ci struct iwl_fw_runtime *fwrt) 35662306a36Sopenharmony_ci{ 35762306a36Sopenharmony_ci struct uefi_cnv_wlan_sgom_data *data; 35862306a36Sopenharmony_ci unsigned long package_size; 35962306a36Sopenharmony_ci int ret; 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci if (!fwrt->geo_enabled) 36262306a36Sopenharmony_ci return; 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci data = iwl_uefi_get_variable(IWL_UEFI_SGOM_NAME, &IWL_EFI_VAR_GUID, 36562306a36Sopenharmony_ci &package_size); 36662306a36Sopenharmony_ci if (IS_ERR(data)) { 36762306a36Sopenharmony_ci IWL_DEBUG_FW(trans, 36862306a36Sopenharmony_ci "SGOM UEFI variable not found 0x%lx\n", 36962306a36Sopenharmony_ci PTR_ERR(data)); 37062306a36Sopenharmony_ci return; 37162306a36Sopenharmony_ci } 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci if (package_size < sizeof(*data)) { 37462306a36Sopenharmony_ci IWL_DEBUG_FW(trans, 37562306a36Sopenharmony_ci "Invalid SGOM table UEFI variable len (%lu)\n", 37662306a36Sopenharmony_ci package_size); 37762306a36Sopenharmony_ci kfree(data); 37862306a36Sopenharmony_ci return; 37962306a36Sopenharmony_ci } 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci IWL_DEBUG_FW(trans, "Read SGOM from UEFI with size %lu\n", 38262306a36Sopenharmony_ci package_size); 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci ret = iwl_uefi_sgom_parse(data, fwrt); 38562306a36Sopenharmony_ci if (ret < 0) 38662306a36Sopenharmony_ci IWL_DEBUG_FW(trans, "Cannot read SGOM tables. rev is invalid\n"); 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci kfree(data); 38962306a36Sopenharmony_ci} 39062306a36Sopenharmony_ciIWL_EXPORT_SYMBOL(iwl_uefi_get_sgom_table); 39162306a36Sopenharmony_ci#endif /* CONFIG_ACPI */ 392