From fb746fdec6d58eacd7d9323eda7ccbde9419a41e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 1 Dec 2021 09:02:46 -0700 Subject: acpi: Add a table start It is useful to record the start of an ACPI table so that offsets from that point can be easily calculated. Add this to the context and set it before calling the writer method. Signed-off-by: Simon Glass --- include/dm/acpi.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include/dm') diff --git a/include/dm/acpi.h b/include/dm/acpi.h index 0fa239eb3a8..a2da57fe224 100644 --- a/include/dm/acpi.h +++ b/include/dm/acpi.h @@ -43,6 +43,9 @@ enum acpi_dump_option { * * @base: Base address of ACPI tables * @current: Current address for writing + * @tab_start: Address of start of the table being written. This is set up + * before the writer or driver method is called. It must not be changed by the + * method * @rsdp: Pointer to the Root System Description Pointer, typically used when * adding a new table. The RSDP holds pointers to the RSDT and XSDT. * @rsdt: Pointer to the Root System Description Table @@ -56,6 +59,7 @@ enum acpi_dump_option { struct acpi_ctx { void *base; void *current; + void *tab_start; struct acpi_rsdp *rsdp; struct acpi_rsdt *rsdt; struct acpi_xsdt *xsdt; -- cgit v1.3.1 From 6afa63a5a63662fa7e517b29da613f51e9e68429 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 1 Dec 2021 09:02:47 -0700 Subject: acpi: Add a linker list for ACPI tables At present we call lots of functions to generate the required ACPI tables. It would be better to standardise these functions and allow them to be automatically collected and used when needed. Add a linker list to handle this. Signed-off-by: Simon Glass --- include/dm/acpi.h | 57 +++++++++++++++++++++++++++++++ lib/acpi/acpi_writer.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+) create mode 100644 lib/acpi/acpi_writer.c (limited to 'include/dm') diff --git a/include/dm/acpi.h b/include/dm/acpi.h index a2da57fe224..2f52950d16e 100644 --- a/include/dm/acpi.h +++ b/include/dm/acpi.h @@ -27,6 +27,8 @@ #if !defined(__ACPI__) +#include + struct nhlt; struct udevice; @@ -68,6 +70,48 @@ struct acpi_ctx { int ltop; }; +/** + * enum acpi_writer_flags_t - flags to use for the ACPI writers + */ +enum acpi_writer_flags_t { + ACPIWF_ALIGN64_, +}; + +struct acpi_writer; + +/** + * acpi_writer_func() - Function that can write an ACPI table + * + * @ctx: ACPI context to use for writing + * @entry: Linker-list entry for this writer + * @return 0 if OK, -ve on error + */ +typedef int (*acpi_writer_func)(struct acpi_ctx *ctx, + const struct acpi_writer *entry); + +/** + * struct acpi_writer - an ACPI table that can be written + * + * @name: Name of the writer + * @table: Table name that is generated (e.g. "DSDT") + * @h_write: Writer function + */ +struct acpi_writer { + const char *name; + const char *table; + acpi_writer_func h_write; + int flags; +}; + +/* Declare a new ACPI table writer */ +#define ACPI_WRITER(_name, _table, _write, _flags) \ + ll_entry_declare(struct acpi_writer, _name, acpi_writer) = { \ + .name = #_name, \ + .table = _table, \ + .h_write = _write, \ + .flags = _flags, \ + } + /** * struct acpi_ops - ACPI operations supported by driver model */ @@ -240,6 +284,19 @@ int acpi_get_path(const struct udevice *dev, char *out_path, int maxlen); */ void acpi_reset_items(void); +/** + * acpi_write_one() - Call a single ACPI writer entry + * + * This handles aligning the context afterwards, if the entry flags indicate + * that. + * + * @ctx: ACPI context to use + * @entry: Entry to call + * @return 0 if OK, -ENOENT if this writer produced an empty entry, other -ve + * value on error + */ +int acpi_write_one(struct acpi_ctx *ctx, const struct acpi_writer *entry); + #endif /* __ACPI__ */ #endif diff --git a/lib/acpi/acpi_writer.c b/lib/acpi/acpi_writer.c new file mode 100644 index 00000000000..5ddffc87343 --- /dev/null +++ b/lib/acpi/acpi_writer.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Handles writing the declared ACPI tables + * + * Copyright 2021 Google LLC + */ + +#define LOG_CATEGORY LOGC_ACPI + +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +int acpi_write_one(struct acpi_ctx *ctx, const struct acpi_writer *entry) +{ + int ret; + + log_debug("%s: writing table '%s'\n", entry->name, + entry->table); + ctx->tab_start = ctx->current; + ret = entry->h_write(ctx, entry); + if (ret == -ENOENT) { + log_debug("%s: Omitted due to being empty\n", + entry->name); + ret = 0; + ctx->current = ctx->tab_start; /* drop the table */ + return ret; + } + if (ret) + return log_msg_ret("write", ret); + + acpi_align(ctx); + + return 0; +} + +static int acpi_write_all(struct acpi_ctx *ctx) +{ + const struct acpi_writer *writer = + ll_entry_start(struct acpi_writer, acpi_writer); + const int n_ents = ll_entry_count(struct acpi_writer, acpi_writer); + const struct acpi_writer *entry; + int ret; + + for (entry = writer; entry != writer + n_ents; entry++) { + ret = acpi_write_one(ctx, entry); + if (ret && ret != -ENOENT) + return log_msg_ret("one", ret); + } + + return 0; +} + +/* + * QEMU's version of write_acpi_tables is defined in drivers/misc/qfw.c + */ +ulong write_acpi_tables(ulong start_addr) +{ + struct acpi_ctx *ctx; + ulong addr; + void *start; + int ret; + + ctx = calloc(1, sizeof(*ctx)); + if (!ctx) + return log_msg_ret("mem", -ENOMEM); + gd->acpi_ctx = ctx; + + start = map_sysmem(start_addr, 0); + + log_debug("ACPI: Writing ACPI tables at %lx\n", start_addr); + + acpi_reset_items(); + + ret = acpi_write_all(ctx); + if (ret) { + log_err("Failed to write ACPI tables (err=%d)\n", ret); + return log_msg_ret("write", -ENOMEM); + } + + addr = map_to_sysmem(ctx->current); + log_debug("ACPI current = %lx\n", addr); + + return addr; +} -- cgit v1.3.1 From cc1f8c39882c5100ec07dfa46e32ff395d792b94 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 1 Dec 2021 09:02:48 -0700 Subject: x86: acpi: Split out context creation from base tables At present acpi_setup_base_tables() both sets up the ACPI context and writes out the base tables. We want to use an ACPI writer to write the base tables, so split this function into two, with acpi_setup_ctx() doing the context set, and acpi_setup_base_tables() just doing the base tables. Disable the writer's write_acpi_tables() function for now, to avoid build errors. It is enabled in a following patch. Signed-off-by: Simon Glass --- arch/x86/lib/acpi_table.c | 6 +++--- include/acpi/acpi_table.h | 10 +++++----- include/dm/acpi.h | 12 ++++++++++++ lib/acpi/Makefile | 1 + lib/acpi/acpi_table.c | 11 ++--------- lib/acpi/acpi_writer.c | 22 ++++++++++++++++------ test/dm/acpi.c | 31 ++++++++++++++++++++++++++----- 7 files changed, 65 insertions(+), 28 deletions(-) (limited to 'include/dm') diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c index 3f847711e2b..f57323b5c3f 100644 --- a/arch/x86/lib/acpi_table.c +++ b/arch/x86/lib/acpi_table.c @@ -522,17 +522,17 @@ ulong write_acpi_tables(ulong start_addr) int ret; int i; - ctx = calloc(1, sizeof(*ctx)); + ctx = malloc(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); acpi_reset_items(); - acpi_setup_base_tables(ctx, start); + acpi_setup_ctx(ctx, start); + acpi_setup_base_tables(ctx); debug("ACPI: * FACS\n"); facs = ctx->current; diff --git a/include/acpi/acpi_table.h b/include/acpi/acpi_table.h index d3fbdc1de2b..f34bd6311a1 100644 --- a/include/acpi/acpi_table.h +++ b/include/acpi/acpi_table.h @@ -679,14 +679,14 @@ void acpi_inc_align(struct acpi_ctx *ctx, uint amount); int acpi_add_table(struct acpi_ctx *ctx, void *table); /** - * acpi_setup_base_tables() - Set up context along with RSDP, RSDT and XSDT + * acpi_setup_base_tables() - Set up base tables - RSDP, RSDT and XSDT * - * Set up the context with the given start position. Some basic tables are - * always needed, so set them up as well. + * Writes the basic tables to the given context, which must first be set up with + * acpi_setup_ctx(). * - * @ctx: Context to set up + * @ctx: Context to write base tables to */ -void acpi_setup_base_tables(struct acpi_ctx *ctx, void *start); +void acpi_setup_base_tables(struct acpi_ctx *ctx); /** * acpi_write_rsdp() - Write out an RSDP indicating where the ACPI tables are diff --git a/include/dm/acpi.h b/include/dm/acpi.h index 2f52950d16e..f6e54793f79 100644 --- a/include/dm/acpi.h +++ b/include/dm/acpi.h @@ -297,6 +297,18 @@ void acpi_reset_items(void); */ int acpi_write_one(struct acpi_ctx *ctx, const struct acpi_writer *entry); +/** + * acpi_setup_ctx() - Set up a new ACPI context + * + * This zeros the context and sets up the base and current pointers, ensuring + * that they are aligned. Then it writes the acpi_start and acpi_ctx values in + * global_data + * + * @ctx: ACPI context to set up + * @start: Start address for ACPI table + */ +void acpi_setup_ctx(struct acpi_ctx *ctx, ulong start); + #endif /* __ACPI__ */ #endif diff --git a/lib/acpi/Makefile b/lib/acpi/Makefile index f5d58aba908..1318e83dfc4 100644 --- a/lib/acpi/Makefile +++ b/lib/acpi/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_$(SPL_)ACPIGEN) += acpigen.o obj-$(CONFIG_$(SPL_)ACPIGEN) += acpi_device.o obj-$(CONFIG_$(SPL_)ACPIGEN) += acpi_dp.o obj-$(CONFIG_$(SPL_)ACPIGEN) += acpi_table.o +obj-y += acpi_writer.o diff --git a/lib/acpi/acpi_table.c b/lib/acpi/acpi_table.c index 3a72718df89..284b5a9afb8 100644 --- a/lib/acpi/acpi_table.c +++ b/lib/acpi/acpi_table.c @@ -253,15 +253,8 @@ static void acpi_write_xsdt(struct acpi_xsdt *xsdt) sizeof(struct acpi_xsdt)); } -void acpi_setup_base_tables(struct acpi_ctx *ctx, void *start) +void acpi_setup_base_tables(struct acpi_ctx *ctx) { - ctx->base = start; - ctx->current = start; - - /* Align ACPI tables to 16 byte */ - acpi_align(ctx); - gd_set_acpi_start(map_to_sysmem(ctx->current)); - /* We need at least an RSDP and an RSDT Table */ ctx->rsdp = ctx->current; acpi_inc_align(ctx, sizeof(struct acpi_rsdp)); @@ -271,7 +264,7 @@ void acpi_setup_base_tables(struct acpi_ctx *ctx, void *start) acpi_inc_align(ctx, sizeof(struct acpi_xsdt)); /* clear all table memory */ - memset((void *)start, '\0', ctx->current - start); + memset(ctx->base, '\0', ctx->current - ctx->base); acpi_write_rsdp(ctx->rsdp, ctx->rsdt, ctx->xsdt); acpi_write_rsdt(ctx->rsdt); diff --git a/lib/acpi/acpi_writer.c b/lib/acpi/acpi_writer.c index 5ddffc87343..7779bf38aab 100644 --- a/lib/acpi/acpi_writer.c +++ b/lib/acpi/acpi_writer.c @@ -60,23 +60,20 @@ static int acpi_write_all(struct acpi_ctx *ctx) /* * QEMU's version of write_acpi_tables is defined in drivers/misc/qfw.c */ -ulong write_acpi_tables(ulong start_addr) +ulong new_write_acpi_tables(ulong start_addr) { struct acpi_ctx *ctx; ulong addr; - void *start; int ret; - ctx = calloc(1, sizeof(*ctx)); + ctx = malloc(sizeof(*ctx)); if (!ctx) return log_msg_ret("mem", -ENOMEM); - gd->acpi_ctx = ctx; - - start = map_sysmem(start_addr, 0); log_debug("ACPI: Writing ACPI tables at %lx\n", start_addr); acpi_reset_items(); + acpi_setup_ctx(ctx, start_addr); ret = acpi_write_all(ctx); if (ret) { @@ -89,3 +86,16 @@ ulong write_acpi_tables(ulong start_addr) return addr; } + +void acpi_setup_ctx(struct acpi_ctx *ctx, ulong start) +{ + gd->acpi_ctx = ctx; + memset(ctx, '\0', sizeof(*ctx)); + + /* Align ACPI tables to 16-byte boundary */ + start = ALIGN(start, 16); + ctx->base = map_sysmem(start, 0); + ctx->current = ctx->base; + + gd_set_acpi_start(start); +} diff --git a/test/dm/acpi.c b/test/dm/acpi.c index 804124df9e9..a1d70b58597 100644 --- a/test/dm/acpi.c +++ b/test/dm/acpi.c @@ -45,6 +45,22 @@ struct testacpi_plat { bool no_name; }; +/** + * setup_ctx_and_base_tables() - Set up context along with RSDP, RSDT and XSDT + * + * Set up the context with the given start position. Some basic tables are + * always needed, so set them up as well. + * + * @ctx: Context to set up + */ +static int setup_ctx_and_base_tables(struct acpi_ctx *ctx, ulong start) +{ + acpi_setup_ctx(ctx, start); + acpi_setup_base_tables(ctx); + + return 0; +} + static int testacpi_write_tables(const struct udevice *dev, struct acpi_ctx *ctx) { @@ -240,13 +256,15 @@ static int dm_test_acpi_write_tables(struct unit_test_state *uts) { struct acpi_dmar *dmar; struct acpi_ctx ctx; + ulong addr; void *buf; int i; buf = malloc(BUF_SIZE); ut_assertnonnull(buf); + addr = map_to_sysmem(buf); - acpi_setup_base_tables(&ctx, buf); + setup_ctx_and_base_tables(&ctx, addr); dmar = ctx.current; ut_assertok(acpi_write_dev_tables(&ctx)); @@ -312,6 +330,7 @@ static int dm_test_acpi_setup_base_tables(struct unit_test_state *uts) struct acpi_xsdt *xsdt; struct acpi_ctx ctx; void *buf, *end; + ulong addr; /* * Use an unaligned address deliberately, by allocating an aligned @@ -319,7 +338,8 @@ static int dm_test_acpi_setup_base_tables(struct unit_test_state *uts) */ buf = memalign(64, BUF_SIZE); ut_assertnonnull(buf); - acpi_setup_base_tables(&ctx, buf + 4); + addr = map_to_sysmem(buf); + setup_ctx_and_base_tables(&ctx, addr + 4); ut_asserteq(map_to_sysmem(PTR_ALIGN(buf + 4, 16)), gd_acpi_start()); rsdp = buf + 16; @@ -361,13 +381,13 @@ static int dm_test_acpi_cmd_list(struct unit_test_state *uts) buf = memalign(16, BUF_SIZE); ut_assertnonnull(buf); - acpi_setup_base_tables(&ctx, buf); + addr = map_to_sysmem(buf); + setup_ctx_and_base_tables(&ctx, addr); ut_assertok(acpi_write_dev_tables(&ctx)); console_record_reset(); run_command("acpi list", 0); - addr = (ulong)map_to_sysmem(buf); ut_assert_nextline("ACPI tables start at %lx", addr); ut_assert_nextline("RSDP %08lx %06zx (v02 U-BOOT)", addr, sizeof(struct acpi_rsdp)); @@ -403,7 +423,8 @@ static int dm_test_acpi_cmd_dump(struct unit_test_state *uts) buf = memalign(16, BUF_SIZE); ut_assertnonnull(buf); - acpi_setup_base_tables(&ctx, buf); + addr = map_to_sysmem(buf); + setup_ctx_and_base_tables(&ctx, addr); ut_assertok(acpi_write_dev_tables(&ctx)); -- cgit v1.3.1 From 94ba15a3f13ff5b510d426d13854014bb9cb4713 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 1 Dec 2021 09:02:50 -0700 Subject: x86: Move base tables to a writer function Use the new ACPI writer to write the base tables at the start of the area, moving this code from the x86 implementation. Signed-off-by: Simon Glass --- arch/x86/lib/acpi_table.c | 2 -- include/acpi/acpi_table.h | 10 ------ include/dm/acpi.h | 23 ++++++++++-- lib/acpi/Makefile | 5 +++ lib/acpi/acpi_table.c | 75 -------------------------------------- lib/acpi/acpi_writer.c | 5 ++- lib/acpi/base.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++ test/dm/acpi.c | 17 +++++---- 8 files changed, 133 insertions(+), 96 deletions(-) create mode 100644 lib/acpi/base.c (limited to 'include/dm') diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c index 321faaeb185..e6aa3c5a709 100644 --- a/arch/x86/lib/acpi_table.c +++ b/arch/x86/lib/acpi_table.c @@ -521,8 +521,6 @@ static int write_acpi_tables_x86(struct acpi_ctx *ctx, int ret; int i; - acpi_setup_base_tables(ctx); - debug("ACPI: * FACS\n"); facs = ctx->current; acpi_inc_align(ctx, sizeof(struct acpi_facs)); diff --git a/include/acpi/acpi_table.h b/include/acpi/acpi_table.h index f34bd6311a1..fcc9caaddfd 100644 --- a/include/acpi/acpi_table.h +++ b/include/acpi/acpi_table.h @@ -678,16 +678,6 @@ void acpi_inc_align(struct acpi_ctx *ctx, uint amount); */ int acpi_add_table(struct acpi_ctx *ctx, void *table); -/** - * acpi_setup_base_tables() - Set up base tables - RSDP, RSDT and XSDT - * - * Writes the basic tables to the given context, which must first be set up with - * acpi_setup_ctx(). - * - * @ctx: Context to write base tables to - */ -void acpi_setup_base_tables(struct acpi_ctx *ctx); - /** * acpi_write_rsdp() - Write out an RSDP indicating where the ACPI tables are * diff --git a/include/dm/acpi.h b/include/dm/acpi.h index f6e54793f79..2021a690309 100644 --- a/include/dm/acpi.h +++ b/include/dm/acpi.h @@ -72,9 +72,11 @@ struct acpi_ctx { /** * enum acpi_writer_flags_t - flags to use for the ACPI writers + * + * ACPIWF_ALIGN64 - align to 64 bytes after writing this one (default is 16) */ enum acpi_writer_flags_t { - ACPIWF_ALIGN64_, + ACPIWF_ALIGN64 = 1 << 0, }; struct acpi_writer; @@ -103,7 +105,7 @@ struct acpi_writer { int flags; }; -/* Declare a new ACPI table writer */ +/* Declare a new ACPI-table writer */ #define ACPI_WRITER(_name, _table, _write, _flags) \ ll_entry_declare(struct acpi_writer, _name, acpi_writer) = { \ .name = #_name, \ @@ -112,6 +114,10 @@ struct acpi_writer { .flags = _flags, \ } +/* Get a pointer to a given ACPI-table writer */ +#define ACPI_WRITER_GET(_name) \ + ll_entry_get(struct acpi_writer, _name, acpi_writer) + /** * struct acpi_ops - ACPI operations supported by driver model */ @@ -309,6 +315,19 @@ int acpi_write_one(struct acpi_ctx *ctx, const struct acpi_writer *entry); */ void acpi_setup_ctx(struct acpi_ctx *ctx, ulong start); +/** + * acpi_write_one() - Call a single ACPI writer entry + * + * This handles aligning the context afterwards, if the entry flags indicate + * that. + * + * @ctx: ACPI context to use + * @entry: Entry to call + * @return 0 if OK, -ENOENT if this writer produced an empty entry, other -ve + * value on error + */ +int acpi_write_one(struct acpi_ctx *ctx, const struct acpi_writer *entry); + #endif /* __ACPI__ */ #endif diff --git a/lib/acpi/Makefile b/lib/acpi/Makefile index 1318e83dfc4..4674a9287f6 100644 --- a/lib/acpi/Makefile +++ b/lib/acpi/Makefile @@ -6,3 +6,8 @@ obj-$(CONFIG_$(SPL_)ACPIGEN) += acpi_device.o obj-$(CONFIG_$(SPL_)ACPIGEN) += acpi_dp.o obj-$(CONFIG_$(SPL_)ACPIGEN) += acpi_table.o obj-y += acpi_writer.o + +# With QEMU the ACPI tables come from there, not from U-Boot +ifndef CONFIG_QEMU +obj-y += base.o +endif diff --git a/lib/acpi/acpi_table.c b/lib/acpi/acpi_table.c index 284b5a9afb8..f8642f99420 100644 --- a/lib/acpi/acpi_table.c +++ b/lib/acpi/acpi_table.c @@ -201,81 +201,6 @@ int acpi_add_table(struct acpi_ctx *ctx, void *table) return 0; } -void acpi_write_rsdp(struct acpi_rsdp *rsdp, struct acpi_rsdt *rsdt, - struct acpi_xsdt *xsdt) -{ - memset(rsdp, 0, sizeof(struct acpi_rsdp)); - - memcpy(rsdp->signature, RSDP_SIG, 8); - memcpy(rsdp->oem_id, OEM_ID, 6); - - rsdp->length = sizeof(struct acpi_rsdp); - rsdp->rsdt_address = map_to_sysmem(rsdt); - - rsdp->xsdt_address = map_to_sysmem(xsdt); - rsdp->revision = ACPI_RSDP_REV_ACPI_2_0; - - /* Calculate checksums */ - rsdp->checksum = table_compute_checksum(rsdp, 20); - rsdp->ext_checksum = table_compute_checksum(rsdp, - sizeof(struct acpi_rsdp)); -} - -static void acpi_write_rsdt(struct acpi_rsdt *rsdt) -{ - struct acpi_table_header *header = &rsdt->header; - - /* Fill out header fields */ - acpi_fill_header(header, "RSDT"); - header->length = sizeof(struct acpi_rsdt); - header->revision = 1; - - /* Entries are filled in later, we come with an empty set */ - - /* Fix checksum */ - header->checksum = table_compute_checksum(rsdt, - sizeof(struct acpi_rsdt)); -} - -static void acpi_write_xsdt(struct acpi_xsdt *xsdt) -{ - struct acpi_table_header *header = &xsdt->header; - - /* Fill out header fields */ - acpi_fill_header(header, "XSDT"); - header->length = sizeof(struct acpi_xsdt); - header->revision = 1; - - /* Entries are filled in later, we come with an empty set */ - - /* Fix checksum */ - header->checksum = table_compute_checksum(xsdt, - sizeof(struct acpi_xsdt)); -} - -void acpi_setup_base_tables(struct acpi_ctx *ctx) -{ - /* We need at least an RSDP and an RSDT Table */ - ctx->rsdp = ctx->current; - acpi_inc_align(ctx, sizeof(struct acpi_rsdp)); - ctx->rsdt = ctx->current; - acpi_inc_align(ctx, sizeof(struct acpi_rsdt)); - ctx->xsdt = ctx->current; - acpi_inc_align(ctx, sizeof(struct acpi_xsdt)); - - /* clear all table memory */ - memset(ctx->base, '\0', ctx->current - ctx->base); - - acpi_write_rsdp(ctx->rsdp, ctx->rsdt, ctx->xsdt); - acpi_write_rsdt(ctx->rsdt); - acpi_write_xsdt(ctx->xsdt); - /* - * Per ACPI spec, the FACS table address must be aligned to a 64 byte - * boundary (Windows checks this, but Linux does not). - */ - acpi_align64(ctx); -} - void acpi_create_dbg2(struct acpi_dbg2_header *dbg2, int port_type, int port_subtype, struct acpi_gen_regaddr *address, u32 address_size, diff --git a/lib/acpi/acpi_writer.c b/lib/acpi/acpi_writer.c index 53fc753aeeb..d2505e6eaa4 100644 --- a/lib/acpi/acpi_writer.c +++ b/lib/acpi/acpi_writer.c @@ -35,7 +35,10 @@ int acpi_write_one(struct acpi_ctx *ctx, const struct acpi_writer *entry) if (ret) return log_msg_ret("write", ret); - acpi_align(ctx); + if (entry->flags & ACPIWF_ALIGN64) + acpi_align64(ctx); + else + acpi_align(ctx); return 0; } diff --git a/lib/acpi/base.c b/lib/acpi/base.c new file mode 100644 index 00000000000..3e8d703934e --- /dev/null +++ b/lib/acpi/base.c @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Write base ACPI tables + * + * Copyright 2021 Google LLC + */ + +#include +#include +#include +#include +#include + +void acpi_write_rsdp(struct acpi_rsdp *rsdp, struct acpi_rsdt *rsdt, + struct acpi_xsdt *xsdt) +{ + memset(rsdp, 0, sizeof(struct acpi_rsdp)); + + memcpy(rsdp->signature, RSDP_SIG, 8); + memcpy(rsdp->oem_id, OEM_ID, 6); + + rsdp->length = sizeof(struct acpi_rsdp); + rsdp->rsdt_address = map_to_sysmem(rsdt); + + rsdp->xsdt_address = map_to_sysmem(xsdt); + rsdp->revision = ACPI_RSDP_REV_ACPI_2_0; + + /* Calculate checksums */ + rsdp->checksum = table_compute_checksum(rsdp, 20); + rsdp->ext_checksum = table_compute_checksum(rsdp, + sizeof(struct acpi_rsdp)); +} + +static void acpi_write_rsdt(struct acpi_rsdt *rsdt) +{ + struct acpi_table_header *header = &rsdt->header; + + /* Fill out header fields */ + acpi_fill_header(header, "RSDT"); + header->length = sizeof(struct acpi_rsdt); + header->revision = 1; + + /* Entries are filled in later, we come with an empty set */ + + /* Fix checksum */ + header->checksum = table_compute_checksum(rsdt, + sizeof(struct acpi_rsdt)); +} + +static void acpi_write_xsdt(struct acpi_xsdt *xsdt) +{ + struct acpi_table_header *header = &xsdt->header; + + /* Fill out header fields */ + acpi_fill_header(header, "XSDT"); + header->length = sizeof(struct acpi_xsdt); + header->revision = 1; + + /* Entries are filled in later, we come with an empty set */ + + /* Fix checksum */ + header->checksum = table_compute_checksum(xsdt, + sizeof(struct acpi_xsdt)); +} + +static int acpi_write_base(struct acpi_ctx *ctx, + const struct acpi_writer *entry) +{ + /* We need at least an RSDP and an RSDT Table */ + ctx->rsdp = ctx->current; + acpi_inc_align(ctx, sizeof(struct acpi_rsdp)); + ctx->rsdt = ctx->current; + acpi_inc_align(ctx, sizeof(struct acpi_rsdt)); + ctx->xsdt = ctx->current; + acpi_inc_align(ctx, sizeof(struct acpi_xsdt)); + + /* clear all table memory */ + memset(ctx->base, '\0', ctx->current - ctx->base); + + acpi_write_rsdp(ctx->rsdp, ctx->rsdt, ctx->xsdt); + acpi_write_rsdt(ctx->rsdt); + acpi_write_xsdt(ctx->xsdt); + + return 0; +} +/* + * Per ACPI spec, the FACS table address must be aligned to a 64-byte boundary + * (Windows checks this, but Linux does not). + * + * Use the '0' prefix to put this one first + */ +ACPI_WRITER(0base, NULL, acpi_write_base, ACPIWF_ALIGN64); diff --git a/test/dm/acpi.c b/test/dm/acpi.c index 49b71bec3c0..da728692528 100644 --- a/test/dm/acpi.c +++ b/test/dm/acpi.c @@ -53,10 +53,15 @@ struct testacpi_plat { * * @ctx: Context to set up */ -static int setup_ctx_and_base_tables(struct acpi_ctx *ctx, ulong start) +static int setup_ctx_and_base_tables(struct unit_test_state *uts, + struct acpi_ctx *ctx, ulong start) { + struct acpi_writer *entry = ACPI_WRITER_GET(0base); + acpi_setup_ctx(ctx, start); - acpi_setup_base_tables(ctx); + + ctx->tab_start = ctx->current; + ut_assertok(acpi_write_one(ctx, entry)); return 0; } @@ -264,7 +269,7 @@ static int dm_test_acpi_write_tables(struct unit_test_state *uts) ut_assertnonnull(buf); addr = map_to_sysmem(buf); - setup_ctx_and_base_tables(&ctx, addr); + ut_assertok(setup_ctx_and_base_tables(uts, &ctx, addr)); dmar = ctx.current; ut_assertok(acpi_write_dev_tables(&ctx)); @@ -339,7 +344,7 @@ static int dm_test_setup_ctx_and_base_tables(struct unit_test_state *uts) buf = memalign(64, BUF_SIZE); ut_assertnonnull(buf); addr = map_to_sysmem(buf); - setup_ctx_and_base_tables(&ctx, addr + 4); + ut_assertok(setup_ctx_and_base_tables(uts, &ctx, addr + 4)); ut_asserteq(map_to_sysmem(PTR_ALIGN(buf + 4, 16)), gd_acpi_start()); rsdp = buf + 16; @@ -382,7 +387,7 @@ static int dm_test_acpi_cmd_list(struct unit_test_state *uts) buf = memalign(16, BUF_SIZE); ut_assertnonnull(buf); addr = map_to_sysmem(buf); - setup_ctx_and_base_tables(&ctx, addr); + ut_assertok(setup_ctx_and_base_tables(uts, &ctx, addr)); ut_assertok(acpi_write_dev_tables(&ctx)); @@ -424,7 +429,7 @@ static int dm_test_acpi_cmd_dump(struct unit_test_state *uts) buf = memalign(16, BUF_SIZE); ut_assertnonnull(buf); addr = map_to_sysmem(buf); - setup_ctx_and_base_tables(&ctx, addr); + ut_assertok(setup_ctx_and_base_tables(uts, &ctx, addr)); ut_assertok(acpi_write_dev_tables(&ctx)); -- cgit v1.3.1 From a53d38f80a1b7833a7efad6412fbd0b17cc33a99 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 1 Dec 2021 09:02:51 -0700 Subject: x86: Move FACS table to a writer function Move this table over to use a writer function, moving the code from the x86 implementation. Add a pointer to the DSDT in struct acpi_ctx so we can reference it later. Signed-off-by: Simon Glass --- arch/x86/lib/acpi_table.c | 26 ++------------------------ include/dm/acpi.h | 2 ++ lib/acpi/Makefile | 1 + lib/acpi/facs.c | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 38 insertions(+), 24 deletions(-) create mode 100644 lib/acpi/facs.c (limited to 'include/dm') diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c index e6aa3c5a709..22f34a46d07 100644 --- a/arch/x86/lib/acpi_table.c +++ b/arch/x86/lib/acpi_table.c @@ -38,21 +38,6 @@ extern const unsigned char AmlCode[]; /* ACPI RSDP address to be used in boot parameters */ static ulong acpi_rsdp_addr; -static void acpi_create_facs(struct acpi_facs *facs) -{ - memset((void *)facs, 0, sizeof(struct acpi_facs)); - - memcpy(facs->signature, "FACS", 4); - facs->length = sizeof(struct acpi_facs); - facs->hardware_signature = 0; - facs->firmware_waking_vector = 0; - facs->global_lock = 0; - facs->flags = 0; - facs->x_firmware_waking_vector_l = 0; - facs->x_firmware_waking_vector_h = 0; - facs->version = 1; -} - static int acpi_create_madt_lapic(struct acpi_madt_lapic *lapic, u8 cpu, u8 apic) { @@ -507,7 +492,6 @@ static int write_acpi_tables_x86(struct acpi_ctx *ctx, const struct acpi_writer *entry) { const int thl = sizeof(struct acpi_table_header); - struct acpi_facs *facs; struct acpi_table_header *dsdt; struct acpi_fadt *fadt; struct acpi_table_header *ssdt; @@ -521,12 +505,6 @@ static int write_acpi_tables_x86(struct acpi_ctx *ctx, int ret; int i; - debug("ACPI: * FACS\n"); - facs = ctx->current; - acpi_inc_align(ctx, sizeof(struct acpi_facs)); - - acpi_create_facs(facs); - debug("ACPI: * DSDT\n"); dsdt = ctx->current; @@ -599,7 +577,7 @@ static int write_acpi_tables_x86(struct acpi_ctx *ctx, debug("ACPI: * FADT\n"); fadt = ctx->current; acpi_inc_align(ctx, sizeof(struct acpi_fadt)); - acpi_create_fadt(fadt, facs, dsdt); + acpi_create_fadt(fadt, ctx->facs, dsdt); acpi_add_table(ctx, fadt); debug("ACPI: * SSDT\n"); @@ -666,7 +644,7 @@ static int write_acpi_tables_x86(struct acpi_ctx *ctx, return 0; } -ACPI_WRITER(x86, NULL, write_acpi_tables_x86, 0); +ACPI_WRITER(2x86, NULL, write_acpi_tables_x86, 0); ulong acpi_get_rsdp_addr(void) { diff --git a/include/dm/acpi.h b/include/dm/acpi.h index 2021a690309..c4baeb6b8c1 100644 --- a/include/dm/acpi.h +++ b/include/dm/acpi.h @@ -52,6 +52,7 @@ enum acpi_dump_option { * adding a new table. The RSDP holds pointers to the RSDT and XSDT. * @rsdt: Pointer to the Root System Description Table * @xsdt: Pointer to the Extended System Description Table + * @facs: Pointer to the Firmware ACPI Control Structure * @nhlt: Intel Non-High-Definition-Audio Link Table (NHLT) pointer, used to * build up information that audio codecs need to provide in the NHLT ACPI * table @@ -65,6 +66,7 @@ struct acpi_ctx { struct acpi_rsdp *rsdp; struct acpi_rsdt *rsdt; struct acpi_xsdt *xsdt; + struct acpi_facs *facs; struct nhlt *nhlt; char *len_stack[ACPIGEN_LENSTACK_SIZE]; int ltop; diff --git a/lib/acpi/Makefile b/lib/acpi/Makefile index 4674a9287f6..9f70fe69d3e 100644 --- a/lib/acpi/Makefile +++ b/lib/acpi/Makefile @@ -10,4 +10,5 @@ obj-y += acpi_writer.o # With QEMU the ACPI tables come from there, not from U-Boot ifndef CONFIG_QEMU obj-y += base.o +obj-y += facs.o endif diff --git a/lib/acpi/facs.c b/lib/acpi/facs.c new file mode 100644 index 00000000000..8a1568fbaa0 --- /dev/null +++ b/lib/acpi/facs.c @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Write an ACPI Firmware ACPI Control Structure (FACS) table + * + * Copyright 2021 Google LLC + */ + +#include +#include +#include + +int acpi_write_facs(struct acpi_ctx *ctx, const struct acpi_writer *entry) +{ + struct acpi_facs *facs = ctx->current; + + memset((void *)facs, '\0', sizeof(struct acpi_facs)); + + memcpy(facs->signature, "FACS", 4); + facs->length = sizeof(struct acpi_facs); + facs->hardware_signature = 0; + facs->firmware_waking_vector = 0; + facs->global_lock = 0; + facs->flags = 0; + facs->x_firmware_waking_vector_l = 0; + facs->x_firmware_waking_vector_h = 0; + facs->version = 1; + + ctx->facs = facs; + acpi_inc(ctx, sizeof(struct acpi_facs)); + + return 0; +} +ACPI_WRITER(1facs, "FACS", acpi_write_facs, 0); -- cgit v1.3.1 From eacb6d0ba205cae472c46a974fb16fcd783680b1 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 1 Dec 2021 09:02:52 -0700 Subject: x86: Move DSDT table to a writer function Move this table over to use a writer function, moving the code from the x86 implementation. Add a pointer to the DSDT in struct acpi_ctx so we can reference it later. Disable this table for sandbox since we don't actually compile real ASL code. Signed-off-by: Simon Glass --- arch/x86/lib/acpi_table.c | 49 ++++++----------------------------------- include/dm/acpi.h | 2 ++ lib/acpi/Makefile | 6 ++++++ lib/acpi/base.c | 2 ++ lib/acpi/dsdt.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++ lib/acpi/facs.c | 2 ++ 6 files changed, 74 insertions(+), 42 deletions(-) create mode 100644 lib/acpi/dsdt.c (limited to 'include/dm') diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c index 22f34a46d07..e0c76ab279f 100644 --- a/arch/x86/lib/acpi_table.c +++ b/arch/x86/lib/acpi_table.c @@ -29,12 +29,6 @@ #include #include -/* - * IASL compiles the dsdt entries and writes the hex values - * to a C array AmlCode[] (see dsdt.c). - */ -extern const unsigned char AmlCode[]; - /* ACPI RSDP address to be used in boot parameters */ static ulong acpi_rsdp_addr; @@ -491,8 +485,6 @@ static int acpi_create_ssdt(struct acpi_ctx *ctx, static int write_acpi_tables_x86(struct acpi_ctx *ctx, const struct acpi_writer *entry) { - const int thl = sizeof(struct acpi_table_header); - struct acpi_table_header *dsdt; struct acpi_fadt *fadt; struct acpi_table_header *ssdt; struct acpi_mcfg *mcfg; @@ -500,42 +492,14 @@ static int write_acpi_tables_x86(struct acpi_ctx *ctx, struct acpi_madt *madt; struct acpi_csrt *csrt; struct acpi_spcr *spcr; - int aml_len; ulong addr; int ret; int i; - debug("ACPI: * DSDT\n"); - dsdt = ctx->current; - - /* Put the table header first */ - 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 */ - aml_len = dsdt->length - thl; - if (aml_len) { - void *base = ctx->current; - - 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); - } - - 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 */ - for (i = 0; i < dsdt->length; i++) { - u32 *gnvs = (u32 *)((u32)dsdt + i); + for (i = 0; i < ctx->dsdt->length; i++) { + u32 *gnvs = (u32 *)((u32)ctx->dsdt + i); if (*gnvs == ACPI_GNVS_ADDR) { *gnvs = map_to_sysmem(ctx->current); @@ -561,8 +525,9 @@ static int write_acpi_tables_x86(struct acpi_ctx *ctx, * the GNVS address. Set the checksum to zero since it is part of the * region being checksummed. */ - dsdt->checksum = 0; - dsdt->checksum = table_compute_checksum((void *)dsdt, dsdt->length); + ctx->dsdt->checksum = 0; + ctx->dsdt->checksum = table_compute_checksum((void *)ctx->dsdt, + ctx->dsdt->length); /* * Fill in platform-specific global NVS variables. If this fails we @@ -577,7 +542,7 @@ static int write_acpi_tables_x86(struct acpi_ctx *ctx, debug("ACPI: * FADT\n"); fadt = ctx->current; acpi_inc_align(ctx, sizeof(struct acpi_fadt)); - acpi_create_fadt(fadt, ctx->facs, dsdt); + acpi_create_fadt(fadt, ctx->facs, ctx->dsdt); acpi_add_table(ctx, fadt); debug("ACPI: * SSDT\n"); @@ -644,7 +609,7 @@ static int write_acpi_tables_x86(struct acpi_ctx *ctx, return 0; } -ACPI_WRITER(2x86, NULL, write_acpi_tables_x86, 0); +ACPI_WRITER(9x86, NULL, write_acpi_tables_x86, 0); ulong acpi_get_rsdp_addr(void) { diff --git a/include/dm/acpi.h b/include/dm/acpi.h index c4baeb6b8c1..815a887ae43 100644 --- a/include/dm/acpi.h +++ b/include/dm/acpi.h @@ -53,6 +53,7 @@ enum acpi_dump_option { * @rsdt: Pointer to the Root System Description Table * @xsdt: Pointer to the Extended System Description Table * @facs: Pointer to the Firmware ACPI Control Structure + * @dsdt: Pointer to the Differentiated System Description Table * @nhlt: Intel Non-High-Definition-Audio Link Table (NHLT) pointer, used to * build up information that audio codecs need to provide in the NHLT ACPI * table @@ -67,6 +68,7 @@ struct acpi_ctx { struct acpi_rsdt *rsdt; struct acpi_xsdt *xsdt; struct acpi_facs *facs; + struct acpi_table_header *dsdt; struct nhlt *nhlt; char *len_stack[ACPIGEN_LENSTACK_SIZE]; int ltop; diff --git a/lib/acpi/Makefile b/lib/acpi/Makefile index 9f70fe69d3e..ccdf42896dc 100644 --- a/lib/acpi/Makefile +++ b/lib/acpi/Makefile @@ -10,5 +10,11 @@ obj-y += acpi_writer.o # With QEMU the ACPI tables come from there, not from U-Boot ifndef CONFIG_QEMU obj-y += base.o + +# Sandbox does not build a .asl file +ifndef CONFIG_SANDBOX +obj-y += dsdt.o +endif + obj-y += facs.o endif diff --git a/lib/acpi/base.c b/lib/acpi/base.c index 3e8d703934e..2057bd2bef8 100644 --- a/lib/acpi/base.c +++ b/lib/acpi/base.c @@ -5,6 +5,8 @@ * Copyright 2021 Google LLC */ +#define LOG_CATEGORY LOGC_ACPI + #include #include #include diff --git a/lib/acpi/dsdt.c b/lib/acpi/dsdt.c new file mode 100644 index 00000000000..db98cc20e1d --- /dev/null +++ b/lib/acpi/dsdt.c @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Write the ACPI Differentiated System Description Table (DSDT) + * + * Copyright 2021 Google LLC + */ + +#define LOG_CATEGORY LOGC_ACPI + +#include +#include +#include +#include + +/* + * IASL compiles the dsdt entries and writes the hex values + * to a C array AmlCode[] (see dsdt.c). + */ +extern const unsigned char AmlCode[]; + +int acpi_write_dsdt(struct acpi_ctx *ctx, const struct acpi_writer *entry) +{ + const int thl = sizeof(struct acpi_table_header); + struct acpi_table_header *dsdt = ctx->current; + int aml_len; + + /* Put the table header first */ + 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 */ + aml_len = dsdt->length - thl; + if (aml_len) { + void *base = ctx->current; + int ret; + + ret = acpi_inject_dsdt(ctx); + if (ret) + return log_msg_ret("inject", ret); + log_debug("Added %lx bytes from inject_dsdt, now at %p\n", + (ulong)(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); + } + + ctx->dsdt = dsdt; + dsdt->length = ctx->current - (void *)dsdt; + log_debug("Updated DSDT length to %x\n", dsdt->length); + + return 0; +} +ACPI_WRITER(3dsdt, "DSDT", acpi_write_dsdt, 0); diff --git a/lib/acpi/facs.c b/lib/acpi/facs.c index 8a1568fbaa0..e89f43ca5c9 100644 --- a/lib/acpi/facs.c +++ b/lib/acpi/facs.c @@ -5,6 +5,8 @@ * Copyright 2021 Google LLC */ +#define LOG_CATEGORY LOGC_ACPI + #include #include #include -- cgit v1.3.1 From 2d7c7382969ff2a412acb409e76b2959dd715cc3 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 1 Dec 2021 09:03:04 -0700 Subject: acpi: Collect tables in the acpi_item list At present this list is used to collect items within the DSDT and SSDT tables. It is useful for it to collect the whole tables as well, so there is a list of what was created and which write created each one. Refactor the code accordingly. Signed-off-by: Simon Glass --- drivers/core/acpi.c | 43 ++++++++++++++++++++++++++++++++----------- include/dm/acpi.h | 14 ++++++++++++++ lib/acpi/acpi_writer.c | 5 +++++ 3 files changed, 51 insertions(+), 11 deletions(-) (limited to 'include/dm') diff --git a/drivers/core/acpi.c b/drivers/core/acpi.c index 5425e4d0402..1e2f5d56302 100644 --- a/drivers/core/acpi.c +++ b/drivers/core/acpi.c @@ -19,11 +19,19 @@ #define MAX_ACPI_ITEMS 100 -/* Type of table that we collected */ +/** + * Type of table that we collected + * + * @TYPE_NONE: Not yet known + * @TYPE_SSDT: Items in the Secondary System Description Table + * @TYPE_DSDT: Items in the Differentiated System Description Table + * @TYPE_OTHER: Other (whole) + */ enum gen_type_t { TYPE_NONE, TYPE_SSDT, TYPE_DSDT, + TYPE_OTHER, }; /* Type of method to call */ @@ -42,11 +50,13 @@ typedef int (*acpi_method)(const struct udevice *dev, struct acpi_ctx *ctx); * * @dev: Device that generated this data * @type: Table type it refers to + * @writer: Writer that wrote this table * @buf: Buffer containing the data * @size: Size of the data in bytes */ struct acpi_item { struct udevice *dev; + const struct acpi_writer *writer; enum gen_type_t type; char *buf; int size; @@ -103,16 +113,18 @@ int acpi_get_path(const struct udevice *dev, char *out_path, int maxlen) } /** - * acpi_add_item() - Add a new item to the list of data collected + * add_item() - Add a new item to the list of data collected * * @ctx: ACPI context - * @dev: Device that generated the data + * @dev: Device that generated the data, if type != TYPE_OTHER + * @writer: Writer entry that generated the data, if type == TYPE_OTHER * @type: Table type it refers to * @start: The start of the data (the end is obtained from ctx->current) * Return: 0 if OK, -ENOSPC if too many items, -ENOMEM if out of memory */ -static int acpi_add_item(struct acpi_ctx *ctx, struct udevice *dev, - enum gen_type_t type, void *start) +static int add_item(struct acpi_ctx *ctx, struct udevice *dev, + const struct acpi_writer *writer, enum gen_type_t type, + void *start) { struct acpi_item *item; void *end = ctx->current; @@ -124,14 +136,17 @@ static int acpi_add_item(struct acpi_ctx *ctx, struct udevice *dev, item = &acpi_item[item_count]; item->dev = dev; + item->writer = writer; item->type = type; item->size = end - start; if (!item->size) return 0; - item->buf = malloc(item->size); - if (!item->buf) - return log_msg_ret("mem", -ENOMEM); - memcpy(item->buf, start, item->size); + if (type != TYPE_OTHER) { + item->buf = malloc(item->size); + if (!item->buf) + return log_msg_ret("mem", -ENOMEM); + memcpy(item->buf, start, item->size); + } item_count++; log_debug("* %s: Added type %d, %p, size %x\n", dev->name, type, start, item->size); @@ -139,6 +154,12 @@ static int acpi_add_item(struct acpi_ctx *ctx, struct udevice *dev, return 0; } +int acpi_add_other_item(struct acpi_ctx *ctx, const struct acpi_writer *writer, + void *start) +{ + return add_item(ctx, NULL, writer, TYPE_OTHER, start); +} + void acpi_dump_items(enum acpi_dump_option option) { int i; @@ -162,7 +183,7 @@ static struct acpi_item *find_acpi_item(const char *devname) for (i = 0; i < item_count; i++) { struct acpi_item *item = &acpi_item[i]; - if (!strcmp(devname, item->dev->name)) + if (item->dev && !strcmp(devname, item->dev->name)) return item; } @@ -277,7 +298,7 @@ int acpi_recurse_method(struct acpi_ctx *ctx, struct udevice *parent, /* Add the item to the internal list */ if (type != TYPE_NONE) { - ret = acpi_add_item(ctx, parent, type, ctx->tab_start); + ret = add_item(ctx, parent, NULL, type, ctx->tab_start); if (ret) return log_msg_ret("add", ret); } diff --git a/include/dm/acpi.h b/include/dm/acpi.h index 815a887ae43..3adfe217678 100644 --- a/include/dm/acpi.h +++ b/include/dm/acpi.h @@ -262,6 +262,20 @@ int acpi_inject_dsdt(struct acpi_ctx *ctx); */ int acpi_setup_nhlt(struct acpi_ctx *ctx, struct nhlt *nhlt); +/** + * acpi_add_other_item() - Add a new table to the list of ACPI tables + * + * This adds an entry of type ACPIT_TYPE_OTHER + * + * @ctx: ACPI context + * @writer: Writer entry that generated the data + * @type: Table type it refers to + * @start: The start of the data (the end is obtained from ctx->current) + * @return 0 if OK, -ENOSPC if too many items, -ENOMEM if out of memory + */ +int acpi_add_other_item(struct acpi_ctx *ctx, const struct acpi_writer *writer, + void *start); + /** * acpi_dump_items() - Dump out the collected ACPI items * diff --git a/lib/acpi/acpi_writer.c b/lib/acpi/acpi_writer.c index 9b0aa23fd78..946f90e8e7b 100644 --- a/lib/acpi/acpi_writer.c +++ b/lib/acpi/acpi_writer.c @@ -40,6 +40,11 @@ int acpi_write_one(struct acpi_ctx *ctx, const struct acpi_writer *entry) else acpi_align(ctx); + /* Add the item to the internal list */ + ret = acpi_add_other_item(ctx, entry, ctx->tab_start); + if (ret) + return log_msg_ret("add", ret); + return 0; } -- cgit v1.3.1