[PATCH 3/3] efi_loader: add ACPI table dump EFI app
Simon Glass
sjg at chromium.org
Sat May 23 11:43:44 CEST 2026
Hi Heinrich,
On 2026-05-21T18:50:22, Heinrich Schuchardt
<heinrich.schuchardt at canonical.com> wrote:
> efi_loader: add ACPI table dump EFI app
>
> Provide an EFI binary that can dump all ACPI tables to files
> <table_name>.dat. These can then be further analyzed by decompiling
> with iasl.
>
> Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt at canonical.com>
> Acked-by: Ilias Apalodimas <ilias.apalodimas at linaro.org>
> Tested-by: Ilias Apalodimas <ilias.apalodimas at linaro.org>
>
> lib/efi_loader/Makefile | 1 +
> lib/efi_loader/acpidump.c | 999 ++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 1000 insertions(+)
> diff --git a/lib/efi_loader/acpidump.c b/lib/efi_loader/acpidump.c
> @@ -0,0 +1,999 @@
> +#include <efi_api.h>
> +#include <part.h>
> +#include <string.h>
> +#include <acpi/acpi_table.h>
At 999 lines this is the third copy of the same EFI-app skeleton
(after smbiosdump.c and dtbdump.c). color(), print(), cls(), error(),
efi_input_yn(), efi_input(), skip_whitespace(), starts_with(),
open_file_system(), save_file(), command_loop(), get_load_options()
and the efi_main() boilerplate are all near-verbatim from
smbiosdump.c.
Please factor the shared pieces into a small header/object (e.g.
lib/efi_loader/efi_app_helper.c) so the new app only contains the
ACPI-specific code. Otherwise every future fix has to be made in three
places.
> diff --git a/lib/efi_loader/acpidump.c b/lib/efi_loader/acpidump.c
> @@ -0,0 +1,999 @@
> + rsdp = get_acpi_rsdp_addr();
> + print(u"RSDP address: ");
> + printp(rsdp);
> + print(u'\r\n');
> + if (!rsdp) {
> + error(u"No ACPI configuration table\r\n");
> + return EFI_NOT_FOUND;
> + }
When there is no ACPI table we still print 'RSDP address:
0x0000000000000000' before the error. Please move the NULL check ahead
of the printing.
> diff --git a/lib/efi_loader/acpidump.c b/lib/efi_loader/acpidump.c
> @@ -0,0 +1,999 @@
> + if (!memcmp(table->signature, 'FACP', 4)) {
> + struct acpi_fadt *fadt = (struct acpi_fadt *)table;
> + uintptr_t dsdt_addr;
> + uintptr_t facs_addr;
> +
> + dsdt_addr = read_u64(&fadt->x_dsdt);
> + if (!dsdt_addr)
> + dsdt_addr = read_u32(&fadt->dsdt);
x_dsdt and x_firmware_ctrl live past offset 0x8c - an ACPI 1.0 FADT
has a length below that, so this reads beyond the table's declared
(and checksummed) extent. Do we care about old tables? If so, please
gate the 64-bit reads on len >= offsetofend(struct acpi_fadt, x_dsdt)
(and similarly for x_firmware_ctrl).
> diff --git a/lib/efi_loader/acpidump.c b/lib/efi_loader/acpidump.c
> @@ -0,0 +1,999 @@
> + dsdt = (struct acpi_table_header *)dsdt_addr;
> + dsdt_len = read_u32(&dsdt->length);
> + if (dsdt_len < sizeof(*dsdt)) {
> + error(u"Invalid DSDT length\r\n");
> + ret = EFI_LOAD_ERROR;
> + goto err_out;
> + }
> + if (!checksum_ok(dsdt, dsdt_len)) {
> + error(u"Invalid DSDT checksum\r\n");
> + ret = EFI_LOAD_ERROR;
> + goto err_out;
> + }
For FACS you verify the signature before trusting the length, but not
for DSDT - a corrupt FADT pointing at random memory could pass length
and checksum here. Please add a memcmp(dsdt->signature, 'DSDT', 4)
check.
> diff --git a/lib/efi_loader/acpidump.c b/lib/efi_loader/acpidump.c
> @@ -0,0 +1,999 @@
> + memcpy(buf, (void *)tables[i].addr, tables[i].len);
> + ret = save_file(filename, buf, tables[i].len);
> + if (ret == EFI_SUCCESS) {
> + print(filename);
> + print(u" written\r\n");
> + }
> +
> + bs->free_pool(buf);
> + if (ret != EFI_SUCCESS)
> + break;
If the user answers 'n' to the overwrite prompt for one table,
save_file() returns EFI_ACCESS_DENIED and the whole dump aborts,
silently skipping the rest. Is that intended?
> diff --git a/lib/efi_loader/acpidump.c b/lib/efi_loader/acpidump.c
> @@ -0,0 +1,999 @@
> + * starts_with() - check if @string starts with @keyword
> + *
> + * @string: string to search for keyword
> + * @keyword: keyword to be searched
> + * Return: true fi @string starts with the keyword
> + */
'fi' should be 'if'
> diff --git a/lib/efi_loader/acpidump.c b/lib/efi_loader/acpidump.c
> @@ -0,0 +1,999 @@
> + ret = collect_tables(&tables, &table_count);
> + if (ret != EFI_SUCCESS)
> + return ret;
> +
> + if (!table_count) {
> + print(u"No ACPI tables found\r\n");
> + return EFI_NOT_FOUND;
> + }
collect_tables() always seeds the array with RSDP + root before
returning EFI_SUCCESS, so this branch is unreachable - and if it ever
did fire it would leak 'tables'. Either drop the check or free
'tables' on the way out.
Regards,
Simon
More information about the U-Boot
mailing list