1 /* acpi.c - Display acpi tables. */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2008 Free Software Foundation, Inc.
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
19 #include <grub/types.h>
21 #include <grub/misc.h>
22 #include <grub/normal.h>
23 #include <grub/acpi.h>
24 #include <grub/extcmd.h>
25 #include <grub/i18n.h>
28 #pragma GCC diagnostic ignored "-Wcast-align"
30 GRUB_MOD_LICENSE ("GPLv3+");
33 print_strn (grub_uint8_t
*str
, grub_size_t len
)
35 for (; *str
&& len
; str
++, len
--)
36 grub_printf ("%c", *str
);
37 for (len
++; len
; len
--)
41 #define print_field(x) print_strn(x, sizeof (x))
44 disp_acpi_table (struct grub_acpi_table_header
*t
)
46 print_field (t
->signature
);
47 grub_printf ("%4" PRIuGRUB_UINT32_T
"B rev=%u chksum=0x%02x (%s) OEM=", t
->length
, t
->revision
, t
->checksum
,
48 grub_byte_checksum (t
, t
->length
) == 0 ? "valid" : "invalid");
49 print_field (t
->oemid
);
50 print_field (t
->oemtable
);
51 grub_printf ("OEMrev=%08" PRIxGRUB_UINT32_T
" ", t
->oemrev
);
52 print_field (t
->creator_id
);
53 grub_printf (" %08" PRIxGRUB_UINT32_T
"\n", t
->creator_rev
);
57 disp_madt_table (struct grub_acpi_madt
*t
)
59 struct grub_acpi_madt_entry_header
*d
;
62 disp_acpi_table (&t
->hdr
);
63 grub_printf ("Local APIC=%08" PRIxGRUB_UINT32_T
" Flags=%08"
64 PRIxGRUB_UINT32_T
"\n",
65 t
->lapic_addr
, t
->flags
);
66 len
= t
->hdr
.length
- sizeof (struct grub_acpi_madt
);
68 for (;len
> 0; len
-= d
->len
, d
= (void *) ((grub_uint8_t
*) d
+ d
->len
))
72 case GRUB_ACPI_MADT_ENTRY_TYPE_LAPIC
:
74 struct grub_acpi_madt_entry_lapic
*dt
= (void *) d
;
75 grub_printf (" LAPIC ACPI_ID=%02x APIC_ID=%02x Flags=%08x\n",
76 dt
->acpiid
, dt
->apicid
, dt
->flags
);
77 if (dt
->hdr
.len
!= sizeof (*dt
))
78 grub_printf (" table size mismatch %d != %d\n", dt
->hdr
.len
,
83 case GRUB_ACPI_MADT_ENTRY_TYPE_IOAPIC
:
85 struct grub_acpi_madt_entry_ioapic
*dt
= (void *) d
;
86 grub_printf (" IOAPIC ID=%02x address=%08x GSI=%08x\n",
87 dt
->id
, dt
->address
, dt
->global_sys_interrupt
);
88 if (dt
->hdr
.len
!= sizeof (*dt
))
89 grub_printf (" table size mismatch %d != %d\n", dt
->hdr
.len
,
92 grub_printf (" non-zero pad: %02x\n", dt
->pad
);
96 case GRUB_ACPI_MADT_ENTRY_TYPE_INTERRUPT_OVERRIDE
:
98 struct grub_acpi_madt_entry_interrupt_override
*dt
= (void *) d
;
99 grub_printf (" Int Override bus=%x src=%x GSI=%08x Flags=%04x\n",
100 dt
->bus
, dt
->source
, dt
->global_sys_interrupt
,
102 if (dt
->hdr
.len
!= sizeof (*dt
))
103 grub_printf (" table size mismatch %d != %d\n", dt
->hdr
.len
,
108 case GRUB_ACPI_MADT_ENTRY_TYPE_LAPIC_NMI
:
110 struct grub_acpi_madt_entry_lapic_nmi
*dt
= (void *) d
;
111 grub_printf (" LAPIC_NMI ACPI_ID=%02x Flags=%04x lint=%02x\n",
112 dt
->acpiid
, dt
->flags
, dt
->lint
);
113 if (dt
->hdr
.len
!= sizeof (*dt
))
114 grub_printf (" table size mismatch %d != %d\n", dt
->hdr
.len
,
119 case GRUB_ACPI_MADT_ENTRY_TYPE_SAPIC
:
121 struct grub_acpi_madt_entry_sapic
*dt
= (void *) d
;
122 grub_printf (" IOSAPIC Id=%02x GSI=%08x Addr=%016" PRIxGRUB_UINT64_T
124 dt
->id
, dt
->global_sys_interrupt_base
,
126 if (dt
->hdr
.len
!= sizeof (*dt
))
127 grub_printf (" table size mismatch %d != %d\n", dt
->hdr
.len
,
130 grub_printf (" non-zero pad: %02x\n", dt
->pad
);
134 case GRUB_ACPI_MADT_ENTRY_TYPE_LSAPIC
:
136 struct grub_acpi_madt_entry_lsapic
*dt
= (void *) d
;
137 grub_printf (" LSAPIC ProcId=%02x ID=%02x EID=%02x Flags=%x",
138 dt
->cpu_id
, dt
->id
, dt
->eid
, dt
->flags
);
139 if (dt
->flags
& GRUB_ACPI_MADT_ENTRY_SAPIC_FLAGS_ENABLED
)
140 grub_printf (" Enabled\n");
142 grub_printf (" Disabled\n");
143 if (d
->len
> sizeof (struct grub_acpi_madt_entry_sapic
))
144 grub_printf (" UID val=%08x, Str=%s\n", dt
->cpu_uid
,
146 if (dt
->hdr
.len
!= sizeof (*dt
) + grub_strlen ((char *) dt
->cpu_uid_str
) + 1)
147 grub_printf (" table size mismatch %d != %d\n", dt
->hdr
.len
,
149 if (dt
->pad
[0] || dt
->pad
[1] || dt
->pad
[2])
150 grub_printf (" non-zero pad: %02x%02x%02x\n", dt
->pad
[0], dt
->pad
[1], dt
->pad
[2]);
153 case GRUB_ACPI_MADT_ENTRY_TYPE_PLATFORM_INT_SOURCE
:
155 struct grub_acpi_madt_entry_platform_int_source
*dt
= (void *) d
;
156 static const char * const platint_type
[] =
157 {"Nul", "PMI", "INIT", "CPEI"};
159 grub_printf (" Platform INT flags=%04x type=%02x (%s)"
160 " ID=%02x EID=%02x\n",
161 dt
->flags
, dt
->inttype
,
162 (dt
->inttype
< ARRAY_SIZE (platint_type
))
163 ? platint_type
[dt
->inttype
] : "??", dt
->cpu_id
,
165 grub_printf (" IOSAPIC Vec=%02x GSI=%08x source flags=%08x\n",
166 dt
->sapic_vector
, dt
->global_sys_int
, dt
->src_flags
);
170 grub_printf (" type=%x l=%u ", d
->type
, d
->len
);
171 grub_printf (" ??\n");
177 disp_acpi_xsdt_table (struct grub_acpi_table_header
*t
)
183 len
= t
->length
- sizeof (*t
);
184 desc
= (grub_uint64_t
*) (t
+ 1);
185 for (; len
>= sizeof (*desc
); desc
++, len
-= sizeof (*desc
))
187 #if GRUB_CPU_SIZEOF_VOID_P == 4
188 if (*desc
>= (1ULL << 32))
190 grub_printf ("Unreachable table\n");
194 t
= (struct grub_acpi_table_header
*) (grub_addr_t
) *desc
;
199 if (grub_memcmp (t
->signature
, GRUB_ACPI_MADT_SIGNATURE
,
200 sizeof (t
->signature
)) == 0)
201 disp_madt_table ((struct grub_acpi_madt
*) t
);
208 disp_acpi_rsdt_table (struct grub_acpi_table_header
*t
)
214 len
= t
->length
- sizeof (*t
);
215 desc
= (grub_uint32_t
*) (t
+ 1);
216 for (; len
>= sizeof (*desc
); desc
++, len
-= sizeof (*desc
))
218 t
= (struct grub_acpi_table_header
*) (grub_addr_t
) *desc
;
223 if (grub_memcmp (t
->signature
, GRUB_ACPI_MADT_SIGNATURE
,
224 sizeof (t
->signature
)) == 0)
225 disp_madt_table ((struct grub_acpi_madt
*) t
);
232 disp_acpi_rsdpv1 (struct grub_acpi_rsdp_v10
*rsdp
)
234 print_field (rsdp
->signature
);
235 grub_printf ("chksum:%02x (%s), OEM-ID: ", rsdp
->checksum
, grub_byte_checksum (rsdp
, sizeof (*rsdp
)) == 0 ? "valid" : "invalid");
236 print_field (rsdp
->oemid
);
237 grub_printf ("rev=%d\n", rsdp
->revision
);
238 grub_printf ("RSDT=%08" PRIxGRUB_UINT32_T
"\n", rsdp
->rsdt_addr
);
242 disp_acpi_rsdpv2 (struct grub_acpi_rsdp_v20
*rsdp
)
244 disp_acpi_rsdpv1 (&rsdp
->rsdpv1
);
245 grub_printf ("len=%d chksum=%02x (%s) XSDT=%016" PRIxGRUB_UINT64_T
"\n", rsdp
->length
, rsdp
->checksum
, grub_byte_checksum (rsdp
, rsdp
->length
) == 0 ? "valid" : "invalid",
247 if (rsdp
->length
!= sizeof (*rsdp
))
248 grub_printf (" length mismatch %d != %d\n", rsdp
->length
,
249 (int) sizeof (*rsdp
));
250 if (rsdp
->reserved
[0] || rsdp
->reserved
[1] || rsdp
->reserved
[2])
251 grub_printf (" non-zero reserved %02x%02x%02x\n", rsdp
->reserved
[0], rsdp
->reserved
[1], rsdp
->reserved
[2]);
254 static const struct grub_arg_option options
[] = {
255 {"v1", '1', 0, N_("Show version 1 tables only."), 0, ARG_TYPE_NONE
},
256 {"v2", '2', 0, N_("Show version 2 and version 3 tables only."), 0, ARG_TYPE_NONE
},
261 grub_cmd_lsacpi (struct grub_extcmd_context
*ctxt
,
262 int argc
__attribute__ ((unused
)),
263 char **args
__attribute__ ((unused
)))
265 if (!ctxt
->state
[1].set
)
267 struct grub_acpi_rsdp_v10
*rsdp1
= grub_acpi_get_rsdpv1 ();
269 grub_printf ("No RSDPv1\n");
272 grub_printf ("RSDPv1 signature:");
273 disp_acpi_rsdpv1 (rsdp1
);
274 disp_acpi_rsdt_table ((void *) (grub_addr_t
) rsdp1
->rsdt_addr
);
278 if (!ctxt
->state
[0].set
)
280 struct grub_acpi_rsdp_v20
*rsdp2
= grub_acpi_get_rsdpv2 ();
282 grub_printf ("No RSDPv2\n");
285 #if GRUB_CPU_SIZEOF_VOID_P == 4
286 if (rsdp2
->xsdt_addr
>= (1ULL << 32))
287 grub_printf ("Unreachable RSDPv2\n");
291 grub_printf ("RSDPv2 signature:");
292 disp_acpi_rsdpv2 (rsdp2
);
293 disp_acpi_xsdt_table ((void *) (grub_addr_t
) rsdp2
->xsdt_addr
);
298 return GRUB_ERR_NONE
;
301 static grub_extcmd_t cmd
;
305 cmd
= grub_register_extcmd ("lsacpi", grub_cmd_lsacpi
, 0, "[-1|-2]",
306 N_("Show ACPI information."), options
);
309 GRUB_MOD_FINI(lsacpi
)
311 grub_unregister_extcmd (cmd
);