mirror of
https://xff.cz/git/u-boot/
synced 2025-09-02 09:12:08 +02:00
x86: acpi: Add one API to find OS wakeup vector
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> Reviewed-by: Simon Glass <sjg@chromium.org> Tested-by: Stefan Roese <sr@denx.de>
This commit is contained in:
@@ -317,3 +317,13 @@ int acpi_create_madt_lapic_nmi(struct acpi_madt_lapic_nmi *lapic_nmi,
|
|||||||
u32 acpi_fill_madt(u32 current);
|
u32 acpi_fill_madt(u32 current);
|
||||||
void acpi_create_gnvs(struct acpi_global_nvs *gnvs);
|
void acpi_create_gnvs(struct acpi_global_nvs *gnvs);
|
||||||
ulong write_acpi_tables(ulong start);
|
ulong write_acpi_tables(ulong start);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* acpi_find_wakeup_vector() - find OS installed wake up vector address
|
||||||
|
*
|
||||||
|
* This routine parses the ACPI table to locate the wake up vector installed
|
||||||
|
* by the OS previously.
|
||||||
|
*
|
||||||
|
* @return: wake up vector address installed by the OS
|
||||||
|
*/
|
||||||
|
void *acpi_find_wakeup_vector(void);
|
||||||
|
@@ -15,6 +15,7 @@
|
|||||||
* PIRQ routing table, Multi-Processor table and ACPI table.
|
* PIRQ routing table, Multi-Processor table and ACPI table.
|
||||||
*/
|
*/
|
||||||
#define ROM_TABLE_ADDR 0xf0000
|
#define ROM_TABLE_ADDR 0xf0000
|
||||||
|
#define ROM_TABLE_END 0xfffff
|
||||||
|
|
||||||
#define ROM_TABLE_ALIGN 1024
|
#define ROM_TABLE_ALIGN 1024
|
||||||
|
|
||||||
|
@@ -438,3 +438,75 @@ ulong write_acpi_tables(ulong start)
|
|||||||
|
|
||||||
return current;
|
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;
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user