summaryrefslogtreecommitdiff
path: root/src/cpu/x86/smm/smi_trigger.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cpu/x86/smm/smi_trigger.c')
-rw-r--r--src/cpu/x86/smm/smi_trigger.c35
1 files changed, 34 insertions, 1 deletions
diff --git a/src/cpu/x86/smm/smi_trigger.c b/src/cpu/x86/smm/smi_trigger.c
index f1031a00f6..4b637450b7 100644
--- a/src/cpu/x86/smm/smi_trigger.c
+++ b/src/cpu/x86/smm/smi_trigger.c
@@ -1,9 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0-only */
+#include <acpi/acpi_gnvs.h>
#include <arch/io.h>
#include <console/console.h>
#include <cpu/x86/smm.h>
+static void set_smm_gnvs_ptr(void);
+
int apm_control(u8 cmd)
{
if (!CONFIG(HAVE_SMI_HANDLER))
@@ -21,7 +24,8 @@ int apm_control(u8 cmd)
printk(BIOS_DEBUG, "Enabling ACPI via APMC.\n");
break;
case APM_CNT_GNVS_UPDATE:
- break;
+ set_smm_gnvs_ptr();
+ return 0;
case APM_CNT_FINALIZE:
printk(BIOS_DEBUG, "Finalizing SMM.\n");
break;
@@ -41,3 +45,32 @@ int apm_control(u8 cmd)
printk(BIOS_DEBUG, "APMC done.\n");
return 0;
}
+
+static void set_smm_gnvs_ptr(void)
+{
+ uintptr_t gnvs_address;
+
+ if (CONFIG(ACPI_NO_SMI_GNVS)) {
+ printk(BIOS_WARNING, "%s() is not implemented\n", __func__);
+ return;
+ }
+
+ gnvs_address = (uintptr_t)acpi_get_gnvs();
+ if (!gnvs_address)
+ return;
+
+ /*
+ * Issue SMI to set the gnvs pointer in SMM.
+ *
+ * EAX = APM_CNT_GNVS_UPDATE
+ * EBX = gnvs pointer
+ * EDX = APM_CNT
+ */
+ asm volatile (
+ "outb %%al, %%dx\n\t"
+ : /* ignore result */
+ : "a" (APM_CNT_GNVS_UPDATE),
+ "b" (gnvs_address),
+ "d" (APM_CNT)
+ );
+}