diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Kconfig | 31 | ||||
-rw-r--r-- | lib/acpi/acpi_table.c | 630 | ||||
-rw-r--r-- | lib/acpi/acpigen.c | 11 | ||||
-rw-r--r-- | lib/efi_loader/Kconfig | 2 | ||||
-rw-r--r-- | lib/efi_loader/dtbdump.c | 12 | ||||
-rw-r--r-- | lib/efi_loader/efi_bootbin.c | 1 | ||||
-rw-r--r-- | lib/efi_loader/efi_bootmgr.c | 2 | ||||
-rw-r--r-- | lib/efi_loader/efi_device_path.c | 3 | ||||
-rw-r--r-- | lib/efi_loader/efi_disk.c | 4 | ||||
-rw-r--r-- | lib/efi_loader/efi_memory.c | 17 | ||||
-rw-r--r-- | lib/efi_loader/efi_tcg2.c | 2 | ||||
-rw-r--r-- | lib/efi_loader/smbiosdump.c | 6 | ||||
-rw-r--r-- | lib/efi_selftest/efi_selftest_hii.c | 2 | ||||
-rw-r--r-- | lib/efi_selftest/efi_selftest_hii_data.c | 28 | ||||
-rw-r--r-- | lib/lmb.c | 72 |
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; |