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>
diff --git a/drivers/misc/qfw_smbios.c b/drivers/misc/qfw_smbios.c
index c3e8c31..93c4a80 100644
--- a/drivers/misc/qfw_smbios.c
+++ b/drivers/misc/qfw_smbios.c
@@ -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 @@
 /**
  * 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 @@
 
 	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_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 @@
 	 */
 	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 @@
 
 	return 0;
 }
-
 EVENT_SPY_SIMPLE(EVT_LAST_STAGE_INIT, qfw_evt_write_smbios_tables);
+#endif /* !X86 */