FadtParser.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. /** @file
  2. FADT table parser
  3. Copyright (c) 2016 - 2020, ARM Limited. All rights reserved.
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. @par Reference(s):
  6. - ACPI 6.3 Specification - January 2019
  7. **/
  8. #include <IndustryStandard/Acpi.h>
  9. #include <Library/UefiLib.h>
  10. #include "AcpiParser.h"
  11. #include "AcpiTableParser.h"
  12. #include "AcpiView.h"
  13. // Local variables
  14. STATIC CONST UINT32 *DsdtAddress;
  15. STATIC CONST UINT64 *X_DsdtAddress;
  16. STATIC CONST UINT32 *Flags;
  17. STATIC CONST UINT32 *FirmwareCtrl;
  18. STATIC CONST UINT64 *X_FirmwareCtrl;
  19. STATIC CONST UINT8 *FadtMinorRevision;
  20. STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;
  21. /**
  22. A macro defining the Hardware reduced ACPI flag
  23. **/
  24. #define HW_REDUCED_ACPI BIT20
  25. /**
  26. Offset to the FACS signature from the start of the FACS.
  27. **/
  28. #define FACS_SIGNATURE_OFFSET 0
  29. /**
  30. Offset to the FACS revision from the start of the FACS.
  31. **/
  32. #define FACS_VERSION_OFFSET 32
  33. /**
  34. Offset to the FACS length from the start of the FACS.
  35. **/
  36. #define FACS_LENGTH_OFFSET 4
  37. /**
  38. Get the ACPI XSDT header info.
  39. **/
  40. CONST ACPI_DESCRIPTION_HEADER_INFO *
  41. EFIAPI
  42. GetAcpiXsdtHeaderInfo (
  43. VOID
  44. );
  45. /**
  46. This function validates the Firmware Control Field.
  47. @param [in] Ptr Pointer to the start of the field data.
  48. @param [in] Context Pointer to context specific information e.g. this
  49. could be a pointer to the ACPI table header.
  50. **/
  51. STATIC
  52. VOID
  53. EFIAPI
  54. ValidateFirmwareCtrl (
  55. IN UINT8 *Ptr,
  56. IN VOID *Context
  57. )
  58. {
  59. #if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
  60. if (*(UINT32 *)Ptr != 0) {
  61. IncrementErrorCount ();
  62. Print (
  63. L"\nERROR: Firmware Control must be zero for ARM platforms."
  64. );
  65. }
  66. #endif
  67. }
  68. /**
  69. This function validates the X_Firmware Control Field.
  70. @param [in] Ptr Pointer to the start of the field data.
  71. @param [in] Context Pointer to context specific information e.g. this
  72. could be a pointer to the ACPI table header.
  73. **/
  74. STATIC
  75. VOID
  76. EFIAPI
  77. ValidateXFirmwareCtrl (
  78. IN UINT8 *Ptr,
  79. IN VOID *Context
  80. )
  81. {
  82. #if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
  83. if (*(UINT64 *)Ptr != 0) {
  84. IncrementErrorCount ();
  85. Print (
  86. L"\nERROR: X Firmware Control must be zero for ARM platforms."
  87. );
  88. }
  89. #endif
  90. }
  91. /**
  92. This function validates the flags.
  93. @param [in] Ptr Pointer to the start of the field data.
  94. @param [in] Context Pointer to context specific information e.g. this
  95. could be a pointer to the ACPI table header.
  96. **/
  97. STATIC
  98. VOID
  99. EFIAPI
  100. ValidateFlags (
  101. IN UINT8 *Ptr,
  102. IN VOID *Context
  103. )
  104. {
  105. #if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
  106. if (((*(UINT32 *)Ptr) & HW_REDUCED_ACPI) == 0) {
  107. IncrementErrorCount ();
  108. Print (
  109. L"\nERROR: HW_REDUCED_ACPI flag must be set for ARM platforms."
  110. );
  111. }
  112. #endif
  113. }
  114. /**
  115. An ACPI_PARSER array describing the ACPI FADT Table.
  116. **/
  117. STATIC CONST ACPI_PARSER FadtParser[] = {
  118. PARSE_ACPI_HEADER (&AcpiHdrInfo),
  119. { L"FIRMWARE_CTRL", 4, 36, L"0x%x", NULL, (VOID **)&FirmwareCtrl,
  120. ValidateFirmwareCtrl, NULL },
  121. { L"DSDT", 4, 40, L"0x%x", NULL, (VOID **)&DsdtAddress, NULL, NULL },
  122. { L"Reserved", 1, 44, L"%x", NULL, NULL, NULL, NULL },
  123. { L"Preferred_PM_Profile", 1, 45, L"0x%x", NULL, NULL, NULL, NULL },
  124. { L"SCI_INT", 2, 46, L"0x%x", NULL, NULL, NULL, NULL },
  125. { L"SMI_CMD", 4, 48, L"0x%x", NULL, NULL, NULL, NULL },
  126. { L"ACPI_ENABLE", 1, 52, L"0x%x", NULL, NULL, NULL, NULL },
  127. { L"ACPI_DISABLE", 1, 53, L"0x%x", NULL, NULL, NULL, NULL },
  128. { L"S4BIOS_REQ", 1, 54, L"0x%x", NULL, NULL, NULL, NULL },
  129. { L"PSTATE_CNT", 1, 55, L"0x%x", NULL, NULL, NULL, NULL },
  130. { L"PM1a_EVT_BLK", 4, 56, L"0x%x", NULL, NULL, NULL, NULL },
  131. { L"PM1b_EVT_BLK", 4, 60, L"0x%x", NULL, NULL, NULL, NULL },
  132. { L"PM1a_CNT_BLK", 4, 64, L"0x%x", NULL, NULL, NULL, NULL },
  133. { L"PM1b_CNT_BLK", 4, 68, L"0x%x", NULL, NULL, NULL, NULL },
  134. { L"PM2_CNT_BLK", 4, 72, L"0x%x", NULL, NULL, NULL, NULL },
  135. { L"PM_TMR_BLK", 4, 76, L"0x%x", NULL, NULL, NULL, NULL },
  136. { L"GPE0_BLK", 4, 80, L"0x%x", NULL, NULL, NULL, NULL },
  137. { L"GPE1_BLK", 4, 84, L"0x%x", NULL, NULL, NULL, NULL },
  138. { L"PM1_EVT_LEN", 1, 88, L"0x%x", NULL, NULL, NULL, NULL },
  139. { L"PM1_CNT_LEN", 1, 89, L"0x%x", NULL, NULL, NULL, NULL },
  140. { L"PM2_CNT_LEN", 1, 90, L"0x%x", NULL, NULL, NULL, NULL },
  141. { L"PM_TMR_LEN", 1, 91, L"0x%x", NULL, NULL, NULL, NULL },
  142. { L"GPE0_BLK_LEN", 1, 92, L"0x%x", NULL, NULL, NULL, NULL },
  143. { L"GPE1_BLK_LEN", 1, 93, L"0x%x", NULL, NULL, NULL, NULL },
  144. { L"GPE1_BASE", 1, 94, L"0x%x", NULL, NULL, NULL, NULL },
  145. { L"CST_CNT", 1, 95, L"0x%x", NULL, NULL, NULL, NULL },
  146. { L"P_LVL2_LAT", 2, 96, L"0x%x", NULL, NULL, NULL, NULL },
  147. { L"P_LVL3_LAT", 2, 98, L"0x%x", NULL, NULL, NULL, NULL },
  148. { L"FLUSH_SIZE", 2, 100, L"0x%x", NULL, NULL, NULL, NULL },
  149. { L"FLUSH_STRIDE", 2, 102, L"0x%x", NULL, NULL, NULL, NULL },
  150. { L"DUTY_OFFSET", 1, 104, L"0x%x", NULL, NULL, NULL, NULL },
  151. { L"DUTY_WIDTH", 1, 105, L"0x%x", NULL, NULL, NULL, NULL },
  152. { L"DAY_ALRM", 1, 106, L"0x%x", NULL, NULL, NULL, NULL },
  153. { L"MON_ALRM", 1, 107, L"0x%x", NULL, NULL, NULL, NULL },
  154. { L"CENTURY", 1, 108, L"0x%x", NULL, NULL, NULL, NULL },
  155. { L"IAPC_BOOT_ARCH", 2, 109, L"0x%x", NULL, NULL, NULL, NULL },
  156. { L"Reserved", 1, 111, L"0x%x", NULL, NULL, NULL, NULL },
  157. { L"Flags", 4, 112, L"0x%x", NULL, (VOID **)&Flags, ValidateFlags, NULL },
  158. { L"RESET_REG", 12, 116, NULL, DumpGas, NULL, NULL, NULL },
  159. { L"RESET_VALUE", 1, 128, L"0x%x", NULL, NULL, NULL, NULL },
  160. { L"ARM_BOOT_ARCH", 2, 129, L"0x%x", NULL, NULL, NULL, NULL },
  161. { L"FADT Minor Version", 1, 131, L"0x%x", NULL, (VOID **)&FadtMinorRevision,
  162. NULL, NULL },
  163. { L"X_FIRMWARE_CTRL", 8, 132, L"0x%lx", NULL, (VOID **)&X_FirmwareCtrl,
  164. ValidateXFirmwareCtrl, NULL },
  165. { L"X_DSDT", 8, 140, L"0x%lx", NULL, (VOID **)&X_DsdtAddress, NULL, NULL },
  166. { L"X_PM1a_EVT_BLK", 12, 148, NULL, DumpGas, NULL, NULL, NULL },
  167. { L"X_PM1b_EVT_BLK", 12, 160, NULL, DumpGas, NULL, NULL, NULL },
  168. { L"X_PM1a_CNT_BLK", 12, 172, NULL, DumpGas, NULL, NULL, NULL },
  169. { L"X_PM1b_CNT_BLK", 12, 184, NULL, DumpGas, NULL, NULL, NULL },
  170. { L"X_PM2_CNT_BLK", 12, 196, NULL, DumpGas, NULL, NULL, NULL },
  171. { L"X_PM_TMR_BLK", 12, 208, NULL, DumpGas, NULL, NULL, NULL },
  172. { L"X_GPE0_BLK", 12, 220, NULL, DumpGas, NULL, NULL, NULL },
  173. { L"X_GPE1_BLK", 12, 232, NULL, DumpGas, NULL, NULL, NULL },
  174. { L"SLEEP_CONTROL_REG", 12, 244, NULL, DumpGas, NULL, NULL, NULL },
  175. { L"SLEEP_STATUS_REG", 12, 256, NULL, DumpGas, NULL, NULL, NULL },
  176. { L"Hypervisor VendorIdentity", 8, 268, L"%lx", NULL, NULL, NULL, NULL }
  177. };
  178. /**
  179. This function parses the ACPI FADT table.
  180. This function parses the FADT table and optionally traces the ACPI table fields.
  181. This function also performs validation of the ACPI table fields.
  182. @param [in] Trace If TRUE, trace the ACPI fields.
  183. @param [in] Ptr Pointer to the start of the buffer.
  184. @param [in] AcpiTableLength Length of the ACPI table.
  185. @param [in] AcpiTableRevision Revision of the ACPI table.
  186. **/
  187. VOID
  188. EFIAPI
  189. ParseAcpiFadt (
  190. IN BOOLEAN Trace,
  191. IN UINT8 *Ptr,
  192. IN UINT32 AcpiTableLength,
  193. IN UINT8 AcpiTableRevision
  194. )
  195. {
  196. EFI_STATUS Status;
  197. UINT8 *DsdtPtr;
  198. UINT8 *FirmwareCtrlPtr;
  199. UINT32 FacsSignature;
  200. UINT32 FacsLength;
  201. UINT8 FacsRevision;
  202. PARSE_ACPI_TABLE_PROC FacsParserProc;
  203. ParseAcpi (
  204. Trace,
  205. 0,
  206. "FADT",
  207. Ptr,
  208. AcpiTableLength,
  209. PARSER_PARAMS (FadtParser)
  210. );
  211. if (Trace) {
  212. if (FadtMinorRevision != NULL) {
  213. Print (L"\nSummary:\n");
  214. PrintFieldName (2, L"FADT Version");
  215. Print (L"%d.%d\n", *AcpiHdrInfo.Revision, *FadtMinorRevision);
  216. }
  217. if (*GetAcpiXsdtHeaderInfo ()->OemTableId != *AcpiHdrInfo.OemTableId) {
  218. IncrementErrorCount ();
  219. Print (L"ERROR: OEM Table Id does not match with RSDT/XSDT.\n");
  220. }
  221. }
  222. // If X_FIRMWARE_CTRL is not zero then use X_FIRMWARE_CTRL and ignore
  223. // FIRMWARE_CTRL, else use FIRMWARE_CTRL.
  224. if ((X_FirmwareCtrl != NULL) && (*X_FirmwareCtrl != 0)) {
  225. FirmwareCtrlPtr = (UINT8 *)(UINTN)(*X_FirmwareCtrl);
  226. } else if ((FirmwareCtrl != NULL) && (*FirmwareCtrl != 0)) {
  227. FirmwareCtrlPtr = (UINT8 *)(UINTN)(*FirmwareCtrl);
  228. } else {
  229. FirmwareCtrlPtr = NULL;
  230. // if HW_REDUCED_ACPI flag is not set, both FIRMWARE_CTRL and
  231. // X_FIRMWARE_CTRL cannot be zero, and the FACS Table must be
  232. // present.
  233. if ((Trace) &&
  234. (Flags != NULL) &&
  235. ((*Flags & EFI_ACPI_6_3_HW_REDUCED_ACPI) != EFI_ACPI_6_3_HW_REDUCED_ACPI))
  236. {
  237. IncrementErrorCount ();
  238. Print (
  239. L"ERROR: No FACS table found, "
  240. L"both X_FIRMWARE_CTRL and FIRMWARE_CTRL are zero.\n"
  241. );
  242. }
  243. }
  244. if (FirmwareCtrlPtr != NULL) {
  245. // The FACS table does not have a standard ACPI table header. Therefore,
  246. // the signature, length and version needs to be initially parsed.
  247. // The FACS signature is 4 bytes starting at offset 0.
  248. FacsSignature = *(UINT32 *)(FirmwareCtrlPtr + FACS_SIGNATURE_OFFSET);
  249. // The FACS length is 4 bytes starting at offset 4.
  250. FacsLength = *(UINT32 *)(FirmwareCtrlPtr + FACS_LENGTH_OFFSET);
  251. // The FACS version is 1 byte starting at offset 32.
  252. FacsRevision = *(UINT8 *)(FirmwareCtrlPtr + FACS_VERSION_OFFSET);
  253. Trace = ProcessTableReportOptions (
  254. FacsSignature,
  255. FirmwareCtrlPtr,
  256. FacsLength
  257. );
  258. Status = GetParser (FacsSignature, &FacsParserProc);
  259. if (EFI_ERROR (Status)) {
  260. Print (
  261. L"ERROR: No registered parser found for FACS.\n"
  262. );
  263. return;
  264. }
  265. FacsParserProc (
  266. Trace,
  267. FirmwareCtrlPtr,
  268. FacsLength,
  269. FacsRevision
  270. );
  271. }
  272. // If X_DSDT is valid then use X_DSDT and ignore DSDT, else use DSDT.
  273. if ((X_DsdtAddress != NULL) && (*X_DsdtAddress != 0)) {
  274. DsdtPtr = (UINT8 *)(UINTN)(*X_DsdtAddress);
  275. } else if ((DsdtAddress != NULL) && (*DsdtAddress != 0)) {
  276. DsdtPtr = (UINT8 *)(UINTN)(*DsdtAddress);
  277. } else {
  278. // Both DSDT and X_DSDT cannot be invalid.
  279. #if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
  280. if (Trace) {
  281. // The DSDT Table is mandatory for ARM systems
  282. // as the CPU information MUST be presented in
  283. // the DSDT.
  284. IncrementErrorCount ();
  285. Print (L"ERROR: Both X_DSDT and DSDT are invalid.\n");
  286. }
  287. #endif
  288. return;
  289. }
  290. ProcessAcpiTable (DsdtPtr);
  291. }