> On platforms that do not have usable DRAM below 4GiB, like QEMU sbsa, > the RSDT cannot be used. Allow both RSDT and XSDT to be null and only > fill those tables that are present in acpi_add_table().
I'm not sure what ACPI 2.0 from the subject has to do with the above, eg ACPI only started supporting aarch64 with ACPI 5.1 > Fixes a crash on QEMU sbsa. > > Signed-off-by: Patrick Rudolph <patrick.rudo...@9elements.com> > Cc: Simon Glass <s...@chromium.org> > Cc: Tom Rini <tr...@konsulko.com> > --- > lib/acpi/acpi_table.c | 95 ++++++++++++++++++++++++++----------------- > 1 file changed, 57 insertions(+), 38 deletions(-) > > diff --git a/lib/acpi/acpi_table.c b/lib/acpi/acpi_table.c > index 4f5cfe522c..8aab41212a 100644 > --- a/lib/acpi/acpi_table.c > +++ b/lib/acpi/acpi_table.c > @@ -157,51 +157,70 @@ int acpi_add_table(struct acpi_ctx *ctx, void *table) > struct acpi_rsdt *rsdt; > struct acpi_xsdt *xsdt; > > - /* The RSDT is mandatory while the XSDT is not */ > - rsdt = ctx->rsdt; > - > - /* This should always be MAX_ACPI_TABLES */ > - entries_num = ARRAY_SIZE(rsdt->entry); > - > - for (i = 0; i < entries_num; i++) { > - if (rsdt->entry[i] == 0) > - break; > - } > - > - if (i >= entries_num) { > - log_err("ACPI: Error: too many tables\n"); > - return -E2BIG; > - } > + /* On legacy x86 platforms the RSDT is mandatory while the XSDT is > not. > + * On other platforms there might be no memory below 4GiB, thus RSDT > is NULL. > + */ > + if (ctx->rsdt) { > + rsdt = ctx->rsdt; > > - /* Add table to the RSDT */ > - rsdt->entry[i] = nomap_to_sysmem(table); > + /* This should always be MAX_ACPI_TABLES */ > + entries_num = ARRAY_SIZE(rsdt->entry); > > - /* Fix RSDT length or the kernel will assume invalid entries */ > - rsdt->header.length = sizeof(struct acpi_table_header) + > - (sizeof(u32) * (i + 1)); > + for (i = 0; i < entries_num; i++) { > + if (rsdt->entry[i] == 0) > + break; > + } > > - /* Re-calculate checksum */ > - rsdt->header.checksum = 0; > - rsdt->header.checksum = table_compute_checksum((u8 *)rsdt, > - rsdt->header.length); > + if (i >= entries_num) { > + log_err("ACPI: Error: too many tables\n"); > + return -E2BIG; > + } > > - /* > - * And now the same thing for the XSDT. We use the same index as for > - * now we want the XSDT and RSDT to always be in sync in U-Boot > - */ > - xsdt = ctx->xsdt; > + /* Add table to the RSDT */ > + rsdt->entry[i] = nomap_to_sysmem(table); > > - /* Add table to the XSDT */ > - xsdt->entry[i] = nomap_to_sysmem(table); > + /* Fix RSDT length or the kernel will assume invalid entries > */ > + rsdt->header.length = sizeof(struct acpi_table_header) + > + (sizeof(u32) * (i + 1)); > > - /* Fix XSDT length */ > - xsdt->header.length = sizeof(struct acpi_table_header) + > - (sizeof(u64) * (i + 1)); > + /* Re-calculate checksum */ > + rsdt->header.checksum = 0; > + rsdt->header.checksum = table_compute_checksum((u8 *)rsdt, > + > rsdt->header.length); > + } > > - /* Re-calculate checksum */ > - xsdt->header.checksum = 0; > - xsdt->header.checksum = table_compute_checksum((u8 *)xsdt, > - xsdt->header.length); > + if (ctx->xsdt) { > + /* > + * And now the same thing for the XSDT. We use the same index > as for > + * now we want the XSDT and RSDT to always be in sync in > U-Boot > + */ > + xsdt = ctx->xsdt; > + > + /* This should always be MAX_ACPI_TABLES */ > + entries_num = ARRAY_SIZE(xsdt->entry); > + > + for (i = 0; i < entries_num; i++) { > + if (xsdt->entry[i] == 0) > + break; > + } > + > + if (i >= entries_num) { > + log_err("ACPI: Error: too many tables\n"); > + return -E2BIG; > + } > + > + /* Add table to the XSDT */ > + xsdt->entry[i] = nomap_to_sysmem(table); > + > + /* Fix XSDT length */ > + xsdt->header.length = sizeof(struct acpi_table_header) + > + (sizeof(u64) * (i + 1)); > + > + /* Re-calculate checksum */ > + xsdt->header.checksum = 0; > + xsdt->header.checksum = table_compute_checksum((u8 *)xsdt, > + > xsdt->header.length); > + } > > return 0; > } > -- > 2.46.0 >