[PATCH 00/20] emulation: Improve ACPI support for qemu-x86_64

From: Simon Glass <sjg@chromium.org> When running under QEMU U-Boot obtains its ACPI tables from QEMU, since it has the require information. This works well in most cases. QEMU also provides SMBIOS tables, but U-Boot doesn't currently use those on x86. This creates problems if a VM environment is expecting to see particular values (e.g. those which it passed to QEMU!) when booting. So this series switches QEMU on x86 to use those SMBIOS tables. Finally, there is a facility in EFI for showing a boot logo, via a BGRT table. QEMU does not provide this itself, so this series augments the ACPI tables with a new BGRT table containing a suitable logo. Simon Glass (20): scripts: build-qemu: Support a random-number generator efi_loader: Use the first random-number-generator device event: Mark test_event_probe() as sandbox-only hooks: x86: Enable support for a random-number generator x86: Enable random-number support for QEMU acpi: Move calculation of RSDP checksum into a function acpi: Update acpi_find_table() to verify checksums x86: Use the existing function to find the FACP emulation: Simplify write_acpi_tables() acpi: Pull out setup code from acpi_find_table() acpi: Move code table-writing code to lib/acpi/acpi.c acpi Adjust dm_test_acpi_find_table() to use a fixed buffer acpi: Allow finding the RSDT or XSDT acpi: Provide a way to locate the end of the ACPI tables qemu: Use SMBIOS tables from QEMU scripts: Make the build rule for the logo more specific acpi: Provide a way to build in a boot logo acpi: Support a boot logo (BGRT) emulation: Drop computing the ACPI checksum emulation: Add the BGRT on the end of the QEMU tables arch/Kconfig | 2 +- arch/x86/lib/acpi.c | 51 +--- configs/qemu-x86_64_defconfig | 1 + drivers/qfw/qfw_acpi.c | 74 +++--- include/acpi/acpi_table.h | 30 ++- lib/acpi/Makefile | 3 + lib/acpi/acpi.c | 242 ++++++++++++++++++- lib/acpi/acpi_extra.c | 103 ++++++++ lib/acpi/acpi_table.c | 133 +--------- lib/acpi/base.c | 17 +- lib/acpi/bgrt_image.bmp | Bin 0 -> 43926 bytes lib/efi_loader/efi_rng.c | 10 +- scripts/Makefile.lib | 30 ++- scripts/build_helper.py | 7 + test/common/event.c | 5 +- test/dm/acpi.c | 121 +++++++++- test/hooks/bin/travis-ci/conf.qemu-x86_64_na | 5 +- 17 files changed, 584 insertions(+), 250 deletions(-) create mode 100644 lib/acpi/acpi_extra.c create mode 100644 lib/acpi/bgrt_image.bmp -- 2.43.0 base-commit: 7f32b8d7f91652e3bdfe31f2a10f194b7afa1200 branch: qemi

