[U-Boot,10/22] x86: acpi: Add one API to find OS wakeup vector

Submitted by Bin Meng on March 16, 2017, 2:26 p.m.

Details

Message ID 1489674408-17498-11-git-send-email-bmeng.cn@gmail.com
State New
Delegated to: Bin Meng
Headers show

Commit Message

Bin Meng March 16, 2017, 2:26 p.m.
This adds one API acpi_find_wakeup_vector() to locate OS wakeup
vector from the ACPI FACS table, to be used in the S3 boot path.

Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
---

 arch/x86/include/asm/acpi_table.h |  1 +
 arch/x86/include/asm/tables.h     |  1 +
 arch/x86/lib/acpi_table.c         | 72 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 74 insertions(+)

Comments

Simon Glass March 21, 2017, 8:06 p.m.
Hi Bin,

On 16 March 2017 at 08:26, Bin Meng <bmeng.cn@gmail.com> wrote:
> This adds one API acpi_find_wakeup_vector() to locate OS wakeup
> vector from the ACPI FACS table, to be used in the S3 boot path.
>
> Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
> ---
>
>  arch/x86/include/asm/acpi_table.h |  1 +
>  arch/x86/include/asm/tables.h     |  1 +
>  arch/x86/lib/acpi_table.c         | 72 +++++++++++++++++++++++++++++++++++++++
>  3 files changed, 74 insertions(+)
>
> diff --git a/arch/x86/include/asm/acpi_table.h b/arch/x86/include/asm/acpi_table.h
> index bbd80a1..6cadd90 100644
> --- a/arch/x86/include/asm/acpi_table.h
> +++ b/arch/x86/include/asm/acpi_table.h
> @@ -317,3 +317,4 @@ int acpi_create_madt_lapic_nmi(struct acpi_madt_lapic_nmi *lapic_nmi,
>  u32 acpi_fill_madt(u32 current);
>  void acpi_create_gnvs(struct acpi_global_nvs *gnvs);
>  ulong write_acpi_tables(ulong start);
> +void *acpi_find_wakeup_vector(void);

Function comment?
[...]

Regards,
Simon

Patch hide | download patch | download mbox

diff --git a/arch/x86/include/asm/acpi_table.h b/arch/x86/include/asm/acpi_table.h
index bbd80a1..6cadd90 100644
--- a/arch/x86/include/asm/acpi_table.h
+++ b/arch/x86/include/asm/acpi_table.h
@@ -317,3 +317,4 @@  int acpi_create_madt_lapic_nmi(struct acpi_madt_lapic_nmi *lapic_nmi,
 u32 acpi_fill_madt(u32 current);
 void acpi_create_gnvs(struct acpi_global_nvs *gnvs);
 ulong write_acpi_tables(ulong start);
+void *acpi_find_wakeup_vector(void);
diff --git a/arch/x86/include/asm/tables.h b/arch/x86/include/asm/tables.h
index d1b2388..9e8208b 100644
--- a/arch/x86/include/asm/tables.h
+++ b/arch/x86/include/asm/tables.h
@@ -15,6 +15,7 @@ 
  * PIRQ routing table, Multi-Processor table and ACPI table.
  */
 #define ROM_TABLE_ADDR	0xf0000
+#define ROM_TABLE_END	0xfffff
 
 #define ROM_TABLE_ALIGN	1024
 
diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c
index 355456d..f118345 100644
--- a/arch/x86/lib/acpi_table.c
+++ b/arch/x86/lib/acpi_table.c
@@ -438,3 +438,75 @@  ulong write_acpi_tables(ulong start)
 
 	return current;
 }
+
+static struct acpi_rsdp *acpi_valid_rsdp(struct acpi_rsdp *rsdp)
+{
+	if (strncmp((char *)rsdp, RSDP_SIG, sizeof(RSDP_SIG) - 1) != 0)
+		return NULL;
+
+	debug("Looking on %p for valid checksum\n", rsdp);
+
+	if (table_compute_checksum((void *)rsdp, 20) != 0)
+		return NULL;
+	debug("acpi rsdp checksum 1 passed\n");
+
+	if ((rsdp->revision > 1) &&
+	    (table_compute_checksum((void *)rsdp, rsdp->length) != 0))
+		return NULL;
+	debug("acpi rsdp checksum 2 passed\n");
+
+	return rsdp;
+}
+
+void *acpi_find_wakeup_vector(void)
+{
+	char *p, *end;
+	struct acpi_rsdp *rsdp = NULL;
+	struct acpi_rsdt *rsdt;
+	struct acpi_fadt *fadt = NULL;
+	struct acpi_facs *facs;
+	void *wake_vec;
+	int i;
+
+	debug("Trying to find the wakeup vector...\n");
+
+	/* Find RSDP */
+	for (p = (char *)ROM_TABLE_ADDR; p < (char *)ROM_TABLE_END; p += 16) {
+		rsdp = acpi_valid_rsdp((struct acpi_rsdp *)p);
+		if (rsdp)
+			break;
+	}
+
+	if (rsdp == NULL)
+		return NULL;
+
+	debug("RSDP found at %p\n", rsdp);
+	rsdt = (struct acpi_rsdt *)rsdp->rsdt_address;
+
+	end = (char *)rsdt + rsdt->header.length;
+	debug("RSDT found at %p ends at %p\n", rsdt, end);
+
+	for (i = 0; ((char *)&rsdt->entry[i]) < end; i++) {
+		fadt = (struct acpi_fadt *)rsdt->entry[i];
+		if (strncmp((char *)fadt, "FACP", 4) == 0)
+			break;
+		fadt = NULL;
+	}
+
+	if (fadt == NULL)
+		return NULL;
+
+	debug("FADT found at %p\n", fadt);
+	facs = (struct acpi_facs *)fadt->firmware_ctrl;
+
+	if (facs == NULL) {
+		debug("No FACS found, wake up from S3 not possible.\n");
+		return NULL;
+	}
+
+	debug("FACS found at %p\n", facs);
+	wake_vec = (void *)facs->firmware_waking_vector;
+	debug("OS waking vector is %p\n", wake_vec);
+
+	return wake_vec;
+}