summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Kconfig31
-rw-r--r--lib/acpi/acpi_table.c630
-rw-r--r--lib/acpi/acpigen.c11
-rw-r--r--lib/efi_loader/Kconfig2
-rw-r--r--lib/efi_loader/dtbdump.c12
-rw-r--r--lib/efi_loader/efi_bootbin.c1
-rw-r--r--lib/efi_loader/efi_bootmgr.c2
-rw-r--r--lib/efi_loader/efi_device_path.c3
-rw-r--r--lib/efi_loader/efi_disk.c4
-rw-r--r--lib/efi_loader/efi_memory.c17
-rw-r--r--lib/efi_loader/efi_tcg2.c2
-rw-r--r--lib/efi_loader/smbiosdump.c6
-rw-r--r--lib/efi_selftest/efi_selftest_hii.c2
-rw-r--r--lib/efi_selftest/efi_selftest_hii_data.c28
-rw-r--r--lib/lmb.c72
15 files changed, 681 insertions, 142 deletions
diff --git a/lib/Kconfig b/lib/Kconfig
index fc2db747dcc..56ffdfa1839 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -315,6 +315,22 @@ config GENERATE_ACPI_TABLE
by the operating system. It defines platform-independent interfaces
for configuration and power management monitoring.
+config ACPI_PARKING_PROTOCOL
+ bool "Support ACPI parking protocol method"
+ depends on GENERATE_ACPI_TABLE
+ depends on ARMV8_MULTIENTRY
+ depends on BLOBLIST_TABLES
+ default y if !SEC_FIRMWARE_ARMV8_PSCI && !ARMV8_PSCI
+ help
+ Say Y here to support "ACPI parking protocol" enable method
+ for booting Linux.
+
+ To use this feature, you must do:
+ - Bring secondary CPUs into U-Boot proper in a board-specific
+ manner. This must be done *after* relocation. Otherwise, the
+ secondary CPUs will spin in unprotected memory-area because the
+ master CPU protects the relocated spin code.
+
config SPL_TINY_MEMSET
bool "Use a very small memset() in SPL"
depends on SPL
@@ -988,12 +1004,15 @@ menu "System tables"
config BLOBLIST_TABLES
bool "Put tables in a bloblist"
- depends on X86 && BLOBLIST
- help
- Normally tables are placed at address 0xf0000 and can be up to 64KB
- long. With this option, tables are instead placed in the bloblist
- with a pointer from 0xf0000. The size can then be larger and the
- tables can be placed high in memory.
+ depends on BLOBLIST
+ default y if (ARM && EFI_LOADER && GENERATE_ACPI_TABLE)
+ default n
+ help
+ On x86 normally tables are placed at address 0xf0000 and can be up
+ to 64KB long. With this option, tables are instead placed in the
+ bloblist with a pointer from 0xf0000. The size can then be larger
+ and the tables can be placed high in memory.
+ On other architectures the tables are always placed in high memory.
config GENERATE_SMBIOS_TABLE
bool "Generate an SMBIOS (System Management BIOS) table"
diff --git a/lib/acpi/acpi_table.c b/lib/acpi/acpi_table.c
index 6dbfdb22dec..150f75027a5 100644
--- a/lib/acpi/acpi_table.c
+++ b/lib/acpi/acpi_table.c
@@ -5,15 +5,28 @@
* Copyright 2019 Google LLC
*/
-#include <dm.h>
+#include <bloblist.h>
#include <cpu.h>
+#include <dm.h>
+#include <efi_api.h>
+#include <efi_loader.h>
#include <log.h>
#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>
#include <dm/acpi.h>
+#include <linux/sizes.h>
+#include <linux/log2.h>
+
+enum {
+ TABLE_SIZE = SZ_64K,
+};
+
+DECLARE_GLOBAL_DATA_PTR;
/*
* OEM_REVISION is 32-bit unsigned number. It should be increased only when
@@ -61,9 +74,9 @@ int acpi_get_table_revision(enum acpi_tables table)
{
switch (table) {
case ACPITAB_FADT:
- return ACPI_FADT_REV_ACPI_3_0;
+ return ACPI_FADT_REV_ACPI_6_0;
case ACPITAB_MADT:
- return ACPI_MADT_REV_ACPI_3_0;
+ return ACPI_MADT_REV_ACPI_6_2;
case ACPITAB_MCFG:
return ACPI_MCFG_REV_ACPI_3_0;
case ACPITAB_TCPA:
@@ -105,6 +118,10 @@ int acpi_get_table_revision(enum acpi_tables table)
return 1;
case ACPITAB_SPCR:
return 2;
+ case ACPITAB_PPTT: /* ACPI 6.2: 1 */
+ return 1;
+ case ACPITAB_GTDT: /* ACPI 6.2: 2, ACPI 6.3: 3 */
+ return 2;
default:
return -EINVAL;
}
@@ -151,55 +168,148 @@ int acpi_add_table(struct acpi_ctx *ctx, void *table)
struct acpi_rsdt *rsdt;
struct acpi_xsdt *xsdt;
- /* The RSDT is mandatory while the XSDT is not */
- rsdt = ctx->rsdt;
+ /* 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);
- /* This should always be MAX_ACPI_TABLES */
- entries_num = ARRAY_SIZE(rsdt->entry);
+ /* Fix RSDT length or the kernel will assume invalid entries */
+ rsdt->header.length = sizeof(struct acpi_table_header) +
+ (sizeof(u32) * (i + 1));
- for (i = 0; i < entries_num; i++) {
- if (rsdt->entry[i] == 0)
- break;
+ /* Re-calculate checksum */
+ rsdt->header.checksum = 0;
+ rsdt->header.checksum = table_compute_checksum((u8 *)rsdt,
+ rsdt->header.length);
}
- if (i >= entries_num) {
- log_err("ACPI: Error: too many tables\n");
- return -E2BIG;
+ 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 */
+ xsdt->header.checksum = 0;
+ xsdt->header.checksum = table_compute_checksum((u8 *)xsdt,
+ xsdt->header.length);
}
- /* Add table to the RSDT */
- rsdt->entry[i] = nomap_to_sysmem(table);
+ return 0;
+}
- /* Fix RSDT length or the kernel will assume invalid entries */
- rsdt->header.length = sizeof(struct acpi_table_header) +
- (sizeof(u32) * (i + 1));
+int acpi_write_fadt(struct acpi_ctx *ctx, const struct acpi_writer *entry)
+{
+ struct acpi_table_header *header;
+ struct acpi_fadt *fadt;
- /* Re-calculate checksum */
- rsdt->header.checksum = 0;
- rsdt->header.checksum = table_compute_checksum((u8 *)rsdt,
- rsdt->header.length);
+ fadt = ctx->current;
+ header = &fadt->header;
- /*
- * 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;
+ memset((void *)fadt, '\0', sizeof(struct acpi_fadt));
+
+ acpi_fill_header(header, "FACP");
+ header->length = sizeof(struct acpi_fadt);
+ header->revision = acpi_get_table_revision(ACPITAB_FADT);
+ memcpy(header->oem_id, OEM_ID, 6);
+ memcpy(header->oem_table_id, OEM_TABLE_ID, 8);
+ memcpy(header->creator_id, ASLC_ID, 4);
+ header->creator_revision = 1;
+ fadt->minor_revision = 2;
- /* Add table to the XSDT */
- xsdt->entry[i] = nomap_to_sysmem(table);
+ fadt->x_firmware_ctrl = map_to_sysmem(ctx->facs);
+ fadt->x_dsdt = map_to_sysmem(ctx->dsdt);
- /* Fix XSDT length */
- xsdt->header.length = sizeof(struct acpi_table_header) +
- (sizeof(u64) * (i + 1));
+ if (fadt->x_firmware_ctrl < 0x100000000ULL)
+ fadt->firmware_ctrl = fadt->x_firmware_ctrl;
- /* Re-calculate checksum */
- xsdt->header.checksum = 0;
- xsdt->header.checksum = table_compute_checksum((u8 *)xsdt,
- xsdt->header.length);
+ if (fadt->x_dsdt < 0x100000000ULL)
+ fadt->dsdt = fadt->x_dsdt;
+
+ fadt->preferred_pm_profile = ACPI_PM_UNSPECIFIED;
+
+ acpi_fill_fadt(fadt);
+
+ header->checksum = table_compute_checksum(fadt, header->length);
+
+ return acpi_add_fadt(ctx, fadt);
+}
+
+ACPI_WRITER(5fadt, "FADT", acpi_write_fadt, 0);
+
+int acpi_write_madt(struct acpi_ctx *ctx, const struct acpi_writer *entry)
+{
+ struct acpi_table_header *header;
+ struct acpi_madt *madt;
+ void *current;
+
+ madt = ctx->current;
+
+ memset(madt, '\0', sizeof(struct acpi_madt));
+ header = &madt->header;
+
+ /* Fill out header fields */
+ acpi_fill_header(header, "APIC");
+ header->length = sizeof(struct acpi_madt);
+ header->revision = acpi_get_table_revision(ACPITAB_MADT);
+
+ acpi_inc(ctx, sizeof(struct acpi_madt));
+ /* TODO: Get rid of acpi_fill_madt and use driver model */
+ current = acpi_fill_madt(madt, ctx);
+
+ /* (Re)calculate length and checksum */
+ header->length = (uintptr_t)current - (uintptr_t)madt;
+
+ if (IS_ENABLED(CONFIG_ACPI_PARKING_PROTOCOL))
+ acpi_write_park(madt);
+
+ header->checksum = table_compute_checksum((void *)madt, header->length);
+ acpi_add_table(ctx, madt);
+ ctx->current = (void *)madt + madt->header.length;
return 0;
}
+ACPI_WRITER(5madt, "MADT", acpi_write_madt, 0);
+
void acpi_create_dbg2(struct acpi_dbg2_header *dbg2,
int port_type, int port_subtype,
struct acpi_gen_regaddr *address, u32 address_size,
@@ -262,3 +372,451 @@ void acpi_create_dbg2(struct acpi_dbg2_header *dbg2,
header->length = current - (uintptr_t)dbg2;
header->checksum = table_compute_checksum(dbg2, header->length);
}
+
+int acpi_write_dbg2_pci_uart(struct acpi_ctx *ctx, struct udevice *dev,
+ uint access_size)
+{
+ struct acpi_dbg2_header *dbg2 = ctx->current;
+ char path[ACPI_PATH_MAX];
+ struct acpi_gen_regaddr address;
+ u64 addr;
+ int ret;
+
+ if (!device_active(dev)) {
+ log_info("Device not enabled\n");
+ return -EACCES;
+ }
+ /*
+ * PCI devices don't remember their resource allocation information in
+ * U-Boot at present. We assume that MMIO is used for the UART and that
+ * the address space is 32 bytes: ns16550 uses 8 registers of up to
+ * 32-bits each. This is only for debugging so it is not a big deal.
+ */
+ addr = dm_pci_read_bar32(dev, 0);
+ log_debug("UART addr %lx\n", (ulong)addr);
+
+ ret = acpi_device_path(dev, path, sizeof(path));
+ if (ret)
+ return log_msg_ret("path", ret);
+
+ memset(&address, '\0', sizeof(address));
+ address.space_id = ACPI_ADDRESS_SPACE_MEMORY;
+ address.addrl = (uint32_t)addr;
+ address.addrh = (uint32_t)((addr >> 32) & 0xffffffff);
+ address.access_size = access_size;
+
+ ret = acpi_device_path(dev, path, sizeof(path));
+ if (ret)
+ return log_msg_ret("path", ret);
+ acpi_create_dbg2(dbg2, ACPI_DBG2_SERIAL_PORT,
+ ACPI_DBG2_16550_COMPATIBLE, &address, 0x1000, path);
+
+ acpi_inc_align(ctx, dbg2->header.length);
+ acpi_add_table(ctx, dbg2);
+
+ return 0;
+}
+
+static int acpi_write_spcr(struct acpi_ctx *ctx, const struct acpi_writer *entry)
+{
+ struct serial_device_info serial_info = {0};
+ u64 serial_address, serial_offset;
+ struct acpi_table_header *header;
+ struct acpi_spcr *spcr;
+ struct udevice *dev;
+ uint serial_config;
+ uint serial_width;
+ int access_size;
+ int space_id;
+ int ret = -ENODEV;
+
+ spcr = ctx->current;
+ header = &spcr->header;
+
+ memset(spcr, '\0', sizeof(struct acpi_spcr));
+
+ /* Fill out header fields */
+ acpi_fill_header(header, "SPCR");
+ header->length = sizeof(struct acpi_spcr);
+ header->revision = 2;
+
+ /* Read the device once, here. It is reused below */
+ dev = gd->cur_serial_dev;
+ if (dev)
+ ret = serial_getinfo(dev, &serial_info);
+ if (ret)
+ serial_info.type = SERIAL_CHIP_UNKNOWN;
+
+ /* Encode chip type */
+ switch (serial_info.type) {
+ case SERIAL_CHIP_16550_COMPATIBLE:
+ spcr->interface_type = ACPI_DBG2_16550_COMPATIBLE;
+ break;
+ case SERIAL_CHIP_PL01X:
+ spcr->interface_type = ACPI_DBG2_ARM_PL011;
+ break;
+ case SERIAL_CHIP_UNKNOWN:
+ default:
+ spcr->interface_type = ACPI_DBG2_UNKNOWN;
+ break;
+ }
+
+ /* Encode address space */
+ switch (serial_info.addr_space) {
+ case SERIAL_ADDRESS_SPACE_MEMORY:
+ space_id = ACPI_ADDRESS_SPACE_MEMORY;
+ break;
+ case SERIAL_ADDRESS_SPACE_IO:
+ default:
+ space_id = ACPI_ADDRESS_SPACE_IO;
+ break;
+ }
+
+ serial_width = serial_info.reg_width * 8;
+ serial_offset = ((u64)serial_info.reg_offset) << serial_info.reg_shift;
+ serial_address = serial_info.addr + serial_offset;
+
+ /* Encode register access size */
+ switch (serial_info.reg_shift) {
+ case 0:
+ access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
+ break;
+ case 1:
+ access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
+ break;
+ case 2:
+ access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
+ break;
+ case 3:
+ access_size = ACPI_ACCESS_SIZE_QWORD_ACCESS;
+ break;
+ default:
+ access_size = ACPI_ACCESS_SIZE_UNDEFINED;
+ break;
+ }
+
+ debug("UART type %u @ %llx\n", spcr->interface_type, serial_address);
+
+ /* Fill GAS */
+ spcr->serial_port.space_id = space_id;
+ spcr->serial_port.bit_width = serial_width;
+ spcr->serial_port.bit_offset = 0;
+ spcr->serial_port.access_size = access_size;
+ spcr->serial_port.addrl = lower_32_bits(serial_address);
+ spcr->serial_port.addrh = upper_32_bits(serial_address);
+
+ /* Encode baud rate */
+ switch (serial_info.baudrate) {
+ case 9600:
+ spcr->baud_rate = 3;
+ break;
+ case 19200:
+ spcr->baud_rate = 4;
+ break;
+ case 57600:
+ spcr->baud_rate = 6;
+ break;
+ case 115200:
+ spcr->baud_rate = 7;
+ break;
+ default:
+ spcr->baud_rate = 0;
+ break;
+ }
+
+ serial_config = SERIAL_DEFAULT_CONFIG;
+ if (dev)
+ ret = serial_getconfig(dev, &serial_config);
+
+ spcr->parity = SERIAL_GET_PARITY(serial_config);
+ spcr->stop_bits = SERIAL_GET_STOP(serial_config);
+
+ /* No PCI devices for now */
+ spcr->pci_device_id = 0xffff;
+ spcr->pci_vendor_id = 0xffff;
+
+ /*
+ * SPCR has no clue if the UART base clock speed is different
+ * to the default one. However, the SPCR 1.04 defines baud rate
+ * 0 as a preconfigured state of UART and OS is supposed not
+ * to touch the configuration of the serial device.
+ */
+ if (serial_info.clock != SERIAL_DEFAULT_CLOCK)
+ spcr->baud_rate = 0;
+
+ /* Fix checksum */
+ header->checksum = table_compute_checksum((void *)spcr, header->length);
+
+ acpi_add_table(ctx, spcr);
+ acpi_inc(ctx, spcr->header.length);
+
+ return 0;
+}
+
+ACPI_WRITER(5spcr, "SPCR", acpi_write_spcr, 0);
+
+__weak int acpi_fill_iort(struct acpi_ctx *ctx)
+{
+ return 0;
+}
+
+int acpi_iort_add_its_group(struct acpi_ctx *ctx,
+ const u32 its_count,
+ const u32 *identifiers)
+{
+ struct acpi_iort_node *node;
+ struct acpi_iort_its_group *group;
+ int offset;
+
+ offset = ctx->current - ctx->tab_start;
+
+ node = ctx->current;
+ memset(node, '\0', sizeof(struct acpi_iort_node));
+
+ node->type = ACPI_IORT_NODE_ITS_GROUP;
+ node->revision = 1;
+
+ node->length = sizeof(struct acpi_iort_node);
+ node->length += sizeof(struct acpi_iort_its_group);
+ node->length += sizeof(u32) * its_count;
+
+ group = (struct acpi_iort_its_group *)node->node_data;
+ group->its_count = its_count;
+ memcpy(&group->identifiers, identifiers, sizeof(u32) * its_count);
+
+ ctx->current += node->length;
+
+ return offset;
+}
+
+int acpi_iort_add_named_component(struct acpi_ctx *ctx,
+ const u32 node_flags,
+ const u64 memory_properties,
+ const u8 memory_address_limit,
+ const char *device_name)
+{
+ struct acpi_iort_node *node;
+ struct acpi_iort_named_component *comp;
+ int offset;
+
+ offset = ctx->current - ctx->tab_start;
+
+ node = ctx->current;
+ memset(node, '\0', sizeof(struct acpi_iort_node));
+
+ node->type = ACPI_IORT_NODE_NAMED_COMPONENT;
+ node->revision = 4;
+ node->length = sizeof(struct acpi_iort_node);
+ node->length += sizeof(struct acpi_iort_named_component);
+ node->length += strlen(device_name) + 1;
+
+ comp = (struct acpi_iort_named_component *)node->node_data;
+
+ comp->node_flags = node_flags;
+ comp->memory_properties = memory_properties;
+ comp->memory_address_limit = memory_address_limit;
+ memcpy(comp->device_name, device_name, strlen(device_name) + 1);
+
+ ctx->current += node->length;
+
+ return offset;
+}
+
+int acpi_iort_add_rc(struct acpi_ctx *ctx,
+ const u64 mem_access_properties,
+ const u32 ats_attributes,
+ const u32 pci_segment_number,
+ const u8 memory_address_size_limit,
+ const int num_mappings,
+ const struct acpi_iort_id_mapping *map)
+{
+ struct acpi_iort_id_mapping *mapping;
+ struct acpi_iort_node *node;
+ struct acpi_iort_rc *rc;
+ int offset;
+
+ offset = ctx->current - ctx->tab_start;
+
+ node = ctx->current;
+ memset(node, '\0', sizeof(struct acpi_iort_node));
+
+ node->type = ACPI_IORT_NODE_PCI_ROOT_COMPLEX;
+ node->revision = 2;
+
+ node->length = sizeof(struct acpi_iort_node);
+ node->length += sizeof(struct acpi_iort_rc);
+ node->length += sizeof(struct acpi_iort_id_mapping) * num_mappings;
+
+ rc = (struct acpi_iort_rc *)node->node_data;
+ rc->mem_access_properties = mem_access_properties;
+ rc->ats_attributes = ats_attributes;
+ rc->pci_segment_number = pci_segment_number;
+ rc->memory_address_size_limit = memory_address_size_limit;
+
+ mapping = (struct acpi_iort_id_mapping *)(rc + 1);
+ for (int i = 0; i < num_mappings; i++) {
+ memcpy(mapping, &map[i], sizeof(struct acpi_iort_id_mapping));
+ mapping++;
+ }
+
+ ctx->current += node->length;
+
+ return offset;
+}
+
+int acpi_iort_add_smmu_v3(struct acpi_ctx *ctx,
+ const u64 base_address,
+ const u32 flags,
+ const u64 vatos_address,
+ const u32 model,
+ const u32 event_gsiv,
+ const u32 pri_gsiv,
+ const u32 gerr_gsiv,
+ const u32 sync_gsiv,
+ const u32 pxm,
+ const u32 id_mapping_index,
+ const int num_mappings,
+ const struct acpi_iort_id_mapping *map)
+{
+ struct acpi_iort_node *node;
+ struct acpi_iort_smmu_v3 *smmu;
+ struct acpi_iort_id_mapping *mapping;
+ int offset;
+
+ offset = ctx->current - ctx->tab_start;
+
+ node = ctx->current;
+ memset(node, '\0', sizeof(struct acpi_iort_node));
+
+ node->type = ACPI_IORT_NODE_SMMU_V3;
+ node->revision = 5;
+ node->mapping_count = num_mappings;
+ node->mapping_offset = sizeof(struct acpi_iort_node) + sizeof(struct acpi_iort_smmu_v3);
+
+ node->length = sizeof(struct acpi_iort_node);
+ node->length += sizeof(struct acpi_iort_smmu_v3);
+ node->length += sizeof(struct acpi_iort_id_mapping) * num_mappings;
+
+ smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
+
+ smmu->base_address = base_address;
+ smmu->flags = flags;
+ smmu->vatos_address = vatos_address;
+ smmu->model = model;
+ smmu->event_gsiv = event_gsiv;
+ smmu->pri_gsiv = pri_gsiv;
+ smmu->gerr_gsiv = gerr_gsiv;
+ smmu->sync_gsiv = sync_gsiv;
+ smmu->pxm = pxm;
+ smmu->id_mapping_index = id_mapping_index;
+
+ mapping = (struct acpi_iort_id_mapping *)(smmu + 1);
+ for (int i = 0; i < num_mappings; i++) {
+ memcpy(mapping, &map[i], sizeof(struct acpi_iort_id_mapping));
+ mapping++;
+ }
+
+ ctx->current += node->length;
+
+ return offset;
+}
+
+static int acpi_write_iort(struct acpi_ctx *ctx, const struct acpi_writer *entry)
+{
+ struct acpi_table_iort *iort;
+ struct acpi_iort_node *node;
+ u32 offset;
+ int ret;
+
+ iort = ctx->current;
+ ctx->tab_start = ctx->current;
+ memset(iort, '\0', sizeof(struct acpi_table_iort));
+
+ acpi_fill_header(&iort->header, "IORT");
+ iort->header.revision = 1;
+ iort->header.creator_revision = 1;
+ iort->header.length = sizeof(struct acpi_table_iort);
+ iort->node_offset = sizeof(struct acpi_table_iort);
+
+ acpi_inc(ctx, sizeof(struct acpi_table_iort));
+
+ offset = sizeof(struct acpi_table_iort);
+ ret = acpi_fill_iort(ctx);
+ if (ret) {
+ ctx->current = iort;
+ return log_msg_ret("fill", ret);
+ }
+
+ /* Count nodes filled in */
+ for (node = (void *)iort + iort->node_offset;
+ node->length > 0 && (void *)node < ctx->current;
+ node = (void *)node + node->length)
+ iort->node_count++;
+
+ /* (Re)calculate length and checksum */
+ iort->header.length = ctx->current - (void *)iort;
+ iort->header.checksum = table_compute_checksum((void *)iort, iort->header.length);
+ log_debug("IORT at %p, length %x\n", iort, iort->header.length);
+
+ /* Drop the table if it is empty */
+ if (iort->header.length == sizeof(struct acpi_table_iort))
+ return log_msg_ret("fill", -ENOENT);
+ acpi_add_table(ctx, iort);
+
+ return 0;
+}
+
+ACPI_WRITER(5iort, "IORT", acpi_write_iort, 0);
+
+/*
+ * Allocate memory for ACPI tables and write ACPI tables to the
+ * allocated buffer.
+ *
+ * Return: status code
+ */
+static int alloc_write_acpi_tables(void)
+{
+ u64 table_end;
+ void *addr;
+
+ if (IS_ENABLED(CONFIG_X86) ||
+ IS_ENABLED(CONFIG_QFW_ACPI) ||
+ IS_ENABLED(CONFIG_SANDBOX)) {
+ log_debug("Skipping writing ACPI tables as already done\n");
+ return 0;
+ }
+
+ if (!IS_ENABLED(CONFIG_BLOBLIST_TABLES)) {
+ log_debug("Skipping writing ACPI tables as BLOBLIST_TABLES is not selected\n");
+ return 0;
+ }
+
+ /* Align the table to a 4KB boundary to keep EFI happy */
+ addr = bloblist_add(BLOBLISTT_ACPI_TABLES, TABLE_SIZE,
+ ilog2(SZ_4K));
+
+ if (!addr)
+ return log_msg_ret("mem", -ENOMEM);
+
+ gd->arch.table_start_high = virt_to_phys(addr);
+ gd->arch.table_end_high = gd->arch.table_start_high + TABLE_SIZE;
+
+ table_end = write_acpi_tables(gd->arch.table_start_high);
+ if (!table_end) {
+ log_err("Can't create ACPI configuration table\n");
+ return -EINTR;
+ }
+
+ log_debug("- wrote 'acpi' to %lx, end %llx\n", gd->arch.table_start_high, table_end);
+ if (table_end > gd->arch.table_end_high) {
+ log_err("Out of space for configuration tables: need %llx, have %x\n",
+ table_end - gd->arch.table_start_high, TABLE_SIZE);
+ return log_msg_ret("acpi", -ENOSPC);
+ }
+
+ log_debug("- done writing tables\n");
+
+ return 0;
+}
+
+EVENT_SPY_SIMPLE(EVT_LAST_STAGE_INIT, alloc_write_acpi_tables);
diff --git a/lib/acpi/acpigen.c b/lib/acpi/acpigen.c
index ecff5a50d50..fa9dad32a3f 100644
--- a/lib/acpi/acpigen.c
+++ b/lib/acpi/acpigen.c
@@ -361,6 +361,17 @@ void acpigen_write_processor(struct acpi_ctx *ctx, uint cpuindex,
acpigen_emit_byte(ctx, pblock_len);
}
+void acpigen_write_processor_device(struct acpi_ctx *ctx, uint cpuindex)
+{
+ char pscope[16];
+
+ snprintf(pscope, sizeof(pscope), ACPI_CPU_STRING, cpuindex);
+ acpigen_write_device(ctx, pscope);
+ acpigen_write_name_string(ctx, "_HID", "ACPI0007");
+ acpigen_write_name_integer(ctx, "_UID", cpuindex);
+ acpigen_pop_len(ctx); /* Device */
+}
+
void acpigen_write_processor_package(struct acpi_ctx *ctx,
const char *const name,
const uint first_core,
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index 69b2c9360d8..066f0ca0da7 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -545,6 +545,8 @@ config EFI_BOOTMGR
config EFI_HTTP_BOOT
bool "EFI HTTP Boot support"
+ depends on NET || NET_LWIP
+ select CMD_NET
select CMD_DNS
select CMD_WGET
select BLKMAP
diff --git a/lib/efi_loader/dtbdump.c b/lib/efi_loader/dtbdump.c
index 9f1d8fb82cb..a3d59a2fd3b 100644
--- a/lib/efi_loader/dtbdump.c
+++ b/lib/efi_loader/dtbdump.c
@@ -225,7 +225,7 @@ static u32 f2h(fdt32_t val)
* @systable: system table
* Return: device tree or NULL
*/
-void *get_dtb(struct efi_system_table *systable)
+static void *get_dtb(struct efi_system_table *systable)
{
void *dtb = NULL;
efi_uintn_t i;
@@ -246,7 +246,7 @@ void *get_dtb(struct efi_system_table *systable)
* @pos: UTF-16 string
* Return: pointer to first non-whitespace
*/
-u16 *skip_whitespace(u16 *pos)
+static u16 *skip_whitespace(u16 *pos)
{
for (; *pos && *pos <= 0x20; ++pos)
;
@@ -260,7 +260,7 @@ u16 *skip_whitespace(u16 *pos)
* @keyword: keyword to be searched
* Return: true fi @string starts with the keyword
*/
-bool starts_with(u16 *string, u16 *keyword)
+static bool starts_with(u16 *string, u16 *keyword)
{
for (; *keyword; ++string, ++keyword) {
if (*string != *keyword)
@@ -272,7 +272,7 @@ bool starts_with(u16 *string, u16 *keyword)
/**
* do_help() - print help
*/
-void do_help(void)
+static void do_help(void)
{
error(u"dump - print device-tree\r\n");
error(u"load <dtb> - load device-tree from file\r\n");
@@ -332,7 +332,7 @@ open_file_system(struct efi_simple_file_system_protocol **file_system)
* @filename: file name
* Return: status code
*/
-efi_status_t do_load(u16 *filename)
+static efi_status_t do_load(u16 *filename)
{
struct efi_dt_fixup_protocol *dt_fixup_prot;
struct efi_simple_file_system_protocol *file_system;
@@ -469,7 +469,7 @@ out:
* @filename: file name
* Return: status code
*/
-efi_status_t do_save(u16 *filename)
+static efi_status_t do_save(u16 *filename)
{
struct efi_simple_file_system_protocol *file_system;
efi_uintn_t dtb_size;
diff --git a/lib/efi_loader/efi_bootbin.c b/lib/efi_loader/efi_bootbin.c
index a87006b3c0e..bf38392fac3 100644
--- a/lib/efi_loader/efi_bootbin.c
+++ b/lib/efi_loader/efi_bootbin.c
@@ -137,6 +137,7 @@ efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size)
*/
file_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE,
(uintptr_t)source_buffer,
+ (uintptr_t)source_buffer +
source_size);
/*
* Make sure that device for device_path exist
diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c
index a3aa2b8d1b9..f9b5988a06e 100644
--- a/lib/efi_loader/efi_bootmgr.c
+++ b/lib/efi_loader/efi_bootmgr.c
@@ -385,7 +385,7 @@ err:
* @ctx: event context
* Return: status code
*/
-efi_status_t efi_bootmgr_release_uridp(struct uridp_context *ctx)
+static efi_status_t efi_bootmgr_release_uridp(struct uridp_context *ctx)
{
efi_status_t ret = EFI_SUCCESS;
efi_status_t ret2 = EFI_SUCCESS;
diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c
index 9de3b95d073..d7444588aa0 100644
--- a/lib/efi_loader/efi_device_path.c
+++ b/lib/efi_loader/efi_device_path.c
@@ -1073,7 +1073,8 @@ efi_status_t efi_dp_from_name(const char *dev, const char *devnr,
efi_get_image_parameters(&image_addr, &image_size);
dp = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE,
- (uintptr_t)image_addr, image_size);
+ (uintptr_t)image_addr,
+ (uintptr_t)image_addr + image_size);
} else if (IS_ENABLED(CONFIG_NETDEVICES) && !strcmp(dev, "Net")) {
dp = efi_dp_from_eth();
} else if (!strcmp(dev, "Uart")) {
diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
index 93a9a5ac025..1f3de0a2339 100644
--- a/lib/efi_loader/efi_disk.c
+++ b/lib/efi_loader/efi_disk.c
@@ -561,11 +561,9 @@ static int efi_disk_create_raw(struct udevice *dev, efi_handle_t agent_handle)
{
struct efi_disk_obj *disk;
struct blk_desc *desc;
- int diskid;
efi_status_t ret;
desc = dev_get_uclass_plat(dev);
- diskid = desc->devnum;
ret = efi_disk_add_dev(NULL, NULL, desc,
NULL, 0, &disk, agent_handle);
@@ -608,7 +606,6 @@ static int efi_disk_create_part(struct udevice *dev, efi_handle_t agent_handle)
struct disk_part *part_data;
struct disk_partition *info;
unsigned int part;
- int diskid;
struct efi_handler *handler;
struct efi_device_path *dp_parent;
struct efi_disk_obj *disk;
@@ -618,7 +615,6 @@ static int efi_disk_create_part(struct udevice *dev, efi_handle_t agent_handle)
return -1;
desc = dev_get_uclass_plat(dev_get_parent(dev));
- diskid = desc->devnum;
part_data = dev_get_uclass_plat(dev);
part = part_data->partnum;
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index 3d742fa1915..d2f5d563f2a 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -472,7 +472,8 @@ efi_status_t efi_allocate_pages(enum efi_allocate_type type,
switch (type) {
case EFI_ALLOCATE_ANY_PAGES:
/* Any page */
- addr = (u64)lmb_alloc_flags(len, EFI_PAGE_SIZE, flags);
+ addr = (u64)lmb_alloc_base_flags(len, EFI_PAGE_SIZE,
+ LMB_ALLOC_ANYWHERE, flags);
if (!addr)
return EFI_OUT_OF_RESOURCES;
break;
@@ -520,7 +521,6 @@ efi_status_t efi_allocate_pages(enum efi_allocate_type type,
efi_status_t efi_free_pages(uint64_t memory, efi_uintn_t pages)
{
u64 len;
- uint flags;
long status;
efi_status_t ret;
@@ -535,18 +535,17 @@ efi_status_t efi_free_pages(uint64_t memory, efi_uintn_t pages)
return EFI_INVALID_PARAMETER;
}
- flags = LMB_NOOVERWRITE | LMB_NONOTIFY;
len = (u64)pages << EFI_PAGE_SHIFT;
+ /*
+ * The 'memory' variable for sandbox holds a pointer which has already
+ * been mapped with map_sysmem() from efi_allocate_pages(). Convert
+ * it back to an address LMB understands
+ */
status = lmb_free_flags(map_to_sysmem((void *)(uintptr_t)memory), len,
- flags);
+ LMB_NOOVERWRITE);
if (status)
return EFI_NOT_FOUND;
- ret = efi_add_memory_map_pg(memory, pages, EFI_CONVENTIONAL_MEMORY,
- false);
- if (ret != EFI_SUCCESS)
- return EFI_NOT_FOUND;
-
return ret;
}
diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
index 45f451ef6b6..866a529857e 100644
--- a/lib/efi_loader/efi_tcg2.c
+++ b/lib/efi_loader/efi_tcg2.c
@@ -789,7 +789,7 @@ static const struct efi_tcg2_protocol efi_tcg2_protocol = {
/**
* tcg2_uninit - remove the final event table and free efi memory on failures
*/
-void tcg2_uninit(void)
+static void tcg2_uninit(void)
{
efi_status_t ret;
diff --git a/lib/efi_loader/smbiosdump.c b/lib/efi_loader/smbiosdump.c
index 2f0b91a353d..d7f2ba30a95 100644
--- a/lib/efi_loader/smbiosdump.c
+++ b/lib/efi_loader/smbiosdump.c
@@ -289,7 +289,7 @@ static void *get_config_table(const efi_guid_t *guid)
* @len: length of buffer
* Return: checksum
*/
-u8 checksum(void *buf, int len)
+static u8 checksum(void *buf, int len)
{
u8 ret = 0;
@@ -304,7 +304,7 @@ u8 checksum(void *buf, int len)
*
* Return: status code
*/
-efi_status_t do_check(void)
+static efi_status_t do_check(void)
{
struct smbios3_entry *smbios3_anchor;
void *table, *table_end;
@@ -401,7 +401,7 @@ efi_status_t do_check(void)
* @buf: buffer to write
* @size: size of the buffer
*/
-efi_status_t save_file(u16 *filename, void *buf, efi_uintn_t size)
+static efi_status_t save_file(u16 *filename, void *buf, efi_uintn_t size)
{
efi_uintn_t ret;
struct efi_simple_file_system_protocol *file_system;
diff --git a/lib/efi_selftest/efi_selftest_hii.c b/lib/efi_selftest/efi_selftest_hii.c
index f219c0120a3..c363df466dc 100644
--- a/lib/efi_selftest/efi_selftest_hii.c
+++ b/lib/efi_selftest/efi_selftest_hii.c
@@ -913,7 +913,7 @@ static int test_hii_string_get_languages(void)
goto out;
}
- efi_st_printf("got languages are %s\n", languages);
+ efi_st_printf("Available languages: %s\n", languages);
result = EFI_ST_SUCCESS;
diff --git a/lib/efi_selftest/efi_selftest_hii_data.c b/lib/efi_selftest/efi_selftest_hii_data.c
index d19f0682afd..5fc890112b4 100644
--- a/lib/efi_selftest/efi_selftest_hii_data.c
+++ b/lib/efi_selftest/efi_selftest_hii_data.c
@@ -39,7 +39,7 @@
/* HII keyboard layout */
#define EFI_NULL_MODIFIER 0x0000
-u8 packagelist1[] = {
+static u8 packagelist1[] = {
// EFI_HII_PACKAGE_LIST_HEADER, length = 20
// SimpleFont, Font, GUID, Form, String, Image, DevicePath,
// (74) (110) 20 (8) 78 (67) (8)
@@ -262,7 +262,7 @@ u8 packagelist1[] = {
EFI_HII_PACKAGE_END
};
-u8 packagelist2[] = {
+static u8 packagelist2[] = {
// EFI_HII_PACKAGE_LIST_HEADER, length = 20
// SimpleFont, Font, GUID, KeyboardLayout, Form, End
// (74) (122) 20 192 (8) 4
@@ -424,30 +424,10 @@ u8 packagelist2[] = {
EFI_HII_PACKAGE_END // 1
};
-efi_guid_t packagelist_guid1 =
- EFI_GUID(0x03abcd89, 0x03f4, 0x7044,
- 0x81, 0xde, 0x99, 0xb1, 0x81, 0x20, 0xf7, 0x68);
-
-efi_guid_t packagelist_guid2 =
- EFI_GUID(0x8685ded3, 0x1bce, 0x43f3,
- 0xa2, 0x0c, 0xa3, 0x06, 0xec, 0x69, 0x72, 0xdd);
-
-efi_guid_t kb_layout_guid11 =
+static efi_guid_t kb_layout_guid11 =
EFI_GUID(0x8d40e495, 0xe2aa, 0x4c6f,
0x89, 0x70, 0x68, 0x85, 0x09, 0xee, 0xc7, 0xd2);
-efi_guid_t kb_layout_guid12 =
- EFI_GUID(0x2ae60b3e, 0xb9d6, 0x49d8,
- 0x9a, 0x16, 0xc2, 0x48, 0xf1, 0xeb, 0xa8, 0xdb);
-
-efi_guid_t kb_layout_guid21 =
- EFI_GUID(0xe0f56a1f, 0xdf6b, 0x4a7e,
- 0xa3, 0x9a, 0xe7, 0xa5, 0x19, 0x15, 0x45, 0xd6);
-
-efi_guid_t kb_layout_guid22 =
- EFI_GUID(0x47be6ac9, 0x54cc, 0x46f9,
- 0xa2, 0x62, 0xd5, 0x3b, 0x25, 0x6a, 0x0c, 0x34);
-
-efi_guid_t package_guid =
+static efi_guid_t package_guid =
EFI_GUID(0x0387c95a, 0xd703, 0x2346,
0xb2, 0xab, 0xd0, 0xc7, 0xdd, 0x90, 0x44, 0xf8);
diff --git a/lib/lmb.c b/lib/lmb.c
index eec99c185ee..2ed0da21b45 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -27,9 +27,6 @@ DECLARE_GLOBAL_DATA_PTR;
#define MAP_OP_FREE (u8)0x2
#define MAP_OP_ADD (u8)0x3
-#define LMB_ALLOC_ANYWHERE 0
-#define LMB_ALIST_INITIAL_SIZE 4
-
static struct lmb lmb;
static bool lmb_should_notify(enum lmb_flags flags)
@@ -38,9 +35,8 @@ static bool lmb_should_notify(enum lmb_flags flags)
CONFIG_IS_ENABLED(EFI_LOADER);
}
-static int __maybe_unused lmb_map_update_notify(phys_addr_t addr,
- phys_size_t size,
- u8 op)
+static int lmb_map_update_notify(phys_addr_t addr, phys_size_t size, u8 op,
+ enum lmb_flags flags)
{
u64 efi_addr;
u64 pages;
@@ -51,6 +47,9 @@ static int __maybe_unused lmb_map_update_notify(phys_addr_t addr,
return -1;
}
+ if (!lmb_should_notify(flags))
+ return 0;
+
efi_addr = (uintptr_t)map_sysmem(addr, 0);
pages = efi_size_in_pages(size + (efi_addr & EFI_PAGE_MASK));
efi_addr &= ~EFI_PAGE_MASK;
@@ -64,9 +63,10 @@ static int __maybe_unused lmb_map_update_notify(phys_addr_t addr,
log_err("%s: LMB Map notify failure %lu\n", __func__,
status & ~EFI_ERROR_MASK);
return -1;
- } else {
- return 0;
}
+ unmap_sysmem((void *)(uintptr_t)efi_addr);
+
+ return 0;
}
static void lmb_print_region_flags(enum lmb_flags flags)
@@ -76,6 +76,7 @@ static void lmb_print_region_flags(enum lmb_flags flags)
do {
bitpos = flags ? fls(flags) - 1 : 0;
+ assert_noisy(bitpos < ARRAY_SIZE(flag_str));
printf("%s", flag_str[bitpos]);
flags &= ~(1ull << bitpos);
puts(flags ? ", " : "\n");
@@ -450,7 +451,7 @@ static long lmb_add_region_flags(struct alist *lmb_rgn_lst, phys_addr_t base,
}
if (coalesced)
- return coalesced;
+ return 0;
if (alist_full(lmb_rgn_lst) &&
!alist_expand_by(lmb_rgn_lst, lmb_rgn_lst->alloc))
@@ -487,13 +488,10 @@ long lmb_add(phys_addr_t base, phys_size_t size)
struct alist *lmb_rgn_lst = &lmb.free_mem;
ret = lmb_add_region(lmb_rgn_lst, base, size);
- if (ret < 0)
+ if (ret)
return ret;
- if (lmb_should_notify(LMB_NONE))
- return lmb_map_update_notify(base, size, MAP_OP_ADD);
-
- return 0;
+ return lmb_map_update_notify(base, size, MAP_OP_ADD, LMB_NONE);
}
static long _lmb_free(phys_addr_t base, phys_size_t size)
@@ -566,10 +564,7 @@ long lmb_free_flags(phys_addr_t base, phys_size_t size,
if (ret < 0)
return ret;
- if (lmb_should_notify(flags))
- return lmb_map_update_notify(base, size, MAP_OP_FREE);
-
- return ret;
+ return lmb_map_update_notify(base, size, MAP_OP_FREE, flags);
}
long lmb_free(phys_addr_t base, phys_size_t size)
@@ -583,13 +578,10 @@ long lmb_reserve_flags(phys_addr_t base, phys_size_t size, enum lmb_flags flags)
struct alist *lmb_rgn_lst = &lmb.used_mem;
ret = lmb_add_region_flags(lmb_rgn_lst, base, size, flags);
- if (ret < 0)
- return -1;
-
- if (lmb_should_notify(flags))
- return lmb_map_update_notify(base, size, MAP_OP_RESERVE);
+ if (ret)
+ return ret;
- return ret;
+ return lmb_map_update_notify(base, size, MAP_OP_RESERVE, flags);
}
long lmb_reserve(phys_addr_t base, phys_size_t size)
@@ -621,7 +613,6 @@ static phys_addr_t lmb_align_down(phys_addr_t addr, phys_size_t size)
static phys_addr_t _lmb_alloc_base(phys_size_t size, ulong align,
phys_addr_t max_addr, enum lmb_flags flags)
{
- u8 op;
int ret;
long i, rgn;
phys_addr_t base = 0;
@@ -651,16 +642,14 @@ static phys_addr_t _lmb_alloc_base(phys_size_t size, ulong align,
if (rgn < 0) {
/* This area isn't reserved, take it */
if (lmb_add_region_flags(&lmb.used_mem, base,
- size, flags) < 0)
+ size, flags))
return 0;
- if (lmb_should_notify(flags)) {
- op = MAP_OP_RESERVE;
- ret = lmb_map_update_notify(base, size,
- op);
- if (ret)
- return ret;
- }
+ ret = lmb_map_update_notify(base, size,
+ MAP_OP_RESERVE,
+ flags);
+ if (ret)
+ return ret;
return base;
}
@@ -679,23 +668,6 @@ phys_addr_t lmb_alloc(phys_size_t size, ulong align)
return lmb_alloc_base(size, align, LMB_ALLOC_ANYWHERE);
}
-/**
- * lmb_alloc_flags() - Allocate memory region with specified attributes
- * @size: Size of the region requested
- * @align: Alignment of the memory region requested
- * @flags: Memory region attributes to be set
- *
- * Allocate a region of memory with the attributes specified through the
- * parameter.
- *
- * Return: base address on success, 0 on error
- */
-phys_addr_t lmb_alloc_flags(phys_size_t size, ulong align, uint flags)
-{
- return _lmb_alloc_base(size, align, LMB_ALLOC_ANYWHERE,
- flags);
-}
-
phys_addr_t lmb_alloc_base(phys_size_t size, ulong align, phys_addr_t max_addr)
{
phys_addr_t alloc;