mirror of
https://github.com/u-boot/u-boot.git
synced 2024-12-15 07:43:33 +08:00
4735d03a97
The fields Creator ID and Creator Revision contain information about the tool that created an ACPI table. This may be the ASL compiler for some tables but it is not for others. Naming these fields aslc_id and aslc_revision is misleading. It is usual to see diverse values of Creator ID. On a laptop I saw these: 'AMD ', 'INTL, 'MSFT', 'PTEC'. Obviously not all relate to the Intel ASL compiler. Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
200 lines
4.8 KiB
C
200 lines
4.8 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 <log.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->creator_id, hdr->creator_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->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)
|
|
{
|
|
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));
|