int iwl_uefi_get_wgds_table(struct iwl_fw_runtime *fwrt)
{
struct uefi_cnv_var_wgds *data;
+ unsigned long expected_size;
+ unsigned long size;
+ int profile_size;
+ int n_subbands;
int ret = 0;
data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_WGDS_NAME,
"WGDS", UEFI_WGDS_TABLE_SIZE_REV3,
- NULL);
+ &size);
if (IS_ERR(data))
return -EINVAL;
- if (data->revision != IWL_UEFI_WGDS_REVISION) {
+ switch (data->revision) {
+ case 3:
+ expected_size = UEFI_WGDS_TABLE_SIZE_REV3;
+ n_subbands = UEFI_GEO_NUM_BANDS_REV3;
+ break;
+ case 4:
+ expected_size = UEFI_WGDS_TABLE_SIZE_REV4;
+ n_subbands = UEFI_GEO_NUM_BANDS_REV4;
+ break;
+ default:
ret = -EINVAL;
IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI WGDS revision:%d\n",
data->revision);
goto out;
}
+ if (size != expected_size) {
+ ret = -EINVAL;
+ goto out;
+ }
+
if (data->num_profiles < BIOS_GEO_MIN_PROFILE_NUM ||
data->num_profiles > BIOS_GEO_MAX_PROFILE_NUM) {
ret = -EINVAL;
if (WARN_ON(BIOS_GEO_MAX_PROFILE_NUM >
ARRAY_SIZE(fwrt->geo_profiles) ||
- UEFI_GEO_NUM_BANDS_REV3 >
- ARRAY_SIZE(fwrt->geo_profiles[0].bands) ||
+ n_subbands > ARRAY_SIZE(fwrt->geo_profiles[0].bands) ||
BIOS_GEO_NUM_CHAINS >
ARRAY_SIZE(fwrt->geo_profiles[0].bands[0].chains))) {
ret = -EINVAL;
}
fwrt->geo_rev = data->revision;
+ profile_size = 3 * n_subbands;
for (int prof = 0; prof < data->num_profiles; prof++) {
- const u8 *val = &data->vals[UEFI_WGDS_PROFILE_SIZE_REV3 * prof];
+ const u8 *val = &data->vals[profile_size * prof];
struct iwl_geo_profile *geo_prof = &fwrt->geo_profiles[prof];
- for (int subband = 0;
- subband < UEFI_GEO_NUM_BANDS_REV3;
- subband++) {
+ for (int subband = 0; subband < n_subbands; subband++) {
geo_prof->bands[subband].max = *val++;
for (int chain = 0;
#define IWL_SGOM_MAP_SIZE 339
#define IWL_UATS_MAP_SIZE 339
-#define IWL_UEFI_WGDS_REVISION 3
#define IWL_UEFI_MIN_WTAS_REVISION 1
#define IWL_UEFI_MAX_WTAS_REVISION 2
#define IWL_UEFI_SPLC_REVISION 0
#define UEFI_SAR_MAX_CHAINS_PER_PROFILE 4
#define UEFI_GEO_NUM_BANDS_REV3 3
+#define UEFI_GEO_NUM_BANDS_REV4 4
/*
* struct uefi_cnv_var_wrds - WRDS table as defined in UEFI
* @vals: a per-profile table of the offsets to add to SAR values. This is an
* array of profiles, each profile is an array of
* &struct iwl_geo_profile_band, one for each subband.
- * There are %UEFI_GEO_NUM_BANDS_REV3 subbands.
+ * There are %UEFI_GEO_NUM_BANDS_REV3 or %UEFI_GEO_NUM_BANDS_REV4 subbands
+ * depending on the revision.
*/
struct uefi_cnv_var_wgds {
u8 revision;
*/
#define UEFI_WGDS_PROFILE_SIZE_REV3 (sizeof(u8) * 3 * UEFI_GEO_NUM_BANDS_REV3)
+#define UEFI_WGDS_PROFILE_SIZE_REV4 (sizeof(u8) * 3 * UEFI_GEO_NUM_BANDS_REV4)
+
#define UEFI_WGDS_TABLE_SIZE_REV3 \
(offsetof(struct uefi_cnv_var_wgds, vals) + \
UEFI_WGDS_PROFILE_SIZE_REV3 * BIOS_GEO_MAX_PROFILE_NUM)
+#define UEFI_WGDS_TABLE_SIZE_REV4 \
+ (offsetof(struct uefi_cnv_var_wgds, vals) + \
+ UEFI_WGDS_PROFILE_SIZE_REV4 * BIOS_GEO_MAX_PROFILE_NUM)
+
/*
* struct uefi_cnv_var_ppag - PPAG table as defined in UEFI
* @revision: the revision of the table