emulation: Use bloblist to hold tables

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>
This commit is contained in:
Simon Glass 2025-01-10 17:00:17 -07:00 committed by Tom Rini
parent 24768a23a9
commit 53d5a22163
8 changed files with 67 additions and 28 deletions

View file

@ -61,7 +61,7 @@ static struct table_info table_list[] = {
#ifdef CONFIG_GENERATE_ACPI_TABLE #ifdef CONFIG_GENERATE_ACPI_TABLE
{ "acpi", write_acpi_tables, BLOBLISTT_ACPI_TABLES, 0x10000, 0x1000}, { "acpi", write_acpi_tables, BLOBLISTT_ACPI_TABLES, 0x10000, 0x1000},
#endif #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}, { "smbios", write_smbios_table, BLOBLISTT_SMBIOS_TABLES, 0x1000, 0x100},
#endif #endif
}; };

View file

@ -33,7 +33,6 @@ CONFIG_LOGF_FUNC=y
CONFIG_SPL_LOG=y CONFIG_SPL_LOG=y
CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_DISPLAY_BOARDINFO_LATE=y
CONFIG_PCI_INIT_R=y CONFIG_PCI_INIT_R=y
CONFIG_BLOBLIST=y
CONFIG_BLOBLIST_FIXED=y CONFIG_BLOBLIST_FIXED=y
CONFIG_BLOBLIST_ADDR=0x10000 CONFIG_BLOBLIST_ADDR=0x10000
CONFIG_SPL_NO_BSS_LIMIT=y CONFIG_SPL_NO_BSS_LIMIT=y

View file

@ -26,6 +26,8 @@ CONFIG_USE_PREBOOT=y
# CONFIG_DISPLAY_CPUINFO is not set # CONFIG_DISPLAY_CPUINFO is not set
# CONFIG_DISPLAY_BOARDINFO is not set # CONFIG_DISPLAY_BOARDINFO is not set
CONFIG_PCI_INIT_R=y CONFIG_PCI_INIT_R=y
CONFIG_BLOBLIST=y
CONFIG_BLOBLIST_SIZE_RELOC=0x2000
CONFIG_CMD_SMBIOS=y CONFIG_CMD_SMBIOS=y
CONFIG_CMD_BOOTZ=y CONFIG_CMD_BOOTZ=y
CONFIG_CMD_BOOTEFI_SELFTEST=y CONFIG_CMD_BOOTEFI_SELFTEST=y

View file

@ -27,6 +27,8 @@ CONFIG_USE_PREBOOT=y
# CONFIG_DISPLAY_CPUINFO is not set # CONFIG_DISPLAY_CPUINFO is not set
# CONFIG_DISPLAY_BOARDINFO is not set # CONFIG_DISPLAY_BOARDINFO is not set
CONFIG_PCI_INIT_R=y CONFIG_PCI_INIT_R=y
CONFIG_BLOBLIST=y
CONFIG_BLOBLIST_SIZE_RELOC=0x2000
CONFIG_CMD_BOOTEFI_SELFTEST=y CONFIG_CMD_BOOTEFI_SELFTEST=y
CONFIG_CMD_NVEDIT_EFI=y CONFIG_CMD_NVEDIT_EFI=y
CONFIG_CMD_DFU=y CONFIG_CMD_DFU=y

View file

