mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-09-20 22:52:00 +00:00
switch to SMBIOS3 tables
allow devicetree from bloblist ACPI support for ARM and RISC-V -----BEGIN PGP SIGNATURE----- iQFFBAABCgAvFiEEslwAIq+Gp8wWVbYnfxc6PpAIreYFAmWbPygRHHNqZ0BjaHJv bWl1bS5vcmcACgkQfxc6PpAIrebFRQf+MS1t+wtPFz9Y8i7zBrEV1+fpPOp8XhJ5 m7uCkCDYO1oYShI1ht6X1nzvprElk/J9ZWTUg2IXOFzSaaBiPrylcc5bDjkd2F7A FxqXn2oqKPIXYoZsJgVS2ua5m5pQbZk9ahX5NWzQV8xLMNjgK6BvCUX3zQsLtS1C jo3ly+G+FlnFZ187qqxzIQiVkRX6p/U+JLERsgfy9q0Fic5drBydQ3F8UjMdORq2 NxxxjOl76vC+9O2A+XXC2c/1EiXR/DK2Mtz+lxA/d5/ZDrepp1bnJUjdV5qD4LdX +ZuwJBdctrlK0piOIJuAR7YjpNfxeUJl6L9l/3Hg2X3P8U84V0zqiA== =AD87 -----END PGP SIGNATURE----- Merge tag 'dm-next-7jan23' of https://source.denx.de/u-boot/custodians/u-boot-dm into next switch to SMBIOS3 tables allow devicetree from bloblist ACPI support for ARM and RISC-V
This commit is contained in:
commit
f28a77589e
35 changed files with 556 additions and 372 deletions
|
@ -53,6 +53,7 @@ Maintainers List (try to look for most precise areas first)
|
|||
ACPI:
|
||||
M: Simon Glass <sjg@chromium.org>
|
||||
S: Maintained
|
||||
F: board/emulation/configs/acpi.config
|
||||
F: cmd/acpi.c
|
||||
F: lib/acpi/
|
||||
|
||||
|
|
|
@ -108,6 +108,7 @@ config PPC
|
|||
config RISCV
|
||||
bool "RISC-V architecture"
|
||||
select CREATE_ARCH_SYMLINK
|
||||
select SUPPORT_ACPI
|
||||
select SUPPORT_OF_CONTROL
|
||||
select OF_CONTROL
|
||||
select DM
|
||||
|
|
|
@ -18,7 +18,12 @@ struct arch_global_data {
|
|||
#if defined(CONFIG_FSL_ESDHC) || defined(CONFIG_FSL_ESDHC_IMX)
|
||||
u32 sdhc_clk;
|
||||
#endif
|
||||
|
||||
#if CONFIG_IS_ENABLED(ACPI)
|
||||
ulong table_start; /* Start address of ACPI tables */
|
||||
ulong table_end; /* End address of ACPI tables */
|
||||
ulong table_start_high; /* Start address of high ACPI tables */
|
||||
ulong table_end_high; /* End address of high ACPI tables */
|
||||
#endif
|
||||
#if defined(CONFIG_FSL_ESDHC)
|
||||
u32 sdhc_per_clk;
|
||||
#endif
|
||||
|
|
|
@ -33,6 +33,12 @@ struct arch_global_data {
|
|||
ulong available_harts;
|
||||
#endif
|
||||
#endif
|
||||
#if CONFIG_IS_ENABLED(ACPI)
|
||||
ulong table_start; /* Start address of ACPI tables */
|
||||
ulong table_end; /* End address of ACPI tables */
|
||||
ulong table_start_high; /* Start address of high ACPI tables */
|
||||
ulong table_end_high; /* End address of high ACPI tables */
|
||||
#endif
|
||||
#ifdef CONFIG_SMBIOS
|
||||
ulong smbios_start; /* Start address of SMBIOS table */
|
||||
#endif
|
||||
|
|
|
@ -231,5 +231,21 @@ static inline void unmap_sysmem(const void *vaddr)
|
|||
unmap_physmem(vaddr, MAP_WRBACK);
|
||||
}
|
||||
|
||||
/**
|
||||
* nomap_sysmem() - pass through an address unchanged
|
||||
*
|
||||
* This is used to indicate an address which should NOT be mapped, e.g. in
|
||||
* SMBIOS tables. Using this function instead of a case shows that the sandbox
|
||||
* conversion has been done
|
||||
*/
|
||||
static inline void *nomap_sysmem(phys_addr_t paddr, unsigned long len)
|
||||
{
|
||||
return (void *)(uintptr_t)paddr;
|
||||
}
|
||||
|
||||
static inline phys_addr_t nomap_to_sysmem(const void *ptr)
|
||||
{
|
||||
return (phys_addr_t)(uintptr_t)ptr;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <cpu.h>
|
||||
#include <dm.h>
|
||||
#include <log.h>
|
||||
#include <mapmem.h>
|
||||
#include <acpi/acpi_s3.h>
|
||||
#include <acpi/acpi_table.h>
|
||||
#include <asm/io.h>
|
||||
|
@ -31,8 +32,6 @@ static int baytrail_write_fadt(struct acpi_ctx *ctx,
|
|||
header->length = sizeof(struct acpi_fadt);
|
||||
header->revision = 4;
|
||||
|
||||
fadt->firmware_ctrl = (u32)ctx->facs;
|
||||
fadt->dsdt = (u32)ctx->dsdt;
|
||||
fadt->preferred_pm_profile = ACPI_PM_MOBILE;
|
||||
fadt->sci_int = 9;
|
||||
fadt->smi_cmd = 0;
|
||||
|
@ -79,10 +78,8 @@ static int baytrail_write_fadt(struct acpi_ctx *ctx,
|
|||
fadt->reset_reg.addrh = 0;
|
||||
fadt->reset_value = SYS_RST | RST_CPU | FULL_RST;
|
||||
|
||||
fadt->x_firmware_ctl_l = (u32)ctx->facs;
|
||||
fadt->x_firmware_ctl_h = 0;
|
||||
fadt->x_dsdt_l = (u32)ctx->dsdt;
|
||||
fadt->x_dsdt_h = 0;
|
||||
fadt->x_firmware_ctrl = map_to_sysmem(ctx->facs);
|
||||
fadt->x_dsdt = map_to_sysmem(ctx->dsdt);
|
||||
|
||||
fadt->x_pm1a_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
|
||||
fadt->x_pm1a_evt_blk.bit_width = fadt->pm1_evt_len * 8;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <mapmem.h>
|
||||
#include <acpi/acpi_table.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/tables.h>
|
||||
|
@ -26,8 +27,6 @@ static int quark_write_fadt(struct acpi_ctx *ctx,
|
|||
header->length = sizeof(struct acpi_fadt);
|
||||
header->revision = 4;
|
||||
|
||||
fadt->firmware_ctrl = (u32)ctx->facs;
|
||||
fadt->dsdt = (u32)ctx->dsdt;
|
||||
fadt->preferred_pm_profile = ACPI_PM_UNSPECIFIED;
|
||||
fadt->sci_int = 9;
|
||||
fadt->smi_cmd = 0;
|
||||
|
@ -74,10 +73,8 @@ static int quark_write_fadt(struct acpi_ctx *ctx,
|
|||
fadt->reset_reg.addrh = 0;
|
||||
fadt->reset_value = SYS_RST | RST_CPU | FULL_RST;
|
||||
|
||||
fadt->x_firmware_ctl_l = (u32)ctx->facs;
|
||||
fadt->x_firmware_ctl_h = 0;
|
||||
fadt->x_dsdt_l = (u32)ctx->dsdt;
|
||||
fadt->x_dsdt_h = 0;
|
||||
fadt->x_firmware_ctrl = map_to_sysmem(ctx->facs);
|
||||
fadt->x_dsdt = map_to_sysmem(ctx->dsdt);
|
||||
|
||||
fadt->x_pm1a_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
|
||||
fadt->x_pm1a_evt_blk.bit_width = fadt->pm1_evt_len * 8;
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <common.h>
|
||||
#include <cpu.h>
|
||||
#include <dm.h>
|
||||
#include <mapmem.h>
|
||||
#include <acpi/acpi_table.h>
|
||||
#include <asm/ioapic.h>
|
||||
#include <asm/mpspec.h>
|
||||
|
@ -31,8 +32,6 @@ static int tangier_write_fadt(struct acpi_ctx *ctx,
|
|||
header->length = sizeof(struct acpi_fadt);
|
||||
header->revision = 6;
|
||||
|
||||
fadt->firmware_ctrl = (u32)ctx->facs;
|
||||
fadt->dsdt = (u32)ctx->dsdt;
|
||||
fadt->preferred_pm_profile = ACPI_PM_UNSPECIFIED;
|
||||
|
||||
fadt->iapc_boot_arch = ACPI_FADT_VGA_NOT_PRESENT |
|
||||
|
@ -45,10 +44,8 @@ static int tangier_write_fadt(struct acpi_ctx *ctx,
|
|||
|
||||
fadt->minor_revision = 2;
|
||||
|
||||
fadt->x_firmware_ctl_l = (u32)ctx->facs;
|
||||
fadt->x_firmware_ctl_h = 0;
|
||||
fadt->x_dsdt_l = (u32)ctx->dsdt;
|
||||
fadt->x_dsdt_h = 0;
|
||||
fadt->x_firmware_ctrl = map_to_sysmem(ctx->facs);
|
||||
fadt->x_dsdt = map_to_sysmem(ctx->dsdt);
|
||||
|
||||
header->checksum = table_compute_checksum(fadt, header->length);
|
||||
|
||||
|
|
|
@ -197,7 +197,7 @@ int acpi_write_tcpa(struct acpi_ctx *ctx, const struct acpi_writer *entry)
|
|||
|
||||
tcpa->platform_class = 0;
|
||||
tcpa->laml = size;
|
||||
tcpa->lasa = map_to_sysmem(log);
|
||||
tcpa->lasa = nomap_to_sysmem(log);
|
||||
|
||||
/* (Re)calculate length and checksum */
|
||||
current = (u32)tcpa + sizeof(struct acpi_tcpa);
|
||||
|
@ -268,7 +268,7 @@ static int acpi_write_tpm2(struct acpi_ctx *ctx,
|
|||
|
||||
/* Fill the log area size and start address fields. */
|
||||
tpm2->laml = tpm2_log_len;
|
||||
tpm2->lasa = map_to_sysmem(lasa);
|
||||
tpm2->lasa = nomap_to_sysmem(lasa);
|
||||
|
||||
/* Calculate checksum. */
|
||||
header->checksum = table_compute_checksum(tpm2, header->length);
|
||||
|
@ -430,7 +430,7 @@ int acpi_write_gnvs(struct acpi_ctx *ctx, const struct acpi_writer *entry)
|
|||
u32 *gnvs = (u32 *)((u32)ctx->dsdt + i);
|
||||
|
||||
if (*gnvs == ACPI_GNVS_ADDR) {
|
||||
*gnvs = map_to_sysmem(ctx->current);
|
||||
*gnvs = nomap_to_sysmem(ctx->current);
|
||||
log_debug("Fix up global NVS in DSDT to %#08x\n",
|
||||
*gnvs);
|
||||
break;
|
||||
|
@ -572,13 +572,8 @@ void acpi_fadt_common(struct acpi_fadt *fadt, struct acpi_facs *facs,
|
|||
memcpy(header->aslc_id, ASLC_ID, 4);
|
||||
header->aslc_revision = 1;
|
||||
|
||||
fadt->firmware_ctrl = (unsigned long)facs;
|
||||
fadt->dsdt = (unsigned long)dsdt;
|
||||
|
||||
fadt->x_firmware_ctl_l = (unsigned long)facs;
|
||||
fadt->x_firmware_ctl_h = 0;
|
||||
fadt->x_dsdt_l = (unsigned long)dsdt;
|
||||
fadt->x_dsdt_h = 0;
|
||||
fadt->x_firmware_ctrl = map_to_sysmem(facs);
|
||||
fadt->x_dsdt = map_to_sysmem(dsdt);
|
||||
|
||||
fadt->preferred_pm_profile = ACPI_PM_MOBILE;
|
||||
|
||||
|
|
3
board/emulation/configs/acpi.config
Normal file
3
board/emulation/configs/acpi.config
Normal file
|
@ -0,0 +1,3 @@
|
|||
CONFIG_CMD_QFW=y
|
||||
CONFIG_ACPI=y
|
||||
CONFIG_GENERATE_ACPI_TABLE=y
|
|
@ -5,6 +5,7 @@ config TEXT_BASE
|
|||
|
||||
config BOARD_SPECIFIC_OPTIONS # dummy
|
||||
def_bool y
|
||||
select QFW if ACPI
|
||||
select QFW_MMIO if CMD_QFW
|
||||
imply VIRTIO_MMIO
|
||||
imply VIRTIO_PCI
|
||||
|
|
|
@ -33,6 +33,8 @@ config BOARD_SPECIFIC_OPTIONS # dummy
|
|||
def_bool y
|
||||
select GENERIC_RISCV
|
||||
select SUPPORT_SPL
|
||||
select QFW if ACPI
|
||||
select QFW_MMIO if QFW
|
||||
imply AHCI
|
||||
imply SMP
|
||||
imply BOARD_LATE_INIT
|
||||
|
|
24
cmd/acpi.c
24
cmd/acpi.c
|
@ -6,6 +6,7 @@
|
|||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <display_options.h>
|
||||
#include <log.h>
|
||||
#include <mapmem.h>
|
||||
#include <acpi/acpi_table.h>
|
||||
#include <asm/acpi_table.h>
|
||||
|
@ -45,7 +46,7 @@ static int dump_table_name(const char *sig)
|
|||
if (!hdr)
|
||||
return -ENOENT;
|
||||
printf("%.*s @ %16lx\n", ACPI_NAME_LEN, hdr->signature,
|
||||
(ulong)map_to_sysmem(hdr));
|
||||
(ulong)nomap_to_sysmem(hdr));
|
||||
print_buffer(0, hdr, 1, hdr->length, 0);
|
||||
|
||||
return 0;
|
||||
|
@ -53,10 +54,17 @@ static int dump_table_name(const char *sig)
|
|||
|
||||
static void list_fadt(struct acpi_fadt *fadt)
|
||||
{
|
||||
if (fadt->dsdt)
|
||||
dump_hdr(map_sysmem(fadt->dsdt, 0));
|
||||
if (fadt->firmware_ctrl)
|
||||
dump_hdr(map_sysmem(fadt->firmware_ctrl, 0));
|
||||
if (fadt->header.revision >= 3 && fadt->x_dsdt)
|
||||
dump_hdr(nomap_sysmem(fadt->x_dsdt, 0));
|
||||
else if (fadt->dsdt)
|
||||
dump_hdr(nomap_sysmem(fadt->dsdt, 0));
|
||||
if (!IS_ENABLED(CONFIG_X86) &&
|
||||
!(fadt->flags & ACPI_FADT_HW_REDUCED_ACPI))
|
||||
log_err("FADT not ACPI-hardware-reduced-compliant\n");
|
||||
if (fadt->header.revision >= 3 && fadt->x_firmware_ctrl)
|
||||
dump_hdr(nomap_sysmem(fadt->x_firmware_ctrl, 0));
|
||||
else if (fadt->firmware_ctrl)
|
||||
dump_hdr(nomap_sysmem(fadt->firmware_ctrl, 0));
|
||||
}
|
||||
|
||||
static void list_rsdt(struct acpi_rsdp *rsdp)
|
||||
|
@ -66,11 +74,11 @@ static void list_rsdt(struct acpi_rsdp *rsdp)
|
|||
struct acpi_xsdt *xsdt;
|
||||
|
||||
if (rsdp->rsdt_address) {
|
||||
rsdt = map_sysmem(rsdp->rsdt_address, 0);
|
||||
rsdt = nomap_sysmem(rsdp->rsdt_address, 0);
|
||||
dump_hdr(&rsdt->header);
|
||||
}
|
||||
if (rsdp->xsdt_address) {
|
||||
xsdt = map_sysmem(rsdp->xsdt_address, 0);
|
||||
xsdt = nomap_sysmem(rsdp->xsdt_address, 0);
|
||||
dump_hdr(&xsdt->header);
|
||||
len = xsdt->header.length - sizeof(xsdt->header);
|
||||
count = len / sizeof(u64);
|
||||
|
@ -91,7 +99,7 @@ static void list_rsdt(struct acpi_rsdp *rsdp)
|
|||
entry = rsdt->entry[i];
|
||||
if (!entry)
|
||||
break;
|
||||
hdr = map_sysmem(entry, 0);
|
||||
hdr = nomap_sysmem(entry, 0);
|
||||
dump_hdr(hdr);
|
||||
if (!memcmp(hdr->signature, "FACP", ACPI_NAME_LEN))
|
||||
list_fadt((struct acpi_fadt *)hdr);
|
||||
|
|
23
doc/board/emulation/acpi.rst
Normal file
23
doc/board/emulation/acpi.rst
Normal file
|
@ -0,0 +1,23 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
ACPI on QEMU
|
||||
============
|
||||
|
||||
QEMU can provide ACPI tables on ARM, RISC-V (since QEMU v8.0.0), and x86.
|
||||
|
||||
The following U-Boot settings are needed for ACPI support::
|
||||
|
||||
CONFIG_CMD_QFW=y
|
||||
CONFIG_ACPI=y
|
||||
CONFIG_GENERATE_ACPI_TABLE=y
|
||||
|
||||
On x86 these settings are already included in the defconfig files. ARM and
|
||||
RISC-V default to use device-trees.
|
||||
|
||||
Instead of updating the configuration manually you can add the configuration
|
||||
fragment `acpi.config` to the make command for initializing the configuration.
|
||||
E.g.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
make qemu-riscv64_smode_defconfig acpi.config
|
|
@ -6,6 +6,7 @@ Emulation
|
|||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
acpi
|
||||
blkdev
|
||||
../../usage/semihosting
|
||||
qemu-arm
|
||||
|
|
|
@ -108,6 +108,9 @@ If CONFIG_OF_BOARD is defined, a board-specific routine will provide the
|
|||
devicetree at runtime, for example if an earlier bootloader stage creates
|
||||
it and passes it to U-Boot.
|
||||
|
||||
If CONFIG_BLOBLIST is defined, the devicetree may come from a bloblist passed
|
||||
from a previous stage, if present.
|
||||
|
||||
If CONFIG_SANDBOX is defined, then it will be read from a file on
|
||||
startup. Use the -d flag to U-Boot to specify the file to read, -D for the
|
||||
default and -T for the test devicetree, used to run sandbox unit tests.
|
||||
|
|
|
@ -540,6 +540,13 @@ config QFW
|
|||
Hidden option to enable QEMU fw_cfg interface and uclass. This will
|
||||
be selected by either CONFIG_CMD_QFW or CONFIG_GENERATE_ACPI_TABLE.
|
||||
|
||||
config QFW_ACPI
|
||||
bool
|
||||
default y
|
||||
depends on QFW && GENERATE_ACPI_TABLE && !SANDBOX
|
||||
help
|
||||
Hidden option to read ACPI tables from QEMU.
|
||||
|
||||
config QFW_PIO
|
||||
bool
|
||||
depends on QFW
|
||||
|
|
|
@ -63,6 +63,7 @@ obj-$(CONFIG_$(SPL_)PWRSEQ) += pwrseq-uclass.o
|
|||
obj-$(CONFIG_QCOM_GENI_SE) += qcom-geni-se.o
|
||||
ifdef CONFIG_QFW
|
||||
obj-y += qfw.o
|
||||
obj-$(CONFIG_QFW_ACPI) += qfw_acpi.o
|
||||
obj-$(CONFIG_QFW_PIO) += qfw_pio.o
|
||||
obj-$(CONFIG_QFW_MMIO) += qfw_mmio.o
|
||||
obj-$(CONFIG_SANDBOX) += qfw_sandbox.o
|
||||
|
|
|
@ -21,246 +21,6 @@
|
|||
#include <tables_csum.h>
|
||||
#include <asm/acpi_table.h>
|
||||
|
||||
#if defined(CONFIG_GENERATE_ACPI_TABLE) && !defined(CONFIG_SANDBOX)
|
||||
/*
|
||||
* This function allocates memory for ACPI tables
|
||||
*
|
||||
* @entry : BIOS linker command entry which tells where to allocate memory
|
||||
* (either high memory or low memory)
|
||||
* @addr : The address that should be used for low memory allcation. If the
|
||||
* memory allocation request is 'ZONE_HIGH' then this parameter will
|
||||
* be ignored.
|
||||
* @return: 0 on success, or negative value on failure
|
||||
*/
|
||||
static int bios_linker_allocate(struct udevice *dev,
|
||||
struct bios_linker_entry *entry, ulong *addr)
|
||||
{
|
||||
uint32_t size, align;
|
||||
struct fw_file *file;
|
||||
unsigned long aligned_addr;
|
||||
|
||||
align = le32_to_cpu(entry->alloc.align);
|
||||
/* align must be power of 2 */
|
||||
if (align & (align - 1)) {
|
||||
printf("error: wrong alignment %u\n", align);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
file = qfw_find_file(dev, entry->alloc.file);
|
||||
if (!file) {
|
||||
printf("error: can't find file %s\n", entry->alloc.file);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
size = be32_to_cpu(file->cfg.size);
|
||||
|
||||
/*
|
||||
* ZONE_HIGH means we need to allocate from high memory, since
|
||||
* malloc space is already at the end of RAM, so we directly use it.
|
||||
* If allocation zone is ZONE_FSEG, then we use the 'addr' passed
|
||||
* in which is low memory
|
||||
*/
|
||||
if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_HIGH) {
|
||||
aligned_addr = (unsigned long)memalign(align, size);
|
||||
if (!aligned_addr) {
|
||||
printf("error: allocating resource\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (aligned_addr < gd->arch.table_start_high)
|
||||
gd->arch.table_start_high = aligned_addr;
|
||||
if (aligned_addr + size > gd->arch.table_end_high)
|
||||
gd->arch.table_end_high = aligned_addr + size;
|
||||
|
||||
} else if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG) {
|
||||
aligned_addr = ALIGN(*addr, align);
|
||||
} else {
|
||||
printf("error: invalid allocation zone\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
debug("bios_linker_allocate: allocate file %s, size %u, zone %d, align %u, addr 0x%lx\n",
|
||||
file->cfg.name, size, entry->alloc.zone, align, aligned_addr);
|
||||
|
||||
qfw_read_entry(dev, be16_to_cpu(file->cfg.select), size,
|
||||
(void *)aligned_addr);
|
||||
file->addr = aligned_addr;
|
||||
|
||||
/* adjust address for low memory allocation */
|
||||
if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG)
|
||||
*addr = (aligned_addr + size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function patches ACPI tables previously loaded
|
||||
* by bios_linker_allocate()
|
||||
*
|
||||
* @entry : BIOS linker command entry which tells how to patch
|
||||
* ACPI tables
|
||||
* @return: 0 on success, or negative value on failure
|
||||
*/
|
||||
static int bios_linker_add_pointer(struct udevice *dev,
|
||||
struct bios_linker_entry *entry)
|
||||
{
|
||||
struct fw_file *dest, *src;
|
||||
uint32_t offset = le32_to_cpu(entry->pointer.offset);
|
||||
uint64_t pointer = 0;
|
||||
|
||||
dest = qfw_find_file(dev, entry->pointer.dest_file);
|
||||
if (!dest || !dest->addr)
|
||||
return -ENOENT;
|
||||
src = qfw_find_file(dev, entry->pointer.src_file);
|
||||
if (!src || !src->addr)
|
||||
return -ENOENT;
|
||||
|
||||
debug("bios_linker_add_pointer: dest->addr 0x%lx, src->addr 0x%lx, offset 0x%x size %u, 0x%llx\n",
|
||||
dest->addr, src->addr, offset, entry->pointer.size, pointer);
|
||||
|
||||
memcpy(&pointer, (char *)dest->addr + offset, entry->pointer.size);
|
||||
pointer = le64_to_cpu(pointer);
|
||||
pointer += (unsigned long)src->addr;
|
||||
pointer = cpu_to_le64(pointer);
|
||||
memcpy((char *)dest->addr + offset, &pointer, entry->pointer.size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function updates checksum fields of ACPI tables previously loaded
|
||||
* by bios_linker_allocate()
|
||||
*
|
||||
* @entry : BIOS linker command entry which tells where to update ACPI table
|
||||
* checksums
|
||||
* @return: 0 on success, or negative value on failure
|
||||
*/
|
||||
static int bios_linker_add_checksum(struct udevice *dev,
|
||||
struct bios_linker_entry *entry)
|
||||
{
|
||||
struct fw_file *file;
|
||||
uint8_t *data, cksum = 0;
|
||||
uint8_t *cksum_start;
|
||||
|
||||
file = qfw_find_file(dev, entry->cksum.file);
|
||||
if (!file || !file->addr)
|
||||
return -ENOENT;
|
||||
|
||||
data = (uint8_t *)(file->addr + le32_to_cpu(entry->cksum.offset));
|
||||
cksum_start = (uint8_t *)(file->addr + le32_to_cpu(entry->cksum.start));
|
||||
cksum = table_compute_checksum(cksum_start,
|
||||
le32_to_cpu(entry->cksum.length));
|
||||
*data = cksum;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This function loads and patches ACPI tables provided by QEMU */
|
||||
ulong write_acpi_tables(ulong addr)
|
||||
{
|
||||
int i, ret;
|
||||
struct fw_file *file;
|
||||
struct bios_linker_entry *table_loader;
|
||||
struct bios_linker_entry *entry;
|
||||
uint32_t size;
|
||||
struct udevice *dev;
|
||||
|
||||
ret = qfw_get_dev(&dev);
|
||||
if (ret) {
|
||||
printf("error: no qfw\n");
|
||||
return addr;
|
||||
}
|
||||
|
||||
/* make sure fw_list is loaded */
|
||||
ret = qfw_read_firmware_list(dev);
|
||||
if (ret) {
|
||||
printf("error: can't read firmware file list\n");
|
||||
return addr;
|
||||
}
|
||||
|
||||
file = qfw_find_file(dev, "etc/table-loader");
|
||||
if (!file) {
|
||||
printf("error: can't find etc/table-loader\n");
|
||||
return addr;
|
||||
}
|
||||
|
||||
size = be32_to_cpu(file->cfg.size);
|
||||
if ((size % sizeof(*entry)) != 0) {
|
||||
printf("error: table-loader maybe corrupted\n");
|
||||
return addr;
|
||||
}
|
||||
|
||||
table_loader = malloc(size);
|
||||
if (!table_loader) {
|
||||
printf("error: no memory for table-loader\n");
|
||||
return addr;
|
||||
}
|
||||
|
||||
/* QFW always puts tables at high addresses */
|
||||
gd->arch.table_start_high = (ulong)table_loader;
|
||||
gd->arch.table_end_high = (ulong)table_loader;
|
||||
|
||||
qfw_read_entry(dev, be16_to_cpu(file->cfg.select), size, table_loader);
|
||||
|
||||
for (i = 0; i < (size / sizeof(*entry)); i++) {
|
||||
entry = table_loader + i;
|
||||
switch (le32_to_cpu(entry->command)) {
|
||||
case BIOS_LINKER_LOADER_COMMAND_ALLOCATE:
|
||||
ret = bios_linker_allocate(dev, entry, &addr);
|
||||
if (ret)
|
||||
goto out;
|
||||
break;
|
||||
case BIOS_LINKER_LOADER_COMMAND_ADD_POINTER:
|
||||
ret = bios_linker_add_pointer(dev, entry);
|
||||
if (ret)
|
||||
goto out;
|
||||
break;
|
||||
case BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM:
|
||||
ret = bios_linker_add_checksum(dev, entry);
|
||||
if (ret)
|
||||
goto out;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (ret) {
|
||||
struct fw_cfg_file_iter iter;
|
||||
for (file = qfw_file_iter_init(dev, &iter);
|
||||
!qfw_file_iter_end(&iter);
|
||||
file = qfw_file_iter_next(&iter)) {
|
||||
if (file->addr) {
|
||||
free((void *)file->addr);
|
||||
file->addr = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(table_loader);
|
||||
|
||||
gd_set_acpi_start(acpi_get_rsdp_addr());
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
ulong acpi_get_rsdp_addr(void)
|
||||
{
|
||||
int ret;
|
||||
struct fw_file *file;
|
||||
struct udevice *dev;
|
||||
|
||||
ret = qfw_get_dev(&dev);
|
||||
if (ret) {
|
||||
printf("error: no qfw\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
file = qfw_find_file(dev, "etc/acpi/rsdp");
|
||||
return file->addr;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void qfw_read_entry_io(struct qfw_dev *qdev, u16 entry, u32 size,
|
||||
void *address)
|
||||
{
|
||||
|
|
281
drivers/misc/qfw_acpi.c
Normal file
281
drivers/misc/qfw_acpi.c
Normal file
|
@ -0,0 +1,281 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2015 Miao Yan <yanmiaobest@gmail.com>
|
||||
* (C) Copyright 2021 Asherah Connor <ashe@kivikakk.ee>
|
||||
*/
|
||||
|
||||
#define LOG_CATEGORY UCLASS_QFW
|
||||
|
||||
#include <acpi/acpi_table.h>
|
||||
#include <errno.h>
|
||||
#include <malloc.h>
|
||||
#include <mapmem.h>
|
||||
#include <qfw.h>
|
||||
#include <tables_csum.h>
|
||||
#include <stdio.h>
|
||||
#include <linux/sizes.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/global_data.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
/*
|
||||
* This function allocates memory for ACPI tables
|
||||
*
|
||||
* @entry : BIOS linker command entry which tells where to allocate memory
|
||||
* (either high memory or low memory)
|
||||
* @addr : The address that should be used for low memory allcation. If the
|
||||
* memory allocation request is 'ZONE_HIGH' then this parameter will
|
||||
* be ignored.
|
||||
* @return: 0 on success, or negative value on failure
|
||||
*/
|
||||
static int bios_linker_allocate(struct udevice *dev,
|
||||
struct bios_linker_entry *entry, ulong *addr)
|
||||
{
|
||||
uint32_t size, align;
|
||||
struct fw_file *file;
|
||||
unsigned long aligned_addr;
|
||||
|
||||
align = le32_to_cpu(entry->alloc.align);
|
||||
/* align must be power of 2 */
|
||||
if (align & (align - 1)) {
|
||||
printf("error: wrong alignment %u\n", align);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
file = qfw_find_file(dev, entry->alloc.file);
|
||||
if (!file) {
|
||||
printf("error: can't find file %s\n", entry->alloc.file);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
size = be32_to_cpu(file->cfg.size);
|
||||
|
||||
/*
|
||||
* ZONE_HIGH means we need to allocate from high memory, since
|
||||
* malloc space is already at the end of RAM, so we directly use it.
|
||||
* If allocation zone is ZONE_FSEG, then we use the 'addr' passed
|
||||
* in which is low memory
|
||||
*/
|
||||
if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_HIGH) {
|
||||
aligned_addr = (unsigned long)memalign(align, size);
|
||||
if (!aligned_addr) {
|
||||
printf("error: allocating resource\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (aligned_addr < gd->arch.table_start_high)
|
||||
gd->arch.table_start_high = aligned_addr;
|
||||
if (aligned_addr + size > gd->arch.table_end_high)
|
||||
gd->arch.table_end_high = aligned_addr + size;
|
||||
|
||||
} else if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG) {
|
||||
aligned_addr = ALIGN(*addr, align);
|
||||
} else {
|
||||
printf("error: invalid allocation zone\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
debug("bios_linker_allocate: allocate file %s, size %u, zone %d, align %u, addr 0x%lx\n",
|
||||
file->cfg.name, size, entry->alloc.zone, align, aligned_addr);
|
||||
|
||||
qfw_read_entry(dev, be16_to_cpu(file->cfg.select), size,
|
||||
(void *)aligned_addr);
|
||||
file->addr = aligned_addr;
|
||||
|
||||
/* adjust address for low memory allocation */
|
||||
if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG)
|
||||
*addr = (aligned_addr + size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function patches ACPI tables previously loaded
|
||||
* by bios_linker_allocate()
|
||||
*
|
||||
* @entry : BIOS linker command entry which tells how to patch
|
||||
* ACPI tables
|
||||
* @return: 0 on success, or negative value on failure
|
||||
*/
|
||||
static int bios_linker_add_pointer(struct udevice *dev,
|
||||
struct bios_linker_entry *entry)
|
||||
{
|
||||
struct fw_file *dest, *src;
|
||||
uint32_t offset = le32_to_cpu(entry->pointer.offset);
|
||||
uint64_t pointer = 0;
|
||||
|
||||
dest = qfw_find_file(dev, entry->pointer.dest_file);
|
||||
if (!dest || !dest->addr)
|
||||
return -ENOENT;
|
||||
src = qfw_find_file(dev, entry->pointer.src_file);
|
||||
if (!src || !src->addr)
|
||||
return -ENOENT;
|
||||
|
||||
debug("bios_linker_add_pointer: dest->addr 0x%lx, src->addr 0x%lx, offset 0x%x size %u, 0x%llx\n",
|
||||
dest->addr, src->addr, offset, entry->pointer.size, pointer);
|
||||
|
||||
memcpy(&pointer, (char *)dest->addr + offset, entry->pointer.size);
|
||||
pointer = le64_to_cpu(pointer);
|
||||
pointer += (unsigned long)src->addr;
|
||||
pointer = cpu_to_le64(pointer);
|
||||
memcpy((char *)dest->addr + offset, &pointer, entry->pointer.size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function updates checksum fields of ACPI tables previously loaded
|
||||
* by bios_linker_allocate()
|
||||
*
|
||||
* @entry : BIOS linker command entry which tells where to update ACPI table
|
||||
* checksums
|
||||
* @return: 0 on success, or negative value on failure
|
||||
*/
|
||||
static int bios_linker_add_checksum(struct udevice *dev,
|
||||
struct bios_linker_entry *entry)
|
||||
{
|
||||
struct fw_file *file;
|
||||
uint8_t *data, cksum = 0;
|
||||
uint8_t *cksum_start;
|
||||
|
||||
file = qfw_find_file(dev, entry->cksum.file);
|
||||
if (!file || !file->addr)
|
||||
return -ENOENT;
|
||||
|
||||
data = (uint8_t *)(file->addr + le32_to_cpu(entry->cksum.offset));
|
||||
cksum_start = (uint8_t *)(file->addr + le32_to_cpu(entry->cksum.start));
|
||||
cksum = table_compute_checksum(cksum_start,
|
||||
le32_to_cpu(entry->cksum.length));
|
||||
*data = cksum;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This function loads and patches ACPI tables provided by QEMU */
|
||||
ulong write_acpi_tables(ulong addr)
|
||||
{
|
||||
int i, ret;
|
||||
struct fw_file *file;
|
||||
struct bios_linker_entry *table_loader;
|
||||
struct bios_linker_entry *entry;
|
||||
uint32_t size;
|
||||
struct udevice *dev;
|
||||
|
||||
ret = qfw_get_dev(&dev);
|
||||
if (ret) {
|
||||
printf("error: no qfw\n");
|
||||
return addr;
|
||||
}
|
||||
|
||||
/* make sure fw_list is loaded */
|
||||
ret = qfw_read_firmware_list(dev);
|
||||
if (ret) {
|
||||
printf("error: can't read firmware file list\n");
|
||||
return addr;
|
||||
}
|
||||
|
||||
file = qfw_find_file(dev, "etc/table-loader");
|
||||
if (!file) {
|
||||
printf("error: can't find etc/table-loader\n");
|
||||
return addr;
|
||||
}
|
||||
|
||||
size = be32_to_cpu(file->cfg.size);
|
||||
if ((size % sizeof(*entry)) != 0) {
|
||||
printf("error: table-loader maybe corrupted\n");
|
||||
return addr;
|
||||
}
|
||||
|
||||
table_loader = malloc(size);
|
||||
if (!table_loader) {
|
||||
printf("error: no memory for table-loader\n");
|
||||
return addr;
|
||||
}
|
||||
|
||||
/* QFW always puts tables at high addresses */
|
||||
gd->arch.table_start_high = (ulong)table_loader;
|
||||
gd->arch.table_end_high = (ulong)table_loader;
|
||||
|
||||
qfw_read_entry(dev, be16_to_cpu(file->cfg.select), size, table_loader);
|
||||
|
||||
for (i = 0; i < (size / sizeof(*entry)); i++) {
|
||||
entry = table_loader + i;
|
||||
switch (le32_to_cpu(entry->command)) {
|
||||
case BIOS_LINKER_LOADER_COMMAND_ALLOCATE:
|
||||
ret = bios_linker_allocate(dev, entry, &addr);
|
||||
if (ret)
|
||||
goto out;
|
||||
break;
|
||||
case BIOS_LINKER_LOADER_COMMAND_ADD_POINTER:
|
||||
ret = bios_linker_add_pointer(dev, entry);
|
||||
if (ret)
|
||||
goto out;
|
||||
break;
|
||||
case BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM:
|
||||
ret = bios_linker_add_checksum(dev, entry);
|
||||
if (ret)
|
||||
goto out;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (ret) {
|
||||
struct fw_cfg_file_iter iter;
|
||||
for (file = qfw_file_iter_init(dev, &iter);
|
||||
!qfw_file_iter_end(&iter);
|
||||
file = qfw_file_iter_next(&iter)) {
|
||||
if (file->addr) {
|
||||
free((void *)file->addr);
|
||||
file->addr = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(table_loader);
|
||||
|
||||
gd_set_acpi_start(acpi_get_rsdp_addr());
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
ulong acpi_get_rsdp_addr(void)
|
||||
{
|
||||
int ret;
|
||||
struct fw_file *file;
|
||||
struct udevice *dev;
|
||||
|
||||
ret = qfw_get_dev(&dev);
|
||||
if (ret) {
|
||||
printf("error: no qfw\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
file = qfw_find_file(dev, "etc/acpi/rsdp");
|
||||
return file->addr;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_X86
|
||||
static int evt_write_acpi_tables(void)
|
||||
{
|
||||
ulong addr, end;
|
||||
void *ptr;
|
||||
|
||||
/* Reserve 64K for ACPI tables, aligned to a 4K boundary */
|
||||
ptr = memalign(SZ_4K, SZ_64K);
|
||||
if (!ptr)
|
||||
return -ENOMEM;
|
||||
addr = map_to_sysmem(ptr);
|
||||
|
||||
/* Generate ACPI tables */
|
||||
end = write_acpi_tables(addr);
|
||||
gd->arch.table_start = addr;
|
||||
gd->arch.table_end = addr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EVENT_SPY_SIMPLE(EVT_LAST_STAGE_INIT, evt_write_acpi_tables);
|
||||
#endif
|
|
@ -228,10 +228,8 @@ struct __packed acpi_fadt {
|
|||
u8 reset_value;
|
||||
u16 arm_boot_arch;
|
||||
u8 minor_revision;
|
||||
u32 x_firmware_ctl_l;
|
||||
u32 x_firmware_ctl_h;
|
||||
u32 x_dsdt_l;
|
||||
u32 x_dsdt_h;
|
||||
u64 x_firmware_ctrl;
|
||||
u64 x_dsdt;
|
||||
struct acpi_gen_regaddr x_pm1a_evt_blk;
|
||||
struct acpi_gen_regaddr x_pm1b_evt_blk;
|
||||
struct acpi_gen_regaddr x_pm1a_cnt_blk;
|
||||
|
|
|
@ -553,7 +553,7 @@ static_assert(sizeof(struct global_data) == GD_SIZE);
|
|||
#endif
|
||||
|
||||
#ifdef CONFIG_SMBIOS
|
||||
#define gd_smbios_start() gd->smbios_start
|
||||
#define gd_smbios_start() gd->arch.smbios_start
|
||||
#define gd_set_smbios_start(addr) gd->arch.smbios_start = addr
|
||||
#else
|
||||
#define gd_smbios_start() 0UL
|
||||
|
|
|
@ -433,6 +433,10 @@ struct efi_runtime_services {
|
|||
EFI_GUID(0xeb9d2d31, 0x2d88, 0x11d3, \
|
||||
0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
|
||||
|
||||
#define SMBIOS3_TABLE_GUID \
|
||||
EFI_GUID(0xf2fd1544, 0x9794, 0x4a2c, \
|
||||
0x99, 0x2e, 0xe5, 0xbb, 0xcf, 0x20, 0xe3, 0x94)
|
||||
|
||||
#define EFI_LOAD_FILE_PROTOCOL_GUID \
|
||||
EFI_GUID(0x56ec3091, 0x954c, 0x11d2, \
|
||||
0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
|
||||
|
|
|
@ -72,7 +72,7 @@ struct bd_info;
|
|||
* U-Boot is packaged as an ELF file, e.g. for debugging purposes
|
||||
* @FDTSRC_ENV: Provided by the fdtcontroladdr environment variable. This should
|
||||
* be used for debugging/development only
|
||||
* @FDTSRC_NONE: No devicetree at all
|
||||
* @FDTSRC_BLOBLIST: Provided by a bloblist from an earlier phase
|
||||
*/
|
||||
enum fdt_source_t {
|
||||
FDTSRC_SEPARATE,
|
||||
|
@ -80,6 +80,7 @@ enum fdt_source_t {
|
|||
FDTSRC_BOARD,
|
||||
FDTSRC_EMBED,
|
||||
FDTSRC_ENV,
|
||||
FDTSRC_BLOBLIST,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -1190,7 +1191,8 @@ int fdtdec_resetup(int *rescan);
|
|||
*
|
||||
* The existing devicetree is available at gd->fdt_blob
|
||||
*
|
||||
* @err internal error code if we fail to setup a DTB
|
||||
* @err: 0 on success, -EEXIST if the devicetree is already correct, or other
|
||||
* internal error code if we fail to setup a DTB
|
||||
* @returns new devicetree blob pointer
|
||||
*/
|
||||
void *board_fdt_blob_setup(int *err);
|
||||
|
|
|
@ -28,6 +28,24 @@ static inline phys_addr_t map_to_sysmem(const void *ptr)
|
|||
{
|
||||
return (phys_addr_t)(uintptr_t)ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* nomap_sysmem() - pass through an address unchanged
|
||||
*
|
||||
* This is used to indicate an address which should NOT be mapped, e.g. in
|
||||
* SMBIOS tables. Using this function instead of a case shows that the sandbox
|
||||
* conversion has been done
|
||||
*/
|
||||
static inline void *nomap_sysmem(phys_addr_t paddr, unsigned long len)
|
||||
{
|
||||
return (void *)(uintptr_t)paddr;
|
||||
}
|
||||
|
||||
static inline phys_addr_t nomap_to_sysmem(const void *ptr)
|
||||
{
|
||||
return (phys_addr_t)(uintptr_t)ptr;
|
||||
}
|
||||
|
||||
# endif
|
||||
|
||||
#endif /* __MAPMEM_H */
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
/* SMBIOS spec version implemented */
|
||||
#define SMBIOS_MAJOR_VER 3
|
||||
#define SMBIOS_MINOR_VER 0
|
||||
#define SMBIOS_MINOR_VER 7
|
||||
|
||||
enum {
|
||||
SMBIOS_STR_MAX = 64, /* Maximum length allowed for a string */
|
||||
|
@ -54,6 +54,36 @@ struct __packed smbios_entry {
|
|||
u8 bcd_rev;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct smbios3_entry - SMBIOS 3.0 (64-bit) Entry Point structure
|
||||
*/
|
||||
struct __packed smbios3_entry {
|
||||
/** @anchor: anchor string */
|
||||
u8 anchor[5];
|
||||
/** @checksum: checksum of the entry point structure */
|
||||
u8 checksum;
|
||||
/** @length: length of the entry point structure */
|
||||
u8 length;
|
||||
/** @major_ver: major version of the SMBIOS specification */
|
||||
u8 major_ver;
|
||||
/** @minor_ver: minor version of the SMBIOS specification */
|
||||
u8 minor_ver;
|
||||
/** @docrev: revision of the SMBIOS specification */
|
||||
u8 doc_rev;
|
||||
/** @entry_point_rev: revision of the entry point structure */
|
||||
u8 entry_point_rev;
|
||||
/** @reserved: reserved */
|
||||
u8 reserved;
|
||||
/** maximum size of SMBIOS table */
|
||||
u32 max_struct_size;
|
||||
/** @struct_table_address: 64-bit physical starting address */
|
||||
u64 struct_table_address;
|
||||
};
|
||||
|
||||
/* These two structures should use the same amount of 16-byte-aligned space */
|
||||
static_assert(ALIGN(16, sizeof(struct smbios_entry)) ==
|
||||
ALIGN(16, sizeof(struct smbios3_entry)));
|
||||
|
||||
/* BIOS characteristics */
|
||||
#define BIOS_CHARACTERISTICS_PCI_SUPPORTED (1 << 7)
|
||||
#define BIOS_CHARACTERISTICS_UPGRADEABLE (1 << 11)
|
||||
|
@ -228,12 +258,13 @@ static inline void fill_smbios_header(void *table, int type,
|
|||
*
|
||||
* This writes SMBIOS table at a given address.
|
||||
*
|
||||
* @addr: start address to write SMBIOS table. If this is not
|
||||
* 16-byte-aligned then it will be aligned before the table is
|
||||
* written.
|
||||
* @addr: start address to write SMBIOS table, 16-byte-alignment
|
||||
* recommended. Note that while the SMBIOS tables themself have no alignment
|
||||
* requirement, some systems may requires alignment. For example x86 systems
|
||||
* which put tables at f0000 require 16-byte alignment
|
||||
*
|
||||
* Return: end address of SMBIOS table (and start address for next entry)
|
||||
* or NULL in case of an error
|
||||
*
|
||||
*/
|
||||
ulong write_smbios_table(ulong addr);
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ obj-$(CONFIG_$(SPL_)ACPIGEN) += acpi_table.o
|
|||
obj-y += acpi_writer.o
|
||||
|
||||
# With QEMU the ACPI tables come from there, not from U-Boot
|
||||
ifndef CONFIG_QEMU
|
||||
ifndef CONFIG_QFW_ACPI
|
||||
obj-y += base.o
|
||||
obj-y += csrt.o
|
||||
obj-y += mcfg.o
|
||||
|
|
|
@ -22,13 +22,13 @@ struct acpi_table_header *acpi_find_table(const char *sig)
|
|||
if (!rsdp)
|
||||
return NULL;
|
||||
if (rsdp->xsdt_address) {
|
||||
xsdt = map_sysmem(rsdp->xsdt_address, 0);
|
||||
xsdt = nomap_sysmem(rsdp->xsdt_address, 0);
|
||||
len = xsdt->header.length - sizeof(xsdt->header);
|
||||
count = len / sizeof(u64);
|
||||
} else {
|
||||
if (!rsdp->rsdt_address)
|
||||
return NULL;
|
||||
rsdt = map_sysmem(rsdp->rsdt_address, 0);
|
||||
rsdt = nomap_sysmem(rsdp->rsdt_address, 0);
|
||||
len = rsdt->header.length - sizeof(rsdt->header);
|
||||
count = len / sizeof(u32);
|
||||
}
|
||||
|
@ -36,19 +36,38 @@ struct acpi_table_header *acpi_find_table(const char *sig)
|
|||
struct acpi_table_header *hdr;
|
||||
|
||||
if (rsdp->xsdt_address)
|
||||
hdr = map_sysmem(xsdt->entry[i], 0);
|
||||
hdr = nomap_sysmem(xsdt->entry[i], 0);
|
||||
else
|
||||
hdr = map_sysmem(rsdt->entry[i], 0);
|
||||
hdr = nomap_sysmem(rsdt->entry[i], 0);
|
||||
if (!memcmp(hdr->signature, sig, ACPI_NAME_LEN))
|
||||
return hdr;
|
||||
if (!memcmp(hdr->signature, "FACP", ACPI_NAME_LEN)) {
|
||||
struct acpi_fadt *fadt = (struct acpi_fadt *)hdr;
|
||||
|
||||
if (!memcmp(sig, "DSDT", ACPI_NAME_LEN) && fadt->dsdt)
|
||||
return map_sysmem(fadt->dsdt, 0);
|
||||
if (!memcmp(sig, "FACS", ACPI_NAME_LEN) &&
|
||||
fadt->firmware_ctrl)
|
||||
return map_sysmem(fadt->firmware_ctrl, 0);
|
||||
if (!memcmp(sig, "DSDT", ACPI_NAME_LEN)) {
|
||||
void *dsdt;
|
||||
|
||||
if (fadt->header.revision >= 3 && fadt->x_dsdt)
|
||||
dsdt = nomap_sysmem(fadt->x_dsdt, 0);
|
||||
else if (fadt->dsdt)
|
||||
dsdt = nomap_sysmem(fadt->dsdt, 0);
|
||||
else
|
||||
dsdt = NULL;
|
||||
return dsdt;
|
||||
}
|
||||
|
||||
if (!memcmp(sig, "FACS", ACPI_NAME_LEN)) {
|
||||
void *facs;
|
||||
|
||||
if (fadt->header.revision >= 3 &&
|
||||
fadt->x_firmware_ctrl)
|
||||
facs = nomap_sysmem(fadt->x_firmware_ctrl, 0);
|
||||
else if (fadt->firmware_ctrl)
|
||||
facs = nomap_sysmem(fadt->firmware_ctrl, 0);
|
||||
else
|
||||
facs = NULL;
|
||||
return facs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -167,7 +167,7 @@ int acpi_add_table(struct acpi_ctx *ctx, void *table)
|
|||
}
|
||||
|
||||
/* Add table to the RSDT */
|
||||
rsdt->entry[i] = map_to_sysmem(table);
|
||||
rsdt->entry[i] = nomap_to_sysmem(table);
|
||||
|
||||
/* Fix RSDT length or the kernel will assume invalid entries */
|
||||
rsdt->header.length = sizeof(struct acpi_table_header) +
|
||||
|
@ -185,7 +185,7 @@ int acpi_add_table(struct acpi_ctx *ctx, void *table)
|
|||
xsdt = ctx->xsdt;
|
||||
|
||||
/* Add table to the XSDT */
|
||||
xsdt->entry[i] = map_to_sysmem(table);
|
||||
xsdt->entry[i] = nomap_to_sysmem(table);
|
||||
|
||||
/* Fix XSDT length */
|
||||
xsdt->header.length = sizeof(struct acpi_table_header) +
|
||||
|
|
|
@ -48,7 +48,7 @@ int acpi_write_one(struct acpi_ctx *ctx, const struct acpi_writer *entry)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_QEMU
|
||||
#ifndef CONFIG_QFW_ACPI
|
||||
static int acpi_write_all(struct acpi_ctx *ctx)
|
||||
{
|
||||
const struct acpi_writer *writer =
|
||||
|
@ -115,7 +115,7 @@ ulong acpi_get_rsdp_addr(void)
|
|||
|
||||
return map_to_sysmem(gd->acpi_ctx->rsdp);
|
||||
}
|
||||
#endif /* QEMU */
|
||||
#endif /* QFW_ACPI */
|
||||
|
||||
void acpi_setup_ctx(struct acpi_ctx *ctx, ulong start)
|
||||
{
|
||||
|
|
|
@ -24,10 +24,10 @@ void acpi_write_rsdp(struct acpi_rsdp *rsdp, struct acpi_rsdt *rsdt,
|
|||
memcpy(rsdp->oem_id, OEM_ID, 6);
|
||||
|
||||
if (rsdt)
|
||||
rsdp->rsdt_address = map_to_sysmem(rsdt);
|
||||
rsdp->rsdt_address = nomap_to_sysmem(rsdt);
|
||||
|
||||
if (xsdt)
|
||||
rsdp->xsdt_address = map_to_sysmem(xsdt);
|
||||
rsdp->xsdt_address = nomap_to_sysmem(xsdt);
|
||||
|
||||
rsdp->length = sizeof(struct acpi_rsdp);
|
||||
rsdp->revision = ACPI_RSDP_REV_ACPI_2_0;
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#include <smbios.h>
|
||||
#include <linux/sizes.h>
|
||||
|
||||
const efi_guid_t smbios3_guid = SMBIOS3_TABLE_GUID;
|
||||
|
||||
enum {
|
||||
TABLE_SIZE = SZ_4K,
|
||||
};
|
||||
|
@ -27,8 +29,9 @@ efi_status_t efi_smbios_register(void)
|
|||
{
|
||||
ulong addr;
|
||||
efi_status_t ret;
|
||||
void *buf;
|
||||
|
||||
addr = gd->arch.smbios_start;
|
||||
addr = gd_smbios_start();
|
||||
if (!addr) {
|
||||
log_err("No SMBIOS tables to install\n");
|
||||
return EFI_NOT_FOUND;
|
||||
|
@ -42,33 +45,34 @@ efi_status_t efi_smbios_register(void)
|
|||
log_debug("EFI using SMBIOS tables at %lx\n", addr);
|
||||
|
||||
/* Install SMBIOS information as configuration table */
|
||||
return efi_install_configuration_table(&smbios_guid,
|
||||
map_sysmem(addr, 0));
|
||||
buf = map_sysmem(addr, 0);
|
||||
ret = efi_install_configuration_table(&smbios3_guid, buf);
|
||||
unmap_sysmem(buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int install_smbios_table(void)
|
||||
{
|
||||
u64 addr;
|
||||
efi_status_t ret;
|
||||
ulong addr;
|
||||
void *buf;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE) || IS_ENABLED(CONFIG_X86))
|
||||
return 0;
|
||||
|
||||
addr = SZ_4G;
|
||||
ret = efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS,
|
||||
EFI_RUNTIME_SERVICES_DATA,
|
||||
efi_size_in_pages(TABLE_SIZE), &addr);
|
||||
if (ret != EFI_SUCCESS)
|
||||
/* Align the table to a 4KB boundary to keep EFI happy */
|
||||
buf = memalign(SZ_4K, TABLE_SIZE);
|
||||
if (!buf)
|
||||
return log_msg_ret("mem", -ENOMEM);
|
||||
|
||||
addr = map_to_sysmem((void *)(uintptr_t)addr);
|
||||
addr = map_to_sysmem(buf);
|
||||
if (!write_smbios_table(addr)) {
|
||||
log_err("Failed to write SMBIOS table\n");
|
||||
return log_msg_ret("smbios", -EINVAL);
|
||||
}
|
||||
|
||||
/* Make a note of where we put it */
|
||||
log_debug("SMBIOS tables written to %llx\n", addr);
|
||||
log_debug("SMBIOS tables written to %lx\n", addr);
|
||||
gd->arch.smbios_start = addr;
|
||||
|
||||
return 0;
|
||||
|
|
32
lib/fdtdec.c
32
lib/fdtdec.c
|
@ -7,6 +7,10 @@
|
|||
*/
|
||||
|
||||
#ifndef USE_HOSTCC
|
||||
|
||||
#define LOG_CATEGORY LOGC_DT
|
||||
|
||||
#include <bloblist.h>
|
||||
#include <boot_fit.h>
|
||||
#include <display_options.h>
|
||||
#include <dm.h>
|
||||
|
@ -86,6 +90,7 @@ static const char *const fdt_src_name[] = {
|
|||
[FDTSRC_BOARD] = "board",
|
||||
[FDTSRC_EMBED] = "embed",
|
||||
[FDTSRC_ENV] = "env",
|
||||
[FDTSRC_BLOBLIST] = "bloblist",
|
||||
};
|
||||
|
||||
const char *fdtdec_get_srcname(void)
|
||||
|
@ -1662,9 +1667,26 @@ static void setup_multi_dtb_fit(void)
|
|||
|
||||
int fdtdec_setup(void)
|
||||
{
|
||||
int ret;
|
||||
int ret = -ENOENT;
|
||||
|
||||
/* The devicetree is typically appended to U-Boot */
|
||||
/* If allowing a bloblist, check that first */
|
||||
if (CONFIG_IS_ENABLED(BLOBLIST)) {
|
||||
ret = bloblist_maybe_init();
|
||||
if (!ret) {
|
||||
gd->fdt_blob = bloblist_find(BLOBLISTT_CONTROL_FDT, 0);
|
||||
if (gd->fdt_blob) {
|
||||
gd->fdt_src = FDTSRC_BLOBLIST;
|
||||
log_debug("Devicetree is in bloblist at %p\n",
|
||||
gd->fdt_blob);
|
||||
} else {
|
||||
log_debug("No FDT found in bloblist\n");
|
||||
ret = -ENOENT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, the devicetree is typically appended to U-Boot */
|
||||
if (ret) {
|
||||
if (IS_ENABLED(CONFIG_OF_SEPARATE)) {
|
||||
gd->fdt_blob = fdt_find_separate();
|
||||
gd->fdt_src = FDTSRC_SEPARATE;
|
||||
|
@ -1672,13 +1694,15 @@ int fdtdec_setup(void)
|
|||
gd->fdt_blob = dtb_dt_embedded();
|
||||
gd->fdt_src = FDTSRC_EMBED;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allow the board to override the fdt address. */
|
||||
if (IS_ENABLED(CONFIG_OF_BOARD)) {
|
||||
gd->fdt_blob = board_fdt_blob_setup(&ret);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (!ret)
|
||||
gd->fdt_src = FDTSRC_BOARD;
|
||||
else if (ret != -EEXIST)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Allow the early environment to override the fdt address */
|
||||
|
|
55
lib/smbios.c
55
lib/smbios.c
|
@ -544,15 +544,13 @@ static struct smbios_write_method smbios_write_funcs[] = {
|
|||
ulong write_smbios_table(ulong addr)
|
||||
{
|
||||
ofnode parent_node = ofnode_null();
|
||||
struct smbios_entry *se;
|
||||
ulong table_addr, start_addr;
|
||||
struct smbios3_entry *se;
|
||||
struct smbios_ctx ctx;
|
||||
ulong table_addr;
|
||||
ulong tables;
|
||||
int len = 0;
|
||||
int max_struct_size = 0;
|
||||
int handle = 0;
|
||||
char *istart;
|
||||
int isize;
|
||||
int i;
|
||||
|
||||
ctx.node = ofnode_null();
|
||||
|
@ -564,14 +562,10 @@ ulong write_smbios_table(ulong addr)
|
|||
ctx.dev = NULL;
|
||||
}
|
||||
|
||||
/* 16 byte align the table address */
|
||||
addr = ALIGN(addr, 16);
|
||||
start_addr = addr;
|
||||
|
||||
se = map_sysmem(addr, sizeof(struct smbios_entry));
|
||||
memset(se, 0, sizeof(struct smbios_entry));
|
||||
|
||||
addr += sizeof(struct smbios_entry);
|
||||
addr = ALIGN(addr, 16);
|
||||
/* move past the (so-far-unwritten) header to start writing structs */
|
||||
addr = ALIGN(addr + sizeof(struct smbios3_entry), 16);
|
||||
tables = addr;
|
||||
|
||||
/* populate minimum required tables */
|
||||
|
@ -589,40 +583,25 @@ ulong write_smbios_table(ulong addr)
|
|||
len += tmp;
|
||||
}
|
||||
|
||||
memcpy(se->anchor, "_SM_", 4);
|
||||
se->length = sizeof(struct smbios_entry);
|
||||
se->major_ver = SMBIOS_MAJOR_VER;
|
||||
se->minor_ver = SMBIOS_MINOR_VER;
|
||||
se->max_struct_size = max_struct_size;
|
||||
memcpy(se->intermediate_anchor, "_DMI_", 5);
|
||||
se->struct_table_length = len;
|
||||
|
||||
/*
|
||||
* We must use a pointer here so things work correctly on sandbox. The
|
||||
* user of this table is not aware of the mapping of addresses to
|
||||
* sandbox's DRAM buffer.
|
||||
*/
|
||||
table_addr = (ulong)map_sysmem(tables, 0);
|
||||
if (sizeof(table_addr) > sizeof(u32) && table_addr > (ulong)UINT_MAX) {
|
||||
/*
|
||||
* We need to put this >32-bit pointer into the table but the
|
||||
* field is only 32 bits wide.
|
||||
*/
|
||||
printf("WARNING: SMBIOS table_address overflow %llx\n",
|
||||
(unsigned long long)table_addr);
|
||||
addr = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* now go back and write the SMBIOS3 header */
|
||||
se = map_sysmem(start_addr, sizeof(struct smbios_entry));
|
||||
memset(se, '\0', sizeof(struct smbios_entry));
|
||||
memcpy(se->anchor, "_SM3_", 5);
|
||||
se->length = sizeof(struct smbios3_entry);
|
||||
se->major_ver = SMBIOS_MAJOR_VER;
|
||||
se->minor_ver = SMBIOS_MINOR_VER;
|
||||
se->doc_rev = 0;
|
||||
se->entry_point_rev = 1;
|
||||
se->max_struct_size = len;
|
||||
se->struct_table_address = table_addr;
|
||||
|
||||
se->struct_count = handle;
|
||||
|
||||
/* calculate checksums */
|
||||
istart = (char *)se + SMBIOS_INTERMEDIATE_OFFSET;
|
||||
isize = sizeof(struct smbios_entry) - SMBIOS_INTERMEDIATE_OFFSET;
|
||||
se->intermediate_checksum = table_compute_checksum(istart, isize);
|
||||
se->checksum = table_compute_checksum(se, sizeof(struct smbios_entry));
|
||||
out:
|
||||
se->checksum = table_compute_checksum(se, sizeof(struct smbios3_entry));
|
||||
unmap_sysmem(se);
|
||||
|
||||
return addr;
|
||||
|
|
|
@ -291,8 +291,8 @@ static int dm_test_acpi_write_tables(struct unit_test_state *uts)
|
|||
|
||||
/* Check that the pointers were added correctly */
|
||||
for (i = 0; i < 3; i++) {
|
||||
ut_asserteq(map_to_sysmem(dmar + i), ctx.rsdt->entry[i]);
|
||||
ut_asserteq(map_to_sysmem(dmar + i), ctx.xsdt->entry[i]);
|
||||
ut_asserteq(nomap_to_sysmem(dmar + i), ctx.rsdt->entry[i]);
|
||||
ut_asserteq(nomap_to_sysmem(dmar + i), ctx.xsdt->entry[i]);
|
||||
}
|
||||
ut_asserteq(0, ctx.rsdt->entry[3]);
|
||||
ut_asserteq(0, ctx.xsdt->entry[3]);
|
||||
|
@ -330,7 +330,7 @@ static int dm_test_acpi_basic(struct unit_test_state *uts)
|
|||
DM_TEST(dm_test_acpi_basic, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
|
||||
|
||||
/* Test setup_ctx_and_base_tables */
|
||||
static int dm_test_setup_ctx_and_base_tables(struct unit_test_state *uts)
|
||||
static int dm_test_acpi_ctx_and_base_tables(struct unit_test_state *uts)
|
||||
{
|
||||
struct acpi_rsdp *rsdp;
|
||||
struct acpi_rsdt *rsdt;
|
||||
|
@ -371,12 +371,12 @@ static int dm_test_setup_ctx_and_base_tables(struct unit_test_state *uts)
|
|||
end = PTR_ALIGN((void *)xsdt + sizeof(*xsdt), 64);
|
||||
ut_asserteq_ptr(end, ctx.current);
|
||||
|
||||
ut_asserteq(map_to_sysmem(rsdt), rsdp->rsdt_address);
|
||||
ut_asserteq(map_to_sysmem(xsdt), rsdp->xsdt_address);
|
||||
ut_asserteq(nomap_to_sysmem(rsdt), rsdp->rsdt_address);
|
||||
ut_asserteq(nomap_to_sysmem(xsdt), rsdp->xsdt_address);
|
||||
|
||||
return 0;
|
||||
}
|
||||
DM_TEST(dm_test_setup_ctx_and_base_tables,
|
||||
DM_TEST(dm_test_acpi_ctx_and_base_tables,
|
||||
UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
|
||||
|
||||
/* Test 'acpi list' command */
|
||||
|
@ -445,7 +445,7 @@ static int dm_test_acpi_cmd_dump(struct unit_test_state *uts)
|
|||
/* Now a real table */
|
||||
console_record_reset();
|
||||
run_command("acpi dump dmar", 0);
|
||||
addr = ALIGN(map_to_sysmem(ctx.xsdt) + sizeof(struct acpi_xsdt), 64);
|
||||
addr = ALIGN(nomap_to_sysmem(ctx.xsdt) + sizeof(struct acpi_xsdt), 64);
|
||||
ut_assert_nextline("DMAR @ %16lx", addr);
|
||||
ut_assert_nextlines_are_dump(0x30);
|
||||
ut_assert_console_end();
|
||||
|
|
Loading…
Reference in a new issue