mirror of
https://github.com/AsahiLinux/u-boot
synced 2025-01-10 12:18:55 +00:00
a8efebe719
Sandbox uses an API to map between addresses and pointers. This allows it to have (emulated) memory at zero and avoid arch-specific addressing details. It also allows memory-mapped peripherals to work. As an example, on many machines sandbox maps address 100 to pointer value 10000000. However this is not correct for ACPI, if sandbox starts another program (e.g EFI app) and passes it the tables. That app has no knowledge of sandbox's address mapping. So to make this work we want to store 10000000 as the value in the table. Add two new 'nomap' functions which clearly make this exeption to how sandbox works. This should allow EFI apps to access ACPI tables with sandbox, e.g. for testing purposes. Signed-off-by: Simon Glass <sjg@chromium.org> Suggested-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
191 lines
4.5 KiB
C
191 lines
4.5 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
/*
|
|
* Copyright 2019 Google LLC
|
|
* Written by Simon Glass <sjg@chromium.org>
|
|
*/
|
|
#include <common.h>
|
|
#include <command.h>
|
|
#include <display_options.h>
|
|
#include <mapmem.h>
|
|
#include <acpi/acpi_table.h>
|
|
#include <asm/acpi_table.h>
|
|
#include <asm/global_data.h>
|
|
#include <dm/acpi.h>
|
|
|
|
DECLARE_GLOBAL_DATA_PTR;
|
|
|
|
/**
|
|
* dump_hdr() - Dump an ACPI header
|
|
*
|
|
* Except for the Firmware ACPI Control Structure (FACS)
|
|
* additionally show the revision information.
|
|
*
|
|
* @hdr: ACPI header to dump
|
|
*/
|
|
static void dump_hdr(struct acpi_table_header *hdr)
|
|
{
|
|
bool has_hdr = memcmp(hdr->signature, "FACS", ACPI_NAME_LEN);
|
|
|
|
printf("%.*s %16lx %5x", ACPI_NAME_LEN, hdr->signature,
|
|
(ulong)map_to_sysmem(hdr), hdr->length);
|
|
if (has_hdr) {
|
|
printf(" v%02d %.6s %.8s %x %.4s %x\n", hdr->revision,
|
|
hdr->oem_id, hdr->oem_table_id, hdr->oem_revision,
|
|
hdr->aslc_id, hdr->aslc_revision);
|
|
} else {
|
|
printf("\n");
|
|
}
|
|
}
|
|
|
|
static int dump_table_name(const char *sig)
|
|
{
|
|
struct acpi_table_header *hdr;
|
|
|
|
hdr = acpi_find_table(sig);
|
|
if (!hdr)
|
|
return -ENOENT;
|
|
printf("%.*s @ %16lx\n", ACPI_NAME_LEN, hdr->signature,
|
|
(ulong)nomap_to_sysmem(hdr));
|
|
print_buffer(0, hdr, 1, hdr->length, 0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void list_fadt(struct acpi_fadt *fadt)
|
|
{
|
|
if (fadt->dsdt)
|
|
dump_hdr(nomap_sysmem(fadt->dsdt, 0));
|
|
if (fadt->firmware_ctrl)
|
|
dump_hdr(nomap_sysmem(fadt->firmware_ctrl, 0));
|
|
}
|
|
|
|
static void list_rsdt(struct acpi_rsdp *rsdp)
|
|
{
|
|
int len, i, count;
|
|
struct acpi_rsdt *rsdt;
|
|
struct acpi_xsdt *xsdt;
|
|
|
|
if (rsdp->rsdt_address) {
|
|
rsdt = nomap_sysmem(rsdp->rsdt_address, 0);
|
|
dump_hdr(&rsdt->header);
|
|
}
|
|
if (rsdp->xsdt_address) {
|
|
xsdt = nomap_sysmem(rsdp->xsdt_address, 0);
|
|
dump_hdr(&xsdt->header);
|
|
len = xsdt->header.length - sizeof(xsdt->header);
|
|
count = len / sizeof(u64);
|
|
} else if (rsdp->rsdt_address) {
|
|
len = rsdt->header.length - sizeof(rsdt->header);
|
|
count = len / sizeof(u32);
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < count; i++) {
|
|
struct acpi_table_header *hdr;
|
|
u64 entry;
|
|
|
|
if (rsdp->xsdt_address)
|
|
entry = xsdt->entry[i];
|
|
else
|
|
entry = rsdt->entry[i];
|
|
if (!entry)
|
|
break;
|
|
hdr = nomap_sysmem(entry, 0);
|
|
dump_hdr(hdr);
|
|
if (!memcmp(hdr->signature, "FACP", ACPI_NAME_LEN))
|
|
list_fadt((struct acpi_fadt *)hdr);
|
|
}
|
|
}
|
|
|
|
static void list_rsdp(struct acpi_rsdp *rsdp)
|
|
{
|
|
printf("RSDP %16lx %5x v%02d %.6s\n", (ulong)map_to_sysmem(rsdp),
|
|
rsdp->length, rsdp->revision, rsdp->oem_id);
|
|
list_rsdt(rsdp);
|
|
}
|
|
|
|
static int do_acpi_list(struct cmd_tbl *cmdtp, int flag, int argc,
|
|
char *const argv[])
|
|
{
|
|
struct acpi_rsdp *rsdp;
|
|
|
|
rsdp = map_sysmem(gd_acpi_start(), 0);
|
|
if (!rsdp) {
|
|
printf("No ACPI tables present\n");
|
|
return 0;
|
|
}
|
|
printf("Name Base Size Detail\n"
|
|
"---- ---------------- ----- ----------------------------\n");
|
|
list_rsdp(rsdp);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int do_acpi_set(struct cmd_tbl *cmdtp, int flag, int argc,
|
|
char *const argv[])
|
|
{
|
|
ulong val;
|
|
|
|
if (argc < 2) {
|
|
printf("ACPI pointer: %lx\n", gd_acpi_start());
|
|
} else {
|
|
val = hextoul(argv[1], NULL);
|
|
printf("Setting ACPI pointer to %lx\n", val);
|
|
gd_set_acpi_start(val);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int do_acpi_items(struct cmd_tbl *cmdtp, int flag, int argc,
|
|
char *const argv[])
|
|
{
|
|
bool dump_contents;
|
|
|
|
dump_contents = argc >= 2 && !strcmp("-d", argv[1]);
|
|
if (!IS_ENABLED(CONFIG_ACPIGEN)) {
|
|
printf("Not supported (enable ACPIGEN)\n");
|
|
return CMD_RET_FAILURE;
|
|
}
|
|
acpi_dump_items(dump_contents ? ACPI_DUMP_CONTENTS : ACPI_DUMP_LIST);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int do_acpi_dump(struct cmd_tbl *cmdtp, int flag, int argc,
|
|
char *const argv[])
|
|
{
|
|
const char *name;
|
|
char sig[ACPI_NAME_LEN];
|
|
int ret;
|
|
|
|
if (argc < 2)
|
|
return CMD_RET_USAGE;
|
|
|
|
name = argv[1];
|
|
if (strlen(name) != ACPI_NAME_LEN) {
|
|
printf("Table name '%s' must be four characters\n", name);
|
|
return CMD_RET_FAILURE;
|
|
}
|
|
str_to_upper(name, sig, ACPI_NAME_LEN);
|
|
ret = dump_table_name(sig);
|
|
if (ret) {
|
|
printf("Table '%.*s' not found\n", ACPI_NAME_LEN, sig);
|
|
return CMD_RET_FAILURE;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
U_BOOT_LONGHELP(acpi,
|
|
"list - list ACPI tables\n"
|
|
"acpi items [-d] - List/dump each piece of ACPI data from devices\n"
|
|
"acpi set [<addr>] - Set or show address of ACPI tables\n"
|
|
"acpi dump <name> - Dump ACPI table");
|
|
|
|
U_BOOT_CMD_WITH_SUBCMDS(acpi, "ACPI tables", acpi_help_text,
|
|
U_BOOT_SUBCMD_MKENT(list, 1, 1, do_acpi_list),
|
|
U_BOOT_SUBCMD_MKENT(items, 2, 1, do_acpi_items),
|
|
U_BOOT_SUBCMD_MKENT(set, 2, 1, do_acpi_set),
|
|
U_BOOT_SUBCMD_MKENT(dump, 2, 1, do_acpi_dump));
|