emulation: Use bloblist to hold tables
authorSimon Glass <sjg@chromium.org>
Sat, 11 Jan 2025 00:00:17 +0000 (17:00 -0700)
committerTom Rini <trini@konsulko.com>
Wed, 22 Jan 2025 23:08:23 +0000 (17:08 -0600)
QEMU can have its own internal ACPI and SMBIOS tables. At present U-Boot
copies out the SMBIOS tables but points directly to the ACPI ones.

The ACPI tables are not aligned on a 4KB boundary, which means that UPL
cannot use them directly, since it uses a reserved-memory node for the
tables and that it assumed (by EDK2) to be 4KB-aligned.

On x86, QEMU provides the tables in a mapped memory region and U-Boot
makes use of these directly, thus making it difficult to use any common
code.

Adjust the logic to fit within the existing table-generation code. Use a
bloblist always and ensure that the ACPI tables is placed in an aligned
region. Set a size of 8K for QEMU. This does not actually put all the
tables in one place, for QEMU, since it currently adds a pointer to the
tables in QFW.

On ARM, enable bloblist so that SMBIOS tables can be added to the
bloblist.

Signed-off-by: Simon Glass <sjg@chromium.org>
arch/x86/lib/tables.c
configs/qemu-x86_64_defconfig
configs/qemu_arm64_defconfig
configs/qemu_arm_defconfig
drivers/misc/qfw_acpi.c
drivers/misc/qfw_smbios.c
lib/Kconfig
lib/Makefile

index 45a70e9..5fc7dc7 100644 (file)
@@ -61,7 +61,7 @@ static struct table_info table_list[] = {
 #ifdef CONFIG_GENERATE_ACPI_TABLE
        { "acpi", write_acpi_tables, BLOBLISTT_ACPI_TABLES, 0x10000, 0x1000},
 #endif
-#if defined(CONFIG_GENERATE_SMBIOS_TABLE) && !defined(CONFIG_QFW_SMBIOS)
+#ifdef CONFIG_GENERATE_SMBIOS_TABLE
        { "smbios", write_smbios_table, BLOBLISTT_SMBIOS_TABLES, 0x1000, 0x100},
 #endif
 };
index f93721f..3c0fc7a 100644 (file)
@@ -33,7 +33,6 @@ CONFIG_LOGF_FUNC=y
 CONFIG_SPL_LOG=y
 CONFIG_DISPLAY_BOARDINFO_LATE=y
 CONFIG_PCI_INIT_R=y
-CONFIG_BLOBLIST=y
 CONFIG_BLOBLIST_FIXED=y
 CONFIG_BLOBLIST_ADDR=0x10000
 CONFIG_SPL_NO_BSS_LIMIT=y
index 06ac6fe..e760e98 100644 (file)
@@ -26,6 +26,8 @@ CONFIG_USE_PREBOOT=y
 # CONFIG_DISPLAY_CPUINFO is not set
 # CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_PCI_INIT_R=y
+CONFIG_BLOBLIST=y
+CONFIG_BLOBLIST_SIZE_RELOC=0x2000
 CONFIG_CMD_SMBIOS=y
 CONFIG_CMD_BOOTZ=y
 CONFIG_CMD_BOOTEFI_SELFTEST=y
index e164407..d8e916d 100644 (file)
@@ -27,6 +27,8 @@ CONFIG_USE_PREBOOT=y
 # CONFIG_DISPLAY_CPUINFO is not set
 # CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_PCI_INIT_R=y
+CONFIG_BLOBLIST=y
+CONFIG_BLOBLIST_SIZE_RELOC=0x2000
 CONFIG_CMD_BOOTEFI_SELFTEST=y
 CONFIG_CMD_NVEDIT_EFI=y
 CONFIG_CMD_DFU=y
index 7ffed1e..0d0cf76 100644 (file)
@@ -7,6 +7,7 @@
 #define LOG_CATEGORY UCLASS_QFW
 
 #include <acpi/acpi_table.h>
+#include <bloblist.h>
 #include <errno.h>
 #include <malloc.h>
 #include <mapmem.h>
@@ -160,6 +161,15 @@ ulong write_acpi_tables(ulong addr)
        struct bios_linker_entry *entry;
        uint32_t size;
        struct udevice *dev;
+       struct acpi_ctx *ctx;
+
+       ctx = malloc(sizeof(*ctx));
+       if (!ctx) {
+               printf("error: out of memory for acpi ctx\n");
+               return addr;
+       }
+
+       acpi_setup_ctx(ctx, addr);
 
        ret = qfw_get_dev(&dev);
        if (ret) {
@@ -257,6 +267,29 @@ ulong acpi_get_rsdp_addr(void)
        return file->addr;
 }
 
