From 29b351122ed23124f70473a411c65074d5a61146 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 26 Apr 2020 09:19:50 -0600 Subject: acpi: Move acpi_add_table() to generic code Move this code to a generic location so that we can test it with sandbox. This requires adding a few new fields to acpi_ctx, so drop the local variables used in the original code. Also use mapmem to avoid pointer-to-address casts which don't work on sandbox. Signed-off-by: Simon Glass Reviewed-by: Wolfgang Wallner --- lib/acpi/acpi_table.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) (limited to 'lib') diff --git a/lib/acpi/acpi_table.c b/lib/acpi/acpi_table.c index 07d9bbb0af..4e354d313f 100644 --- a/lib/acpi/acpi_table.c +++ b/lib/acpi/acpi_table.c @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include #include #include @@ -120,3 +122,62 @@ void acpi_inc_align(struct acpi_ctx *ctx, uint amount) ctx->current += amount; acpi_align(ctx); } + +/** + * Add an ACPI table to the RSDT (and XSDT) structure, recalculate length + * and checksum. + */ +int acpi_add_table(struct acpi_ctx *ctx, void *table) +{ + int i, entries_num; + 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; + } + + /* Add table to the RSDT */ + rsdt->entry[i] = map_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)); + + /* Re-calculate checksum */ + rsdt->header.checksum = 0; + rsdt->header.checksum = table_compute_checksum((u8 *)rsdt, + rsdt->header.length); + + /* + * 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 = map_sysmem(ctx->rsdp->xsdt_address, sizeof(*xsdt)); + + /* Add table to the XSDT */ + xsdt->entry[i] = map_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; +} -- cgit v1.2.3