From: Simon Glass <sjg@chromium.org> Add a --rand option to enable access to /dev/random from QEMU. Signed-off-by: Simon Glass <sjg@chromium.org> --- scripts/build_helper.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/scripts/build_helper.py b/scripts/build_helper.py index caf83848bc3..b126dee34c6 100644 --- a/scripts/build_helper.py +++ b/scripts/build_helper.py @@ -178,6 +178,11 @@ sct_mnt = /mnt/sct else: tout.warning(f"Disk image '{disk}' not found") + if args.rand: + cmd.extend(['-object', 'rng-random,filename=/dev/random,id=rng0', + '-device', + 'virtio-rng-pci,rng=rng0,max-bytes=1024,period=1000']) + def add_common_args(parser): """Add some arguments which are common to build-efi/qemu scripts @@ -206,6 +211,8 @@ def add_common_args(parser): parser.add_argument( '-R', '--release', default='24.04.1', help='Select OS release version (e.g, 24.04) Default: 24.04.1') + parser.add_argument('--rand', '--random', action='store_true', + help='Provide a random-number device') parser.add_argument('-s', '--serial-only', action='store_true', help='Run QEMU with serial only (no display)') parser.add_argument( -- 2.43.0

From: Simon Glass <sjg@chromium.org> There is no guarantee that the RNG device has a sequence number of zero. Use the first available device instead, by default. This resolved a failure to find the device with qemu-x86_64 when the virtio device is used. Signed-off-by: Simon Glass <sjg@chromium.org> --- lib/efi_loader/efi_rng.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/efi_loader/efi_rng.c b/lib/efi_loader/efi_rng.c index 4734f95eee1..a422a605c7e 100644 --- a/lib/efi_loader/efi_rng.c +++ b/lib/efi_loader/efi_rng.c @@ -24,21 +24,21 @@ const efi_guid_t efi_guid_rng_protocol = EFI_RNG_PROTOCOL_GUID; * * This function may be overridden if special initialization is needed. * - * @dev: udevice + * @devp: udevice * Return: status code */ -__weak efi_status_t platform_get_rng_device(struct udevice **dev) +__weak efi_status_t platform_get_rng_device(struct udevice **devp) { int ret; - struct udevice *devp; + struct udevice *dev; - ret = uclass_get_device(UCLASS_RNG, 0, &devp); + ret = uclass_first_device_err(UCLASS_RNG, &dev); if (ret) { debug("Unable to get rng device\n"); return EFI_DEVICE_ERROR; } - *dev = devp; + *devp = dev; return EFI_SUCCESS; } -- 2.43.0

From: Simon Glass <sjg@chromium.org> This test skips itself if not running on sandbox, but by that time the driver model state has already been reset. This can impact other tests. Change the test so that it is only started on sandbox. Signed-off-by: Simon Glass <sjg@chromium.org> --- test/common/event.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/common/event.c b/test/common/event.c index bfbbf019768..22dce2ee88f 100644 --- a/test/common/event.c +++ b/test/common/event.c @@ -67,6 +67,7 @@ static int test_event_simple(struct unit_test_state *uts) } COMMON_TEST(test_event_simple, 0); +#ifdef CONFIG_SANDBOX static int h_probe(void *ctx, struct event *event) { struct test_state *test_state = ctx; @@ -91,9 +92,6 @@ static int test_event_probe(struct unit_test_state *uts) struct test_state state; struct udevice *dev; - if (!IS_ENABLED(SANDBOX)) - return -EAGAIN; - state.val = 0; ut_assertok(event_register("pre", EVT_DM_PRE_PROBE, h_probe, &state)); ut_assertok(event_register("post", EVT_DM_POST_PROBE, h_probe, &state)); @@ -107,3 +105,4 @@ static int test_event_probe(struct unit_test_state *uts) return 0; } COMMON_TEST(test_event_probe, UTF_DM | UTF_SCAN_FDT); +#endif /* SANDBOX */ -- 2.43.0

From: Simon Glass <sjg@chromium.org> Enable the virtio-rnd-pci device in QEMU so that fdt_test_chosen() can operated. Since overlays are enabled for qemu-x886_64 Signed-off-by: Simon Glass <sjg@chromium.org> --- test/hooks/bin/travis-ci/conf.qemu-x86_64_na | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/hooks/bin/travis-ci/conf.qemu-x86_64_na b/test/hooks/bin/travis-ci/conf.qemu-x86_64_na index 356c5cf47a5..f6a1b5e65a7 100644 --- a/test/hooks/bin/travis-ci/conf.qemu-x86_64_na +++ b/test/hooks/bin/travis-ci/conf.qemu-x86_64_na @@ -21,7 +21,10 @@ console_impl=qemu qemu_machine="pc" qemu_binary="qemu-system-x86_64" -qemu_extra_args="-nographic -cpu qemu64 -netdev user,id=net0,tftp=${UBOOT_TRAVIS_BUILD_DIR} -device e1000,netdev=net0" +qemu_extra_args="-nographic -cpu qemu64 -netdev user,id=net0,tftp=${UBOOT_TRAVIS_BUILD_DIR} -device e1000,netdev=net0 " +qemu_extra_args+=" -object rng-random,filename=/dev/random,id=rng0" +qemu_extra_args+=" -device virtio-rng-pci,rng=rng0,max-bytes=1024,period=1000" + qemu_kernel_args="-bios ${U_BOOT_BUILD_DIR}/u-boot.rom" reset_impl=none flash_impl=none -- 2.43.0

From: Simon Glass <sjg@chromium.org> Enable CONFIG_DM_RNG so the virtio driver for random numbers is supported. Signed-off-by: Simon Glass <sjg@chromium.org> --- configs/qemu-x86_64_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/qemu-x86_64_defconfig b/configs/qemu-x86_64_defconfig index a01470fb89f..b0922ae8008 100644 --- a/configs/qemu-x86_64_defconfig +++ b/configs/qemu-x86_64_defconfig @@ -81,6 +81,7 @@ CONFIG_SYS_64BIT_LBA=y CONFIG_CPU=y CONFIG_NVME_PCI=y CONFIG_SPL_PCI_PNP=y +CONFIG_DM_RNG=y CONFIG_SPL_DM_RTC=y CONFIG_SYS_NS16550_PORT_MAPPED=y CONFIG_SPI=y -- 2.43.0

From: Simon Glass <sjg@chromium.org> Create a function for this checksumming, since it is not trivial. This will allow the code to be shared with tests. Signed-off-by: Simon Glass <sjg@chromium.org> --- include/acpi/acpi_table.h | 7 +++++++ lib/acpi/base.c | 17 ++++++++++++----- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/include/acpi/acpi_table.h b/include/acpi/acpi_table.h index 05b6385544e..6d599455bd6 100644 --- a/include/acpi/acpi_table.h +++ b/include/acpi/acpi_table.h @@ -1095,6 +1095,13 @@ int acpi_write_dbg2_pci_uart(struct acpi_ctx *ctx, struct udevice *dev, void acpi_write_rsdp(struct acpi_rsdp *rsdp, struct acpi_rsdt *rsdt, struct acpi_xsdt *xsdt); +/** + * acpi_udpate_rsdp_checksum() - Set up the checksum for the RSDP table + * + * @rsdp: Pointer to RSDP + */ +void acpi_udpate_rsdp_checksum(struct acpi_rsdp *rsdp); + /** * acpi_fill_header() - Set up a table header * diff --git a/lib/acpi/base.c b/lib/acpi/base.c index 5c755b14c16..a724acbc9bd 100644 --- a/lib/acpi/base.c +++ b/lib/acpi/base.c @@ -15,6 +15,17 @@ #include <linux/errno.h> #include <linux/string.h> +void acpi_udpate_rsdp_checksum(struct acpi_rsdp *rsdp) +{ + rsdp->checksum = 0; + rsdp->ext_checksum = 0; + + /* Calculate checksums */ + rsdp->checksum = table_compute_checksum(rsdp, 20); + rsdp->ext_checksum = table_compute_checksum(rsdp, + sizeof(struct acpi_rsdp)); +} + void acpi_write_rsdp(struct acpi_rsdp *rsdp, struct acpi_rsdt *rsdt, struct acpi_xsdt *xsdt) { @@ -31,11 +42,7 @@ void acpi_write_rsdp(struct acpi_rsdp *rsdp, struct acpi_rsdt *rsdt, rsdp->length = sizeof(struct acpi_rsdp); 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)); + acpi_udpate_rsdp_checksum(rsdp); } static void acpi_write_rsdt(struct acpi_rsdt *rsdt) -- 2.43.0

From: Simon Glass <sjg@chromium.org> The RSP is not valid unless the checksums are corrrect, so add a test for this. Add a few blank lines for readability while here. Signed-off-by: Simon Glass <sjg@chromium.org> --- lib/acpi/acpi.c | 25 ++++++++++++++++++++++++- test/dm/acpi.c | 4 ++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/lib/acpi/acpi.c b/lib/acpi/acpi.c index 596301a43fe..2174e570633 100644 --- a/lib/acpi/acpi.c +++ b/lib/acpi/acpi.c @@ -5,6 +5,8 @@ * Copyright 2023 Google LLC */ +#define LOG_CATEGORY LOGC_ACPI + #include <mapmem.h> #include <tables_csum.h> #include <acpi/acpi_table.h> @@ -18,6 +20,25 @@ void acpi_update_checksum(struct acpi_table_header *header) header->checksum = table_compute_checksum(header, header->length); } +static bool acpi_valid_rsdp(struct acpi_rsdp *rsdp) +{ + if (strncmp((char *)rsdp, RSDP_SIG, sizeof(RSDP_SIG) - 1) != 0) + return false; + + debug("Looking on %p for valid checksum\n", rsdp); + + if (table_compute_checksum((void *)rsdp, 20) != 0) + return false; + debug("acpi rsdp checksum 1 passed\n"); + + if (rsdp->revision > 1 && + table_compute_checksum((void *)rsdp, rsdp->length)) + return false; + debug("acpi rsdp checksum 2 passed\n"); + + return true; +} + struct acpi_table_header *acpi_find_table(const char *sig) { struct acpi_rsdp *rsdp; @@ -26,8 +47,9 @@ struct acpi_table_header *acpi_find_table(const char *sig) int len, i, count; rsdp = map_sysmem(gd_acpi_start(), 0); - if (!rsdp) + if (!rsdp || !acpi_valid_rsdp(rsdp)) return NULL; + if (rsdp->xsdt_address) { xsdt = nomap_sysmem(rsdp->xsdt_address, 0); len = xsdt->header.length - sizeof(xsdt->header); @@ -39,6 +61,7 @@ struct acpi_table_header *acpi_find_table(const char *sig) len = rsdt->header.length - sizeof(rsdt->header); count = len / sizeof(u32); } + for (i = 0; i < count; i++) { struct acpi_table_header *hdr; diff --git a/test/dm/acpi.c b/test/dm/acpi.c index db012b6d2f1..addc2773220 100644 --- a/test/dm/acpi.c +++ b/test/dm/acpi.c @@ -812,6 +812,8 @@ static int dm_test_acpi_find_table(struct unit_test_state *uts) /* Find with XSDT only */ rsdp->rsdt_address = 0; + acpi_udpate_rsdp_checksum(rsdp); + table = acpi_find_table("TST1"); ut_asserteq_ptr(table1, table); table = acpi_find_table("TST2"); @@ -822,6 +824,8 @@ static int dm_test_acpi_find_table(struct unit_test_state *uts) /* Find with RSDT only */ rsdp->xsdt_address = 0; + acpi_udpate_rsdp_checksum(rsdp); + table = acpi_find_table("TST1"); ut_asserteq_ptr(table1, table); table = acpi_find_table("TST2"); -- 2.43.0

From: Simon Glass <sjg@chromium.org> Rather than searching for this table, use the existing search function. Update that to check the header and checksums. This allows the code to work correctly with boards that have the tables in a bloblist, such as QEMU. Signed-off-by: Simon Glass <sjg@chromium.org> --- arch/x86/lib/acpi.c | 51 ++++----------------------------------------- 1 file changed, 4 insertions(+), 47 deletions(-) diff --git a/arch/x86/lib/acpi.c b/arch/x86/lib/acpi.c index a73a2539ad3..9faba9c0b4f 100644 --- a/arch/x86/lib/acpi.c +++ b/arch/x86/lib/acpi.c @@ -8,61 +8,18 @@ #include <asm/io.h> #include <asm/tables.h> -static struct acpi_rsdp *acpi_valid_rsdp(struct acpi_rsdp *rsdp) -{ - if (strncmp((char *)rsdp, RSDP_SIG, sizeof(RSDP_SIG) - 1) != 0) - return NULL; - - debug("Looking on %p for valid checksum\n", rsdp); - - if (table_compute_checksum((void *)rsdp, 20) != 0) - return NULL; - debug("acpi rsdp checksum 1 passed\n"); - - if ((rsdp->revision > 1) && - (table_compute_checksum((void *)rsdp, rsdp->length) != 0)) - return NULL; - debug("acpi rsdp checksum 2 passed\n"); - - return rsdp; -} - struct acpi_fadt *acpi_find_fadt(void) { - char *p, *end; - struct acpi_rsdp *rsdp = NULL; - struct acpi_rsdt *rsdt; - struct acpi_fadt *fadt = NULL; - int i; - - /* Find RSDP */ - for (p = (char *)ROM_TABLE_ADDR; p < (char *)ROM_TABLE_END; p += 16) { - rsdp = acpi_valid_rsdp((struct acpi_rsdp *)p); - if (rsdp) - break; - } - - if (!rsdp) - return NULL; + struct acpi_table_header *fadt = NULL; - debug("RSDP found at %p\n", rsdp); - rsdt = (struct acpi_rsdt *)(uintptr_t)rsdp->rsdt_address; - - end = (char *)rsdt + rsdt->header.length; - debug("RSDT found at %p ends at %p\n", rsdt, end); - - for (i = 0; ((char *)&rsdt->entry[i]) < end; i++) { - fadt = (struct acpi_fadt *)(uintptr_t)rsdt->entry[i]; - if (strncmp((char *)fadt, "FACP", 4) == 0) - break; - fadt = NULL; - } + fadt = acpi_find_table("FACP"); if (!fadt) return NULL; debug("FADT found at %p\n", fadt); - return fadt; + + return (struct acpi_fadt *)fadt; } void *acpi_find_wakeup_vector(struct acpi_fadt *fadt) -- 2.43.0

From: Simon Glass <sjg@chromium.org> Update this function to make use of the new support for reading qfw files, this simplifying it considerably. Fix up the header order while we are here. Signed-off-by: Simon Glass <sjg@chromium.org> --- drivers/qfw/qfw_acpi.c | 55 ++++++++++++------------------------------ 1 file changed, 16 insertions(+), 39 deletions(-) diff --git a/drivers/qfw/qfw_acpi.c b/drivers/qfw/qfw_acpi.c index ec00ba65ade..16dd94ba71f 100644 --- a/drivers/qfw/qfw_acpi.c +++ b/drivers/qfw/qfw_acpi.c @@ -6,17 +6,18 @@ #define LOG_CATEGORY UCLASS_QFW -#include <acpi/acpi_table.h> +#include <abuf.h> #include <bloblist.h> #include <errno.h> #include <malloc.h> #include <mapmem.h> #include <qfw.h> -#include <tables_csum.h> #include <stdio.h> -#include <linux/sizes.h> +#include <tables_csum.h> +#include <acpi/acpi_table.h> #include <asm/byteorder.h> #include <asm/global_data.h> +#include <linux/sizes.h> DECLARE_GLOBAL_DATA_PTR; @@ -164,12 +165,10 @@ static int bios_linker_add_checksum(struct udevice *dev, ulong write_acpi_tables(ulong addr) { int i, ret; - struct fw_file *file; - struct bios_linker_entry *table_loader; struct bios_linker_entry *entry; - uint32_t size; struct udevice *dev; struct acpi_ctx *ctx; + struct abuf loader; ctx = malloc(sizeof(*ctx)); if (!ctx) { @@ -177,48 +176,24 @@ ulong write_acpi_tables(ulong addr) return addr; } - acpi_setup_ctx(ctx, addr); - ret = qfw_get_dev(&dev); if (ret) { printf("error: no qfw\n"); - return addr; - } - - /* make sure fw_list is loaded */ - ret = qfw_read_firmware_list(dev); - if (ret) { - printf("error: can't read firmware file list\n"); - return addr; + return -ENOENT; } - - file = qfw_find_file(dev, "etc/table-loader"); - if (!file) { - printf("error: can't find etc/table-loader\n"); + ret = qfw_get_table_loader(dev, &loader); + if (ret) return addr; - } - size = be32_to_cpu(file->cfg.size); - if ((size % sizeof(*entry)) != 0) { - printf("error: table-loader maybe corrupted\n"); - return addr; - } - - table_loader = malloc(size); - if (!table_loader) { - printf("error: no memory for table-loader\n"); - return addr; - } + acpi_setup_ctx(ctx, addr); /* QFW always puts tables at high addresses */ - gd->arch.table_start_high = (ulong)table_loader; - gd->arch.table_end_high = (ulong)table_loader; - - qfw_read_entry(dev, be16_to_cpu(file->cfg.select), size, table_loader); + gd->arch.table_start_high = abuf_addr(&loader); + gd->arch.table_end_high = abuf_addr(&loader); - for (i = 0; i < (size / sizeof(*entry)); i++) { + for (i = 0; i < loader.size / sizeof(*entry); i++) { log_content("entry %d: addr %lx\n", i, addr); - entry = table_loader + i; + entry = ((struct bios_linker_entry *)loader.data) + i; switch (le32_to_cpu(entry->command)) { case BIOS_LINKER_LOADER_COMMAND_ALLOCATE: log_content(" - %s\n", entry->alloc.file); @@ -246,6 +221,8 @@ ulong write_acpi_tables(ulong addr) out: if (ret) { struct fw_cfg_file_iter iter; + struct fw_file *file; + for (file = qfw_file_iter_init(dev, &iter); !qfw_file_iter_end(&iter); file = qfw_file_iter_next(&iter)) { @@ -256,7 +233,7 @@ out: } } - free(table_loader); + abuf_uninit(&loader); if (!ctx->rsdp) { printf("error: no RSDP found\n"); -- 2.43.0

From: Simon Glass <sjg@chromium.org> The start of this function determines whether xdst or rdsp is used for locating tables. Move it into a separate function so that we can use this logic elsewhere. Signed-off-by: Simon Glass <sjg@chromium.org> --- lib/acpi/acpi.c | 66 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 12 deletions(-) diff --git a/lib/acpi/acpi.c b/lib/acpi/acpi.c index 2174e570633..01cc606d61c 100644 --- a/lib/acpi/acpi.c +++ b/lib/acpi/acpi.c @@ -7,6 +7,7 @@ #define LOG_CATEGORY LOGC_ACPI +#include <errno.h> #include <mapmem.h> #include <tables_csum.h> #include <acpi/acpi_table.h> @@ -39,33 +40,74 @@ static bool acpi_valid_rsdp(struct acpi_rsdp *rsdp) return true; } -struct acpi_table_header *acpi_find_table(const char *sig) +/** + * setup_search() - Set up for searching through the RSDT/XSDT + * + * Looks for XSDT first and uses those entries if available, else RSDT + * + * @rsdtp: Returns RSDT if present + * @xsdtp: Returns XSDT if present + * Return: number of entries in table, -ENOENT if there is no RSDP, -EINVAL if + * the RSDP is invalid, -ENOTSYNC if both tables exist and their counts + * disagree + */ +static int setup_search(struct acpi_rsdt **rsdtp, struct acpi_xsdt **xsdtp) { struct acpi_rsdp *rsdp; - struct acpi_rsdt *rsdt; - struct acpi_xsdt *xsdt; - int len, i, count; + struct acpi_rsdt *rsdt = NULL; + struct acpi_xsdt *xsdt = NULL; + int len, count = 0; - rsdp = map_sysmem(gd_acpi_start(), 0); - if (!rsdp || !acpi_valid_rsdp(rsdp)) - return NULL; + rsdp = map_sysmem(gd_acpi_start(), 0); + if (!rsdp) + return -ENOENT; + if (!acpi_valid_rsdp(rsdp)) + return -EINVAL; if (rsdp->xsdt_address) { xsdt = nomap_sysmem(rsdp->xsdt_address, 0); len = xsdt->header.length - sizeof(xsdt->header); count = len / sizeof(u64); - } else { - if (!rsdp->rsdt_address) - return NULL; + } + + if (rsdp->rsdt_address) { + int rcount; + rsdt = nomap_sysmem(rsdp->rsdt_address, 0); len = rsdt->header.length - sizeof(rsdt->header); - count = len / sizeof(u32); + rcount = len / sizeof(u32); + if (xsdt) { + if (rcount != count) + return -ENOTSYNC; + } else { + count = rcount; + } + } + *rsdtp = rsdt; + *xsdtp = xsdt; + + return count; +} + +struct acpi_table_header *acpi_find_table(const char *sig) +{ + struct acpi_rsdt *rsdt; + struct acpi_xsdt *xsdt; + int i, count, ret; + + ret = setup_search(&rsdt, &xsdt); + if (ret < 0) { + log_warning("acpi: Failed to find tables (err=%d)\n", ret); + return NULL; } + if (!ret) + return NULL; + count = ret; for (i = 0; i < count; i++) { struct acpi_table_header *hdr; - if (rsdp->xsdt_address) + if (xsdt) hdr = nomap_sysmem(xsdt->entry[i], 0); else hdr = nomap_sysmem(rsdt->entry[i], 0); -- 2.43.0

From: Simon Glass <sjg@chromium.org> The acpi_table.c file includes ACPI_WRITER() declarations and is only included in the build if CONFIG_ACPIGEN is enabled. For QEMU we want to augment the tables provided via qfw, but CONFIG_ACPIGEN is not enabled. Move the core functions out to the acpi.c file which is included in all x86 builds. This allows the QEMU build to make use of these functions. Signed-off-by: Simon Glass <sjg@chromium.org> --- lib/acpi/acpi.c | 122 ++++++++++++++++++++++++++++++++++++++++++ lib/acpi/acpi_table.c | 122 ------------------------------------------ 2 files changed, 122 insertions(+), 122 deletions(-) diff --git a/lib/acpi/acpi.c b/lib/acpi/acpi.c index 01cc606d61c..dc327dc08c7 100644 --- a/lib/acpi/acpi.c +++ b/lib/acpi/acpi.c @@ -10,11 +10,28 @@ #include <errno.h> #include <mapmem.h> #include <tables_csum.h> +#include <version_string.h> #include <acpi/acpi_table.h> #include <asm/global_data.h> DECLARE_GLOBAL_DATA_PTR; +/* + * OEM_REVISION is 32-bit unsigned number. It should be increased only when + * changing software version. Therefore it should not depend on build time. + * U-Boot calculates it from U-Boot version and represent it in hexadecimal + * notation. As U-Boot version is in form year.month set low 8 bits to 0x01 + * to have valid date. So for U-Boot version 2021.04 OEM_REVISION is set to + * value 0x20210401. + */ +#define OEM_REVISION ((((version_num / 1000) % 10) << 28) | \ + (((version_num / 100) % 10) << 24) | \ + (((version_num / 10) % 10) << 20) | \ + ((version_num % 10) << 16) | \ + (((version_num_patch / 10) % 10) << 12) | \ + ((version_num_patch % 10) << 8) | \ + 0x01) + void acpi_update_checksum(struct acpi_table_header *header) { header->checksum = 0; @@ -145,3 +162,108 @@ struct acpi_table_header *acpi_find_table(const char *sig) return NULL; } + +void acpi_fill_header(struct acpi_table_header *header, char *signature) +{ + memcpy(header->signature, signature, 4); + memcpy(header->oem_id, OEM_ID, 6); + memcpy(header->oem_table_id, OEM_TABLE_ID, 8); + header->oem_revision = OEM_REVISION; + memcpy(header->creator_id, ASLC_ID, 4); + header->creator_revision = ASL_REVISION; +} + +void acpi_align(struct acpi_ctx *ctx) +{ + ctx->current = (void *)ALIGN((ulong)ctx->current, 16); +} + +void acpi_align64(struct acpi_ctx *ctx) +{ + ctx->current = (void *)ALIGN((ulong)ctx->current, 64); +} + +void acpi_inc(struct acpi_ctx *ctx, uint amount) +{ + ctx->current += amount; +} + +void acpi_inc_align(struct acpi_ctx *ctx, uint amount) +{ + ctx->current += amount; + acpi_align(ctx); +} + +/** + * Add an ACPI table to the RSDT (and XSDT) structure, recalculate length + * and checksum. + */ +int acpi_add_table(struct acpi_ctx *ctx, void *table) +{ + int i, entries_num; + struct acpi_rsdt *rsdt; + struct acpi_xsdt *xsdt; + + /* On legacy x86 platforms the RSDT is mandatory while the XSDT is not. + * On other platforms there might be no memory below 4GiB, thus RSDT is NULL. + */ + if (ctx->rsdt) { + rsdt = ctx->rsdt; + + /* This should always be MAX_ACPI_TABLES */ + entries_num = ARRAY_SIZE(rsdt->entry); + + for (i = 0; i < entries_num; i++) { + if (rsdt->entry[i] == 0) + break; + } + + if (i >= entries_num) { + log_err("ACPI: Error: too many tables\n"); + return -E2BIG; + } + + /* Add table to the RSDT */ + rsdt->entry[i] = nomap_to_sysmem(table); + + /* Fix RSDT length or the kernel will assume invalid entries */ + rsdt->header.length = sizeof(struct acpi_table_header) + + (sizeof(u32) * (i + 1)); + + /* Re-calculate checksum */ + acpi_update_checksum(&rsdt->header); + } + + if (ctx->xsdt) { + /* + * And now the same thing for the XSDT. We use the same index as for + * now we want the XSDT and RSDT to always be in sync in U-Boot + */ + xsdt = ctx->xsdt; + + /* This should always be MAX_ACPI_TABLES */ + entries_num = ARRAY_SIZE(xsdt->entry); + + for (i = 0; i < entries_num; i++) { + if (xsdt->entry[i] == 0) + break; + } + + if (i >= entries_num) { + log_err("ACPI: Error: too many tables\n"); + return -E2BIG; + } + + /* Add table to the XSDT */ + xsdt->entry[i] = nomap_to_sysmem(table); + + /* Fix XSDT length */ + xsdt->header.length = sizeof(struct acpi_table_header) + + (sizeof(u64) * (i + 1)); + + /* Re-calculate checksum */ + acpi_update_checksum(&xsdt->header); + } + + return 0; +} diff --git a/lib/acpi/acpi_table.c b/lib/acpi/acpi_table.c index 84d60f74c1c..8423786fff3 100644 --- a/lib/acpi/acpi_table.c +++ b/lib/acpi/acpi_table.c @@ -14,7 +14,6 @@ #include <mapmem.h> #include <tables_csum.h> #include <serial.h> -#include <version_string.h> #include <acpi/acpi_table.h> #include <acpi/acpi_device.h> #include <asm/global_data.h> @@ -28,22 +27,6 @@ enum { DECLARE_GLOBAL_DATA_PTR; -/* - * OEM_REVISION is 32-bit unsigned number. It should be increased only when - * changing software version. Therefore it should not depend on build time. - * U-Boot calculates it from U-Boot version and represent it in hexadecimal - * notation. As U-Boot version is in form year.month set low 8 bits to 0x01 - * to have valid date. So for U-Boot version 2021.04 OEM_REVISION is set to - * value 0x20210401. - */ -#define OEM_REVISION ((((version_num / 1000) % 10) << 28) | \ - (((version_num / 100) % 10) << 24) | \ - (((version_num / 10) % 10) << 20) | \ - ((version_num % 10) << 16) | \ - (((version_num_patch / 10) % 10) << 12) | \ - ((version_num_patch % 10) << 8) | \ - 0x01) - int acpi_create_dmar(struct acpi_dmar *dmar, enum dmar_flags flags) { struct acpi_table_header *header = &dmar->header; @@ -128,111 +111,6 @@ int acpi_get_table_revision(enum acpi_tables table) } } -void acpi_fill_header(struct acpi_table_header *header, char *signature) -{ - memcpy(header->signature, signature, 4); - memcpy(header->oem_id, OEM_ID, 6); - memcpy(header->oem_table_id, OEM_TABLE_ID, 8); - header->oem_revision = OEM_REVISION; - memcpy(header->creator_id, ASLC_ID, 4); - header->creator_revision = ASL_REVISION; -} - -void acpi_align(struct acpi_ctx *ctx) -{ - ctx->current = (void *)ALIGN((ulong)ctx->current, 16); -} - -void acpi_align64(struct acpi_ctx *ctx) -{ - ctx->current = (void *)ALIGN((ulong)ctx->current, 64); -} - -void acpi_inc(struct acpi_ctx *ctx, uint amount) -{ - ctx->current += amount; -} - -void acpi_inc_align(struct acpi_ctx *ctx, uint amount) -{ - ctx->current += amount; - acpi_align(ctx); -} - -/** - * Add an ACPI table to the RSDT (and XSDT) structure, recalculate length - * and checksum. - */ -int acpi_add_table(struct acpi_ctx *ctx, void *table) -{ - int i, entries_num; - struct acpi_rsdt *rsdt; - struct acpi_xsdt *xsdt; - - /* On legacy x86 platforms the RSDT is mandatory while the XSDT is not. - * On other platforms there might be no memory below 4GiB, thus RSDT is NULL. - */ - if (ctx->rsdt) { - rsdt = ctx->rsdt; - - /* This should always be MAX_ACPI_TABLES */ - entries_num = ARRAY_SIZE(rsdt->entry); - - for (i = 0; i < entries_num; i++) { - if (rsdt->entry[i] == 0) - break; - } - - if (i >= entries_num) { - log_err("ACPI: Error: too many tables\n"); - return -E2BIG; - } - - /* Add table to the RSDT */ - rsdt->entry[i] = nomap_to_sysmem(table); - - /* Fix RSDT length or the kernel will assume invalid entries */ - rsdt->header.length = sizeof(struct acpi_table_header) + - (sizeof(u32) * (i + 1)); - - /* Re-calculate checksum */ - acpi_update_checksum(&rsdt->header); - } - - if (ctx->xsdt) { - /* - * And now the same thing for the XSDT. We use the same index as for - * now we want the XSDT and RSDT to always be in sync in U-Boot - */ - xsdt = ctx->xsdt; - - /* This should always be MAX_ACPI_TABLES */ - entries_num = ARRAY_SIZE(xsdt->entry); - - for (i = 0; i < entries_num; i++) { - if (xsdt->entry[i] == 0) - break; - } - - if (i >= entries_num) { - log_err("ACPI: Error: too many tables\n"); - return -E2BIG; - } - - /* Add table to the XSDT */ - xsdt->entry[i] = nomap_to_sysmem(table); - - /* Fix XSDT length */ - xsdt->header.length = sizeof(struct acpi_table_header) + - (sizeof(u64) * (i + 1)); - - /* Re-calculate checksum */ - acpi_update_checksum(&xsdt->header); - } - - return 0; -} - int acpi_write_fadt(struct acpi_ctx *ctx, const struct acpi_writer *entry) { struct acpi_table_header *header; -- 2.43.0

From: Simon Glass <sjg@chromium.org> Most sandbox tests use a fixed address in emulated RAM so that it is easier to debug test failures. Update dm_test_acpi_find_table() to work this way. Signed-off-by: Simon Glass <sjg@chromium.org> --- test/dm/acpi.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/dm/acpi.c b/test/dm/acpi.c index addc2773220..d38a13e7f84 100644 --- a/test/dm/acpi.c +++ b/test/dm/acpi.c @@ -783,9 +783,8 @@ static int dm_test_acpi_find_table(struct unit_test_state *uts) acpi_start = gd_acpi_start(); /* Setup new ACPI tables */ - buf = memalign(16, BUF_SIZE); - ut_assertnonnull(buf); - addr = map_to_sysmem(buf); + addr = 0x1000; + buf = map_sysmem(addr, BUF_SIZE); ut_assertok(setup_ctx_and_base_tables(uts, &ctx, addr)); table3 = dm_test_write_test_table(&ctx, 3); table1 = dm_test_write_test_table(&ctx, 1); @@ -837,7 +836,6 @@ static int dm_test_acpi_find_table(struct unit_test_state *uts) /* Restore previous ACPI tables */ gd_set_acpi_start(acpi_start); unmap_sysmem(buf); - free(buf); return 0; } -- 2.43.0

From: Simon Glass <sjg@chromium.org> At present acpi_find_table() support locating most of the tables, but not these two, since they are the pointers to the rest. When adding new tables, these tables need to be located and updated, so update acpi_find_table() to allow searching for them. Signed-off-by: Simon Glass <sjg@chromium.org> --- lib/acpi/acpi.c | 10 ++++++++++ test/dm/acpi.c | 3 +++ 2 files changed, 13 insertions(+) diff --git a/lib/acpi/acpi.c b/lib/acpi/acpi.c index dc327dc08c7..44ea5136de4 100644 --- a/lib/acpi/acpi.c +++ b/lib/acpi/acpi.c @@ -121,6 +121,11 @@ struct acpi_table_header *acpi_find_table(const char *sig) return NULL; count = ret; + if (!strcmp("RSDT", sig)) + return &rsdt->header; + if (!strcmp("XSDT", sig)) + return &xsdt->header; + for (i = 0; i < count; i++) { struct acpi_table_header *hdr; @@ -204,6 +209,11 @@ int acpi_add_table(struct acpi_ctx *ctx, void *table) struct acpi_rsdt *rsdt; struct acpi_xsdt *xsdt; + if (!ctx->rsdt && !ctx->xsdt) { + log_err("ACPI: Error: no RSDT / XSDT\n"); + return -EINVAL; + } + /* On legacy x86 platforms the RSDT is mandatory while the XSDT is not. * On other platforms there might be no memory below 4GiB, thus RSDT is NULL. */ diff --git a/test/dm/acpi.c b/test/dm/acpi.c index d38a13e7f84..bb37e7da88f 100644 --- a/test/dm/acpi.c +++ b/test/dm/acpi.c @@ -809,6 +809,9 @@ static int dm_test_acpi_find_table(struct unit_test_state *uts) ut_asserteq_ptr(table3, table); ut_asserteq_strn("TST3", table->signature); + table = acpi_find_table("RSDT"); + ut_asserteq_ptr(nomap_sysmem(rsdt, 0), table); + /* Find with XSDT only */ rsdp->rsdt_address = 0; acpi_udpate_rsdp_checksum(rsdp); -- 2.43.0

From: Simon Glass <sjg@chromium.org> For QEMU we want to add new tables to the end of what QEMU provides. Add a function to find the correct place for a new table. Add a function to support this. Signed-off-by: Simon Glass <sjg@chromium.org> --- include/acpi/acpi_table.h | 10 +++++++++ lib/acpi/acpi.c | 25 +++++++++++++++++++++ test/dm/acpi.c | 46 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+) diff --git a/include/acpi/acpi_table.h b/include/acpi/acpi_table.h index 6d599455bd6..7a75e3afc49 100644 --- a/include/acpi/acpi_table.h +++ b/include/acpi/acpi_table.h @@ -1288,6 +1288,16 @@ struct acpi_table_header *acpi_find_table(const char *sig); */ void acpi_update_checksum(struct acpi_table_header *header); +/** + * acpi_get_end() - Find the first place where an ACPI table can be added + * + * Searches for the last ACPI table in memory and returns the address + * immediately after it, where a new table coule added + * + * Return: Address at the end of all tables + */ +void *acpi_get_end(void); + #endif /* !__ACPI__*/ #include <asm/acpi_table.h> diff --git a/lib/acpi/acpi.c b/lib/acpi/acpi.c index 44ea5136de4..b13cba1a608 100644 --- a/lib/acpi/acpi.c +++ b/lib/acpi/acpi.c @@ -277,3 +277,28 @@ int acpi_add_table(struct acpi_ctx *ctx, void *table) return 0; } + +void *acpi_get_end(void) +{ + const struct acpi_table_header *end; + struct acpi_rsdt *rsdt; + struct acpi_xsdt *xsdt; + int i, count; + + count = setup_search(&rsdt, &xsdt); + if (!count) + return NULL; + + end = xsdt ? &xsdt->header : &rsdt->header; + for (i = 0; i < count; i++) { + const struct acpi_table_header *hdr; + + if (xsdt) + hdr = nomap_sysmem(xsdt->entry[i], 0); + else + hdr = nomap_sysmem(rsdt->entry[i], 0); + end = max(hdr, end); + } + + return (void *)end + end->length; +} diff --git a/test/dm/acpi.c b/test/dm/acpi.c index bb37e7da88f..6c157de0e3b 100644 --- a/test/dm/acpi.c +++ b/test/dm/acpi.c @@ -853,3 +853,49 @@ static int dm_test_acpi_offsets(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_acpi_offsets, 0); + +/* Test finding the end of the ACPI tables */ +static int dm_test_acpi_get_end(struct unit_test_state *uts) +{ + struct acpi_ctx ctx; + ulong acpi_start, addr; + void *buf; + struct acpi_table_header *table1, *table2, *table3; + void *ptr; + + /* Keep reference to original ACPI tables */ + acpi_start = gd_acpi_start(); + + /* Setup new ACPI tables */ + addr = 0; + buf = map_sysmem(addr, BUF_SIZE); + ut_assertok(setup_ctx_and_base_tables(uts, &ctx, addr)); + table3 = dm_test_write_test_table(&ctx, 3); + table1 = dm_test_write_test_table(&ctx, 1); + table2 = dm_test_write_test_table(&ctx, 2); + + ptr = acpi_get_end(); + ut_asserteq(0x288 + 0x24, ptr - buf); + + run_command("acpi list", 0); + ut_assert_nextline("Name Base Size Detail"); + ut_assert_nextlinen("--"); + ut_assert_nextline("RSDP 0 24 v02 U-BOOT"); + ut_assert_nextline( + "RSDT 30 30 v01 U-BOOT U-BOOTBL 20250101 INTL 0"); + ut_assert_nextline( + "XSDT e0 3c v01 U-BOOT U-BOOTBL 20250101 INTL 0"); + ut_assert_nextline( + "TST3 240 24 v00 U-BOOT U-BOOTBL 20250101 INTL 0"); + ut_assert_nextline( + "TST1 264 24 v00 U-BOOT U-BOOTBL 20250101 INTL 0"); + ut_assert_nextline( + "TST2 288 24 v00 U-BOOT U-BOOTBL 20250101 INTL 0"); + + /* Restore previous ACPI tables */ + gd_set_acpi_start(acpi_start); + unmap_sysmem(buf); + + return 0; +} +DM_TEST(dm_test_acpi_get_end, 0); -- 2.43.0

From: Simon Glass <sjg@chromium.org> While U-Boot can create its own tables, the ones from QEMU should be used when booting within QEMU. For example, LXD uses some of the fields to decide whether to start cloud-init or not. Signed-off-by: Simon Glass <sjg@chromium.org> --- arch/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/Kconfig b/arch/Kconfig index 49ab4f825d8..b86e27cd5f9 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -309,7 +309,7 @@ config X86 imply ACPI imply ACPIGEN if !ARCH_QEMU_X86 && !EFI_APP imply SYSINFO if GENERATE_SMBIOS_TABLE - imply SYSINFO_SMBIOS if GENERATE_SMBIOS_TABLE + imply SYSINFO_SMBIOS if GENERATE_SMBIOS_TABLE && !ARCH_QEMU_X86 imply TIMESTAMP # Thing to enable for when SPL/TPL are enabled: SPL -- 2.43.0

From: Simon Glass <sjg@chromium.org> This rule assumes that any .bmp file relates to the logo. We want to be able to add a second BMP in some cases, so update the rule to match a filename ending in '_logo.bmp' Signed-off-by: Simon Glass <sjg@chromium.org> --- scripts/Makefile.lib | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index d360e569645..d0327c00d7d 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -478,21 +478,21 @@ $(obj)/%.S: $(src)/%.ttf # --------------------------------------------------------------------------- # Generate an assembly file to wrap the splash data -quiet_cmd_S_splash= TTF $@ +quiet_cmd_S_splash= SPLASH $@ # Modified for U-Boot cmd_S_splash= \ ( \ echo '.section .rodata.splash.init,"a"'; \ echo '.balign 16'; \ - echo '.global __splash_$(*F)_begin'; \ - echo '__splash_$(*F)_begin:'; \ + echo '.global __splash_$(*F)_logo_begin'; \ + echo '__splash_$(*F)_logo_begin:'; \ echo '.incbin "$<" '; \ - echo '__splash_$(*F)_end:'; \ - echo '.global __splash_$(*F)_end'; \ + echo '__splash_$(*F)_logo_end:'; \ + echo '.global __splash_$(*F)_logo_end'; \ echo '.balign 16'; \ ) > $@ -$(obj)/%.S: $(src)/%.bmp +$(obj)/%_logo.S: $(src)/%_logo.bmp $(call cmd,S_splash) # EFI applications -- 2.43.0

From: Simon Glass <sjg@chromium.org> EFI has a Boot Graphics Record Table which can be used to show a logo when booting up and shutting down. Add support for adding this to the image, using a U-Boot logo which includes the name, since many people will be unfamiliar with the logo. Signed-off-by: Simon Glass <sjg@chromium.org> --- lib/acpi/Makefile | 2 ++ lib/acpi/bgrt_image.bmp | Bin 0 -> 43926 bytes scripts/Makefile.lib | 18 ++++++++++++++++++ 3 files changed, 20 insertions(+) create mode 100644 lib/acpi/bgrt_image.bmp diff --git a/lib/acpi/Makefile b/lib/acpi/Makefile index 64f06deaf11..56009fb222e 100644 --- a/lib/acpi/Makefile +++ b/lib/acpi/Makefile @@ -11,6 +11,8 @@ obj-$(CONFIG_$(PHASE_)ACPIGEN) += acpi_dp.o obj-$(CONFIG_$(PHASE_)ACPIGEN) += acpi_table.o obj-y += acpi_writer.o +obj-y += bgrt_image.o + # With QEMU the ACPI tables come from there, not from U-Boot ifndef CONFIG_QFW_ACPI obj-y += base.o diff --git a/lib/acpi/bgrt_image.bmp b/lib/acpi/bgrt_image.bmp new file mode 100644 index 0000000000000000000000000000000000000000..b4c95a641014552f19b7479c1ddfb5b83c0ac489 GIT binary patch literal 43926 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 U&jW8eIqiNC6=>WP()8o^e~AeE00000 literal 0 HcmV?d00001 diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index d0327c00d7d..4102e662c5f 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -495,6 +495,24 @@ cmd_S_splash= \ $(obj)/%_logo.S: $(src)/%_logo.bmp $(call cmd,S_splash) +# Generate an assembly file to wrap the EFI 'Boot Graphics Resource Table' image +quiet_cmd_S_bgrt= BGRT $@ +# Modified for U-Boot +cmd_S_bgrt= \ +( \ + echo '.section .rodata.bgrt.init,"a"'; \ + echo '.balign 16'; \ + echo '.global __$(*F)_image_begin'; \ + echo '__$(*F)_image_begin:'; \ + echo '.incbin "$<" '; \ + echo '__$(*F)_image_end:'; \ + echo '.global __$(*F)_image_end'; \ + echo '.balign 16'; \ +) > $@ + +$(obj)/%_image.S: $(src)/%_image.bmp + $(call cmd,S_bgrt) + # EFI applications # A Makefile target *.efi is built as EFI application. # A Makefile target *_efi.S wraps *.efi as built-in EFI application. -- 2.43.0

From: Simon Glass <sjg@chromium.org> Add support for creating a BGRT so that Linux will show a logo on startup and shutdown. Signed-off-by: Simon Glass <sjg@chromium.org> --- include/acpi/acpi_table.h | 13 ++++- lib/acpi/Makefile | 1 + lib/acpi/acpi_extra.c | 103 ++++++++++++++++++++++++++++++++++++++ lib/acpi/acpi_table.c | 11 ++++ test/dm/acpi.c | 62 +++++++++++++++++++++++ 5 files changed, 188 insertions(+), 2 deletions(-) create mode 100644 lib/acpi/acpi_extra.c diff --git a/include/acpi/acpi_table.h b/include/acpi/acpi_table.h index 7a75e3afc49..850cb8db816 100644 --- a/include/acpi/acpi_table.h +++ b/include/acpi/acpi_table.h @@ -750,7 +750,7 @@ struct acpi_gtdt { * * See ACPI Spec v6.3 section 5.2.22 for details */ -struct acpi_bgrt { +struct __packed acpi_bgrt { struct acpi_table_header header; u16 version; u8 status; @@ -758,7 +758,7 @@ struct acpi_bgrt { u64 addr; u32 offset_x; u32 offset_y; -} __packed; +}; /* Types for PPTT */ #define ACPI_PPTT_TYPE_PROC 0 @@ -1298,6 +1298,15 @@ void acpi_update_checksum(struct acpi_table_header *header); */ void *acpi_get_end(void); +/** + * acpi_write_bgrt() - Write a BGRT + * + * @ctx: ACPI context + * Return 0 if OK, -ENOTSUPP if there is no video-device or not log, -EIO if + * the video device could not be probed, -ENOENT if there is no logo + */ +int acpi_write_bgrt(struct acpi_ctx *ctx); + #endif /* !__ACPI__*/ #include <asm/acpi_table.h> diff --git a/lib/acpi/Makefile b/lib/acpi/Makefile index 56009fb222e..a4850fcc108 100644 --- a/lib/acpi/Makefile +++ b/lib/acpi/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_$(PHASE_)ACPIGEN) += acpigen.o obj-$(CONFIG_$(PHASE_)ACPIGEN) += acpi_device.o obj-$(CONFIG_$(PHASE_)ACPIGEN) += acpi_dp.o obj-$(CONFIG_$(PHASE_)ACPIGEN) += acpi_table.o +obj-y += acpi_extra.o obj-y += acpi_writer.o obj-y += bgrt_image.o diff --git a/lib/acpi/acpi_extra.c b/lib/acpi/acpi_extra.c new file mode 100644 index 00000000000..7620f953add --- /dev/null +++ b/lib/acpi/acpi_extra.c @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Generation of tables for particular device types + * + * Copyright 2025 Simon Glass <sjg@chromium.org> + */ + +#define LOG_CATEGORY LOGC_ACPI + +#include <dm.h> +#include <efi_loader.h> +#include <mapmem.h> +#include <video.h> +#include <acpi/acpi_table.h> + +#define BGRT_DECL(_name) \ + extern u8 __bgrt_ ## _name ## _begin[]; \ + extern u8 __bgrt_ ## _name ## _end[] + +#define BGRT_START(_name) __bgrt_ ## _name ## _begin +#define BGRT_END(_name) __bgrt_ ## _name ## _end + +BGRT_DECL(image); + +static void *bgrt_get_image(int *sizep) +{ + if (sizep) + *sizep = BGRT_END(image) - BGRT_START(image); + + return BGRT_START(image); +} + +int acpi_write_bgrt(struct acpi_ctx *ctx) +{ + struct udevice *dev; + struct acpi_bgrt *bgrt; + efi_status_t eret; + void *logo, *buf; + bool have_video; + int size; + + /* If video is available, use the screen size to centre the logo */ + have_video = !uclass_first_device_err(UCLASS_VIDEO, &dev); + + logo = bgrt_get_image(&size); + + /* If there's no logo data, there's nothing to report */ + if (!logo) + return -ENOENT; + + bgrt = ctx->current; + ctx->tab_start = ctx->current; + memset(bgrt, '\0', sizeof(struct acpi_table_iort)); + + acpi_fill_header(&bgrt->header, "BGRT"); + bgrt->version = 1; + + /* Status: Bit 0 (Displayed) = 1, Bits 1-2 (Orientation) = 0 */ + bgrt->status = 1; + + /* Image Type: 0 = Bitmap */ + bgrt->image_type = 0; + + /* Mark space used for tables */ + eret = efi_allocate_pool(EFI_BOOT_SERVICES_DATA, size, &buf); + if (eret) + return -ENOMEM; + memcpy(buf, logo, size); + + /* The physical address of the in-memory logo bitmap */ + bgrt->addr = nomap_to_sysmem(buf); + + /* Calculate offsets to center the logo on the screen */ + bgrt->offset_x = 0; + bgrt->offset_y = 0; + + /* + * centering is disabled for now, since it seems to be done by the + * startup code + */ + if (0 && IS_ENABLED(CONFIG_VIDEO) && have_video) { + struct video_priv *priv = dev_get_uclass_priv(dev); + ulong width, height; + uint bpix; + + video_bmp_get_info(logo, &width, &height, &bpix); + + if (priv->xsize > width) + bgrt->offset_x = (priv->xsize - width) / 2; + if (priv->ysize > height) + bgrt->offset_y = (priv->ysize - height) / 2; + } + acpi_inc(ctx, sizeof(*bgrt)); + + /* Calculate length and checksum */ + bgrt->header.length = (ulong)ctx->current - (ulong)bgrt; + acpi_update_checksum(&bgrt->header); + log_debug("BGRT at %p length %x logo copied to bs-data at %p\n", bgrt, + bgrt->header.length, buf); + acpi_add_table(ctx, bgrt); + + return 0; +} diff --git a/lib/acpi/acpi_table.c b/lib/acpi/acpi_table.c index 8423786fff3..f2dadd792bd 100644 --- a/lib/acpi/acpi_table.c +++ b/lib/acpi/acpi_table.c @@ -699,3 +699,14 @@ static int alloc_write_acpi_tables(void) } EVENT_SPY_SIMPLE(EVT_LAST_STAGE_INIT, alloc_write_acpi_tables); + +#ifdef CONFIG_EFI_LOADER +static int acpi_create_bgrt(struct acpi_ctx *ctx, + const struct acpi_writer *entry) +{ + acpi_write_bgrt(ctx); + + return 0; +} +ACPI_WRITER(6bgrt, "BGRT", acpi_create_bgrt, 0); +#endif diff --git a/test/dm/acpi.c b/test/dm/acpi.c index 6c157de0e3b..db9c13a2af8 100644 --- a/test/dm/acpi.c +++ b/test/dm/acpi.c @@ -6,8 +6,10 @@ * Written by Simon Glass <sjg@chromium.org> */ +#include <bloblist.h> #include <console.h> #include <dm.h> +#include <efi_log.h> #include <malloc.h> #include <mapmem.h> #include <tables_csum.h> @@ -899,3 +901,63 @@ static int dm_test_acpi_get_end(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_acpi_get_end, 0); + +/* Test generating the BGRT */ +static int dm_test_acpi_bgrt(struct unit_test_state *uts) +{ + struct efil_hdr *hdr = bloblist_find(BLOBLISTT_EFI_LOG, 0); + struct acpi_table_header *table; + struct efil_rec_hdr *rec_hdr; + struct acpi_ctx ctx; + ulong acpi_start, addr; + struct acpi_bgrt *bgrt; + void *buf; + + /* Keep reference to original ACPI tables */ + acpi_start = gd_acpi_start(); + + /* Setup new ACPI tables */ + addr = 0; + buf = map_sysmem(addr, BUF_SIZE); + ut_assertok(setup_ctx_and_base_tables(uts, &ctx, addr)); + + if (IS_ENABLED(CONFIG_EFI_LOG)) + ut_assertok(efi_log_reset()); + + ut_assertok(acpi_write_bgrt(&ctx)); + table = acpi_find_table("BGRT"); + ut_assertnonnull(table); + bgrt = (struct acpi_bgrt *)table; + + ut_asserteq(sizeof(*bgrt), table->length); + ut_asserteq_strn("BGRT", table->signature); + ut_asserteq(1, bgrt->version); + ut_asserteq(1, bgrt->status); + ut_asserteq(0, bgrt->image_type); + ut_asserteq(0, bgrt->offset_x); + ut_asserteq(0, bgrt->offset_y); + + if (!IS_ENABLED(CONFIG_EFI_LOG)) + return 0; + + /* check the BGRT has been allocated in the EFI pool */ + for (rec_hdr = (void *)hdr + sizeof(*hdr); + (void *)rec_hdr - (void *)hdr < hdr->upto; + rec_hdr = (void *)rec_hdr + rec_hdr->size) { + void *start = (void *)rec_hdr + sizeof(struct efil_rec_hdr); + + switch (rec_hdr->tag) { + case EFILT_ALLOCATE_POOL: { + struct efil_allocate_pool *rec = start; + + ut_asserteq(bgrt->addr, nomap_to_sysmem(rec->e_buffer)); + break; + } + default: + break; + } + } + + return 0; +} +DM_TEST(dm_test_acpi_bgrt, UTF_SCAN_FDT); -- 2.43.0

From: Simon Glass <sjg@chromium.org> QEMU provides a table indicating the checksums to be calculated. U-Boot already handles this, so we don't need to compute the checksums at the end. Drop this unnecessary code. Signed-off-by: Simon Glass <sjg@chromium.org> --- drivers/qfw/qfw_acpi.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/qfw/qfw_acpi.c b/drivers/qfw/qfw_acpi.c index 16dd94ba71f..0eef0650e26 100644 --- a/drivers/qfw/qfw_acpi.c +++ b/drivers/qfw/qfw_acpi.c @@ -239,11 +239,6 @@ out: printf("error: no RSDP found\n"); return addr; } - struct acpi_rsdp *rsdp = ctx->rsdp; - - rsdp->length = sizeof(*rsdp); - rsdp->xsdt_address = 0; - rsdp->ext_checksum = table_compute_checksum((u8 *)rsdp, sizeof(*rsdp)); gd_set_acpi_start(acpi_get_rsdp_addr()); -- 2.43.0

From: Simon Glass <sjg@chromium.org> It is useful to show a boot logo when starting up. Add the BGRT table after the QEMU-provided tables. Signed-off-by: Simon Glass <sjg@chromium.org> --- drivers/qfw/qfw_acpi.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/qfw/qfw_acpi.c b/drivers/qfw/qfw_acpi.c index 0eef0650e26..916a59be7fb 100644 --- a/drivers/qfw/qfw_acpi.c +++ b/drivers/qfw/qfw_acpi.c @@ -242,6 +242,20 @@ out: gd_set_acpi_start(acpi_get_rsdp_addr()); + ctx->rsdt = (struct acpi_rsdt *)acpi_find_table("RSDT"); + ctx->xsdt = (struct acpi_xsdt *)acpi_find_table("XSDT"); + + /* + * leave space for four 64-bit pointers so we can add up to four more + * tables + */ + ctx->current = acpi_get_end() + 0x20; + ret = acpi_write_bgrt(ctx); + if (ret) { + printf("error: failed to write BGRT (err=%dE)\n", ret); + return addr; + } + return addr; } -- 2.43.0
participants (1)
-
Simon Glass