From 233f0e35a3536102e13bed924a1c4aa33726f244 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 1 Dec 2021 09:02:37 -0700 Subject: x86: Move the acpi table to generic global_data Allow this to be used on any arch. Also convert to using macros so that we can check the CONFIG option in C code. Signed-off-by: Simon Glass --- include/asm-generic/global_data.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'include') diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h index 104282bd479..c2f8fad1cb9 100644 --- a/include/asm-generic/global_data.h +++ b/include/asm-generic/global_data.h @@ -456,6 +456,10 @@ struct global_data { * @acpi_ctx: ACPI context pointer */ struct acpi_ctx *acpi_ctx; + /** + * @acpi_start: Start address of ACPI tables + */ + ulong acpi_start; #endif #if CONFIG_IS_ENABLED(GENERATE_SMBIOS_TABLE) /** @@ -512,8 +516,12 @@ static_assert(sizeof(struct global_data) == GD_SIZE); #ifdef CONFIG_GENERATE_ACPI_TABLE #define gd_acpi_ctx() gd->acpi_ctx +#define gd_acpi_start() gd->acpi_start +#define gd_set_acpi_start(addr) gd->acpi_start = addr #else #define gd_acpi_ctx() NULL +#define gd_acpi_start() 0UL +#define gd_set_acpi_start(addr) #endif #if CONFIG_IS_ENABLED(MULTI_DTB_FIT) -- cgit v1.3.1 From 383bf1bc9ee21c649d04a03a19eedbffa84b7237 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 1 Dec 2021 09:02:45 -0700 Subject: acpi: Move acpi_fill_header() to the generic header This function is not x86-specific so move it into the common header file. Signed-off-by: Simon Glass --- arch/x86/include/asm/acpi_table.h | 1 - include/acpi/acpi_table.h | 8 ++++++++ 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/arch/x86/include/asm/acpi_table.h b/arch/x86/include/asm/acpi_table.h index 55b1a3d3f17..914ca988aaf 100644 --- a/arch/x86/include/asm/acpi_table.h +++ b/arch/x86/include/asm/acpi_table.h @@ -24,7 +24,6 @@ struct acpi_table_header; /* These can be used by the target port */ -void acpi_fill_header(struct acpi_table_header *header, char *signature); void acpi_create_fadt(struct acpi_fadt *fadt, struct acpi_facs *facs, void *dsdt); int acpi_create_madt_lapics(u32 current); diff --git a/include/acpi/acpi_table.h b/include/acpi/acpi_table.h index dbfea3be706..d3fbdc1de2b 100644 --- a/include/acpi/acpi_table.h +++ b/include/acpi/acpi_table.h @@ -698,6 +698,14 @@ void acpi_setup_base_tables(struct acpi_ctx *ctx, void *start); void acpi_write_rsdp(struct acpi_rsdp *rsdp, struct acpi_rsdt *rsdt, struct acpi_xsdt *xsdt); +/** + * acpi_fill_header() - Set up a table header + * + * @header: Pointer to header to set up + * @signature: 4-character signature to use (e.g. "FACS") + */ +void acpi_fill_header(struct acpi_table_header *header, char *signature); + #endif /* !__ACPI__*/ #include -- cgit v1.3.1 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 --- drivers/core/acpi.c | 5 ++--- include/dm/acpi.h | 4 ++++ 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/drivers/core/acpi.c b/drivers/core/acpi.c index e988a65ec51..5425e4d0402 100644 --- a/drivers/core/acpi.c +++ b/drivers/core/acpi.c @@ -266,19 +266,18 @@ int acpi_recurse_method(struct acpi_ctx *ctx, struct udevice *parent, func = acpi_get_method(parent, method); if (func) { - void *start = ctx->current; - log_debug("- method %d, %s %p\n", method, parent->name, func); ret = device_of_to_plat(parent); if (ret) return log_msg_ret("ofdata", ret); + ctx->tab_start = ctx->current; ret = func(parent, ctx); if (ret) return log_msg_ret("func", ret); /* Add the item to the internal list */ if (type != TYPE_NONE) { - ret = acpi_add_item(ctx, parent, type, start); + ret = acpi_add_item(ctx, parent, 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 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') 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') 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') 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') 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') 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 78031ad43168d13de5c9ecf72877e8d5d35f749a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 1 Dec 2021 09:03:01 -0700 Subject: x86: acpi: Update acpi_fill_csrt() to use acpi_ctx Update this function to the newer style, so we can avoid passing and returning an address through this function. Also move this function out of the x86 code so it can be used by other archs. Signed-off-by: Simon Glass Reviewed-by: Andy Shevchenko --- arch/x86/cpu/tangier/acpi.c | 9 ++++++--- arch/x86/include/asm/acpi_table.h | 1 - include/acpi/acpi_table.h | 12 ++++++++++++ lib/acpi/csrt.c | 13 ++++++------- 4 files changed, 24 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/arch/x86/cpu/tangier/acpi.c b/arch/x86/cpu/tangier/acpi.c index 11873565366..12f92896124 100644 --- a/arch/x86/cpu/tangier/acpi.c +++ b/arch/x86/cpu/tangier/acpi.c @@ -109,11 +109,14 @@ static u32 acpi_fill_csrt_dma(struct acpi_csrt_group *grp) return grp->length; } -u32 acpi_fill_csrt(u32 current) +int acpi_fill_csrt(struct acpi_ctx *ctx) { - current += acpi_fill_csrt_dma((struct acpi_csrt_group *)current); + int size; - return current; + size = acpi_fill_csrt_dma(ctx->current); + acpi_inc(ctx, size); + + return 0; } int acpi_create_gnvs(struct acpi_global_nvs *gnvs) diff --git a/arch/x86/include/asm/acpi_table.h b/arch/x86/include/asm/acpi_table.h index fb60f859dd6..0d07f7cad87 100644 --- a/arch/x86/include/asm/acpi_table.h +++ b/arch/x86/include/asm/acpi_table.h @@ -35,7 +35,6 @@ u32 acpi_fill_madt(u32 current); int acpi_create_mcfg_mmconfig(struct acpi_mcfg_mmconfig *mmconfig, u32 base, u16 seg_nr, u8 start, u8 end); u32 acpi_fill_mcfg(u32 current); -u32 acpi_fill_csrt(u32 current); /** * acpi_write_hpet() - Write out a HPET table diff --git a/include/acpi/acpi_table.h b/include/acpi/acpi_table.h index fcc9caaddfd..e4050120746 100644 --- a/include/acpi/acpi_table.h +++ b/include/acpi/acpi_table.h @@ -696,6 +696,18 @@ void acpi_write_rsdp(struct acpi_rsdp *rsdp, struct acpi_rsdt *rsdt, */ void acpi_fill_header(struct acpi_table_header *header, char *signature); +/** + * acpi_fill_csrt() - Fill out the body of the CSRT + * + * This should write the contents of the Core System Resource Table (CSRT) + * to the context. The header (struct acpi_table_header) has already been + * written. + * + * @ctx: ACPI context to write to + * @return 0 if OK, -ve on error + */ +int acpi_fill_csrt(struct acpi_ctx *ctx); + #endif /* !__ACPI__*/ #include diff --git a/lib/acpi/csrt.c b/lib/acpi/csrt.c index 76069318416..2ba86f22952 100644 --- a/lib/acpi/csrt.c +++ b/lib/acpi/csrt.c @@ -13,7 +13,7 @@ #include #include -__weak u32 acpi_fill_csrt(u32 current) +__weak int acpi_fill_csrt(struct acpi_ctx *ctx) { return 0; } @@ -22,7 +22,7 @@ int acpi_write_csrt(struct acpi_ctx *ctx, const struct acpi_writer *entry) { struct acpi_table_header *header; struct acpi_csrt *csrt; - uint ptr; + int ret; csrt = ctx->current; header = &csrt->header; @@ -31,19 +31,18 @@ int acpi_write_csrt(struct acpi_ctx *ctx, const struct acpi_writer *entry) /* Fill out header fields */ acpi_fill_header(header, "CSRT"); - header->length = sizeof(struct acpi_csrt); header->revision = 0; + acpi_inc(ctx, sizeof(*header)); - ptr = acpi_fill_csrt(map_to_sysmem(csrt)); - if (!ptr) - return log_msg_ret("fill", -ENOENT); + ret = acpi_fill_csrt(ctx); + if (ret) + return log_msg_ret("fill", ret); /* (Re)calculate length and checksum */ header->length = (ulong)ctx->current - (ulong)csrt; header->checksum = table_compute_checksum(csrt, header->length); acpi_add_table(ctx, csrt); - acpi_inc(ctx, csrt->header.length); return 0; } -- 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') 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 From 979a24e48805e71e1c9c5b39d1e04ba64d8a79b8 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 1 Dec 2021 09:03:08 -0700 Subject: acpi: Add some tables needed by ARM devices Add some tables needed for ARM devices, including more MADT subtables, a CSRT descriptor, GTDT and PPTT. WIP: This needs comments added. Signed-off-by: Simon Glass --- include/acpi/acpi_table.h | 205 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) (limited to 'include') diff --git a/include/acpi/acpi_table.h b/include/acpi/acpi_table.h index e4050120746..c98c874fe40 100644 --- a/include/acpi/acpi_table.h +++ b/include/acpi/acpi_table.h @@ -162,6 +162,9 @@ enum acpi_pm_profile { #define ACPI_FADT_HW_REDUCED_ACPI BIT(20) #define ACPI_FADT_LOW_PWR_IDLE_S0 BIT(21) +/* ARM boot flags */ +#define ACPI_ARM_PSCI_COMPLIANT BIT(0) + enum acpi_address_space_type { ACPI_ADDRESS_SPACE_MEMORY = 0, /* System memory */ ACPI_ADDRESS_SPACE_IO, /* System I/O */ @@ -237,6 +240,9 @@ struct __packed acpi_fadt { struct acpi_gen_regaddr x_pm_tmr_blk; struct acpi_gen_regaddr x_gpe0_blk; struct acpi_gen_regaddr x_gpe1_blk; + struct acpi_gen_regaddr sleep_control_reg; + struct acpi_gen_regaddr sleep_status_reg; + u64 hyp_vendor_id; }; /* FADT TABLE Revision values - note these do not match the ACPI revision */ @@ -302,6 +308,8 @@ enum acpi_apic_types { ACPI_APIC_PLATFORM_IRQ_SRC, /* Platform interrupt sources */ ACPI_APIC_LX2APIC, /* Processor local x2APIC */ ACPI_APIC_LX2APIC_NMI, /* Local x2APIC NMI */ + ACPI_APIC_GICC, /* Generic Interrupt Ctlr CPU i/f */ + ACPI_APIC_GICD /* Generic Interrupt Ctlr Distributor */ }; /* MADT: Processor Local APIC Structure */ @@ -345,6 +353,57 @@ struct __packed acpi_madt_lapic_nmi { u8 lint; /* Local APIC LINT# */ }; +/* flags for acpi_madr_gicc flags word */ +enum { + ACPI_MADRF_ENABLED = BIT(0), + ACPI_MADRF_PERF = BIT(1), + ACPI_MADRF_VGIC = BIT(2), +}; + +/** + * struct __packed acpi_madr_gicc - GIC CPU interface (type 0xb) + * + * This holds information about the Generic Interrupt Controller (GIC) CPU + * interface. See ACPI Spec v6.3 section 5.2.12.14 + */ +struct __packed acpi_madr_gicc { + u8 type; + u8 length; + u16 reserved; + u32 cpu_if_num; + u32 processor_id; + u32 flags; + u32 parking_proto; + u32 perf_gsiv; + u64 parked_addr; + u64 phys_base; + u64 gicv; + u64 gich; + u32 vgic_maint_irq; + u64 gicr_base; + u64 mpidr; + u8 efficiency; + u8 reserved2; + u16 spi_overflow_irq; +}; + +/** + * struct __packed acpi_madr_gicc - GIC distributor (type 0xc) + * + * This holds information about the Generic Interrupt Controller (GIC) + * Distributor interface. See ACPI Spec v6.3 section 5.2.12.15 + */ +struct __packed acpi_madr_gicd { + u8 type; + u8 length; + u16 reserved; + u32 gic_id; + u64 phys_base; + u32 reserved2; + u8 gic_version; + u8 reserved3[3]; +}; + /* MCFG (PCI Express MMIO config space BAR description table) */ struct acpi_mcfg { struct acpi_table_header header; @@ -371,6 +430,19 @@ struct acpi_csrt { struct acpi_table_header header; }; +/** + * struct acpi_csrt_group - header for a group within the CSRT + * + * The CSRT consists of one or more groups and this is the header for each + * + * See Core System Resources Table (CSRT), March 13, 2017, Microsoft Corporation + * for details + * + * https://uefi.org/sites/default/files/resources/CSRT%20v2.pdf + * + * @shared_info_length indicates the number of shared-info bytes following this + * struct (which may be 0) + */ struct acpi_csrt_group { u32 length; u32 vendor_id; @@ -382,6 +454,25 @@ struct acpi_csrt_group { u32 shared_info_length; }; +/** + * struct acpi_csrt_descriptor - describes the information that follows + * + * See the spec as above for details + */ +struct acpi_csrt_descriptor { + u32 length; + u16 type; + u16 subtype; + u32 uid; +}; + +/** + * struct acpi_csrt_shared_info - shared info for Intel tangier + * + * This provides the shared info for this particular board. Notes that the CSRT + * does not describe the format of data, so this format may not be used by any + * other board. + */ struct acpi_csrt_shared_info { u16 major_version; u16 minor_version; @@ -559,6 +650,120 @@ struct __packed acpi_spcr { u32 reserved2; }; +/** + * struct acpi_gtdt - Generic Timer Description Table (GTDT) + * + * See ACPI Spec v6.3 section 5.2.24 for details + */ +struct __packed acpi_gtdt { + struct acpi_table_header header; + u64 cnt_ctrl_base; + u32 reserved0; + u32 sec_el1_gsiv; + u32 sec_el1_flags; + u32 el1_gsiv; + u32 el1_flags; + u32 virt_el1_gsiv; + u32 virt_el1_flags; + u32 el2_gsiv; + u32 el2_flags; + u64 cnt_read_base; + u32 plat_timer_count; + u32 plat_timer_offset; + u32 virt_el2_gsiv; + u32 virt_el2_flags; +}; + +/** + * struct acpi_bgrt - Boot Graphics Resource Table (BGRT) + * + * Optional table that provides a mechanism to indicate that an image was drawn + * on the screen during boot, and some information about the image. + * + * See ACPI Spec v6.3 section 5.2.22 for details + */ +struct __packed acpi_bgrt { + struct acpi_table_header header; + u16 version; + u8 status; + u8 image_type; + u64 addr; + u32 offset_x; + u32 offset_y; +}; + +/* Types for PPTT */ +#define ACPI_PPTT_TYPE_PROC 0 +#define ACPI_PPTT_TYPE_CACHE 1 + +/* Flags for PPTT */ +#define ACPI_PPTT_PHYSICAL_PACKAGE BIT(0) +#define ACPI_PPTT_PROC_ID_VALID BIT(1) +#define ACPI_PPTT_PROC_IS_THREAD BIT(2) +#define ACPI_PPTT_NODE_IS_LEAF BIT(3) +#define ACPI_PPTT_CHILDREN_IDENTICAL BIT(4) + +/** + * struct acpi_pptt_header - Processor Properties Topology Table (PPTT) header + * + * Describes the topological structure of processors and their shared resources, + * such as caches. + * + * See ACPI Spec v6.3 section 5.2.29 for details + */ +struct __packed acpi_pptt_header { + u8 type; /* ACPI_PPTT_TYPE_... */ + u8 length; + u16 reserved; +}; + +/** + * struct acpi_pptt_proc - a processor as described by PPTT + */ +struct __packed acpi_pptt_proc { + struct acpi_pptt_header hdr; + u32 flags; + u32 parent; + u32 proc_id; + u32 num_resources; +}; + +/* Cache flags for acpi_pptt_cache */ +#define ACPI_PPTT_SIZE_VALID BIT(0) +#define ACPI_PPTT_SETS_VALID BIT(1) +#define ACPI_PPTT_ASSOC_VALID BIT(2) +#define ACPI_PPTT_ALLOC_TYPE_VALID BIT(3) +#define ACPI_PPTT_CACHE_TYPE_VALID BIT(4) +#define ACPI_PPTT_WRITE_POLICY_VALID BIT(5) +#define ACPI_PPTT_LINE_SIZE_VALID BIT(6) + +#define ACPI_PPTT_ALL_VALID 0x7f +#define ACPI_PPTT_ALL_BUT_WRITE_POL 0x5f + +#define ACPI_PPTT_READ_ALLOC BIT(0) +#define ACPI_PPTT_WRITE_ALLOC BIT(1) +#define ACPI_PPTT_CACHE_TYPE_SHIFT 2 +#define ACPI_PPTT_CACHE_TYPE_MASK (3 << ACPI_PPTT_CACHE_TYPE_SHIFT) +#define ACPI_PPTT_CACHE_TYPE_DATA 0 +#define ACPI_PPTT_CACHE_TYPE_INSTR 1 +#define ACPI_PPTT_CACHE_TYPE_UNIFIED 2 +#define ACPI_PPTT_CACHE_TYPE_DATA 0 +#define ACPI_PPTT_WRITE_THROUGH BIT(4) + +/** + * struct acpi_pptt_cache - a cache as described by PPTT + */ +struct __packed acpi_pptt_cache { + struct acpi_pptt_header hdr; + u32 flags; + u32 next_cache_level; + u32 size; + u32 sets; + u8 assoc; + u8 attributes; + u16 line_size; +}; + /* Tables defined/reserved by ACPI and generated by U-Boot */ enum acpi_tables { ACPITAB_BERT, -- cgit v1.3.1 From 9876ae7db6da1cf8e106fcb46a36172fbb5781e5 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 4 Jan 2022 08:42:48 +0100 Subject: dm: Fix OF_BAD_ADDR definition When OF_LIVE flag is enabled on a 64 bits platform, there is an issue when dev_read_addr() is called and need to perform an address translation using __of_translate_address(). In case of error, __of_translate_address() return's value is OF_BAD_ADDR (wich is defined in include/dm/of.h to ((u64)-1) = 0xffffffffffffffff). The return value of dev_read_addr() is often compared to FDT_ADDR_T_NONE which is defined as (-1U) = 0xffffffff. In this case the comparison is always false. To fix this issue, define FDT_ADDR_T_NONE to (ulong)(-1) in case of AARCH64. Update accordingly related tests. Signed-off-by: Patrice Chotard Reviewed-by: Simon Glass --- include/fdtdec.h | 5 ++++- test/dm/ofnode.c | 2 +- test/dm/pci.c | 4 ++-- test/dm/test-fdt.c | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/fdtdec.h b/include/fdtdec.h index 9a7b6a7ee19..4b0b505773d 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -24,16 +24,19 @@ typedef phys_addr_t fdt_addr_t; typedef phys_size_t fdt_size_t; -#define FDT_ADDR_T_NONE (-1U) #define FDT_SIZE_T_NONE (-1U) #ifdef CONFIG_PHYS_64BIT +#define FDT_ADDR_T_NONE ((ulong)(-1)) + #define fdt_addr_to_cpu(reg) be64_to_cpu(reg) #define fdt_size_to_cpu(reg) be64_to_cpu(reg) #define cpu_to_fdt_addr(reg) cpu_to_be64(reg) #define cpu_to_fdt_size(reg) cpu_to_be64(reg) typedef fdt64_t fdt_val_t; #else +#define FDT_ADDR_T_NONE (-1U) + #define fdt_addr_to_cpu(reg) be32_to_cpu(reg) #define fdt_size_to_cpu(reg) be32_to_cpu(reg) #define cpu_to_fdt_addr(reg) cpu_to_be32(reg) diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c index 5e7c9681c79..dab0480a42f 100644 --- a/test/dm/ofnode.c +++ b/test/dm/ofnode.c @@ -286,7 +286,7 @@ static int dm_test_ofnode_get_reg(struct unit_test_state *uts) ut_assert(ofnode_valid(node)); addr = ofnode_get_addr(node); size = ofnode_get_size(node); - ut_asserteq(FDT_ADDR_T_NONE, addr); + ut_asserteq_64(FDT_ADDR_T_NONE, addr); ut_asserteq(FDT_SIZE_T_NONE, size); node = ofnode_path("/translation-test@8000/noxlatebus@3,300/dev@42"); diff --git a/test/dm/pci.c b/test/dm/pci.c index fa2e4a85596..00e4440a9db 100644 --- a/test/dm/pci.c +++ b/test/dm/pci.c @@ -331,10 +331,10 @@ static int dm_test_pci_addr_live(struct unit_test_state *uts) struct udevice *swap1f, *swap1; ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x1f, 0), &swap1f)); - ut_asserteq(FDT_ADDR_T_NONE, dev_read_addr_pci(swap1f)); + ut_asserteq_64(FDT_ADDR_T_NONE, dev_read_addr_pci(swap1f)); ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x1, 0), &swap1)); - ut_asserteq(FDT_ADDR_T_NONE, dev_read_addr_pci(swap1)); + ut_asserteq_64(FDT_ADDR_T_NONE, dev_read_addr_pci(swap1)); return 0; } diff --git a/test/dm/test-fdt.c b/test/dm/test-fdt.c index 8866d4d959d..e1de066226c 100644 --- a/test/dm/test-fdt.c +++ b/test/dm/test-fdt.c @@ -768,7 +768,7 @@ static int dm_test_fdt_livetree_writing(struct unit_test_state *uts) /* Test setting generic properties */ /* Non-existent in DTB */ - ut_asserteq(FDT_ADDR_T_NONE, dev_read_addr(dev)); + ut_asserteq_64(FDT_ADDR_T_NONE, dev_read_addr(dev)); /* reg = 0x42, size = 0x100 */ ut_assertok(ofnode_write_prop(node, "reg", 8, "\x00\x00\x00\x42\x00\x00\x01\x00")); -- cgit v1.3.1 From 70e6bcc43f541fbcb8e878dba8299e8e30943bcd Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 12 Nov 2021 12:28:06 -0700 Subject: tools: Improve comments in signing functions Add some more comments to explain what is going on in the signing functions. Fix two repeated typos. Signed-off-by: Simon Glass --- include/image.h | 2 +- tools/fdt_host.h | 8 +++++ tools/image-host.c | 98 ++++++++++++++++++++++++++++++++++++++++++------------ 3 files changed, 85 insertions(+), 23 deletions(-) (limited to 'include') diff --git a/include/image.h b/include/image.h index fe1356265c8..15cfb2c54b0 100644 --- a/include/image.h +++ b/include/image.h @@ -1025,7 +1025,7 @@ int fit_cipher_data(const char *keydir, void *keydest, void *fit, * fit_add_verification_data() - add verification data to FIT image nodes * * @keydir: Directory containing keys - * @kwydest: FDT blob to write public key information to + * @kwydest: FDT blob to write public key information to (NULL if none) * @fit: Pointer to the FIT format image header * @comment: Comment to add to signature nodes * @require_keys: Mark all keys as 'required' diff --git a/tools/fdt_host.h b/tools/fdt_host.h index 15c07c7a96e..bc42306c9e5 100644 --- a/tools/fdt_host.h +++ b/tools/fdt_host.h @@ -27,6 +27,14 @@ */ int fdt_remove_unused_strings(const void *old, void *new); +/** + * fit_check_sign() - Check a signature in a FIT + * + * @fit: FIT to check + * @key: Key FDT blob to check against + * @fit_uname_config: Name of configuration to check (NULL for default) + * @return 0 if OK, -ve if signature failed + */ int fit_check_sign(const void *fit, const void *key, const char *fit_uname_config); diff --git a/tools/image-host.c b/tools/image-host.c index f86e1fbb1b9..a5d47a4f997 100644 --- a/tools/image-host.c +++ b/tools/image-host.c @@ -48,10 +48,10 @@ static int fit_set_hash_value(void *fit, int noffset, uint8_t *value, * fit_image_process_hash - Process a single subnode of the images/ node * * Check each subnode and process accordingly. For hash nodes we generate - * a hash of the supplised data and store it in the node. + * a hash of the supplied data and store it in the node. * * @fit: pointer to the FIT format image header - * @image_name: name of image being processes (used to display errors) + * @image_name: name of image being processed (used to display errors) * @noffset: subnode offset * @data: data to process * @size: size of data in bytes @@ -200,12 +200,12 @@ static int fit_image_setup_sig(struct image_sign_info *info, * fit_image_process_sig- Process a single subnode of the images/ node * * Check each subnode and process accordingly. For signature nodes we - * generate a signed hash of the supplised data and store it in the node. + * generate a signed hash of the supplied data and store it in the node. * * @keydir: Directory containing keys to use for signing - * @keydest: Destination FDT blob to write public keys into + * @keydest: Destination FDT blob to write public keys into (NULL if none) * @fit: pointer to the FIT format image header - * @image_name: name of image being processes (used to display errors) + * @image_name: name of image being processed (used to display errors) * @noffset: subnode offset * @data: data to process * @size: size of data in bytes @@ -689,14 +689,14 @@ static int strlist_add(struct strlist *list, const char *str) return 0; } -static const char *fit_config_get_image_list(void *fit, int noffset, - int *lenp, int *allow_missingp) +static const char *fit_config_get_image_list(const void *fit, int noffset, + int *lenp, int *allow_missingp) { static const char default_list[] = FIT_KERNEL_PROP "\0" FIT_FDT_PROP; const char *prop; - /* If there is an "image" property, use that */ + /* If there is an "sign-image" property, use that */ prop = fdt_getprop(fit, noffset, "sign-images", lenp); if (prop) { *allow_missingp = 0; @@ -710,8 +710,24 @@ static const char *fit_config_get_image_list(void *fit, int noffset, return default_list; } -static int fit_config_add_hash(void *fit, const char *conf_name, const char *sig_name, - struct strlist *node_inc, const char *iname, int image_noffset) +/** + * fit_config_add_hash() - Add a list of nodes to hash for an image + * + * This adds a list of paths to image nodes (as referred to by a particular + * offset) that need to be hashed, to protect a configuration + * + * @fit: Pointer to the FIT format image header + * @image_noffset: Offset of image to process (e.g. /images/kernel-1) + * @node_inc: List of nodes to add to + * @conf_name Configuration-node name, child of /configurations node (only + * used for error messages) + * @sig_name Signature-node name (only used for error messages) + * @iname: Name of image being processed (e.g. "kernel-1" (only used + * for error messages) + */ +static int fit_config_add_hash(const void *fit, int image_noffset, + struct strlist *node_inc, const char *conf_name, + const char *sig_name, const char *iname) { char name[200], path[200]; int noffset; @@ -781,7 +797,21 @@ err_path: return -ENOENT; } -static int fit_config_get_hash_list(void *fit, int conf_noffset, +/** + * fit_config_get_hash_list() - Get the regions to sign + * + * This calculates a list of nodes to hash for this particular configuration, + * returning it as a string list (struct strlist, not a devicetree string list) + * + * @fit: Pointer to the FIT format image header + * @conf_noffset: Offset of configuration node to sign (child of + * /configurations node) + * @sig_offset: Offset of signature node containing info about how to sign it + * (child of 'signatures' node) + * @return 0 if OK, -ENOENT if an image referred to by the configuration cannot + * be found, -ENOMSG if ther were no images in the configuration + */ +static int fit_config_get_hash_list(const void *fit, int conf_noffset, int sig_offset, struct strlist *node_inc) { int allow_missing; @@ -832,9 +862,8 @@ static int fit_config_get_hash_list(void *fit, int conf_noffset, return -ENOENT; } - ret = fit_config_add_hash(fit, conf_name, - sig_name, node_inc, - iname, image_noffset); + ret = fit_config_add_hash(fit, image_noffset, node_inc, + conf_name, sig_name, iname); if (ret < 0) return ret; @@ -856,9 +885,32 @@ err_mem: return -ENOMEM; } -static int fit_config_get_data(void *fit, int conf_noffset, int noffset, - struct image_region **regionp, int *region_countp, - char **region_propp, int *region_proplen) +/** + * fit_config_get_regions() - Get the regions to sign + * + * This calculates a list of node to hash for this particular configuration, + * then finds which regions of the devicetree they correspond to. + * + * @fit: Pointer to the FIT format image header + * @conf_noffset: Offset of configuration node to sign (child of + * /configurations node) + * @sig_offset: Offset of signature node containing info about how to sign it + * (child of 'signatures' node) + * @regionp: Returns list of regions that need to be hashed (allocated; must be + * freed by the caller) + * @region_count: Returns number of regions + * @region_propp: Returns string-list property containing the list of nodes + * that correspond to the regions. Each entry is a full path to the node. + * This is in devicetree format, i.e. a \0 between each string. This is + * allocated and must be freed by the caller. + * @region_proplen: Returns length of *@@region_propp in bytes + * @return 0 if OK, -ENOMEM if out of memory, -EIO if the regions to hash could + * not be found, -EINVAL if no registers were found to hash + */ +static int fit_config_get_regions(const void *fit, int conf_noffset, + int sig_offset, struct image_region **regionp, + int *region_countp, char **region_propp, + int *region_proplen) { char * const exc_prop[] = {"data"}; struct strlist node_inc; @@ -871,11 +923,12 @@ static int fit_config_get_data(void *fit, int conf_noffset, int noffset, int ret, len; conf_name = fit_get_name(fit, conf_noffset, NULL); - sig_name = fit_get_name(fit, noffset, NULL); + sig_name = fit_get_name(fit, sig_offset, NULL); debug("%s: conf='%s', sig='%s'\n", __func__, conf_name, sig_name); /* Get a list of nodes we want to hash */ - ret = fit_config_get_hash_list(fit, conf_noffset, noffset, &node_inc); + ret = fit_config_get_hash_list(fit, conf_noffset, sig_offset, + &node_inc); if (ret) return ret; @@ -929,7 +982,7 @@ static int fit_config_get_data(void *fit, int conf_noffset, int noffset, } static int fit_config_process_sig(const char *keydir, const char *keyfile, - void *keydest, void *fit, const char *conf_name, + void *keydest, void *fit, const char *conf_name, int conf_noffset, int noffset, const char *comment, int require_keys, const char *engine_id, const char *cmdname, const char *algo_name) @@ -945,8 +998,9 @@ static int fit_config_process_sig(const char *keydir, const char *keyfile, int ret; node_name = fit_get_name(fit, noffset, NULL); - if (fit_config_get_data(fit, conf_noffset, noffset, ®ion, - ®ion_count, ®ion_prop, ®ion_proplen)) + if (fit_config_get_regions(fit, conf_noffset, noffset, ®ion, + ®ion_count, ®ion_prop, + ®ion_proplen)) return -1; if (fit_image_setup_sig(&info, keydir, keyfile, fit, conf_name, noffset, -- cgit v1.3.1 From 99f844ba3a6b3ddd73742cddf7dee955bbb96c61 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 12 Nov 2021 12:28:10 -0700 Subject: tools: Pass the key blob around At present we rely on the key blob being in the global_data fdt_blob pointer. This is true in U-Boot but not with tools. For clarity, pass the parameter around. Signed-off-by: Simon Glass --- boot/image-fit-sig.c | 31 ++++++++++++++++++------------- boot/image-fit.c | 12 +++++++----- common/spl/spl_fit.c | 3 ++- include/image.h | 23 ++++++++++++++++++----- 4 files changed, 45 insertions(+), 24 deletions(-) (limited to 'include') diff --git a/boot/image-fit-sig.c b/boot/image-fit-sig.c index d6e16c29ed3..a461d591a0e 100644 --- a/boot/image-fit-sig.c +++ b/boot/image-fit-sig.c @@ -65,7 +65,8 @@ struct image_region *fit_region_make_list(const void *fit, static int fit_image_setup_verify(struct image_sign_info *info, const void *fit, int noffset, - int required_keynode, char **err_msgp) + const void *key_blob, int required_keynode, + char **err_msgp) { const char *algo_name; const char *padding_name; @@ -91,7 +92,7 @@ static int fit_image_setup_verify(struct image_sign_info *info, info->checksum = image_get_checksum_algo(algo_name); info->crypto = image_get_crypto_algo(algo_name); info->padding = image_get_padding_algo(padding_name); - info->fdt_blob = gd_fdt_blob(); + info->fdt_blob = key_blob; info->required_keynode = required_keynode; printf("%s:%s", algo_name, info->keyname); @@ -104,7 +105,8 @@ static int fit_image_setup_verify(struct image_sign_info *info, } int fit_image_check_sig(const void *fit, int noffset, const void *data, - size_t size, int required_keynode, char **err_msgp) + size_t size, const void *key_blob, int required_keynode, + char **err_msgp) { struct image_sign_info info; struct image_region region; @@ -112,8 +114,8 @@ int fit_image_check_sig(const void *fit, int noffset, const void *data, int fit_value_len; *err_msgp = NULL; - if (fit_image_setup_verify(&info, fit, noffset, required_keynode, - err_msgp)) + if (fit_image_setup_verify(&info, fit, noffset, key_blob, + required_keynode, err_msgp)) return -1; if (fit_image_hash_get_value(fit, noffset, &fit_value, @@ -156,8 +158,8 @@ static int fit_image_verify_sig(const void *fit, int image_noffset, } if (!strncmp(name, FIT_SIG_NODENAME, strlen(FIT_SIG_NODENAME))) { - ret = fit_image_check_sig(fit, noffset, data, - size, -1, &err_msg); + ret = fit_image_check_sig(fit, noffset, data, size, + key_blob, -1, &err_msg); if (ret) { puts("- "); } else { @@ -244,6 +246,7 @@ int fit_image_verify_required_sigs(const void *fit, int image_noffset, * @noffset: Offset of the signature node being checked (e.g. * /configurations/conf-1/signature-1) * @conf_noffset: Offset of configuration node (e.g. /configurations/conf-1) + * @key_blob: Blob containing the keys to check against * @required_keynode: Offset in @key_blob of the required key node, * if any. If this is given, then the configuration wil not * pass verification unless that key is used. If this is @@ -253,7 +256,8 @@ int fit_image_verify_required_sigs(const void *fit, int image_noffset, * Return: 0 if all verified ok, <0 on error */ static int fit_config_check_sig(const void *fit, int noffset, int conf_noffset, - int required_keynode, char **err_msgp) + const void *key_blob, int required_keynode, + char **err_msgp) { static char * const exc_prop[] = { "data", @@ -275,12 +279,12 @@ static int fit_config_check_sig(const void *fit, int noffset, int conf_noffset, int count; config_name = fit_get_name(fit, conf_noffset, NULL); - debug("%s: fdt=%p, conf='%s', sig='%s'\n", __func__, gd_fdt_blob(), + debug("%s: fdt=%p, conf='%s', sig='%s'\n", __func__, key_blob, fit_get_name(fit, noffset, NULL), - fit_get_name(gd_fdt_blob(), required_keynode, NULL)); + fit_get_name(key_blob, required_keynode, NULL)); *err_msgp = NULL; - if (fit_image_setup_verify(&info, fit, noffset, required_keynode, - err_msgp)) + if (fit_image_setup_verify(&info, fit, noffset, key_blob, + required_keynode, err_msgp)) return -1; if (fit_image_hash_get_value(fit, noffset, &fit_value, @@ -423,7 +427,8 @@ static int fit_config_verify_key(const void *fit, int conf_noffset, if (!strncmp(name, FIT_SIG_NODENAME, strlen(FIT_SIG_NODENAME))) { ret = fit_config_check_sig(fit, noffset, conf_noffset, - key_offset, &err_msg); + key_blob, key_offset, + &err_msg); if (ret) { puts("- "); } else { diff --git a/boot/image-fit.c b/boot/image-fit.c index 85a6f223c85..f01cafe4e27 100644 --- a/boot/image-fit.c +++ b/boot/image-fit.c @@ -1309,7 +1309,8 @@ static int fit_image_check_hash(const void *fit, int noffset, const void *data, } int fit_image_verify_with_data(const void *fit, int image_noffset, - const void *data, size_t size) + const void *key_blob, const void *data, + size_t size) { int noffset = 0; char *err_msg = ""; @@ -1319,7 +1320,7 @@ int fit_image_verify_with_data(const void *fit, int image_noffset, /* Verify all required signatures */ if (FIT_IMAGE_ENABLE_VERIFY && fit_image_verify_required_sigs(fit, image_noffset, data, size, - gd_fdt_blob(), &verify_all)) { + key_blob, &verify_all)) { err_msg = "Unable to verify required signature"; goto error; } @@ -1342,8 +1343,8 @@ int fit_image_verify_with_data(const void *fit, int image_noffset, } else if (FIT_IMAGE_ENABLE_VERIFY && verify_all && !strncmp(name, FIT_SIG_NODENAME, strlen(FIT_SIG_NODENAME))) { - ret = fit_image_check_sig(fit, noffset, data, - size, -1, &err_msg); + ret = fit_image_check_sig(fit, noffset, data, size, + gd_fdt_blob(), -1, &err_msg); /* * Show an indication on failure, but do not return @@ -1406,7 +1407,8 @@ int fit_image_verify(const void *fit, int image_noffset) goto err; } - return fit_image_verify_with_data(fit, image_noffset, data, size); + return fit_image_verify_with_data(fit, image_noffset, gd_fdt_blob(), + data, size); err: printf("error!\n%s in '%s' image node\n", err_msg, diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index 774072b85c5..1bbf824684a 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -321,7 +321,8 @@ static int spl_load_fit_image(struct spl_load_info *info, ulong sector, if (CONFIG_IS_ENABLED(FIT_SIGNATURE)) { printf("## Checking hash(es) for Image %s ... ", fit_get_name(fit, node, NULL)); - if (!fit_image_verify_with_data(fit, node, src, length)) + if (!fit_image_verify_with_data(fit, node, gd_fdt_blob(), src, + length)) return -EPERM; puts("OK\n"); } diff --git a/include/image.h b/include/image.h index 15cfb2c54b0..780b624c8c9 100644 --- a/include/image.h +++ b/include/image.h @@ -1048,8 +1048,19 @@ int fit_add_verification_data(const char *keydir, const char *keyfile, int require_keys, const char *engine_id, const char *cmdname, const char *algo_name); +/** + * fit_image_verify_with_data() - Verify an image with given data + * + * @fit: Pointer to the FIT format image header + * @image_offset: Offset in @fit of image to verify + * @key_blob: FDT containing public keys + * @data: Image data to verify + * @size: Size of image data + */ int fit_image_verify_with_data(const void *fit, int image_noffset, - const void *data, size_t size); + const void *key_blob, const void *data, + size_t size); + int fit_image_verify(const void *fit, int noffset); int fit_config_verify(const void *fit, int conf_noffset); int fit_all_image_verify(const void *fit); @@ -1297,7 +1308,7 @@ struct padding_algo *image_get_padding_algo(const char *name); * @image_noffset: Offset of image node to check * @data: Image data to check * @size: Size of image data - * @sig_blob: FDT containing public keys + * @key_blob: FDT containing public keys * @no_sigsp: Returns 1 if no signatures were required, and * therefore nothing was checked. The caller may wish * to fall back to other mechanisms, or refuse to @@ -1305,7 +1316,7 @@ struct padding_algo *image_get_padding_algo(const char *name); * Return: 0 if all verified ok, <0 on error */ int fit_image_verify_required_sigs(const void *fit, int image_noffset, - const char *data, size_t size, const void *sig_blob, + const char *data, size_t size, const void *key_blob, int *no_sigsp); /** @@ -1315,7 +1326,8 @@ int fit_image_verify_required_sigs(const void *fit, int image_noffset, * @noffset: Offset of signature node to check * @data: Image data to check * @size: Size of image data - * @required_keynode: Offset in the control FDT of the required key node, + * @keyblob: Key blob to check (typically the control FDT) + * @required_keynode: Offset in the keyblob of the required key node, * if any. If this is given, then the image wil not * pass verification unless that key is used. If this is * -1 then any signature will do. @@ -1324,7 +1336,8 @@ int fit_image_verify_required_sigs(const void *fit, int image_noffset, * Return: 0 if all verified ok, <0 on error */ int fit_image_check_sig(const void *fit, int noffset, const void *data, - size_t size, int required_keynode, char **err_msgp); + size_t size, const void *key_blob, int required_keynode, + char **err_msgp); int fit_image_decrypt_data(const void *fit, int image_noffset, int cipher_noffset, -- cgit v1.3.1 From c033dc8c0c4b744e028e124f88be4829309c75d1 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 12 Nov 2021 12:28:11 -0700 Subject: image: Return destination node for add_verify_data() method It is useful to know where the verification data was written. Update the API to return this. Signed-off-by: Simon Glass --- include/image.h | 3 ++- include/u-boot/ecdsa.h | 5 +++-- include/u-boot/rsa.h | 5 +++-- lib/ecdsa/ecdsa-libcrypto.c | 4 ++-- lib/rsa/rsa-sign.c | 5 ++++- tools/image-host.c | 5 ++--- 6 files changed, 16 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/include/image.h b/include/image.h index 780b624c8c9..cf38aecaa9b 100644 --- a/include/image.h +++ b/include/image.h @@ -1243,7 +1243,8 @@ struct crypto_algo { * * @info: Specifies key and FIT information * @keydest: Destination FDT blob for public key data - * @return: 0, on success, -ve on error + * @return: node offset within the FDT blob where the data was written, + * or -ve on error */ int (*add_verify_data)(struct image_sign_info *info, void *keydest); diff --git a/include/u-boot/ecdsa.h b/include/u-boot/ecdsa.h index 0ceb0c1a084..6e0269e3aed 100644 --- a/include/u-boot/ecdsa.h +++ b/include/u-boot/ecdsa.h @@ -44,8 +44,9 @@ int ecdsa_sign(struct image_sign_info *info, const struct image_region region[], * * @info: Specifies key and FIT information * @keydest: Destination FDT blob for public key data - * @return: 0, on success, -ENOSPC if the keydest FDT blob ran out of space, - * other -ve value on error + * @return: node offset within the FDT blob where the data was written on + * success, -ENOSPC if the keydest FDT blob ran out of space, other -ve + * value on other error */ int ecdsa_add_verify_data(struct image_sign_info *info, void *keydest); diff --git a/include/u-boot/rsa.h b/include/u-boot/rsa.h index 2ed2ac7e531..01b480d0f3e 100644 --- a/include/u-boot/rsa.h +++ b/include/u-boot/rsa.h @@ -61,8 +61,9 @@ int rsa_sign(struct image_sign_info *info, * * @info: Specifies key and FIT information * @keydest: Destination FDT blob for public key data - * @return: 0, on success, -ENOSPC if the keydest FDT blob ran out of space, - other -ve value on error + * @return: node offset within the FDT blob where the data was written on + * success, -ENOSPC if the keydest FDT blob ran out of space, other -ve + * value on other error */ int rsa_add_verify_data(struct image_sign_info *info, void *keydest); diff --git a/lib/ecdsa/ecdsa-libcrypto.c b/lib/ecdsa/ecdsa-libcrypto.c index ae6dfa0ba97..d5939af2c56 100644 --- a/lib/ecdsa/ecdsa-libcrypto.c +++ b/lib/ecdsa/ecdsa-libcrypto.c @@ -301,7 +301,7 @@ static int do_add(struct signer *ctx, void *fdt, const char *key_node_name) if (ret < 0) return ret; - return 0; + return key_node; } int ecdsa_add_verify_data(struct image_sign_info *info, void *fdt) @@ -313,7 +313,7 @@ int ecdsa_add_verify_data(struct image_sign_info *info, void *fdt) fdt_key_name = info->keyname ? info->keyname : "default-key"; ret = prepare_ctx(&ctx, info); if (ret >= 0) - do_add(&ctx, fdt, fdt_key_name); + ret = do_add(&ctx, fdt, fdt_key_name); free_ctx(&ctx); return ret; diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c index a95a3d2748a..3e7b7982890 100644 --- a/lib/rsa/rsa-sign.c +++ b/lib/rsa/rsa-sign.c @@ -703,5 +703,8 @@ err_get_pub_key: if (info->engine_id) rsa_engine_remove(e); - return ret; + if (ret) + return ret; + + return node; } diff --git a/tools/image-host.c b/tools/image-host.c index f13a9441364..89520915aff 100644 --- a/tools/image-host.c +++ b/tools/image-host.c @@ -267,7 +267,7 @@ static int fit_image_process_sig(const char *keydir, const char *keyfile, */ if (keydest) { ret = info.crypto->add_verify_data(&info, keydest); - if (ret) { + if (ret < 0) { printf("Failed to add verification data for '%s' signature node in '%s' image node\n", node_name, image_name); return ret; @@ -1037,11 +1037,10 @@ static int fit_config_process_sig(const char *keydir, const char *keyfile, /* Write the public key into the supplied FDT file */ if (keydest) { ret = info.crypto->add_verify_data(&info, keydest); - if (ret) { + if (ret < 0) { printf("Failed to add verification data for '%s' signature node in '%s' configuration node\n", node_name, conf_name); } - return ret; } return 0; -- cgit v1.3.1 From 2d2384bbaff0ab84c868b553c74048a5f6acc9e3 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 12 Nov 2021 12:28:13 -0700 Subject: tools: mkimage: Show where signatures/keys are written At present mkimage displays the node information but it is not clear what signing action was taken. Add a message that shows it. For now it only supports showing a single signing action, since that is the common case. Sample: Signature written to 'sha1-basic/test.fit', node '/configurations/conf-1/signature' Public key written to 'sha1-basic/sandbox-u-boot.dtb', node '/signature/key-dev' Signed-off-by: Simon Glass --- include/image.h | 23 ++++++++++++++++++++++- tools/fit_common.c | 13 +++++++++++++ tools/fit_common.h | 10 ++++++++++ tools/fit_image.c | 3 ++- tools/image-host.c | 23 ++++++++++++++++++----- tools/imagetool.h | 3 +++ tools/mkimage.c | 4 ++++ 7 files changed, 72 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/include/image.h b/include/image.h index cf38aecaa9b..97e5f2eb24d 100644 --- a/include/image.h +++ b/include/image.h @@ -1021,6 +1021,25 @@ int fit_cipher_data(const char *keydir, void *keydest, void *fit, const char *comment, int require_keys, const char *engine_id, const char *cmdname); +#define NODE_MAX_NAME_LEN 80 + +/** + * struct image_summary - Provides information about signing info added + * + * @sig_offset: Offset of the node in the blob devicetree where the signature + * was wriiten + * @sig_path: Path to @sig_offset + * @keydest_offset: Offset of the node in the keydest devicetree where the + * public key was written (-1 if none) + * @keydest_path: Path to @keydest_offset + */ +struct image_summary { + int sig_offset; + char sig_path[NODE_MAX_NAME_LEN]; + int keydest_offset; + char keydest_path[NODE_MAX_NAME_LEN]; +}; + /** * fit_add_verification_data() - add verification data to FIT image nodes * @@ -1032,6 +1051,7 @@ int fit_cipher_data(const char *keydir, void *keydest, void *fit, * @engine_id: Engine to use for signing * @cmdname: Command name used when reporting errors * @algo_name: Algorithm name, or NULL if to be read from FIT + * @summary: Returns information about what data was written * * Adds hash values for all component images in the FIT blob. * Hashes are calculated for all component images which have hash subnodes @@ -1046,7 +1066,8 @@ int fit_cipher_data(const char *keydir, void *keydest, void *fit, int fit_add_verification_data(const char *keydir, const char *keyfile, void *keydest, void *fit, const char *comment, int require_keys, const char *engine_id, - const char *cmdname, const char *algo_name); + const char *cmdname, const char *algo_name, + struct image_summary *summary); /** * fit_image_verify_with_data() - Verify an image with given data diff --git a/tools/fit_common.c b/tools/fit_common.c index 5ea43f5fec8..01649760ac0 100644 --- a/tools/fit_common.c +++ b/tools/fit_common.c @@ -175,3 +175,16 @@ int copyfile(const char *src, const char *dst) return ret; } + +void summary_show(struct image_summary *summary, const char *imagefile, + const char *keydest) +{ + if (summary->sig_offset) { + printf("Signature written to '%s', node '%s'\n", imagefile, + summary->sig_path); + if (keydest) { + printf("Public key written to '%s', node '%s'\n", + keydest, summary->keydest_path); + } + } +} diff --git a/tools/fit_common.h b/tools/fit_common.h index c600dc2ba48..920a16acfdb 100644 --- a/tools/fit_common.h +++ b/tools/fit_common.h @@ -52,4 +52,14 @@ int mmap_fdt(const char *cmdname, const char *fname, size_t size_inc, */ int copyfile(const char *src, const char *dst); +/** + * summary_show() - Show summary information about the signing process + * + * @summary: Summary info to show + * @imagefile: Filename of the output image + * @keydest: Filename where the key information is written (NULL if none) + */ +void summary_show(struct image_summary *summary, const char *imagefile, + const char *keydest); + #endif /* _FIT_COMMON_H_ */ diff --git a/tools/fit_image.c b/tools/fit_image.c index 0e31f7dca6e..15f7c82d619 100644 --- a/tools/fit_image.c +++ b/tools/fit_image.c @@ -74,7 +74,8 @@ static int fit_add_file_data(struct image_tool_params *params, size_t size_inc, params->require_keys, params->engine_id, params->cmdname, - params->algo_name); + params->algo_name, + ¶ms->summary); } if (dest_blob) { diff --git a/tools/image-host.c b/tools/image-host.c index 030d4eb89c4..eaeb76545c6 100644 --- a/tools/image-host.c +++ b/tools/image-host.c @@ -1071,7 +1071,8 @@ static int fit_config_process_sig(const char *keydir, const char *keyfile, static int fit_config_add_verification_data(const char *keydir, const char *keyfile, void *keydest, void *fit, int conf_noffset, const char *comment, int require_keys, const char *engine_id, - const char *cmdname, const char *algo_name) + const char *cmdname, const char *algo_name, + struct image_summary *summary) { const char *conf_name; int noffset; @@ -1091,9 +1092,20 @@ static int fit_config_add_verification_data(const char *keydir, ret = fit_config_process_sig(keydir, keyfile, keydest, fit, conf_name, conf_noffset, noffset, comment, require_keys, engine_id, cmdname, algo_name); + if (ret < 0) + return ret; + + summary->sig_offset = noffset; + fdt_get_path(fit, noffset, summary->sig_path, + sizeof(summary->sig_path)); + + if (keydest) { + summary->keydest_offset = ret; + fdt_get_path(keydest, ret, + summary->keydest_path, + sizeof(summary->keydest_path)); + } } - if (ret < 0) - return ret; } return 0; @@ -1137,7 +1149,8 @@ int fit_cipher_data(const char *keydir, void *keydest, void *fit, int fit_add_verification_data(const char *keydir, const char *keyfile, void *keydest, void *fit, const char *comment, int require_keys, const char *engine_id, - const char *cmdname, const char *algo_name) + const char *cmdname, const char *algo_name, + struct image_summary *summary) { int images_noffset, confs_noffset; int noffset; @@ -1186,7 +1199,7 @@ int fit_add_verification_data(const char *keydir, const char *keyfile, fit, noffset, comment, require_keys, engine_id, cmdname, - algo_name); + algo_name, summary); if (ret) return ret; } diff --git a/tools/imagetool.h b/tools/imagetool.h index b7ac3a23d0f..413e97cbeb2 100644 --- a/tools/imagetool.h +++ b/tools/imagetool.h @@ -21,6 +21,8 @@ #include #include +#include + #include "fdt_host.h" #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) @@ -84,6 +86,7 @@ struct image_tool_params { int bl_len; /* Block length in byte for external data */ const char *engine_id; /* Engine to use for signing */ bool reset_timestamp; /* Reset the timestamp on an existing image */ + struct image_summary summary; /* results of signing process */ }; /* diff --git a/tools/mkimage.c b/tools/mkimage.c index 0ec28da33cb..c8f4ecd473d 100644 --- a/tools/mkimage.c +++ b/tools/mkimage.c @@ -10,6 +10,7 @@ #include "imagetool.h" #include "mkimage.h" #include "imximage.h" +#include #include #include #ifdef __linux__ @@ -472,6 +473,9 @@ int main(int argc, char **argv) (void) munmap((void *)ptr, sbuf.st_size); (void) close (ifd); + if (!retval) + summary_show(¶ms.summary, params.imagefile, + params.keydest); exit (retval); } -- cgit v1.3.1