wifi: iwlwifi: implement GLAI ACPI table loading
authorMiri Korenblit <miriam.rachel.korenblit@intel.com>
Sun, 28 Jan 2024 06:53:59 +0000 (08:53 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 2 Feb 2024 12:50:34 +0000 (13:50 +0100)
All the regulatory tables from BIOS are going to be loaded
(preferably) from the UEFI instead of the ACPI.
There is a security issue with the fact that anyone can
add these UEFI variables.
The solution for that is to have a lock for all WIFI GUID UEFI
variables, and only if the UEFI variables are locked then we can
read it.
The status of the lock (unlocked, locked, test mode) is indicated
in a ACPI table: Guid Lock ACPI Indicator.
Load this table so the driver knows whether to read from UEFI or
not

Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Reviewed-by: Gregory Greenman <gregory.greenman@intel.com>
Link: https://msgid.link/20240128084842.53994809fbdd.I1bd10aafc387bc04f375e386861ee2bcb82f0a61@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/intel/iwlwifi/fw/acpi.c
drivers/net/wireless/intel/iwlwifi/fw/acpi.h
drivers/net/wireless/intel/iwlwifi/fw/runtime.h
drivers/net/wireless/intel/iwlwifi/mvm/fw.c

index 72a0a9565371f9b4fba07efa580c2c9efa269fe5..dd68d382d7deed542355b5fe496a3f7db6435637 100644 (file)
@@ -1318,3 +1318,38 @@ out_free:
        kfree(data);
 }
 IWL_EXPORT_SYMBOL(iwl_acpi_get_phy_filters);
+
+void iwl_acpi_get_guid_lock_status(struct iwl_fw_runtime *fwrt)
+{
+       union acpi_object *wifi_pkg, *data;
+       int tbl_rev;
+
+       data = iwl_acpi_get_object(fwrt->dev, ACPI_GLAI_METHOD);
+       if (IS_ERR(data))
+               return;
+
+       wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
+                                        ACPI_GLAI_WIFI_DATA_SIZE,
+                                        &tbl_rev);
+       if (IS_ERR(wifi_pkg))
+               goto out_free;
+
+       if (tbl_rev != 0) {
+               IWL_DEBUG_RADIO(fwrt, "Invalid GLAI revision: %d\n", tbl_rev);
+               goto out_free;
+       }
+
+       if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER ||
+           wifi_pkg->package.elements[1].integer.value > ACPI_GLAI_MAX_STATUS)
+               goto out_free;
+
+       fwrt->uefi_tables_lock_status =
+               wifi_pkg->package.elements[1].integer.value;
+
+       IWL_DEBUG_RADIO(fwrt,
+                       "Loaded UEFI WIFI GUID lock status: %d from ACPI\n",
+                       fwrt->uefi_tables_lock_status);
+out_free:
+       kfree(data);
+}
+IWL_EXPORT_SYMBOL(iwl_acpi_get_guid_lock_status);
index 39106ccb4b9b663b6b17221b016009bbc3a821c5..7b3c6fca7591fcc01415045f3aced0944d6b3235 100644 (file)
@@ -25,6 +25,7 @@
 #define ACPI_PPAG_METHOD       "PPAG"
 #define ACPI_WTAS_METHOD       "WTAS"
 #define ACPI_WPFC_METHOD       "WPFC"
+#define ACPI_GLAI_METHOD       "GLAI"
 
 #define ACPI_WIFI_DOMAIN       (0x07)
 
 #define ACPI_WRDD_WIFI_DATA_SIZE       2
 #define ACPI_SPLC_WIFI_DATA_SIZE       2
 #define ACPI_ECKV_WIFI_DATA_SIZE       2
-
+/*
+ * One element for domain type,
+ * and one for the status
+ */
+#define ACPI_GLAI_WIFI_DATA_SIZE       2
+#define ACPI_GLAI_MAX_STATUS           2
 /*
  * TAS size: 1 elelment for type,
  *          1 element for enabled field,
@@ -237,6 +243,8 @@ bool iwl_acpi_is_ppag_approved(struct iwl_fw_runtime *fwrt);
 void iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt,
                              struct iwl_phy_specific_cfg *filters);
 
+void iwl_acpi_get_guid_lock_status(struct iwl_fw_runtime *fwrt);
+
 #else /* CONFIG_ACPI */
 
 static inline void *iwl_acpi_get_dsm_object(struct device *dev, int rev,
@@ -331,6 +339,9 @@ static inline void iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt,
 {
 }
 
+static inline void iwl_acpi_get_guid_lock_status(struct iwl_fw_runtime *fwrt)
+{
+}
 #endif /* CONFIG_ACPI */
 
 #endif /* __iwl_fw_acpi__ */
index 357727774db908f1a5e13f1a4199ec391cb69d04..1ec2bcdf92b80ac7f9aaadafa3d69ddd104ba0a9 100644 (file)
@@ -100,6 +100,9 @@ struct iwl_txf_iter_data {
  * @dump: debug dump data
  * @uats_enabled: VLP or AFC AP is enabled
  * @uats_table: AP type table
+ * @uefi_tables_lock_status: The status of the WIFI GUID UEFI variables lock:
+ *     0: Unlocked, 1 and 2: Locked.
+ *     Only read the UEFI variables if locked.
  */
 struct iwl_fw_runtime {
        struct iwl_trans *trans;
@@ -175,6 +178,7 @@ struct iwl_fw_runtime {
        u8 reduced_power_flags;
        bool uats_enabled;
        struct iwl_uats_table_cmd uats_table;
+       u8 uefi_tables_lock_status;
 #endif
 };
 
index 175024170357dedf042866d3964247dfc6379da3..a6db290923cd4132f9c02cc04469e56ea0427f86 100644 (file)
@@ -1402,6 +1402,8 @@ void iwl_mvm_get_acpi_tables(struct iwl_mvm *mvm)
 {
        int ret;
 
+       iwl_acpi_get_guid_lock_status(&mvm->fwrt);
+
        /* read PPAG table */
        ret = iwl_acpi_get_ppag_table(&mvm->fwrt);
        if (ret < 0) {