mirror of
https://github.com/edk2-porting/linux-next.git
synced 2025-01-21 03:54:03 +08:00
wifi: iwlwifi: fw: don't use constant size with efi.get_variable
Use efi.get_variable() with NULL pointer for data in order to obtain entry size and then call it again with the correct size to get the entry itself. Signed-off-by: Gregory Greenman <gregory.greenman@intel.com> Link: https://lore.kernel.org/r/20230606103519.ef95a8055a50.Iae5389baaf0a9a3c89469f7502275ee119d378b6@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
875d035f37
commit
8ae3e23195
@ -17,38 +17,53 @@
|
||||
0xb2, 0xec, 0xf5, 0xa3, \
|
||||
0x59, 0x4f, 0x4a, 0xea)
|
||||
|
||||
void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
|
||||
static void *iwl_uefi_get_variable(efi_char16_t *name, efi_guid_t *guid,
|
||||
unsigned long *data_size)
|
||||
{
|
||||
void *data;
|
||||
unsigned long package_size;
|
||||
efi_status_t status;
|
||||
void *data;
|
||||
|
||||
*len = 0;
|
||||
if (!data_size)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE))
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
/*
|
||||
* TODO: we hardcode a maximum length here, because reading
|
||||
* from the UEFI is not working. To implement this properly,
|
||||
* we have to call efivar_entry_size().
|
||||
*/
|
||||
package_size = IWL_HARDCODED_PNVM_SIZE;
|
||||
/* first call with NULL data to get the exact entry size */
|
||||
*data_size = 0;
|
||||
status = efi.get_variable(name, guid, NULL, data_size, NULL);
|
||||
if (status != EFI_BUFFER_TOO_SMALL || !*data_size)
|
||||
return ERR_PTR(-EIO);
|
||||
|
||||
data = kmalloc(package_size, GFP_KERNEL);
|
||||
data = kmalloc(*data_size, GFP_KERNEL);
|
||||
if (!data)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
status = efi.get_variable(IWL_UEFI_OEM_PNVM_NAME, &IWL_EFI_VAR_GUID,
|
||||
NULL, &package_size, data);
|
||||
status = efi.get_variable(name, guid, NULL, data_size, data);
|
||||
if (status != EFI_SUCCESS) {
|
||||
IWL_DEBUG_FW(trans,
|
||||
"PNVM UEFI variable not found 0x%lx (len %lu)\n",
|
||||
status, package_size);
|
||||
kfree(data);
|
||||
return ERR_PTR(-ENOENT);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
|
||||
{
|
||||
unsigned long package_size;
|
||||
void *data;
|
||||
|
||||
*len = 0;
|
||||
|
||||
data = iwl_uefi_get_variable(IWL_UEFI_OEM_PNVM_NAME, &IWL_EFI_VAR_GUID,
|
||||
&package_size);
|
||||
if (IS_ERR(data)) {
|
||||
IWL_DEBUG_FW(trans,
|
||||
"PNVM UEFI variable not found 0x%lx (len %lu)\n",
|
||||
PTR_ERR(data), package_size);
|
||||
return data;
|
||||
}
|
||||
|
||||
IWL_DEBUG_FW(trans, "Read PNVM from UEFI with size %lu\n", package_size);
|
||||
*len = package_size;
|
||||
|
||||
@ -185,31 +200,24 @@ u8 *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len)
|
||||
{
|
||||
struct pnvm_sku_package *package;
|
||||
unsigned long package_size;
|
||||
efi_status_t status;
|
||||
u8 *data;
|
||||
|
||||
if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE))
|
||||
return ERR_PTR(-ENODEV);
|
||||
package = iwl_uefi_get_variable(IWL_UEFI_REDUCED_POWER_NAME,
|
||||
&IWL_EFI_VAR_GUID, &package_size);
|
||||
|
||||
/*
|
||||
* TODO: we hardcode a maximum length here, because reading
|
||||
* from the UEFI is not working. To implement this properly,
|
||||
* we have to call efivar_entry_size().
|
||||
*/
|
||||
package_size = IWL_HARDCODED_REDUCE_POWER_SIZE;
|
||||
|
||||
package = kmalloc(package_size, GFP_KERNEL);
|
||||
if (!package)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
status = efi.get_variable(IWL_UEFI_REDUCED_POWER_NAME, &IWL_EFI_VAR_GUID,
|
||||
NULL, &package_size, package);
|
||||
if (status != EFI_SUCCESS) {
|
||||
if (IS_ERR(package)) {
|
||||
IWL_DEBUG_FW(trans,
|
||||
"Reduced Power UEFI variable not found 0x%lx (len %lu)\n",
|
||||
status, package_size);
|
||||
PTR_ERR(package), package_size);
|
||||
return ERR_CAST(package);
|
||||
}
|
||||
|
||||
if (package_size < sizeof(*package)) {
|
||||
IWL_DEBUG_FW(trans,
|
||||
"Invalid Reduced Power UEFI variable len (%lu)\n",
|
||||
package_size);
|
||||
kfree(package);
|
||||
return ERR_PTR(-ENOENT);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
IWL_DEBUG_FW(trans, "Read reduced power from UEFI with size %lu\n",
|
||||
@ -220,8 +228,11 @@ u8 *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len)
|
||||
|
||||
*len = package_size - sizeof(*package);
|
||||
data = kmemdup(package->data, *len, GFP_KERNEL);
|
||||
if (!data)
|
||||
if (!data) {
|
||||
kfree(package);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
kfree(package);
|
||||
|
||||
return data;
|
||||
@ -245,31 +256,27 @@ void iwl_uefi_get_step_table(struct iwl_trans *trans)
|
||||
{
|
||||
struct uefi_cnv_common_step_data *data;
|
||||
unsigned long package_size;
|
||||
efi_status_t status;
|
||||
int ret;
|
||||
|
||||
if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
|
||||
return;
|
||||
|
||||
if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE))
|
||||
return;
|
||||
data = iwl_uefi_get_variable(IWL_UEFI_STEP_NAME, &IWL_EFI_VAR_GUID,
|
||||
&package_size);
|
||||
|
||||
/* TODO: we hardcode a maximum length here, because reading
|
||||
* from the UEFI is not working. To implement this properly,
|
||||
* we have to call efivar_entry_size().
|
||||
*/
|
||||
package_size = IWL_HARDCODED_STEP_SIZE;
|
||||
|
||||
data = kmalloc(package_size, GFP_KERNEL);
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
status = efi.get_variable(IWL_UEFI_STEP_NAME, &IWL_EFI_VAR_GUID,
|
||||
NULL, &package_size, data);
|
||||
if (status != EFI_SUCCESS) {
|
||||
if (IS_ERR(data)) {
|
||||
IWL_DEBUG_FW(trans,
|
||||
"STEP UEFI variable not found 0x%lx\n", status);
|
||||
goto out_free;
|
||||
"STEP UEFI variable not found 0x%lx\n",
|
||||
PTR_ERR(data));
|
||||
return;
|
||||
}
|
||||
|
||||
if (package_size < sizeof(*data)) {
|
||||
IWL_DEBUG_FW(trans,
|
||||
"Invalid STEP table UEFI variable len (%lu)\n",
|
||||
package_size);
|
||||
kfree(data);
|
||||
return;
|
||||
}
|
||||
|
||||
IWL_DEBUG_FW(trans, "Read STEP from UEFI with size %lu\n",
|
||||
@ -279,7 +286,6 @@ void iwl_uefi_get_step_table(struct iwl_trans *trans)
|
||||
if (ret < 0)
|
||||
IWL_DEBUG_FW(trans, "Cannot read STEP tables. rev is invalid\n");
|
||||
|
||||
out_free:
|
||||
kfree(data);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_uefi_get_step_table);
|
||||
@ -322,29 +328,26 @@ void iwl_uefi_get_sgom_table(struct iwl_trans *trans,
|
||||
{
|
||||
struct uefi_cnv_wlan_sgom_data *data;
|
||||
unsigned long package_size;
|
||||
efi_status_t status;
|
||||
int ret;
|
||||
|
||||
if (!fwrt->geo_enabled ||
|
||||
!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE))
|
||||
if (!fwrt->geo_enabled)
|
||||
return;
|
||||
|
||||
/* TODO: we hardcode a maximum length here, because reading
|
||||
* from the UEFI is not working. To implement this properly,
|
||||
* we have to call efivar_entry_size().
|
||||
*/
|
||||
package_size = IWL_HARDCODED_SGOM_SIZE;
|
||||
|
||||
data = kmalloc(package_size, GFP_KERNEL);
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
status = efi.get_variable(IWL_UEFI_SGOM_NAME, &IWL_EFI_VAR_GUID,
|
||||
NULL, &package_size, data);
|
||||
if (status != EFI_SUCCESS) {
|
||||
data = iwl_uefi_get_variable(IWL_UEFI_SGOM_NAME, &IWL_EFI_VAR_GUID,
|
||||
&package_size);
|
||||
if (IS_ERR(data)) {
|
||||
IWL_DEBUG_FW(trans,
|
||||
"SGOM UEFI variable not found 0x%lx\n", status);
|
||||
goto out_free;
|
||||
"SGOM UEFI variable not found 0x%lx\n",
|
||||
PTR_ERR(data));
|
||||
return;
|
||||
}
|
||||
|
||||
if (package_size < sizeof(*data)) {
|
||||
IWL_DEBUG_FW(trans,
|
||||
"Invalid SGOM table UEFI variable len (%lu)\n",
|
||||
package_size);
|
||||
kfree(data);
|
||||
return;
|
||||
}
|
||||
|
||||
IWL_DEBUG_FW(trans, "Read SGOM from UEFI with size %lu\n",
|
||||
@ -354,9 +357,7 @@ void iwl_uefi_get_sgom_table(struct iwl_trans *trans,
|
||||
if (ret < 0)
|
||||
IWL_DEBUG_FW(trans, "Cannot read SGOM tables. rev is invalid\n");
|
||||
|
||||
out_free:
|
||||
kfree(data);
|
||||
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_uefi_get_sgom_table);
|
||||
#endif /* CONFIG_ACPI */
|
||||
|
@ -10,16 +10,7 @@
|
||||
#define IWL_UEFI_SGOM_NAME L"UefiCnvWlanSarGeoOffsetMapping"
|
||||
#define IWL_UEFI_STEP_NAME L"UefiCnvCommonSTEP"
|
||||
|
||||
/*
|
||||
* TODO: we have these hardcoded values that the caller must pass,
|
||||
* because reading from the UEFI is not working. To implement this
|
||||
* properly, we have to change iwl_pnvm_get_from_uefi() to call
|
||||
* efivar_entry_size() and return the value to the caller instead.
|
||||
*/
|
||||
#define IWL_HARDCODED_PNVM_SIZE 4096
|
||||
#define IWL_HARDCODED_REDUCE_POWER_SIZE 32768
|
||||
#define IWL_HARDCODED_SGOM_SIZE 339
|
||||
#define IWL_HARDCODED_STEP_SIZE 6
|
||||
#define IWL_SGOM_MAP_SIZE 339
|
||||
|
||||
struct pnvm_sku_package {
|
||||
u8 rev;
|
||||
@ -31,7 +22,7 @@ struct pnvm_sku_package {
|
||||
|
||||
struct uefi_cnv_wlan_sgom_data {
|
||||
u8 revision;
|
||||
u8 offset_map[IWL_HARDCODED_SGOM_SIZE - 1];
|
||||
u8 offset_map[IWL_SGOM_MAP_SIZE - 1];
|
||||
} __packed;
|
||||
|
||||
struct uefi_cnv_common_step_data {
|
||||
|
Loading…
Reference in New Issue
Block a user