[PATCH v3 08/57] x86: acpi: Support external GNVS tables

Simon Glass
2020-09-06T21:43:16Z

At present U-Boot puts a magic number in the ASL for the GNVS table and
searches for it later.

Add a Kconfig option to use a different approach, where the ASL files
declare the table as an external symbol. U-Boot can then put it wherever
it likes, without any magic numbers or searching.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

arch/x86/Kconfig | 7 +++++
arch/x86/cpu/apollolake/Kconfig | 1 +
arch/x86/include/asm/acpi/global_nvs.h | 3 ++
arch/x86/lib/acpi_table.c | 42 ++++++++++++++------------
4 files changed, 33 insertions(+), 20 deletions(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 256a1100bd3..680f26f1b8e 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -788,6 +788,13 @@ config GENERATE_ACPI_TABLE
by the operating system. It defines platform-independent interfaces
for configuration and power management monitoring.

+config ACPI_GNVS_EXTERNAL
+ bool
+ help
+ Put the GNVS (Global Non-Volatile Sleeping) table separate from the
+ DSDT and add a pointer to the table from the DSDT. This allows
+ U-Boot to better control the address of the GNVS.
+
endmenu

config HAVE_ACPI_RESUME
diff --git a/arch/x86/cpu/apollolake/Kconfig b/arch/x86/cpu/apollolake/Kconfig
index 37d6289ee41..16ac2b3f504 100644
--- a/arch/x86/cpu/apollolake/Kconfig
+++ b/arch/x86/cpu/apollolake/Kconfig
@@ -17,6 +17,7 @@ config INTEL_APOLLOLAKE
select PCH_SUPPORT
select P2SB
select SMP_AP_WORK
+ select ACPI_GNVS_EXTERNAL
imply ENABLE_MRC_CACHE
imply AHCI_PCI
imply SCSI
diff --git a/arch/x86/include/asm/acpi/global_nvs.h b/arch/x86/include/asm/acpi/global_nvs.h
index d56d35ca533..a552cf6374f 100644
--- a/arch/x86/include/asm/acpi/global_nvs.h
+++ b/arch/x86/include/asm/acpi/global_nvs.h
@@ -11,6 +11,9 @@
* ACPI_GNVS_SIZE. They are to be used in platform's global_nvs.asl file
* to declare the GNVS OperationRegion, as well as write_acpi_tables()
* for the GNVS address runtime fix up.
+ *
+ * If using CONFIG_ACPI_GNVS_EXTERNAL, we don't need to locate the GNVS in
+ * DSDT, since it is created by code, so ACPI_GNVS_ADDR is unused.
*/
#define ACPI_GNVS_ADDR 0xdeadbeef
#define ACPI_GNVS_SIZE 0x100
diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c
index 3a93fedfc3e..942b2334eab 100644
--- a/arch/x86/lib/acpi_table.c
+++ b/arch/x86/lib/acpi_table.c
@@ -428,17 +428,30 @@ ulong write_acpi_tables(ulong start_addr)
dsdt->length - sizeof(struct acpi_table_header));

acpi_inc_align(ctx, dsdt->length - sizeof(struct acpi_table_header));
+ dsdt->length = ctx->current - (void *)dsdt;

- /* Pack GNVS into the ACPI table area */
- for (i = 0; i < dsdt->length; i++) {
- u32 *gnvs = (u32 *)((u32)dsdt + i);
- if (*gnvs == ACPI_GNVS_ADDR) {
- ulong addr = (ulong)map_to_sysmem(ctx->current);
-
- debug("Fix up global NVS in DSDT to %#08lx\n", addr);
- *gnvs = addr;
- break;
+ if (!IS_ENABLED(CONFIG_ACPI_GNVS_EXTERNAL)) {
+ /* Pack GNVS into the ACPI table area */
+ for (i = 0; i < dsdt->length; i++) {
+ u32 *gnvs = (u32 *)((u32)dsdt + i);
+
+ if (*gnvs == ACPI_GNVS_ADDR) {
+ *gnvs = map_to_sysmem(ctx->current);
+ debug("Fix up global NVS in DSDT to %#08x\n",
+ *gnvs);
+ break;
+ }
}
+
+ /*
+ * Fill in platform-specific global NVS variables. If this fails
+ * we cannot return the error but this should only happen while
+ * debugging.
+ */
+ addr = acpi_create_gnvs(ctx->current);
+ if (IS_ERR_VALUE(addr))
+ printf("Error: Gailed to create GNVS\n");
+ acpi_inc_align(ctx, sizeof(struct acpi_global_nvs));
}

/*
@@ -446,20 +459,9 @@ ulong write_acpi_tables(ulong start_addr)
* the GNVS address. Set the checksum to zero since it is part of the
* region being checksummed.
*/
- dsdt->length = ctx->current - (void *)dsdt;
dsdt->checksum = 0;
dsdt->checksum = table_compute_checksum((void *)dsdt, dsdt->length);

- /*
- * Fill in platform-specific global NVS variables. If this fails we
- * cannot return the error but this should only happen while debugging.
- */
- addr = acpi_create_gnvs(ctx->current);
- if (IS_ERR_VALUE(addr))
- printf("Error: Failed to create GNVS\n");
-
- acpi_inc_align(ctx, sizeof(struct acpi_global_nvs));
-
debug("ACPI: * FADT\n");
fadt = ctx->current;
acpi_inc_align(ctx, sizeof(struct acpi_fadt));
--
2.28.0.526.ge36021eeef-goog