+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);
+
+       if (rsdt)
+               rsdp->rsdt_address = nomap_to_sysmem(rsdt);
+
+       if (xsdt)
+               rsdp->xsdt_address = nomap_to_sysmem(xsdt);
+
+       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));
+}
+
 #ifndef CONFIG_X86
 static int evt_write_acpi_tables(void)
 {
@@ -264,9 +297,9 @@ static int evt_write_acpi_tables(void)
        void *ptr;
 
        /* Reserve 64K for ACPI tables, aligned to a 4K boundary */
-       ptr = memalign(SZ_4K, SZ_64K);
+       ptr = bloblist_add(BLOBLISTT_ACPI_TABLES, SZ_64K, 12);
        if (!ptr)
-               return -ENOMEM;
+               return -ENOBUFS;
        addr = map_to_sysmem(ptr);
 
        /* Generate ACPI tables */
index c3e8c31..93c4a80 100644 (file)
@@ -5,6 +5,7 @@
 
 #define LOG_CATEGORY UCLASS_QFW
 
+#include <bloblist.h>
 #include <efi_loader.h>
 #include <errno.h>
 #include <log.h>
@@ -15,6 +16,7 @@
 #include <tables_csum.h>
 #include <linux/sizes.h>
 #include <asm/global_data.h>
+#include <linux/err.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -105,11 +107,10 @@ out:
 /**
  * qfw_write_smbios_tables() - copy SMBIOS tables from QEMU
  *
- * @addr:      target buffer
- * @size:      size of target buffer
+ * @addr:      address of target buffer
  * Return:     0 for success, -ve on error
  */
-static int qfw_write_smbios_tables(u8 *addr, uint32_t size)
+ulong write_smbios_table(ulong addr)
 {
        int ret;
        struct udevice *dev;
@@ -143,16 +144,13 @@ static int qfw_write_smbios_tables(u8 *addr, uint32_t size)
 
        table = qfw_load_smbios_table(dev, &table_size,
                                      "etc/smbios/smbios-tables");
-       if (table_size + sizeof(struct smbios3_entry) > size) {
-               free(table);
-               return -ENOMEM;
-       }
-       memcpy(addr, table, table_size);
+       memcpy((void *)addr, table, table_size);
        free(table);
 
-       return 0;
+       return addr + table_size;
 }
 
+#ifndef CONFIG_X86
 /**
  * qfw_evt_write_smbios_tables() - event handler for copying QEMU SMBIOS tables
  *
@@ -160,9 +158,9 @@ static int qfw_write_smbios_tables(u8 *addr, uint32_t size)
  */
 static int qfw_evt_write_smbios_tables(void)
 {
-       phys_addr_t addr;
+       ulong addr, end;
        void *ptr;
-       int ret;
+
        /*
         * TODO:
         * This size is currently hard coded in lib/efi_loader/efi_smbios.c.
@@ -170,22 +168,21 @@ static int qfw_evt_write_smbios_tables(void)
         */
        uint32_t size = SZ_4K;
 
-       /* Reserve 64K for SMBIOS tables, aligned to a 4K boundary */
-       ptr = memalign(SZ_4K, size);
-       if (!ptr) {
-               log_err("Out of memory\n");
-               return -ENOMEM;
-       }
+       log_debug("qfw_evt_write_smbios_tables bloblist\n");
+       /* Reserve 4K for SMBIOS tables, aligned to a 4K boundary */
+       ptr = bloblist_add(BLOBLISTT_SMBIOS_TABLES, size, 12);
+       if (!ptr)
+               return log_msg_ret("bloblist", -ENOBUFS);
+
        addr = map_to_sysmem(ptr);
 
        /* Generate SMBIOS tables */
-       ret = qfw_write_smbios_tables(ptr, size);
-       if (ret) {
-               if (CONFIG_IS_ENABLED(GENERATE_SMBIOS_TABLE)) {
-                       log_info("Falling back to U-Boot generated SMBIOS tables\n");
-                       write_smbios_table(addr);
-               }
+       end = write_smbios_table(addr);
+       if (IS_ERR_VALUE(end)) {
+               log_warning("SMBIOS: Failed to write (err=%dE)\n", (int)end);
        } else {
+               if (end - addr > size)
+                       return -ENOMEM;
                log_debug("SMBIOS tables copied from QEMU\n");
        }
 
@@ -193,5 +190,5 @@ static int qfw_evt_write_smbios_tables(void)
 
        return 0;
 }
-
 EVENT_SPY_SIMPLE(EVT_LAST_STAGE_INIT, qfw_evt_write_smbios_tables);
+#endif /* !X86 */
index 8f1a96d..5217ede 100644 (file)
@@ -1067,6 +1067,7 @@ menu "System tables"
 config BLOBLIST_TABLES
        bool "Put tables in a bloblist"
        depends on BLOBLIST
+       default y if X86
        default y if (ARM && EFI_LOADER && GENERATE_ACPI_TABLE)
        default n
        help
index 5cb3278..228c9cf 100644 (file)
@@ -41,7 +41,12 @@ obj-$(CONFIG_ERRNO_STR) += errno_str.o
 obj-$(CONFIG_FIT) += fdtdec_common.o
 obj-$(CONFIG_TEST_FDTDEC) += fdtdec_test.o
 obj-$(CONFIG_GZIP_COMPRESSED) += gzip.o
+
+# With QEMU the SMBIOS tables come from there, not from U-Boot
+ifndef CONFIG_QFW_SMBIOS
 obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += smbios.o
+endif
+
 obj-$(CONFIG_SMBIOS_PARSER) += smbios-parser.o
 obj-$(CONFIG_IMAGE_SPARSE) += image-sparse.o
 obj-y += initcall.o