From 5019e201ccaee4bd54ba707dfc4eece885857629 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 4 Nov 2020 09:57:19 -0700 Subject: x86: acpi: Store the ACPI context in global_data At present we create the ACPI context but then drop it after generation of tables is complete. This is annoying because we have to then search for tables later. To fix this, allocate the context and store it in global_data. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/lib/acpi_table.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'arch/x86/lib/acpi_table.c') diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c index 6d405b09fd..f0f342d893 100644 --- a/arch/x86/lib/acpi_table.c +++ b/arch/x86/lib/acpi_table.c @@ -494,7 +494,7 @@ void acpi_create_ssdt(struct acpi_ctx *ctx, struct acpi_table_header *ssdt, */ ulong write_acpi_tables(ulong start_addr) { - struct acpi_ctx sctx, *ctx = &sctx; + struct acpi_ctx *ctx; struct acpi_facs *facs; struct acpi_table_header *dsdt; struct acpi_fadt *fadt; @@ -509,6 +509,11 @@ ulong write_acpi_tables(ulong start_addr) int ret; int i; + ctx = calloc(1, sizeof(*ctx)); + if (!ctx) + return log_msg_ret("mem", -ENOMEM); + gd->acpi_ctx = ctx; + start = map_sysmem(start_addr, 0); debug("ACPI: Writing ACPI tables at %lx\n", start_addr); -- cgit v1.2.3 From 2de4744dae572b6ba9c1c3e3a40b377e53994630 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 4 Nov 2020 09:57:31 -0700 Subject: x86: acpi: Allow the SSDT to be empty If there is nothing in the SSDT we should not include it in the tables. Update the implementation to check this. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/lib/acpi_table.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'arch/x86/lib/acpi_table.c') diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c index f0f342d893..c5c5c6e679 100644 --- a/arch/x86/lib/acpi_table.c +++ b/arch/x86/lib/acpi_table.c @@ -470,8 +470,9 @@ static void acpi_create_spcr(struct acpi_spcr *spcr) header->checksum = table_compute_checksum((void *)spcr, header->length); } -void acpi_create_ssdt(struct acpi_ctx *ctx, struct acpi_table_header *ssdt, - const char *oem_table_id) +static int acpi_create_ssdt(struct acpi_ctx *ctx, + struct acpi_table_header *ssdt, + const char *oem_table_id) { memset((void *)ssdt, '\0', sizeof(struct acpi_table_header)); @@ -484,9 +485,19 @@ void acpi_create_ssdt(struct acpi_ctx *ctx, struct acpi_table_header *ssdt, acpi_fill_ssdt(ctx); - /* (Re)calculate length and checksum. */ + /* (Re)calculate length and checksum */ ssdt->length = ctx->current - (void *)ssdt; ssdt->checksum = table_compute_checksum((void *)ssdt, ssdt->length); + log_debug("SSDT at %p, length %x\n", ssdt, ssdt->length); + + /* Drop the table if it is empty */ + if (ssdt->length == sizeof(struct acpi_table_header)) { + ctx->current = ssdt; + return -ENOENT; + } + acpi_align(ctx); + + return 0; } /* @@ -596,11 +607,8 @@ ulong write_acpi_tables(ulong start_addr) debug("ACPI: * SSDT\n"); ssdt = (struct acpi_table_header *)ctx->current; - acpi_create_ssdt(ctx, ssdt, OEM_TABLE_ID); - if (ssdt->length > sizeof(struct acpi_table_header)) { - acpi_inc_align(ctx, ssdt->length); + if (!acpi_create_ssdt(ctx, ssdt, OEM_TABLE_ID)) acpi_add_table(ctx, ssdt); - } debug("ACPI: * MCFG\n"); mcfg = ctx->current; -- cgit v1.2.3 From 01e3c9d2ecbb532ab98da46ceebe8507b6bceec8 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 4 Nov 2020 09:57:32 -0700 Subject: x86: acpi: Put the generated code first in DSDT The current implementation for DSDT tables is not correct for the case where there is generated code, as the length ends up being incorrect. Also, we want the generated code to go first in the table. Rewrite this piece to correct these problems. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/lib/acpi_table.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'arch/x86/lib/acpi_table.c') diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c index c5c5c6e679..423df5cbf9 100644 --- a/arch/x86/lib/acpi_table.c +++ b/arch/x86/lib/acpi_table.c @@ -505,6 +505,7 @@ static int acpi_create_ssdt(struct acpi_ctx *ctx, */ ulong write_acpi_tables(ulong start_addr) { + const int thl = sizeof(struct acpi_table_header); struct acpi_ctx *ctx; struct acpi_facs *facs; struct acpi_table_header *dsdt; @@ -516,6 +517,7 @@ ulong write_acpi_tables(ulong start_addr) struct acpi_csrt *csrt; struct acpi_spcr *spcr; void *start; + int aml_len; ulong addr; int ret; int i; @@ -541,21 +543,28 @@ ulong write_acpi_tables(ulong start_addr) dsdt = ctx->current; /* Put the table header first */ - memcpy(dsdt, &AmlCode, sizeof(struct acpi_table_header)); - acpi_inc(ctx, sizeof(struct acpi_table_header)); + memcpy(dsdt, &AmlCode, thl); + acpi_inc(ctx, thl); + log_debug("DSDT starts at %p, hdr ends at %p\n", dsdt, ctx->current); /* If the table is not empty, allow devices to inject things */ - if (dsdt->length >= sizeof(struct acpi_table_header)) - acpi_inject_dsdt(ctx); + aml_len = dsdt->length - thl; + if (aml_len) { + void *base = ctx->current; - /* Copy in the AML code itself if any (after the header) */ - memcpy(ctx->current, - (char *)&AmlCode + sizeof(struct acpi_table_header), - dsdt->length - sizeof(struct acpi_table_header)); + acpi_inject_dsdt(ctx); + log_debug("Added %x bytes from inject_dsdt, now at %p\n", + ctx->current - base, ctx->current); + log_debug("Copy AML code size %x to %p\n", aml_len, + ctx->current); + memcpy(ctx->current, AmlCode + thl, aml_len); + acpi_inc(ctx, aml_len); + } - acpi_inc(ctx, dsdt->length - sizeof(struct acpi_table_header)); dsdt->length = ctx->current - (void *)dsdt; acpi_align(ctx); + log_debug("Updated DSDT length to %x, total %x\n", dsdt->length, + ctx->current - (void *)dsdt); if (!IS_ENABLED(CONFIG_ACPI_GNVS_EXTERNAL)) { /* Pack GNVS into the ACPI table area */ -- cgit v1.2.3 From 18434aec1b69d8490cb23ef35b2f39cf1784d1d0 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 4 Nov 2020 09:57:33 -0700 Subject: acpi: Don't reset the tables with every new generation At present if SSDT and DSDT code is created, only the latter is retained for examination by the 'acpi items' command. Fix this by only resetting the list when explicitly requested. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/lib/acpi_table.c | 1 + drivers/core/acpi.c | 10 ++++++---- include/dm/acpi.h | 9 +++++++++ test/dm/acpi.c | 4 ++++ 4 files changed, 20 insertions(+), 4 deletions(-) (limited to 'arch/x86/lib/acpi_table.c') diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c index 423df5cbf9..66cff822dc 100644 --- a/arch/x86/lib/acpi_table.c +++ b/arch/x86/lib/acpi_table.c @@ -531,6 +531,7 @@ ulong write_acpi_tables(ulong start_addr) debug("ACPI: Writing ACPI tables at %lx\n", start_addr); + acpi_reset_items(); acpi_setup_base_tables(ctx, start); debug("ACPI: * FACS\n"); diff --git a/drivers/core/acpi.c b/drivers/core/acpi.c index 7fe93992b5..63a791f335 100644 --- a/drivers/core/acpi.c +++ b/drivers/core/acpi.c @@ -268,8 +268,7 @@ int acpi_recurse_method(struct acpi_ctx *ctx, struct udevice *parent, if (func) { void *start = ctx->current; - log_debug("\n"); - log_debug("- %s %p\n", parent->name, func); + log_debug("- method %d, %s %p\n", method, parent->name, func); ret = device_ofdata_to_platdata(parent); if (ret) return log_msg_ret("ofdata", ret); @@ -299,7 +298,6 @@ int acpi_fill_ssdt(struct acpi_ctx *ctx) int ret; log_debug("Writing SSDT tables\n"); - item_count = 0; ret = acpi_recurse_method(ctx, dm_root(), METHOD_FILL_SSDT, TYPE_SSDT); log_debug("Writing SSDT finished, err=%d\n", ret); ret = sort_acpi_item_type(ctx, start, TYPE_SSDT); @@ -315,7 +313,6 @@ int acpi_inject_dsdt(struct acpi_ctx *ctx) int ret; log_debug("Writing DSDT tables\n"); - item_count = 0; ret = acpi_recurse_method(ctx, dm_root(), METHOD_INJECT_DSDT, TYPE_DSDT); log_debug("Writing DSDT finished, err=%d\n", ret); @@ -326,6 +323,11 @@ int acpi_inject_dsdt(struct acpi_ctx *ctx) return ret; } +void acpi_reset_items(void) +{ + item_count = 0; +} + int acpi_write_dev_tables(struct acpi_ctx *ctx) { int ret; diff --git a/include/dm/acpi.h b/include/dm/acpi.h index e8b0336f6d..e6951b6a25 100644 --- a/include/dm/acpi.h +++ b/include/dm/acpi.h @@ -226,6 +226,15 @@ void acpi_dump_items(enum acpi_dump_option option); */ int acpi_get_path(const struct udevice *dev, char *out_path, int maxlen); +/** + * acpi_reset_items() - Reset the list of ACPI items to empty + * + * This list keeps track of DSDT and SSDT items that are generated + * programmatically. The 'acpi items' command shows the list. Use this function + * to empty the list, before writing new items. + */ +void acpi_reset_items(void); + #endif /* __ACPI__ */ #endif diff --git a/test/dm/acpi.c b/test/dm/acpi.c index 1f252a8d45..f5eddac10d 100644 --- a/test/dm/acpi.c +++ b/test/dm/acpi.c @@ -477,6 +477,7 @@ static int dm_test_acpi_fill_ssdt(struct unit_test_state *uts) buf = malloc(BUF_SIZE); ut_assertnonnull(buf); + acpi_reset_items(); ctx.current = buf; buf[4] = 'z'; /* sentinel */ ut_assertok(acpi_fill_ssdt(&ctx)); @@ -507,6 +508,7 @@ static int dm_test_acpi_inject_dsdt(struct unit_test_state *uts) buf = malloc(BUF_SIZE); ut_assertnonnull(buf); + acpi_reset_items(); ctx.current = buf; buf[4] = 'z'; /* sentinel */ ut_assertok(acpi_inject_dsdt(&ctx)); @@ -537,6 +539,7 @@ static int dm_test_acpi_cmd_items(struct unit_test_state *uts) buf = malloc(BUF_SIZE); ut_assertnonnull(buf); + acpi_reset_items(); ctx.current = buf; ut_assertok(acpi_fill_ssdt(&ctx)); console_record_reset(); @@ -545,6 +548,7 @@ static int dm_test_acpi_cmd_items(struct unit_test_state *uts) ut_assert_nextline("dev 'acpi-test2', type 1, size 2"); ut_assert_console_end(); + acpi_reset_items(); ctx.current = buf; ut_assertok(acpi_inject_dsdt(&ctx)); console_record_reset(); -- cgit v1.2.3 From 7f061e0d255d5cdfbd216960134ea66e474ae819 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 4 Nov 2020 09:57:40 -0700 Subject: x86: acpi: Include the TPMv1 table only if needed This table is not needed if a v2 TPM is in use. Add a condition to avoid adding it when not needed. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/lib/acpi_table.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'arch/x86/lib/acpi_table.c') diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c index 66cff822dc..9f0871c9f4 100644 --- a/arch/x86/lib/acpi_table.c +++ b/arch/x86/lib/acpi_table.c @@ -646,14 +646,17 @@ ulong write_acpi_tables(ulong start_addr) acpi_inc_align(ctx, madt->header.length); acpi_add_table(ctx, madt); - debug("ACPI: * TCPA\n"); - tcpa = (struct acpi_tcpa *)ctx->current; - ret = acpi_create_tcpa(tcpa); - if (ret) { - log_warning("Failed to create TCPA table (err=%d)\n", ret); - } else { - acpi_inc_align(ctx, tcpa->header.length); - acpi_add_table(ctx, tcpa); + if (IS_ENABLED(CONFIG_TPM_V1)) { + debug("ACPI: * TCPA\n"); + tcpa = (struct acpi_tcpa *)ctx->current; + ret = acpi_create_tcpa(tcpa); + if (ret) { + log_warning("Failed to create TCPA table (err=%d)\n", + ret); + } else { + acpi_inc_align(ctx, tcpa->header.length); + acpi_add_table(ctx, tcpa); + } } debug("ACPI: * CSRT\n"); -- cgit v1.2.3 From 98bf740e7f690951acf672486d57587e21237da8 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 4 Nov 2020 09:57:41 -0700 Subject: x86: acpi: Don't show the UART address by default This is useful when using Linux's earlycon since the MMIO address must be provided on some platforms, e.g.: earlycon=uart8250,mmio32,0xddffc000,115200n8 However this is only for debugging, so don't show it by default. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/lib/acpi_table.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86/lib/acpi_table.c') diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c index 9f0871c9f4..4fd8dc8ad9 100644 --- a/arch/x86/lib/acpi_table.c +++ b/arch/x86/lib/acpi_table.c @@ -767,7 +767,7 @@ int acpi_write_dbg2_pci_uart(struct acpi_ctx *ctx, struct udevice *dev, * 32-bits each. This is only for debugging so it is not a big deal. */ addr = dm_pci_read_bar32(dev, 0); - printf("UART addr %lx\n", (ulong)addr); + log_debug("UART addr %lx\n", (ulong)addr); memset(&address, '\0', sizeof(address)); address.space_id = ACPI_ADDRESS_SPACE_MEMORY; -- cgit v1.2.3