AestParser.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760
  1. /** @file
  2. AEST table parser
  3. Copyright (c) 2020, Arm Limited.
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. @par Reference(s):
  6. - ACPI for the Armv8 RAS Extensions 1.1 Platform Design Document,
  7. dated 28 September 2020.
  8. (https://developer.arm.com/documentation/den0085/0101/)
  9. **/
  10. #include <Library/PrintLib.h>
  11. #include <Library/UefiLib.h>
  12. #include <IndustryStandard/ArmErrorSourceTable.h>
  13. #include "AcpiParser.h"
  14. #include "AcpiView.h"
  15. #include "AcpiViewConfig.h"
  16. // Local variables
  17. STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;
  18. STATIC UINT8 *AestNodeType;
  19. STATIC UINT16 *AestNodeLength;
  20. STATIC UINT32 *NodeDataOffset;
  21. STATIC UINT32 *NodeInterfaceOffset;
  22. STATIC UINT32 *NodeInterruptArrayOffset;
  23. STATIC UINT32 *NodeInterruptCount;
  24. STATIC UINT32 *ProcessorId;
  25. STATIC UINT8 *ProcessorFlags;
  26. STATIC UINT8 *ProcessorResourceType;
  27. /**
  28. Validate Processor Flags.
  29. @param [in] Ptr Pointer to the start of the field data.
  30. @param [in] Context Pointer to context specific information e.g. this
  31. could be a pointer to the ACPI table header.
  32. **/
  33. STATIC
  34. VOID
  35. EFIAPI
  36. ValidateProcessorFlags (
  37. IN UINT8 *Ptr,
  38. IN VOID *Context
  39. )
  40. {
  41. // If the global or shared node flag is set then the ACPI Processor ID
  42. // field must be set to 0 and ignored.
  43. if (((*Ptr & 0x3) != 0) && (*ProcessorId != 0)) {
  44. IncrementErrorCount ();
  45. Print (
  46. L"\nERROR: 'ACPI Processor ID' field must be set to 0 for global"
  47. L" or shared nodes."
  48. );
  49. }
  50. }
  51. /**
  52. Validate GIC Interface Type.
  53. @param [in] Ptr Pointer to the start of the field data.
  54. @param [in] Context Pointer to context specific information e.g. this
  55. could be a pointer to the ACPI table header.
  56. **/
  57. STATIC
  58. VOID
  59. EFIAPI
  60. ValidateGicInterfaceType (
  61. IN UINT8 *Ptr,
  62. IN VOID *Context
  63. )
  64. {
  65. UINT32 GicInterfaceType;
  66. GicInterfaceType = *(UINT32 *)Ptr;
  67. if (GicInterfaceType > 3) {
  68. IncrementErrorCount ();
  69. Print (L"\nError: Invalid GIC Interface type %d", GicInterfaceType);
  70. }
  71. }
  72. /**
  73. Validate Interface Type.
  74. @param [in] Ptr Pointer to the start of the field data.
  75. @param [in] Context Pointer to context specific information e.g. this
  76. could be a pointer to the ACPI table header.
  77. **/
  78. STATIC
  79. VOID
  80. EFIAPI
  81. ValidateInterfaceType (
  82. IN UINT8 *Ptr,
  83. IN VOID *Context
  84. )
  85. {
  86. if (*Ptr > 1) {
  87. IncrementErrorCount ();
  88. Print (L"\nError: Interface type should be 0 or 1");
  89. }
  90. }
  91. /**
  92. Validate Interrupt Type.
  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. ValidateInterruptType (
  101. IN UINT8 *Ptr,
  102. IN VOID *Context
  103. )
  104. {
  105. if (*Ptr > 1) {
  106. IncrementErrorCount ();
  107. Print (L"\nError: Interrupt type should be 0 or 1");
  108. }
  109. }
  110. /**
  111. Validate interrupt flags.
  112. @param [in] Ptr Pointer to the start of the field data.
  113. @param [in] Context Pointer to context specific information e.g. this
  114. could be a pointer to the ACPI table header.
  115. **/
  116. STATIC
  117. VOID
  118. EFIAPI
  119. ValidateInterruptFlags (
  120. IN UINT8 *Ptr,
  121. IN VOID *Context
  122. )
  123. {
  124. if ((*Ptr & 0xfe) != 0) {
  125. IncrementErrorCount ();
  126. Print (L"\nError: Reserved Flag bits not set to 0");
  127. }
  128. }
  129. /**
  130. Dumps 16 bytes of data.
  131. @param [in] Format Optional format string for tracing the data.
  132. @param [in] Ptr Pointer to the start of the buffer.
  133. **/
  134. VOID
  135. EFIAPI
  136. DumpVendorSpecificData (
  137. IN CONST CHAR16 *Format OPTIONAL,
  138. IN UINT8 *Ptr
  139. )
  140. {
  141. Print (
  142. L"%02X %02X %02X %02X %02X %02X %02X %02X\n",
  143. Ptr[0],
  144. Ptr[1],
  145. Ptr[2],
  146. Ptr[3],
  147. Ptr[4],
  148. Ptr[5],
  149. Ptr[6],
  150. Ptr[7]
  151. );
  152. Print (
  153. L"%*a %02X %02X %02X %02X %02X %02X %02X %02X",
  154. OUTPUT_FIELD_COLUMN_WIDTH,
  155. "",
  156. Ptr[8],
  157. Ptr[9],
  158. Ptr[10],
  159. Ptr[11],
  160. Ptr[12],
  161. Ptr[13],
  162. Ptr[14],
  163. Ptr[15]
  164. );
  165. }
  166. /**
  167. An ACPI_PARSER array describing the ACPI AEST Table.
  168. **/
  169. STATIC CONST ACPI_PARSER AestParser[] = {
  170. PARSE_ACPI_HEADER (&AcpiHdrInfo)
  171. };
  172. /**
  173. An ACPI_PARSER array describing the AEST Node Header.
  174. **/
  175. STATIC CONST ACPI_PARSER AestNodeHeaderParser[] = {
  176. { L"Type", 1, 0, L"%d", NULL, (VOID **)&AestNodeType, NULL, NULL },
  177. { L"Length", 2, 1, L"%d", NULL, (VOID **)&AestNodeLength, NULL, NULL },
  178. { L"Reserved", 1, 3, L"0x%x", NULL, NULL, NULL, NULL },
  179. { L"Node Data Offset", 4, 4, L"%d", NULL, (VOID **)&NodeDataOffset, NULL, NULL },
  180. { L"Node Interface Offset", 4, 8, L"%d", NULL,
  181. (VOID **)&NodeInterfaceOffset, NULL, NULL },
  182. { L"Node Interrupt Array Offset", 4, 12, L"%d", NULL,
  183. (VOID **)&NodeInterruptArrayOffset, NULL, NULL },
  184. { L"Node Interrupt Count", 4, 16, L"%d", NULL,
  185. (VOID **)&NodeInterruptCount, NULL, NULL },
  186. { L"Timestamp Rate", 8, 20, L"%ld", NULL, NULL, NULL, NULL },
  187. { L"Reserved1", 8, 28, L"0x%lx", NULL, NULL, NULL, NULL },
  188. { L"Error Injection Countdown Rate", 8, 36, L"%ld", NULL, NULL, NULL, NULL }
  189. // Node specific data...
  190. // Node interface...
  191. // Node interrupt array...
  192. };
  193. /**
  194. An ACPI_PARSER array describing the Processor error node specific data.
  195. **/
  196. STATIC CONST ACPI_PARSER AestProcessorStructure[] = {
  197. { L"ACPI Processor ID", 4, 0, L"0x%x", NULL, (VOID **)&ProcessorId, NULL, NULL },
  198. { L"Resource Type", 1, 4, L"%d", NULL, (VOID **)&ProcessorResourceType, NULL,
  199. NULL },
  200. { L"Reserved", 1, 5, L"0x%x", NULL, NULL, NULL, NULL },
  201. { L"Flags", 1, 6, L"0x%x", NULL, (VOID **)&ProcessorFlags,
  202. ValidateProcessorFlags, NULL },
  203. { L"Revision", 1, 7, L"%d", NULL, NULL, NULL, NULL },
  204. { L"Processor Affinity Level Indicator", 8, 8, L"0x%lx", NULL, NULL, NULL,
  205. NULL },
  206. // Resource specific data...
  207. };
  208. /**
  209. An ACPI_PARSER array describing the processor cache resource substructure.
  210. **/
  211. STATIC CONST ACPI_PARSER AestProcessorCacheResourceSubstructure[] = {
  212. { L"Cache reference ID", 4, 0, L"0x%x", NULL, NULL, NULL, NULL },
  213. { L"Reserved", 4, 4, L"%d", NULL, NULL, NULL, NULL }
  214. };
  215. /**
  216. An ACPI_PARSER array describing the processor TLB resource substructure.
  217. **/
  218. STATIC CONST ACPI_PARSER AestProcessorTlbResourceSubstructure[] = {
  219. { L"TLB reference ID", 4, 0, L"0x%x", NULL, NULL, NULL, NULL },
  220. { L"Reserved", 4, 4, L"%d", NULL, NULL, NULL, NULL }
  221. };
  222. /**
  223. An ACPI_PARSER array describing the processor generic resource substructure.
  224. **/
  225. STATIC CONST ACPI_PARSER AestProcessorGenericResourceSubstructure[] = {
  226. { L"Vendor-defined data", 4, 0, L"%x", NULL, NULL, NULL, NULL }
  227. };
  228. /**
  229. An ACPI_PARSER array describing the memory controller structure.
  230. **/
  231. STATIC CONST ACPI_PARSER AestMemoryControllerStructure[] = {
  232. { L"Proximity Domain", 4, 0, L"0x%x", NULL, NULL, NULL, NULL }
  233. };
  234. /**
  235. An ACPI_PARSER array describing the SMMU structure.
  236. **/
  237. STATIC CONST ACPI_PARSER AestSmmuStructure[] = {
  238. { L"IORT Node reference ID", 4, 0, L"0x%x", NULL, NULL, NULL, NULL },
  239. { L"SubComponent reference ID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL }
  240. };
  241. /**
  242. An ACPI_PARSER array describing the vendor-defined structure.
  243. **/
  244. STATIC CONST ACPI_PARSER AestVendorDefinedStructure[] = {
  245. { L"Hardware ID", 4, 0, L"0x%x", NULL, NULL, NULL, NULL },
  246. { L"Unique ID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL },
  247. { L"Vendor-specific data", 16, 8, NULL, DumpVendorSpecificData, NULL, NULL }
  248. };
  249. /**
  250. An ACPI_PARSER array describing the GIC structure.
  251. **/
  252. STATIC CONST ACPI_PARSER AestGicStructure[] = {
  253. { L"GIC Interface Type", 4, 0, L"0x%x", NULL, NULL, ValidateGicInterfaceType,
  254. NULL },
  255. { L"GIC Interface reference ID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL}
  256. };
  257. /**
  258. An ACPI_PARSER array describing the node interface.
  259. **/
  260. STATIC CONST ACPI_PARSER AestNodeInterface[] = {
  261. { L"Interface Type", 1, 0, L"%d", NULL, NULL, ValidateInterfaceType, NULL },
  262. { L"Reserved", 3, 1, L"%x %x %x", Dump3Chars, NULL, NULL, NULL },
  263. { L"Flags", 4, 4, L"0x%x", NULL, NULL, NULL, NULL },
  264. { L"Base Address", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL },
  265. { L"Start Error Record Index", 4, 16, L"0x%x", NULL, NULL, NULL, NULL },
  266. { L"Number of Error Records", 4, 20, L"0x%x", NULL, NULL, NULL, NULL },
  267. { L"Error Records Implemented", 8, 24, L"0x%lx", NULL, NULL, NULL, NULL },
  268. { L"Error Records Support", 8, 32, L"0x%lx", NULL, NULL, NULL, NULL },
  269. { L"Addressing mode", 8, 40, L"0x%lx", NULL, NULL, NULL, NULL }
  270. };
  271. /**
  272. An ACPI_PARSER array describing the node interrupts.
  273. **/
  274. STATIC CONST ACPI_PARSER AestNodeInterrupt[] = {
  275. { L"Interrupt Type", 1, 0, L"%d", NULL, NULL, ValidateInterruptType, NULL },
  276. { L"Reserved", 2, 1, L"0x%x", NULL, NULL, NULL, NULL },
  277. { L"Interrupt Flags", 1, 3, L"0x%x", NULL, NULL, ValidateInterruptFlags, NULL },
  278. { L"Interrupt GSIV", 4, 4, L"0x%x", NULL, NULL, NULL, NULL },
  279. { L"ID", 1, 8, L"0x%x", NULL, NULL, NULL, NULL },
  280. { L"Reserved1", 3, 9, L"%x %x %x", Dump3Chars, NULL, NULL, NULL }
  281. };
  282. /**
  283. Parses the Processor Error Node structure along with its resource
  284. specific data.
  285. @param [in] Ptr Pointer to the start of the Processor node.
  286. @param [in] Length Maximum length of the Processor node.
  287. **/
  288. STATIC
  289. VOID
  290. DumpProcessorNode (
  291. IN UINT8 *Ptr,
  292. IN UINT32 Length
  293. )
  294. {
  295. UINT32 Offset;
  296. Offset = ParseAcpi (
  297. TRUE,
  298. 2,
  299. "Processor",
  300. Ptr,
  301. Length,
  302. PARSER_PARAMS (AestProcessorStructure)
  303. );
  304. // Check if the values used to control the parsing logic have been
  305. // successfully read.
  306. if ((ProcessorId == NULL) ||
  307. (ProcessorResourceType == NULL) ||
  308. (ProcessorFlags == NULL))
  309. {
  310. IncrementErrorCount ();
  311. Print (
  312. L"ERROR: Insufficient Processor Error Node length. Length = %d.\n",
  313. Length
  314. );
  315. return;
  316. }
  317. switch (*ProcessorResourceType) {
  318. case EFI_ACPI_AEST_PROCESSOR_RESOURCE_TYPE_CACHE:
  319. ParseAcpi (
  320. TRUE,
  321. 2,
  322. "Cache Resource",
  323. Ptr + Offset,
  324. Length - Offset,
  325. PARSER_PARAMS (AestProcessorCacheResourceSubstructure)
  326. );
  327. break;
  328. case EFI_ACPI_AEST_PROCESSOR_RESOURCE_TYPE_TLB:
  329. ParseAcpi (
  330. TRUE,
  331. 2,
  332. "TLB Resource",
  333. Ptr + Offset,
  334. Length - Offset,
  335. PARSER_PARAMS (AestProcessorTlbResourceSubstructure)
  336. );
  337. break;
  338. case EFI_ACPI_AEST_PROCESSOR_RESOURCE_TYPE_GENERIC:
  339. ParseAcpi (
  340. TRUE,
  341. 2,
  342. "Generic Resource",
  343. Ptr + Offset,
  344. Length - Offset,
  345. PARSER_PARAMS (AestProcessorGenericResourceSubstructure)
  346. );
  347. break;
  348. default:
  349. IncrementErrorCount ();
  350. Print (L"ERROR: Invalid Processor Resource Type.");
  351. return;
  352. } // switch
  353. }
  354. /**
  355. Parses the Memory Controller node.
  356. @param [in] Ptr Pointer to the start of the Memory Controller node.
  357. @param [in] Length Maximum length of the Memory Controller node.
  358. **/
  359. STATIC
  360. VOID
  361. DumpMemoryControllerNode (
  362. IN UINT8 *Ptr,
  363. IN UINT32 Length
  364. )
  365. {
  366. ParseAcpi (
  367. TRUE,
  368. 2,
  369. "Memory Controller",
  370. Ptr,
  371. Length,
  372. PARSER_PARAMS (AestMemoryControllerStructure)
  373. );
  374. }
  375. /**
  376. Parses the SMMU node.
  377. @param [in] Ptr Pointer to the start of the SMMU node.
  378. @param [in] Length Maximum length of the SMMU node.
  379. **/
  380. STATIC
  381. VOID
  382. DumpSmmuNode (
  383. IN UINT8 *Ptr,
  384. IN UINT32 Length
  385. )
  386. {
  387. ParseAcpi (
  388. TRUE,
  389. 2,
  390. "SMMU",
  391. Ptr,
  392. Length,
  393. PARSER_PARAMS (AestSmmuStructure)
  394. );
  395. }
  396. /**
  397. Parses the Vendor-defined structure.
  398. @param [in] Ptr Pointer to the start of the Vendor-defined node.
  399. @param [in] Length Maximum length of the Vendor-defined node.
  400. **/
  401. STATIC
  402. VOID
  403. DumpVendorDefinedNode (
  404. IN UINT8 *Ptr,
  405. IN UINT32 Length
  406. )
  407. {
  408. ParseAcpi (
  409. TRUE,
  410. 2,
  411. "Vendor-defined",
  412. Ptr,
  413. Length,
  414. PARSER_PARAMS (AestVendorDefinedStructure)
  415. );
  416. }
  417. /**
  418. Parses the GIC node.
  419. @param [in] Ptr Pointer to the start of the GIC node.
  420. @param [in] Length Maximum length of the GIC node.
  421. **/
  422. STATIC
  423. VOID
  424. DumpGicNode (
  425. IN UINT8 *Ptr,
  426. IN UINT32 Length
  427. )
  428. {
  429. ParseAcpi (
  430. TRUE,
  431. 2,
  432. "GIC",
  433. Ptr,
  434. Length,
  435. PARSER_PARAMS (AestGicStructure)
  436. );
  437. }
  438. /**
  439. Parses the Node Interface structure.
  440. @param [in] Ptr Pointer to the start of the Node Interface Structure.
  441. @param [in] Length Maximum length of the Node Interface Structure.
  442. **/
  443. STATIC
  444. VOID
  445. DumpNodeInterface (
  446. IN UINT8 *Ptr,
  447. IN UINT32 Length
  448. )
  449. {
  450. ParseAcpi (
  451. TRUE,
  452. 2,
  453. "Node Interface",
  454. Ptr,
  455. Length,
  456. PARSER_PARAMS (AestNodeInterface)
  457. );
  458. }
  459. /**
  460. Parses the Node Interrupts Structure.
  461. @param [in] Ptr Pointer to the start of the Node Interrupt array.
  462. @param [in] Length Maximum length of the Node Interrupt array.
  463. @param [in] InterruptCount Number if interrupts in the Node Interrupts array.
  464. **/
  465. STATIC
  466. VOID
  467. DumpNodeInterrupts (
  468. IN UINT8 *Ptr,
  469. IN UINT32 Length,
  470. IN UINT32 InterruptCount
  471. )
  472. {
  473. UINT32 Offset;
  474. UINT32 Index;
  475. CHAR8 Buffer[64];
  476. if (Length < (InterruptCount * sizeof (EFI_ACPI_AEST_INTERRUPT_STRUCT))) {
  477. IncrementErrorCount ();
  478. Print (
  479. L"ERROR: Node not long enough for Interrupt Array.\n" \
  480. L" Length left = %d, Required = %d, Interrupt Count = %d\n",
  481. Length,
  482. (InterruptCount * sizeof (EFI_ACPI_AEST_INTERRUPT_STRUCT)),
  483. InterruptCount
  484. );
  485. return;
  486. }
  487. Offset = 0;
  488. for (Index = 0; Index < InterruptCount; Index++) {
  489. AsciiSPrint (
  490. Buffer,
  491. sizeof (Buffer),
  492. "Node Interrupt [%d]",
  493. Index
  494. );
  495. Offset += ParseAcpi (
  496. TRUE,
  497. 4,
  498. Buffer,
  499. Ptr + Offset,
  500. Length - Offset,
  501. PARSER_PARAMS (AestNodeInterrupt)
  502. );
  503. } // for
  504. }
  505. /**
  506. Parses a single AEST Node Structure.
  507. @param [in] Ptr Pointer to the start of the Node.
  508. @param [in] Length Maximum length of the Node.
  509. @param [in] NodeType AEST node type.
  510. @param [in] DataOffset Offset to the node data.
  511. @param [in] InterfaceOffset Offset to the node interface data.
  512. @param [in] InterruptArrayOffset Offset to the node interrupt array.
  513. @param [in] InterruptCount Number of interrupts.
  514. **/
  515. STATIC
  516. VOID
  517. DumpAestNodeStructure (
  518. IN UINT8 *Ptr,
  519. IN UINT32 Length,
  520. IN UINT8 NodeType,
  521. IN UINT32 DataOffset,
  522. IN UINT32 InterfaceOffset,
  523. IN UINT32 InterruptArrayOffset,
  524. IN UINT32 InterruptCount
  525. )
  526. {
  527. UINT32 Offset;
  528. UINT32 RemainingLength;
  529. UINT8 *NodeDataPtr;
  530. Offset = ParseAcpi (
  531. TRUE,
  532. 2,
  533. "Node Structure",
  534. Ptr,
  535. Length,
  536. PARSER_PARAMS (AestNodeHeaderParser)
  537. );
  538. if ((Offset > DataOffset) || (DataOffset > Length)) {
  539. IncrementErrorCount ();
  540. Print (
  541. L"ERROR: Invalid Node Data Offset: %d.\n" \
  542. L" It should be between %d and %d.\n",
  543. DataOffset,
  544. Offset,
  545. Length
  546. );
  547. }
  548. if ((Offset > InterfaceOffset) || (InterfaceOffset > Length)) {
  549. IncrementErrorCount ();
  550. Print (
  551. L"ERROR: Invalid Node Interface Offset: %d.\n" \
  552. L" It should be between %d and %d.\n",
  553. InterfaceOffset,
  554. Offset,
  555. Length
  556. );
  557. }
  558. if ((Offset > InterruptArrayOffset) || (InterruptArrayOffset > Length)) {
  559. IncrementErrorCount ();
  560. Print (
  561. L"ERROR: Invalid Node Interrupt Array Offset: %d.\n" \
  562. L" It should be between %d and %d.\n",
  563. InterruptArrayOffset,
  564. Offset,
  565. Length
  566. );
  567. }
  568. // Parse Node Data Field.
  569. NodeDataPtr = Ptr + DataOffset;
  570. RemainingLength = Length - DataOffset;
  571. switch (NodeType) {
  572. case EFI_ACPI_AEST_NODE_TYPE_PROCESSOR:
  573. DumpProcessorNode (NodeDataPtr, RemainingLength);
  574. break;
  575. case EFI_ACPI_AEST_NODE_TYPE_MEMORY:
  576. DumpMemoryControllerNode (NodeDataPtr, RemainingLength);
  577. break;
  578. case EFI_ACPI_AEST_NODE_TYPE_SMMU:
  579. DumpSmmuNode (NodeDataPtr, RemainingLength);
  580. break;
  581. case EFI_ACPI_AEST_NODE_TYPE_VENDOR_DEFINED:
  582. DumpVendorDefinedNode (NodeDataPtr, RemainingLength);
  583. break;
  584. case EFI_ACPI_AEST_NODE_TYPE_GIC:
  585. DumpGicNode (NodeDataPtr, RemainingLength);
  586. break;
  587. default:
  588. IncrementErrorCount ();
  589. Print (L"ERROR: Invalid Error Node Type.\n");
  590. return;
  591. } // switch
  592. // Parse the Interface Field.
  593. DumpNodeInterface (
  594. Ptr + InterfaceOffset,
  595. Length - InterfaceOffset
  596. );
  597. // Parse the Node Interrupt Array.
  598. DumpNodeInterrupts (
  599. Ptr + InterruptArrayOffset,
  600. Length - InterruptArrayOffset,
  601. InterruptCount
  602. );
  603. return;
  604. }
  605. /**
  606. This function parses the ACPI AEST table.
  607. When trace is enabled this function parses the AEST table and
  608. traces the ACPI table fields.
  609. This function also performs validation of the ACPI table fields.
  610. @param [in] Trace If TRUE, trace the ACPI fields.
  611. @param [in] Ptr Pointer to the start of the buffer.
  612. @param [in] AcpiTableLength Length of the ACPI table.
  613. @param [in] AcpiTableRevision Revision of the ACPI table.
  614. **/
  615. VOID
  616. EFIAPI
  617. ParseAcpiAest (
  618. IN BOOLEAN Trace,
  619. IN UINT8 *Ptr,
  620. IN UINT32 AcpiTableLength,
  621. IN UINT8 AcpiTableRevision
  622. )
  623. {
  624. UINT32 Offset;
  625. UINT8 *NodePtr;
  626. if (!Trace) {
  627. return;
  628. }
  629. Offset = ParseAcpi (
  630. TRUE,
  631. 0,
  632. "AEST",
  633. Ptr,
  634. AcpiTableLength,
  635. PARSER_PARAMS (AestParser)
  636. );
  637. while (Offset < AcpiTableLength) {
  638. NodePtr = Ptr + Offset;
  639. ParseAcpi (
  640. FALSE,
  641. 0,
  642. NULL,
  643. NodePtr,
  644. AcpiTableLength - Offset,
  645. PARSER_PARAMS (AestNodeHeaderParser)
  646. );
  647. // Check if the values used to control the parsing logic have been
  648. // successfully read.
  649. if ((AestNodeType == NULL) ||
  650. (AestNodeLength == NULL) ||
  651. (NodeDataOffset == NULL) ||
  652. (NodeInterfaceOffset == NULL) ||
  653. (NodeInterruptArrayOffset == NULL) ||
  654. (NodeInterruptCount == NULL))
  655. {
  656. IncrementErrorCount ();
  657. Print (
  658. L"ERROR: Insufficient length left for Node Structure.\n" \
  659. L" Length left = %d.\n",
  660. AcpiTableLength - Offset
  661. );
  662. return;
  663. }
  664. // Validate AEST Node length
  665. if ((*AestNodeLength == 0) ||
  666. ((Offset + (*AestNodeLength)) > AcpiTableLength))
  667. {
  668. IncrementErrorCount ();
  669. Print (
  670. L"ERROR: Invalid AEST Node length. " \
  671. L"Length = %d. Offset = %d. AcpiTableLength = %d.\n",
  672. *AestNodeLength,
  673. Offset,
  674. AcpiTableLength
  675. );
  676. return;
  677. }
  678. DumpAestNodeStructure (
  679. NodePtr,
  680. *AestNodeLength,
  681. *AestNodeType,
  682. *NodeDataOffset,
  683. *NodeInterfaceOffset,
  684. *NodeInterruptArrayOffset,
  685. *NodeInterruptCount
  686. );
  687. Offset += *AestNodeLength;
  688. } // while
  689. }