@ -7,6 +7,7 @@
#define LOG_CATEGORY UCLASS_QFW #define LOG_CATEGORY UCLASS_QFW
#include <acpi/acpi_table.h> #include <acpi/acpi_table.h>
#include <bloblist.h>
#include <errno.h> #include <errno.h>
#include <malloc.h> #include <malloc.h>
#include <mapmem.h> #include <mapmem.h>
@ -160,6 +161,15 @@ ulong write_acpi_tables(ulong addr)
struct bios_linker_entry *entry; struct bios_linker_entry *entry;
uint32_t size; uint32_t size;
struct udevice *dev; 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); ret = qfw_get_dev(&dev);
if (ret) { if (ret) {
@ -257,6 +267,29 @@ ulong acpi_get_rsdp_addr(void)
return file->addr; 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 #ifndef CONFIG_X86
static int evt_write_acpi_tables(void) static int evt_write_acpi_tables(void)
{ {
@ -264,9 +297,9 @@ static int evt_write_acpi_tables(void)
void *ptr; void *ptr;
/* Reserve 64K for ACPI tables, aligned to a 4K boundary */ /* 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) if (!ptr)
return -ENOMEM; return -ENOBUFS;
addr = map_to_sysmem(ptr); addr = map_to_sysmem(ptr);
/* Generate ACPI tables */ /* Generate ACPI tables */

View file

@ -5,6 +5,7 @@
#define LOG_CATEGORY UCLASS_QFW #define LOG_CATEGORY UCLASS_QFW
#include <bloblist.h>
#include <efi_loader.h> #include <efi_loader.h>
#include <errno.h> #include <errno.h>
#include <log.h> #include <log.h>
@ -15,6 +16,7 @@
#include <tables_csum.h> #include <tables_csum.h>
#include <linux/sizes.h> #include <linux/sizes.h>
#include <asm/global_data.h> #include <asm/global_data.h>
#include <linux/err.h>
DECLARE_GLOBAL_DATA_PTR; DECLARE_GLOBAL_DATA_PTR;
@ -105,11 +107,10 @@ out:
/** /**
* qfw_write_smbios_tables() - copy SMBIOS tables from QEMU * qfw_write_smbios_tables() - copy SMBIOS tables from QEMU
* *
* @addr: target buffer * @addr: address of target buffer
* @size: size of target buffer
* Return: 0 for success, -ve on error * 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; int ret;
struct udevice *dev; 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, table = qfw_load_smbios_table(dev, &table_size,
"etc/smbios/smbios-tables"); "etc/smbios/smbios-tables");
if (table_size + sizeof(struct smbios3_entry) > size) { memcpy((void *)addr, table, table_size);
free(table);
return -ENOMEM;
}
memcpy(addr, table, table_size);
free(table); free(table);
return 0; return addr + table_size;
} }
#ifndef CONFIG_X86
/** /**
* qfw_evt_write_smbios_tables() - event handler for copying QEMU SMBIOS tables * 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) static int qfw_evt_write_smbios_tables(void)
{ {
phys_addr_t addr; ulong addr, end;
void *ptr; void *ptr;
int ret;
/* /*
* TODO: * TODO:
* This size is currently hard coded in lib/efi_loader/efi_smbios.c. * 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; uint32_t size = SZ_4K;
/* Reserve 64K for SMBIOS tables, aligned to a 4K boundary */ log_debug("qfw_evt_write_smbios_tables bloblist\n");
ptr = memalign(SZ_4K, size); /* Reserve 4K for SMBIOS tables, aligned to a 4K boundary */
if (!ptr) { ptr = bloblist_add(BLOBLISTT_SMBIOS_TABLES, size, 12);
log_err("Out of memory\n"); if (!ptr)
return -ENOMEM; return log_msg_ret("bloblist", -ENOBUFS);
}
addr = map_to_sysmem(ptr); addr = map_to_sysmem(ptr);
/* Generate SMBIOS tables */ /* Generate SMBIOS tables */
ret = qfw_write_smbios_tables(ptr, size); end = write_smbios_table(addr);
if (ret) { if (IS_ERR_VALUE(end)) {
if (CONFIG_IS_ENABLED(GENERATE_SMBIOS_TABLE)) { log_warning("SMBIOS: Failed to write (err=%dE)\n", (int)end);
log_info("Falling back to U-Boot generated SMBIOS tables\n");
write_smbios_table(addr);
}
} else { } else {
if (end - addr > size)
return -ENOMEM;
log_debug("SMBIOS tables copied from QEMU\n"); log_debug("SMBIOS tables copied from QEMU\n");
} }
@ -193,5 +190,5 @@ static int qfw_evt_write_smbios_tables(void)
return 0; return 0;
} }
EVENT_SPY_SIMPLE(EVT_LAST_STAGE_INIT, qfw_evt_write_smbios_tables); EVENT_SPY_SIMPLE(EVT_LAST_STAGE_INIT, qfw_evt_write_smbios_tables);
#endif /* !X86 */

View file

@ -1067,6 +1067,7 @@ menu "System tables"
config BLOBLIST_TABLES config BLOBLIST_TABLES
bool "Put tables in a bloblist" bool "Put tables in a bloblist"
depends on BLOBLIST depends on BLOBLIST
default y if X86
default y if (ARM && EFI_LOADER && GENERATE_ACPI_TABLE) default y if (ARM && EFI_LOADER && GENERATE_ACPI_TABLE)
default n default n
help help

View file

@ -41,7 +41,12 @@ obj-$(CONFIG_ERRNO_STR) += errno_str.o
obj-$(CONFIG_FIT) += fdtdec_common.o obj-$(CONFIG_FIT) += fdtdec_common.o
obj-$(CONFIG_TEST_FDTDEC) += fdtdec_test.o obj-$(CONFIG_TEST_FDTDEC) += fdtdec_test.o
obj-$(CONFIG_GZIP_COMPRESSED) += gzip.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 obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += smbios.o
endif
obj-$(CONFIG_SMBIOS_PARSER) += smbios-parser.o obj-$(CONFIG_SMBIOS_PARSER) += smbios-parser.o
obj-$(CONFIG_IMAGE_SPARSE) += image-sparse.o obj-$(CONFIG_IMAGE_SPARSE) += image-sparse.o
obj-y += initcall.o obj-y += initcall.o