diff --git a/ChangeLog.gingold1 b/ChangeLog.gingold1 new file mode 100644 index 000000000..b2bef5d0c --- /dev/null +++ b/ChangeLog.gingold1 @@ -0,0 +1,17 @@ +2008-01-28 Tristan Gingold +2010-01-18 Robert Millan +2010-08-31 Vladimir Serbinenko + + * commands/lsacpi.c: New file. + * grub-core/Makefile.core.def (lsacpi): New module. + * include/grub/acpi.h (GRUB_ACPI_FADT_SIGNATURE): New definition. + (GRUB_ACPI_MADT_SIGNATURE): Likewise. + (grub_acpi_madt_entry_header): New struct. + (grub_acpi_madt): Likewise. + (grub_acpi_madt_entry_interrupt_override): Likewise. + (grub_acpi_madt_entry_sapic): Likewise. + (grub_acpi_madt_entry_lsapic): Likewise. + (grub_acpi_madt_entry_platform_int_source): Likewise. + * include/grub/types.h (PRIxGRUB_UINT32_T): New definition. + (PRIuGRUB_UINT32_T): Likewise. + (PRIxGRUB_UINT64_T): Likewise. diff --git a/ChangeLog.ia64 b/ChangeLog.ia64 index 453cbd88c..38325aa53 100644 --- a/ChangeLog.ia64 +++ b/ChangeLog.ia64 @@ -15,7 +15,6 @@ * conf/ia64-efi.rmk: New file. * commands/efi/systab.c: New file. * commands/efi/memmap.c: New file. - * commands/efi/acpi.c: New file. * include/grub/efi/efi.h: Declare grub_efi_allocate_boot_pages and grub_efi_free_boot_pages. * include/grub/kernel.h: Export grub_machine_fini. diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 9e84af283..2b012a7a9 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -414,7 +414,7 @@ module = { module = { name = acpi; - x86 = commands/acpi.c; + common = commands/acpi.c; efi = commands/efi/acpi.c; i386_pc = commands/i386/pc/acpi.c; i386_coreboot = commands/i386/pc/acpi.c; @@ -426,6 +426,17 @@ module = { enable = i386_multiboot; }; +module = { + name = lsacpi; + + common = commands/lsacpi.c; + + enable = x86_efi; + enable = i386_pc; + enable = i386_coreboot; + enable = i386_multiboot; +}; + module = { name = blocklist; common = commands/blocklist.c; diff --git a/grub-core/commands/acpi.c b/grub-core/commands/acpi.c index 884ddf000..016e6fd9c 100644 --- a/grub-core/commands/acpi.c +++ b/grub-core/commands/acpi.c @@ -325,7 +325,7 @@ setup_common_tables (void) /* If it's FADT correct DSDT and FACS addresses. */ fadt = (struct grub_acpi_fadt *) cur->addr; - if (grub_memcmp (fadt->hdr.signature, "FACP", + if (grub_memcmp (fadt->hdr.signature, GRUB_ACPI_FADT_SIGNATURE, sizeof (fadt->hdr.signature)) == 0) { fadt->dsdt_addr = PTR_TO_UINT32 (table_dsdt); @@ -529,7 +529,7 @@ grub_cmd_acpi (struct grub_extcmd *cmd, struct grub_acpi_fadt *fadt = (struct grub_acpi_fadt *) curtable; /* Set root header variables to the same values - as FACP by default. */ + as FADT by default. */ grub_memcpy (&root_oemid, &(fadt->hdr.oemid), sizeof (root_oemid)); grub_memcpy (&root_oemtable, &(fadt->hdr.oemtable), diff --git a/grub-core/commands/efi/acpi2.c b/grub-core/commands/efi/acpi2.c deleted file mode 100644 index e65fa0702..000000000 --- a/grub-core/commands/efi/acpi2.c +++ /dev/null @@ -1,190 +0,0 @@ -/* 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 . - */ -#include -#include -#include -#include - -static grub_uint32_t read16 (grub_uint8_t *p) -{ - return grub_le_to_cpu16 (*(grub_uint16_t *)p); -} - -static grub_uint32_t read32 (grub_uint8_t *p) -{ - return grub_le_to_cpu32 (*(grub_uint32_t *)p); -} - -static grub_uint64_t read64 (grub_uint8_t *p) -{ - return grub_le_to_cpu64 (*(grub_uint64_t *)p); -} - -static void -disp_acpi_table (grub_uint8_t *t) -{ - int i; - grub_printf ("%c%c%c%c %4dB rev=%d OEM=", t[0], t[1], t[2], t[3], - read32 (t + 4), t[8]); - for (i = 0; i < 6; i++) - grub_printf ("%c", t[10 + i]); - grub_printf (" "); - for (i = 0; i < 8; i++) - grub_printf ("%c", t[16 + i]); - grub_printf (" V=%08lx ", read32 (t + 24)); - for (i = 0; i < 4; i++) - grub_printf ("%c", t[28 + i]); - grub_printf (" %08lx\n", read32 (t + 32)); - -} - -static void -disp_acpi_apic_table (grub_uint8_t *t) -{ - grub_uint8_t *d; - grub_uint32_t len; - grub_uint32_t flags; - - disp_acpi_table (t); - grub_printf ("Local APIC=%08lx Flags=%08lx\n", - read32 (t + 36), read32 (t + 40)); - len = read32 (t + 4); - len -= 44; - d = t + 44; - while (len > 0) - { - grub_uint32_t l = d[1]; - grub_printf (" type=%x l=%d ", d[0], l); - - switch (d[0]) - { - case 2: - grub_printf ("Int Override bus=%x src=%x GSI=%08x Flags=%04x", - d[2], d[3], read32 (d + 4), read16 (d + 8)); - break; - case 6: - grub_printf ("IOSAPIC Id=%02x GSI=%08x Addr=%016llx", - d[2], read32 (d + 4), read64 (d + 8)); - break; - case 7: - flags = read32 (d + 8); - grub_printf ("LSAPIC ProcId=%02x ID=%02x EID=%02x Flags=%x", - d[2], d[3], d[4], flags); - if (flags & 1) - grub_printf (" Enabled"); - else - grub_printf (" Disabled"); - if (l >= 17) - grub_printf ("\n" - " UID val=%08x, Str=%s", read32 (d + 12), d + 16); - break; - case 8: - grub_printf ("Platform INT flags=%04x type=%02x (", - read16 (d + 2), d[4]); - if (d[4] <= 3) - { - static const char * const platint_type[4] = - {"Nul", "PMI", "INIT", "CPEI"}; - grub_printf ("%s", platint_type[d[4]]); - } - else - grub_printf ("??"); - grub_printf (") ID=%02x EID=%02x\n", d[5], d[6]); - grub_printf (" IOSAPIC Vec=%02x GSI=%08x source flags=%08x", - d[7], read32 (d + 8), read32 (d + 12)); - break; - default: - grub_printf (" ??"); - } - grub_printf ("\n"); - d += l; - len -= l; - } -} - -static void -disp_acpi_xsdt_table (grub_uint8_t *t) -{ - grub_uint32_t len; - grub_uint8_t *desc; - - disp_acpi_table (t); - len = read32 (t + 4) - 36; - desc = t + 36; - while (len > 0) - { - t = read64 (desc); - - if (t[0] == 'A' && t[1] == 'P' && t[2] == 'I' && t[3] == 'C') - disp_acpi_apic_table (t); - else - disp_acpi_table (t); - desc += 8; - len -= 8; - } -} - -static void -disp_acpi_rsdt_table (grub_uint8_t *t) -{ - grub_uint32_t len; - grub_uint8_t *desc; - - disp_acpi_table (t); - len = read32 (t + 4) - 36; - desc = t + 36; - while (len > 0) - { - t = read32 (desc); - - if (t != NULL) - disp_acpi_table (t); - desc += 4; - len -= 4; - } -} - -void -disp_acpi_rsdp_table (grub_uint8_t *rsdp) -{ - grub_uint8_t *t = rsdp; - int i; - grub_uint8_t *xsdt; - - grub_printf ("RSDP signature:"); - for (i = 0; i < 8; i++) - grub_printf ("%c", t[i]); - grub_printf (" chksum:%02x, OEM-ID: ", t[8]); - for (i = 0; i < 6; i++) - grub_printf ("%c", t[9 + i]); - grub_printf (" rev=%d\n", t[15]); - grub_printf ("RSDT=%08lx", read32 (t + 16)); - if (t[15] == 2) - { - xsdt = read64 (t + 24); - grub_printf (" len=%d XSDT=%016llx\n", read32 (t + 20), xsdt); - grub_printf ("\n"); - disp_acpi_xsdt_table (xsdt); - } - else - { - grub_printf ("\n"); - disp_acpi_rsdt_table (read32 (t + 16)); - } -} diff --git a/grub-core/commands/efi/systab.c b/grub-core/commands/efi/systab.c index 27a2cde83..66677a190 100644 --- a/grub-core/commands/efi/systab.c +++ b/grub-core/commands/efi/systab.c @@ -148,7 +148,7 @@ disp_sal (struct guid_mapping *map, void *table) static void disp_acpi (struct guid_mapping *map, void *table) { - disp_acpi_rsdp_table (table); + grub_printf ("For more information use lsacpi\n"); } static void diff --git a/grub-core/commands/lsacpi.c b/grub-core/commands/lsacpi.c new file mode 100644 index 000000000..d20b80fed --- /dev/null +++ b/grub-core/commands/lsacpi.c @@ -0,0 +1,250 @@ +/* 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 . + */ +#include +#include +#include +#include +#include +#include +#include +#include + +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); + for (; len > 0; desc++, len -= sizeof (*desc)) + { + if (sizeof (grub_addr_t) == 4 && *desc >= (1ULL << 32)) + { + grub_printf ("Unreachable table\n"); + continue; + } + 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); + for (; len > 0; desc++, len -= sizeof (*desc)) + { + 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[] = { + {"v1", '1', 0, N_("Show v1 tables only."), 0, ARG_TYPE_NONE}, + {"v2", '2', 0, N_("Show v2 and v3 tablesv only."), 0, ARG_TYPE_NONE} +}; + +static grub_err_t +grub_cmd_lsacpi (struct grub_extcmd *cmd, int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + if (!cmd->state[1].set) + { + 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); + } + } + + if (!cmd->state[0].set) + { + struct grub_acpi_rsdp_v20 *rsdp2 = grub_acpi_get_rsdpv2 (); + if (!rsdp2) + grub_printf ("No RSDPv2\n"); + else + { + if (sizeof (grub_addr_t) == 4 && rsdp2->xsdt_addr >= (1ULL << 32)) + grub_printf ("Unreachable RSDPv2\n"); + else + { + 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) +{ + cmd = grub_register_extcmd ("lsacpi", grub_cmd_lsacpi, GRUB_COMMAND_FLAG_BOTH, + N_("[-1|-2]"), + N_("Show ACPI information."), options); +} + +GRUB_MOD_FINI(lsacpi) +{ + grub_unregister_extcmd (cmd); +} + + diff --git a/include/grub/acpi.h b/include/grub/acpi.h index 7933db824..17ffd7686 100644 --- a/include/grub/acpi.h +++ b/include/grub/acpi.h @@ -53,6 +53,8 @@ struct grub_acpi_table_header grub_uint32_t creator_rev; } __attribute__ ((packed)); +#define GRUB_ACPI_FADT_SIGNATURE "FACP" + struct grub_acpi_fadt { struct grub_acpi_table_header hdr; @@ -64,6 +66,77 @@ struct grub_acpi_fadt grub_uint8_t somefields2[96]; } __attribute__ ((packed)); +#define GRUB_ACPI_MADT_SIGNATURE "APIC" + +struct grub_acpi_madt_entry_header +{ + grub_uint8_t type; + grub_uint8_t len; +}; + +struct grub_acpi_madt +{ + struct grub_acpi_table_header hdr; + grub_uint32_t lapic_addr; + grub_uint32_t flags; + struct grub_acpi_madt_entry_header entries[0]; +}; + +enum + { + GRUB_ACPI_MADT_ENTRY_TYPE_INTERRUPT_OVERRIDE = 2, + GRUB_ACPI_MADT_ENTRY_TYPE_SAPIC = 6, + GRUB_ACPI_MADT_ENTRY_TYPE_LSAPIC = 7, + GRUB_ACPI_MADT_ENTRY_TYPE_PLATFORM_INT_SOURCE = 8 + }; + +struct grub_acpi_madt_entry_interrupt_override +{ + struct grub_acpi_madt_entry_header hdr; + grub_uint8_t bus; + grub_uint8_t source; + grub_uint32_t global_sys_interrupt; + grub_uint16_t flags; +}; + +struct grub_acpi_madt_entry_sapic +{ + struct grub_acpi_madt_entry_header hdr; + grub_uint8_t id; + grub_uint8_t pad; + grub_uint32_t global_sys_interrupt_base; + grub_uint64_t addr; +}; + +struct grub_acpi_madt_entry_lsapic +{ + struct grub_acpi_madt_entry_header hdr; + grub_uint8_t cpu_id; + grub_uint8_t id; + grub_uint8_t eid; + grub_uint8_t pad[3]; + grub_uint32_t flags; + grub_uint32_t cpu_uid; + grub_uint8_t cpu_uid_str[0]; +}; + +struct grub_acpi_madt_entry_platform_int_source +{ + struct grub_acpi_madt_entry_header hdr; + grub_uint16_t flags; + grub_uint8_t inttype; + grub_uint8_t cpu_id; + grub_uint8_t cpu_eid; + grub_uint8_t sapic_vector; + grub_uint32_t global_sys_int; + grub_uint32_t src_flags; +}; + +enum + { + GRUB_ACPI_MADT_ENTRY_SAPIC_FLAGS_ENABLED = 1 + }; + struct grub_acpi_rsdp_v10 *grub_acpi_get_rsdpv1 (void); struct grub_acpi_rsdp_v20 *grub_acpi_get_rsdpv2 (void); struct grub_acpi_rsdp_v10 *grub_machine_acpi_get_rsdpv1 (void); diff --git a/include/grub/types.h b/include/grub/types.h index 4499e4538..1cabc2ecf 100644 --- a/include/grub/types.h +++ b/include/grub/types.h @@ -69,10 +69,14 @@ typedef long long grub_int64_t; typedef unsigned char grub_uint8_t; typedef unsigned short grub_uint16_t; typedef unsigned grub_uint32_t; +# define PRIxGRUB_UINT32_T "x" +# define PRIuGRUB_UINT32_T "u" #if GRUB_CPU_SIZEOF_LONG == 8 typedef unsigned long grub_uint64_t; +# define PRIxGRUB_UINT64_T "lx" #else typedef unsigned long long grub_uint64_t; +# define PRIxGRUB_UINT64_T "llx" #endif /* Misc types. */