2010-08-31 23:05:32 +00:00
|
|
|
/* acpi.c - Display acpi tables. */
|
|
|
|
/*
|
|
|
|
* GRUB -- GRand Unified Bootloader
|
|
|
|
* Copyright (C) 2008 Free Software Foundation, Inc.
|
|
|
|
*
|
|
|
|
* GRUB is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* GRUB is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
#include <grub/types.h>
|
|
|
|
#include <grub/mm.h>
|
|
|
|
#include <grub/misc.h>
|
|
|
|
#include <grub/normal.h>
|
|
|
|
#include <grub/acpi.h>
|
|
|
|
#include <grub/extcmd.h>
|
|
|
|
#include <grub/i18n.h>
|
|
|
|
#include <grub/dl.h>
|
|
|
|
|
2012-02-10 15:48:48 +00:00
|
|
|
#pragma GCC diagnostic ignored "-Wcast-align"
|
|
|
|
|
2011-04-11 21:01:51 +00:00
|
|
|
GRUB_MOD_LICENSE ("GPLv3+");
|
|
|
|
|
2010-08-31 23:05:32 +00:00
|
|
|
static void
|
|
|
|
print_strn (grub_uint8_t *str, grub_size_t len)
|
|
|
|
{
|
|
|
|
for (; *str && len; str++, len--)
|
|
|
|
grub_printf ("%c", *str);
|
|
|
|
for (len++; len; len--)
|
|
|
|
grub_printf (" ");
|
|
|
|
}
|
|
|
|
|
|
|
|
#define print_field(x) print_strn(x, sizeof (x))
|
|
|
|
|
|
|
|
static void
|
|
|
|
disp_acpi_table (struct grub_acpi_table_header *t)
|
|
|
|
{
|
|
|
|
print_field (t->signature);
|
|
|
|
grub_printf ("%4" PRIuGRUB_UINT32_T "B rev=%u OEM=", t->length, t->revision);
|
|
|
|
print_field (t->oemid);
|
|
|
|
print_field (t->oemtable);
|
|
|
|
grub_printf ("OEMrev=%08" PRIxGRUB_UINT32_T " ", t->oemrev);
|
|
|
|
print_field (t->creator_id);
|
|
|
|
grub_printf (" %08" PRIxGRUB_UINT32_T "\n", t->creator_rev);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
disp_madt_table (struct grub_acpi_madt *t)
|
|
|
|
{
|
|
|
|
struct grub_acpi_madt_entry_header *d;
|
|
|
|
grub_uint32_t len;
|
|
|
|
|
|
|
|
disp_acpi_table (&t->hdr);
|
|
|
|
grub_printf ("Local APIC=%08" PRIxGRUB_UINT32_T " Flags=%08"
|
|
|
|
PRIxGRUB_UINT32_T "\n",
|
|
|
|
t->lapic_addr, t->flags);
|
|
|
|
len = t->hdr.length - sizeof (struct grub_acpi_madt);
|
|
|
|
d = t->entries;
|
|
|
|
for (;len > 0; len -= d->len, d = (void *) ((grub_uint8_t *) d + d->len))
|
|
|
|
{
|
|
|
|
grub_printf (" type=%x l=%u ", d->type, d->len);
|
|
|
|
|
|
|
|
switch (d->type)
|
|
|
|
{
|
|
|
|
case GRUB_ACPI_MADT_ENTRY_TYPE_INTERRUPT_OVERRIDE:
|
|
|
|
{
|
|
|
|
struct grub_acpi_madt_entry_interrupt_override *dt = (void *) d;
|
|
|
|
grub_printf ("Int Override bus=%x src=%x GSI=%08x Flags=%04x\n",
|
|
|
|
dt->bus, dt->source, dt->global_sys_interrupt,
|
|
|
|
dt->flags);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case GRUB_ACPI_MADT_ENTRY_TYPE_SAPIC:
|
|
|
|
{
|
|
|
|
struct grub_acpi_madt_entry_sapic *dt = (void *) d;
|
|
|
|
grub_printf ("IOSAPIC Id=%02x GSI=%08x Addr=%016" PRIxGRUB_UINT64_T
|
|
|
|
"\n",
|
|
|
|
dt->id, dt->global_sys_interrupt_base,
|
|
|
|
dt->addr);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case GRUB_ACPI_MADT_ENTRY_TYPE_LSAPIC:
|
|
|
|
{
|
|
|
|
struct grub_acpi_madt_entry_lsapic *dt = (void *) d;
|
|
|
|
grub_printf ("LSAPIC ProcId=%02x ID=%02x EID=%02x Flags=%x",
|
|
|
|
dt->cpu_id, dt->id, dt->eid, dt->flags);
|
|
|
|
if (dt->flags & GRUB_ACPI_MADT_ENTRY_SAPIC_FLAGS_ENABLED)
|
|
|
|
grub_printf (" Enabled\n");
|
|
|
|
else
|
|
|
|
grub_printf (" Disabled\n");
|
|
|
|
if (d->len > sizeof (struct grub_acpi_madt_entry_sapic))
|
|
|
|
grub_printf (" UID val=%08x, Str=%s\n", dt->cpu_uid,
|
|
|
|
dt->cpu_uid_str);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case GRUB_ACPI_MADT_ENTRY_TYPE_PLATFORM_INT_SOURCE:
|
|
|
|
{
|
|
|
|
struct grub_acpi_madt_entry_platform_int_source *dt = (void *) d;
|
|
|
|
static const char * const platint_type[] =
|
|
|
|
{"Nul", "PMI", "INIT", "CPEI"};
|
|
|
|
|
|
|
|
grub_printf ("Platform INT flags=%04x type=%02x (%s)"
|
|
|
|
" ID=%02x EID=%02x\n",
|
|
|
|
dt->flags, dt->inttype,
|
|
|
|
(dt->inttype < ARRAY_SIZE (platint_type))
|
|
|
|
? platint_type[dt->inttype] : "??", dt->cpu_id,
|
|
|
|
dt->cpu_eid);
|
|
|
|
grub_printf (" IOSAPIC Vec=%02x GSI=%08x source flags=%08x\n",
|
|
|
|
dt->sapic_vector, dt->global_sys_int, dt->src_flags);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
grub_printf (" ??\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
disp_acpi_xsdt_table (struct grub_acpi_table_header *t)
|
|
|
|
{
|
|
|
|
grub_uint32_t len;
|
|
|
|
grub_uint64_t *desc;
|
|
|
|
|
|
|
|
disp_acpi_table (t);
|
|
|
|
len = t->length - sizeof (*t);
|
|
|
|
desc = (grub_uint64_t *) (t + 1);
|
2012-02-24 10:48:07 +00:00
|
|
|
for (; len >= sizeof (*desc); desc++, len -= sizeof (*desc))
|
2010-08-31 23:05:32 +00:00
|
|
|
{
|
2012-02-09 22:48:34 +00:00
|
|
|
#if GRUB_CPU_SIZEOF_VOID_P == 4
|
|
|
|
if (*desc >= (1ULL << 32))
|
2010-08-31 23:05:32 +00:00
|
|
|
{
|
|
|
|
grub_printf ("Unreachable table\n");
|
|
|
|
continue;
|
|
|
|
}
|
2012-02-09 22:48:34 +00:00
|
|
|
#endif
|
2010-08-31 23:05:32 +00:00
|
|
|
t = (struct grub_acpi_table_header *) (grub_addr_t) *desc;
|
|
|
|
|
|
|
|
if (t == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (grub_memcmp (t->signature, GRUB_ACPI_MADT_SIGNATURE,
|
|
|
|
sizeof (t->signature)) == 0)
|
|
|
|
disp_madt_table ((struct grub_acpi_madt *) t);
|
|
|
|
else
|
|
|
|
disp_acpi_table (t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
disp_acpi_rsdt_table (struct grub_acpi_table_header *t)
|
|
|
|
{
|
|
|
|
grub_uint32_t len;
|
|
|
|
grub_uint32_t *desc;
|
|
|
|
|
|
|
|
disp_acpi_table (t);
|
|
|
|
len = t->length - sizeof (*t);
|
|
|
|
desc = (grub_uint32_t *) (t + 1);
|
2012-02-24 10:48:07 +00:00
|
|
|
for (; len >= sizeof (*desc); desc++, len -= sizeof (*desc))
|
2010-08-31 23:05:32 +00:00
|
|
|
{
|
|
|
|
t = (struct grub_acpi_table_header *) (grub_addr_t) *desc;
|
|
|
|
|
|
|
|
if (t == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (grub_memcmp (t->signature, GRUB_ACPI_MADT_SIGNATURE,
|
|
|
|
sizeof (t->signature)) == 0)
|
|
|
|
disp_madt_table ((struct grub_acpi_madt *) t);
|
|
|
|
else
|
|
|
|
disp_acpi_table (t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
disp_acpi_rsdpv1 (struct grub_acpi_rsdp_v10 *rsdp)
|
|
|
|
{
|
|
|
|
print_field (rsdp->signature);
|
|
|
|
grub_printf ("chksum:%02x, OEM-ID: ", rsdp->checksum);
|
|
|
|
print_field (rsdp->oemid);
|
|
|
|
grub_printf ("rev=%d\n", rsdp->revision);
|
|
|
|
grub_printf ("RSDT=%08" PRIxGRUB_UINT32_T "\n", rsdp->rsdt_addr);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
disp_acpi_rsdpv2 (struct grub_acpi_rsdp_v20 *rsdp)
|
|
|
|
{
|
|
|
|
disp_acpi_rsdpv1 (&rsdp->rsdpv1);
|
|
|
|
grub_printf ("len=%d XSDT=%016" PRIxGRUB_UINT64_T "\n", rsdp->length,
|
|
|
|
rsdp->xsdt_addr);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct grub_arg_option options[] = {
|
2012-02-26 16:28:05 +00:00
|
|
|
{"v1", '1', 0, N_("Show version 1 tables only."), 0, ARG_TYPE_NONE},
|
|
|
|
{"v2", '2', 0, N_("Show version 2 and version 3 tables only."), 0, ARG_TYPE_NONE}
|
2010-08-31 23:05:32 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static grub_err_t
|
2010-09-11 18:08:37 +00:00
|
|
|
grub_cmd_lsacpi (struct grub_extcmd_context *ctxt,
|
|
|
|
int argc __attribute__ ((unused)),
|
2010-08-31 23:05:32 +00:00
|
|
|
char **args __attribute__ ((unused)))
|
|
|
|
{
|
2010-09-11 18:08:37 +00:00
|
|
|
if (!ctxt->state[1].set)
|
2010-08-31 23:05:32 +00:00
|
|
|
{
|
|
|
|
struct grub_acpi_rsdp_v10 *rsdp1 = grub_acpi_get_rsdpv1 ();
|
|
|
|
if (!rsdp1)
|
|
|
|
grub_printf ("No RSDPv1\n");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
grub_printf ("RSDPv1 signature:");
|
|
|
|
disp_acpi_rsdpv1 (rsdp1);
|
|
|
|
disp_acpi_rsdt_table ((void *) (grub_addr_t) rsdp1->rsdt_addr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-11 18:08:37 +00:00
|
|
|
if (!ctxt->state[0].set)
|
2010-08-31 23:05:32 +00:00
|
|
|
{
|
|
|
|
struct grub_acpi_rsdp_v20 *rsdp2 = grub_acpi_get_rsdpv2 ();
|
|
|
|
if (!rsdp2)
|
|
|
|
grub_printf ("No RSDPv2\n");
|
|
|
|
else
|
|
|
|
{
|
2012-02-09 22:48:34 +00:00
|
|
|
#if GRUB_CPU_SIZEOF_VOID_P == 4
|
|
|
|
if (rsdp2->xsdt_addr >= (1ULL << 32))
|
|
|
|
grub_printf ("Unreachable RSDPv2\n");
|
2010-08-31 23:05:32 +00:00
|
|
|
else
|
2012-02-09 22:48:34 +00:00
|
|
|
#endif
|
2010-08-31 23:05:32 +00:00
|
|
|
{
|
|
|
|
grub_printf ("RSDPv2 signature:");
|
|
|
|
disp_acpi_rsdpv2 (rsdp2);
|
|
|
|
disp_acpi_xsdt_table ((void *) (grub_addr_t) rsdp2->xsdt_addr);
|
|
|
|
grub_printf ("\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return GRUB_ERR_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static grub_extcmd_t cmd;
|
|
|
|
|
|
|
|
GRUB_MOD_INIT(lsapi)
|
|
|
|
{
|
2012-02-05 10:23:47 +00:00
|
|
|
cmd = grub_register_extcmd ("lsacpi", grub_cmd_lsacpi, 0, "[-1|-2]",
|
2010-08-31 23:05:32 +00:00
|
|
|
N_("Show ACPI information."), options);
|
|
|
|
}
|
|
|
|
|
|
|
|
GRUB_MOD_FINI(lsacpi)
|
|
|
|
{
|
|
|
|
grub_unregister_extcmd (cmd);
|
|
|
|
}
|
|
|
|
|
|
|
|
|