[PATCH v10 11/15] platform/x86: dell-smbios-smm: test for WSMT

From: Mario Limonciello
Date: Thu Oct 19 2017 - 13:50:43 EST


WSMT is as an attestation to the OS that the platform won't
modify memory outside of pre-defined areas.

If a platform has WSMT enabled in BIOS setup, SMM calls through
dcdbas will fail. The only way to access platform data in these
instances is through the WMI SMBIOS calling interface.

Signed-off-by: Mario Limonciello <mario.limonciello@xxxxxxxx>
Reviewed-by: Edward O'Callaghan <quasisec@xxxxxxxxxx>
---
drivers/platform/x86/dell-smbios-smm.c | 33 +++++++++++++++++++++++++++++++++
drivers/platform/x86/dell-smbios.h | 2 ++
2 files changed, 35 insertions(+)

diff --git a/drivers/platform/x86/dell-smbios-smm.c b/drivers/platform/x86/dell-smbios-smm.c
index 53eabb14fb48..4175ccbded15 100644
--- a/drivers/platform/x86/dell-smbios-smm.c
+++ b/drivers/platform/x86/dell-smbios-smm.c
@@ -102,6 +102,31 @@ int dell_smbios_smm_call(struct calling_interface_buffer *input)
return 0;
}

+/* When enabled this indicates that SMM won't work */
+static bool test_wsmt_enabled(void)
+{
+ struct calling_interface_token *token;
+
+ /* if token doesn't exist, SMM will work */
+ token = dell_smbios_find_token(WSMT_EN_TOKEN);
+ if (!token)
+ return false;
+
+ /* if token exists, try to access over SMM */
+ buffer->class = CLASS_TOKEN_READ;
+ buffer->select = SELECT_TOKEN_STD;
+ memset(buffer, 0, sizeof(struct calling_interface_buffer));
+ buffer->input[0] = token->location;
+ dell_smbios_smm_call(buffer);
+
+ /* if lookup failed, we know WSMT was enabled */
+ if (buffer->output[0] != 0)
+ return true;
+
+ /* query token status if it didn't fail */
+ return (buffer->output[1] == token->value);
+}
+
static int __init dell_smbios_smm_init(void)
{
int ret;
@@ -115,6 +140,13 @@ static int __init dell_smbios_smm_init(void)

dmi_walk(find_cmd_address, NULL);

+ ret = test_wsmt_enabled();
+ pr_debug("WSMT enable test: %d\n", ret);
+ if (ret) {
+ ret = -ENODEV;
+ goto fail_wsmt;
+ }
+
platform_device = platform_device_alloc("dell-smbios", 1);
if (!platform_device) {
ret = -ENOMEM;
@@ -138,6 +170,7 @@ static int __init dell_smbios_smm_init(void)
fail_platform_device_add:
platform_device_put(platform_device);

+fail_wsmt:
fail_platform_device_alloc:
free_page((unsigned long)buffer);
return ret;
diff --git a/drivers/platform/x86/dell-smbios.h b/drivers/platform/x86/dell-smbios.h
index 079776421b46..956fe9304ed7 100644
--- a/drivers/platform/x86/dell-smbios.h
+++ b/drivers/platform/x86/dell-smbios.h
@@ -44,6 +44,8 @@
#define KBD_LED_AUTO_100_TOKEN 0x02F6
#define GLOBAL_MIC_MUTE_ENABLE 0x0364
#define GLOBAL_MIC_MUTE_DISABLE 0x0365
+#define WSMT_EN_TOKEN 0x04EC
+#define WSMT_DIS_TOKEN 0x04ED

struct notifier_block;

--
2.14.1