lsacpi.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. /* acpi.c - Display acpi tables. */
  2. /*
  3. * GRUB -- GRand Unified Bootloader
  4. * Copyright (C) 2008 Free Software Foundation, Inc.
  5. *
  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.
  10. *
  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.
  15. *
  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/>.
  18. */
  19. #include <grub/types.h>
  20. #include <grub/mm.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>
  26. #include <grub/dl.h>
  27. #pragma GCC diagnostic ignored "-Wcast-align"
  28. GRUB_MOD_LICENSE ("GPLv3+");
  29. static void
  30. print_strn (grub_uint8_t *str, grub_size_t len)
  31. {
  32. for (; *str && len; str++, len--)
  33. grub_printf ("%c", *str);
  34. for (len++; len; len--)
  35. grub_printf (" ");
  36. }
  37. #define print_field(x) print_strn(x, sizeof (x))
  38. static void
  39. disp_acpi_table (struct grub_acpi_table_header *t)
  40. {
  41. print_field (t->signature);
  42. grub_printf ("%4" PRIuGRUB_UINT32_T "B rev=%u chksum=0x%02x (%s) OEM=", t->length, t->revision, t->checksum,
  43. grub_byte_checksum (t, t->length) == 0 ? "valid" : "invalid");
  44. print_field (t->oemid);
  45. print_field (t->oemtable);
  46. grub_printf ("OEMrev=%08" PRIxGRUB_UINT32_T " ", t->oemrev);
  47. print_field (t->creator_id);
  48. grub_printf (" %08" PRIxGRUB_UINT32_T "\n", t->creator_rev);
  49. }
  50. static void
  51. disp_madt_table (struct grub_acpi_madt *t)
  52. {
  53. struct grub_acpi_madt_entry_header *d;
  54. grub_uint32_t len;
  55. disp_acpi_table (&t->hdr);
  56. grub_printf ("Local APIC=%08" PRIxGRUB_UINT32_T " Flags=%08"
  57. PRIxGRUB_UINT32_T "\n",
  58. t->lapic_addr, t->flags);
  59. len = t->hdr.length - sizeof (struct grub_acpi_madt);
  60. d = t->entries;
  61. for (;len > 0; len -= d->len, d = (void *) ((grub_uint8_t *) d + d->len))
  62. {
  63. switch (d->type)
  64. {
  65. case GRUB_ACPI_MADT_ENTRY_TYPE_LAPIC:
  66. {
  67. struct grub_acpi_madt_entry_lapic *dt = (void *) d;
  68. grub_printf (" LAPIC ACPI_ID=%02x APIC_ID=%02x Flags=%08x\n",
  69. dt->acpiid, dt->apicid, dt->flags);
  70. if (dt->hdr.len != sizeof (*dt))
  71. grub_printf (" table size mismatch %d != %d\n", dt->hdr.len,
  72. (int) sizeof (*dt));
  73. break;
  74. }
  75. case GRUB_ACPI_MADT_ENTRY_TYPE_IOAPIC:
  76. {
  77. struct grub_acpi_madt_entry_ioapic *dt = (void *) d;
  78. grub_printf (" IOAPIC ID=%02x address=%08x GSI=%08x\n",
  79. dt->id, dt->address, dt->global_sys_interrupt);
  80. if (dt->hdr.len != sizeof (*dt))
  81. grub_printf (" table size mismatch %d != %d\n", dt->hdr.len,
  82. (int) sizeof (*dt));
  83. if (dt->pad)
  84. grub_printf (" non-zero pad: %02x\n", dt->pad);
  85. break;
  86. }
  87. case GRUB_ACPI_MADT_ENTRY_TYPE_INTERRUPT_OVERRIDE:
  88. {
  89. struct grub_acpi_madt_entry_interrupt_override *dt = (void *) d;
  90. grub_printf (" Int Override bus=%x src=%x GSI=%08x Flags=%04x\n",
  91. dt->bus, dt->source, dt->global_sys_interrupt,
  92. dt->flags);
  93. if (dt->hdr.len != sizeof (*dt))
  94. grub_printf (" table size mismatch %d != %d\n", dt->hdr.len,
  95. (int) sizeof (*dt));
  96. }
  97. break;
  98. case GRUB_ACPI_MADT_ENTRY_TYPE_LAPIC_NMI:
  99. {
  100. struct grub_acpi_madt_entry_lapic_nmi *dt = (void *) d;
  101. grub_printf (" LAPIC_NMI ACPI_ID=%02x Flags=%04x lint=%02x\n",
  102. dt->acpiid, dt->flags, dt->lint);
  103. if (dt->hdr.len != sizeof (*dt))
  104. grub_printf (" table size mismatch %d != %d\n", dt->hdr.len,
  105. (int) sizeof (*dt));
  106. break;
  107. }
  108. case GRUB_ACPI_MADT_ENTRY_TYPE_SAPIC:
  109. {
  110. struct grub_acpi_madt_entry_sapic *dt = (void *) d;
  111. grub_printf (" IOSAPIC Id=%02x GSI=%08x Addr=%016" PRIxGRUB_UINT64_T
  112. "\n",
  113. dt->id, dt->global_sys_interrupt_base,
  114. dt->addr);
  115. if (dt->hdr.len != sizeof (*dt))
  116. grub_printf (" table size mismatch %d != %d\n", dt->hdr.len,
  117. (int) sizeof (*dt));
  118. if (dt->pad)
  119. grub_printf (" non-zero pad: %02x\n", dt->pad);
  120. }
  121. break;
  122. case GRUB_ACPI_MADT_ENTRY_TYPE_LSAPIC:
  123. {
  124. struct grub_acpi_madt_entry_lsapic *dt = (void *) d;
  125. grub_printf (" LSAPIC ProcId=%02x ID=%02x EID=%02x Flags=%x",
  126. dt->cpu_id, dt->id, dt->eid, dt->flags);
  127. if (dt->flags & GRUB_ACPI_MADT_ENTRY_SAPIC_FLAGS_ENABLED)
  128. grub_printf (" Enabled\n");
  129. else
  130. grub_printf (" Disabled\n");
  131. if (d->len > sizeof (struct grub_acpi_madt_entry_sapic))
  132. grub_printf (" UID val=%08x, Str=%s\n", dt->cpu_uid,
  133. dt->cpu_uid_str);
  134. if (dt->hdr.len != sizeof (*dt) + grub_strlen ((char *) dt->cpu_uid_str) + 1)
  135. grub_printf (" table size mismatch %d != %d\n", dt->hdr.len,
  136. (int) sizeof (*dt));
  137. if (dt->pad[0] || dt->pad[1] || dt->pad[2])
  138. grub_printf (" non-zero pad: %02x%02x%02x\n", dt->pad[0], dt->pad[1], dt->pad[2]);
  139. }
  140. break;
  141. case GRUB_ACPI_MADT_ENTRY_TYPE_PLATFORM_INT_SOURCE:
  142. {
  143. struct grub_acpi_madt_entry_platform_int_source *dt = (void *) d;
  144. static const char * const platint_type[] =
  145. {"Nul", "PMI", "INIT", "CPEI"};
  146. grub_printf (" Platform INT flags=%04x type=%02x (%s)"
  147. " ID=%02x EID=%02x\n",
  148. dt->flags, dt->inttype,
  149. (dt->inttype < ARRAY_SIZE (platint_type))
  150. ? platint_type[dt->inttype] : "??", dt->cpu_id,
  151. dt->cpu_eid);
  152. grub_printf (" IOSAPIC Vec=%02x GSI=%08x source flags=%08x\n",
  153. dt->sapic_vector, dt->global_sys_int, dt->src_flags);
  154. }
  155. break;
  156. default:
  157. grub_printf (" type=%x l=%u ", d->type, d->len);
  158. grub_printf (" ??\n");
  159. }
  160. }
  161. }
  162. static void
  163. disp_acpi_xsdt_table (struct grub_acpi_table_header *t)
  164. {
  165. grub_uint32_t len;
  166. grub_uint64_t *desc;
  167. disp_acpi_table (t);
  168. len = t->length - sizeof (*t);
  169. desc = (grub_uint64_t *) (t + 1);
  170. for (; len >= sizeof (*desc); desc++, len -= sizeof (*desc))
  171. {
  172. #if GRUB_CPU_SIZEOF_VOID_P == 4
  173. if (*desc >= (1ULL << 32))
  174. {
  175. grub_printf ("Unreachable table\n");
  176. continue;
  177. }
  178. #endif
  179. t = (struct grub_acpi_table_header *) (grub_addr_t) *desc;
  180. if (t == NULL)
  181. continue;
  182. if (grub_memcmp (t->signature, GRUB_ACPI_MADT_SIGNATURE,
  183. sizeof (t->signature)) == 0)
  184. disp_madt_table ((struct grub_acpi_madt *) t);
  185. else
  186. disp_acpi_table (t);
  187. }
  188. }
  189. static void
  190. disp_acpi_rsdt_table (struct grub_acpi_table_header *t)
  191. {
  192. grub_uint32_t len;
  193. grub_uint32_t *desc;
  194. disp_acpi_table (t);
  195. len = t->length - sizeof (*t);
  196. desc = (grub_uint32_t *) (t + 1);
  197. for (; len >= sizeof (*desc); desc++, len -= sizeof (*desc))
  198. {
  199. t = (struct grub_acpi_table_header *) (grub_addr_t) *desc;
  200. if (t == NULL)
  201. continue;
  202. if (grub_memcmp (t->signature, GRUB_ACPI_MADT_SIGNATURE,
  203. sizeof (t->signature)) == 0)
  204. disp_madt_table ((struct grub_acpi_madt *) t);
  205. else
  206. disp_acpi_table (t);
  207. }
  208. }
  209. static void
  210. disp_acpi_rsdpv1 (struct grub_acpi_rsdp_v10 *rsdp)
  211. {
  212. print_field (rsdp->signature);
  213. grub_printf ("chksum:%02x (%s), OEM-ID: ", rsdp->checksum, grub_byte_checksum (rsdp, sizeof (*rsdp)) == 0 ? "valid" : "invalid");
  214. print_field (rsdp->oemid);
  215. grub_printf ("rev=%d\n", rsdp->revision);
  216. grub_printf ("RSDT=%08" PRIxGRUB_UINT32_T "\n", rsdp->rsdt_addr);
  217. }
  218. static void
  219. disp_acpi_rsdpv2 (struct grub_acpi_rsdp_v20 *rsdp)
  220. {
  221. disp_acpi_rsdpv1 (&rsdp->rsdpv1);
  222. 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",
  223. rsdp->xsdt_addr);
  224. if (rsdp->length != sizeof (*rsdp))
  225. grub_printf (" length mismatch %d != %d\n", rsdp->length,
  226. (int) sizeof (*rsdp));
  227. if (rsdp->reserved[0] || rsdp->reserved[1] || rsdp->reserved[2])
  228. grub_printf (" non-zero reserved %02x%02x%02x\n", rsdp->reserved[0], rsdp->reserved[1], rsdp->reserved[2]);
  229. }
  230. static const struct grub_arg_option options[] = {
  231. {"v1", '1', 0, N_("Show version 1 tables only."), 0, ARG_TYPE_NONE},
  232. {"v2", '2', 0, N_("Show version 2 and version 3 tables only."), 0, ARG_TYPE_NONE},
  233. {0, 0, 0, 0, 0, 0}
  234. };
  235. static grub_err_t
  236. grub_cmd_lsacpi (struct grub_extcmd_context *ctxt,
  237. int argc __attribute__ ((unused)),
  238. char **args __attribute__ ((unused)))
  239. {
  240. if (!ctxt->state[1].set)
  241. {
  242. struct grub_acpi_rsdp_v10 *rsdp1 = grub_acpi_get_rsdpv1 ();
  243. if (!rsdp1)
  244. grub_printf ("No RSDPv1\n");
  245. else
  246. {
  247. grub_printf ("RSDPv1 signature:");
  248. disp_acpi_rsdpv1 (rsdp1);
  249. disp_acpi_rsdt_table ((void *) (grub_addr_t) rsdp1->rsdt_addr);
  250. }
  251. }
  252. if (!ctxt->state[0].set)
  253. {
  254. struct grub_acpi_rsdp_v20 *rsdp2 = grub_acpi_get_rsdpv2 ();
  255. if (!rsdp2)
  256. grub_printf ("No RSDPv2\n");
  257. else
  258. {
  259. #if GRUB_CPU_SIZEOF_VOID_P == 4
  260. if (rsdp2->xsdt_addr >= (1ULL << 32))
  261. grub_printf ("Unreachable RSDPv2\n");
  262. else
  263. #endif
  264. {
  265. grub_printf ("RSDPv2 signature:");
  266. disp_acpi_rsdpv2 (rsdp2);
  267. disp_acpi_xsdt_table ((void *) (grub_addr_t) rsdp2->xsdt_addr);
  268. grub_printf ("\n");
  269. }
  270. }
  271. }
  272. return GRUB_ERR_NONE;
  273. }
  274. static grub_extcmd_t cmd;
  275. GRUB_MOD_INIT(lsapi)
  276. {
  277. cmd = grub_register_extcmd ("lsacpi", grub_cmd_lsacpi, 0, "[-1|-2]",
  278. N_("Show ACPI information."), options);
  279. }
  280. GRUB_MOD_FINI(lsacpi)
  281. {
  282. grub_unregister_extcmd (cmd);
  283. }