Message ID | 20230428120405.3770496-9-nikos.nikoleris@arm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | EFI and ACPI support for arm64 | expand |
On 4/28/23 20:03, Nikos Nikoleris wrote: > XSDT provides pointers to other ACPI tables much like RSDT. However, > contrary to RSDT that provides 32-bit addresses, XSDT provides 64-bit > pointers. ACPI requires that if XSDT is valid then it takes precedence > over RSDT. > > Signed-off-by: Nikos Nikoleris <nikos.nikoleris@arm.com> > Reviewed-by: Andrew Jones <andrew.jones@linux.dev> > [ Alex E: Use flexible array member for XSDT struct ] > Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com> Reviewed-by: Shaoqin Huang <shahuang@redhat.com> > --- > lib/acpi.h | 6 ++++++ > lib/acpi.c | 40 ++++++++++++++++++++++++++++++++-------- > 2 files changed, 38 insertions(+), 8 deletions(-) > > diff --git a/lib/acpi.h b/lib/acpi.h > index 53e41c4b..74ba00ac 100644 > --- a/lib/acpi.h > +++ b/lib/acpi.h > @@ -14,6 +14,7 @@ > > #define RSDP_SIGNATURE ACPI_SIGNATURE('R','S','D','P') > #define RSDT_SIGNATURE ACPI_SIGNATURE('R','S','D','T') > +#define XSDT_SIGNATURE ACPI_SIGNATURE('X','S','D','T') > #define FACP_SIGNATURE ACPI_SIGNATURE('F','A','C','P') > #define FACS_SIGNATURE ACPI_SIGNATURE('F','A','C','S') > > @@ -56,6 +57,11 @@ struct acpi_table_rsdt_rev1 { > u32 table_offset_entry[]; > }; > > +struct acpi_table_xsdt { > + ACPI_TABLE_HEADER_DEF > + u64 table_offset_entry[]; > +}; > + > struct acpi_table_fadt_rev1 { > ACPI_TABLE_HEADER_DEF /* ACPI common table header */ > u32 firmware_ctrl; /* Physical address of FACS */ > diff --git a/lib/acpi.c b/lib/acpi.c > index 166ffd14..d35f09a6 100644 > --- a/lib/acpi.c > +++ b/lib/acpi.c > @@ -37,7 +37,8 @@ static struct acpi_table_rsdp *get_rsdp(void) > > void *find_acpi_table_addr(u32 sig) > { > - struct acpi_table_rsdt_rev1 *rsdt; > + struct acpi_table_rsdt_rev1 *rsdt = NULL; > + struct acpi_table_xsdt *xsdt = NULL; > struct acpi_table_rsdp *rsdp; > void *end; > int i; > @@ -62,18 +63,41 @@ void *find_acpi_table_addr(u32 sig) > return rsdp; > > rsdt = (void *)(ulong) rsdp->rsdt_physical_address; > - if (!rsdt || rsdt->signature != RSDT_SIGNATURE) > - return NULL; > + if (rsdt && rsdt->signature != RSDT_SIGNATURE) > + rsdt = NULL; > > if (sig == RSDT_SIGNATURE) > return rsdt; > > - end = (void *)rsdt + rsdt->length; > - for (i = 0; (void *)&rsdt->table_offset_entry[i] < end; i++) { > - struct acpi_table *t = (void *)(ulong) rsdt->table_offset_entry[i]; > + if (rsdp->revision >= 2) { > + xsdt = (void *)rsdp->xsdt_physical_address; > + if (xsdt && xsdt->signature != XSDT_SIGNATURE) > + xsdt = NULL; > + } > > - if (t && t->signature == sig) > - return t; > + if (sig == XSDT_SIGNATURE) > + return xsdt; > + > + /* > + * When the system implements APCI 2.0 and above and XSDT is valid we > + * have use XSDT to find other ACPI tables, otherwise, we use RSDT. > + */ > + if (xsdt) { > + end = (void *)xsdt + xsdt->length; > + for (i = 0; (void *)&xsdt->table_offset_entry[i] < end; i++) { > + struct acpi_table *t = (void *)(ulong) xsdt->table_offset_entry[i]; > + > + if (t && t->signature == sig) > + return t; > + } > + } else if (rsdt) { > + end = (void *)rsdt + rsdt->length; > + for (i = 0; (void *)&rsdt->table_offset_entry[i] < end; i++) { > + struct acpi_table *t = (void *)(ulong) rsdt->table_offset_entry[i]; > + > + if (t && t->signature == sig) > + return t; > + } > } > > return NULL;
diff --git a/lib/acpi.h b/lib/acpi.h index 53e41c4b..74ba00ac 100644 --- a/lib/acpi.h +++ b/lib/acpi.h @@ -14,6 +14,7 @@ #define RSDP_SIGNATURE ACPI_SIGNATURE('R','S','D','P') #define RSDT_SIGNATURE ACPI_SIGNATURE('R','S','D','T') +#define XSDT_SIGNATURE ACPI_SIGNATURE('X','S','D','T') #define FACP_SIGNATURE ACPI_SIGNATURE('F','A','C','P') #define FACS_SIGNATURE ACPI_SIGNATURE('F','A','C','S') @@ -56,6 +57,11 @@ struct acpi_table_rsdt_rev1 { u32 table_offset_entry[]; }; +struct acpi_table_xsdt { + ACPI_TABLE_HEADER_DEF + u64 table_offset_entry[]; +}; + struct acpi_table_fadt_rev1 { ACPI_TABLE_HEADER_DEF /* ACPI common table header */ u32 firmware_ctrl; /* Physical address of FACS */ diff --git a/lib/acpi.c b/lib/acpi.c index 166ffd14..d35f09a6 100644 --- a/lib/acpi.c +++ b/lib/acpi.c @@ -37,7 +37,8 @@ static struct acpi_table_rsdp *get_rsdp(void) void *find_acpi_table_addr(u32 sig) { - struct acpi_table_rsdt_rev1 *rsdt; + struct acpi_table_rsdt_rev1 *rsdt = NULL; + struct acpi_table_xsdt *xsdt = NULL; struct acpi_table_rsdp *rsdp; void *end; int i; @@ -62,18 +63,41 @@ void *find_acpi_table_addr(u32 sig) return rsdp; rsdt = (void *)(ulong) rsdp->rsdt_physical_address; - if (!rsdt || rsdt->signature != RSDT_SIGNATURE) - return NULL; + if (rsdt && rsdt->signature != RSDT_SIGNATURE) + rsdt = NULL; if (sig == RSDT_SIGNATURE) return rsdt; - end = (void *)rsdt + rsdt->length; - for (i = 0; (void *)&rsdt->table_offset_entry[i] < end; i++) { - struct acpi_table *t = (void *)(ulong) rsdt->table_offset_entry[i]; + if (rsdp->revision >= 2) { + xsdt = (void *)rsdp->xsdt_physical_address; + if (xsdt && xsdt->signature != XSDT_SIGNATURE) + xsdt = NULL; + } - if (t && t->signature == sig) - return t; + if (sig == XSDT_SIGNATURE) + return xsdt; + + /* + * When the system implements APCI 2.0 and above and XSDT is valid we + * have use XSDT to find other ACPI tables, otherwise, we use RSDT. + */ + if (xsdt) { + end = (void *)xsdt + xsdt->length; + for (i = 0; (void *)&xsdt->table_offset_entry[i] < end; i++) { + struct acpi_table *t = (void *)(ulong) xsdt->table_offset_entry[i]; + + if (t && t->signature == sig) + return t; + } + } else if (rsdt) { + end = (void *)rsdt + rsdt->length; + for (i = 0; (void *)&rsdt->table_offset_entry[i] < end; i++) { + struct acpi_table *t = (void *)(ulong) rsdt->table_offset_entry[i]; + + if (t && t->signature == sig) + return t; + } } return NULL;