PcctParser.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673
  1. /** @file
  2. PCCT table parser
  3. Copyright (c) 2021, Arm Limited.
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. @par Reference(s):
  6. - ACPI 6.4 Specification - January 2021
  7. **/
  8. #include <Library/BaseMemoryLib.h>
  9. #include <Library/PrintLib.h>
  10. #include <Library/UefiLib.h>
  11. #include "AcpiParser.h"
  12. #include "AcpiView.h"
  13. #include "AcpiViewConfig.h"
  14. #include "PcctParser.h"
  15. // Local variables
  16. STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;
  17. STATIC UINT32 *PccGlobalFlags;
  18. STATIC UINT8 *PccSubspaceLength;
  19. STATIC UINT8 *PccSubspaceType;
  20. STATIC UINT8 *ExtendedPccSubspaceInterruptFlags;
  21. /**
  22. This function validates the length coded on 4 bytes of a shared memory range
  23. @param [in] Ptr Pointer to the start of the field data.
  24. @param [in] Context Pointer to context specific information e.g. this
  25. could be a pointer to the ACPI table header.
  26. **/
  27. STATIC
  28. VOID
  29. EFIAPI
  30. ValidateRangeLength4 (
  31. IN UINT8 *Ptr,
  32. IN VOID *Context
  33. )
  34. {
  35. if (*(UINT32 *)Ptr < MIN_EXT_PCC_SUBSPACE_MEM_RANGE_LEN) {
  36. IncrementErrorCount ();
  37. Print (
  38. L"\nError: Shared memory range length is too short.\n"
  39. L"Length is %u when it should be greater than or equal to %u",
  40. *(UINT32 *)Ptr,
  41. MIN_EXT_PCC_SUBSPACE_MEM_RANGE_LEN
  42. );
  43. }
  44. }
  45. /**
  46. This function validates the length coded on 8 bytes of a shared memory range
  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. ValidateRangeLength8 (
  55. IN UINT8 *Ptr,
  56. IN VOID *Context
  57. )
  58. {
  59. if (*(UINT64 *)Ptr <= MIN_MEMORY_RANGE_LENGTH) {
  60. IncrementErrorCount ();
  61. Print (
  62. L"\nError: Shared memory range length is too short.\n"
  63. L"Length is %u when it should be greater than %u",
  64. *(UINT64 *)Ptr,
  65. MIN_MEMORY_RANGE_LENGTH
  66. );
  67. }
  68. }
  69. /**
  70. This function validates address space for Memory/IO GAS.
  71. @param [in] Ptr Pointer to the start of the field data.
  72. @param [in] Context Pointer to context specific information e.g. this
  73. could be a pointer to the ACPI table header.
  74. **/
  75. STATIC
  76. VOID
  77. EFIAPI
  78. ValidatePccMemoryIoGas (
  79. IN UINT8 *Ptr,
  80. IN VOID *Context
  81. )
  82. {
  83. switch (*(UINT8 *)Ptr) {
  84. #if !(defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64))
  85. case EFI_ACPI_6_4_SYSTEM_IO:
  86. #endif //if not (defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64))
  87. case EFI_ACPI_6_4_SYSTEM_MEMORY:
  88. return;
  89. default:
  90. IncrementErrorCount ();
  91. Print (L"\nError: Invalid address space");
  92. }
  93. }
  94. /**
  95. This function validates address space for structures of types other than 0.
  96. @param [in] Ptr Pointer to the start of the field data.
  97. @param [in] Context Pointer to context specific information e.g. this
  98. could be a pointer to the ACPI table header.
  99. **/
  100. STATIC
  101. VOID
  102. EFIAPI
  103. ValidatePccGas (
  104. IN UINT8 *Ptr,
  105. IN VOID *Context
  106. )
  107. {
  108. switch (*(UINT8 *)Ptr) {
  109. #if !(defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64))
  110. case EFI_ACPI_6_4_SYSTEM_IO:
  111. #endif //if not (defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64))
  112. case EFI_ACPI_6_4_FUNCTIONAL_FIXED_HARDWARE:
  113. case EFI_ACPI_6_4_SYSTEM_MEMORY:
  114. return;
  115. default:
  116. IncrementErrorCount ();
  117. Print (L"\nError: Invalid address space");
  118. }
  119. }
  120. /**
  121. This function validates doorbell address space for type 4 structure.
  122. @param [in] Ptr Pointer to the start of the field data.
  123. @param [in] Context Pointer to context specific information e.g. this
  124. could be a pointer to the ACPI table header.
  125. **/
  126. STATIC
  127. VOID
  128. EFIAPI
  129. ValidatePccDoorbellGas (
  130. IN UINT8 *Ptr,
  131. IN VOID *Context
  132. )
  133. {
  134. // For slave subspaces this field is optional, if not present the field
  135. // should just contain zeros.
  136. if (*PccSubspaceType == EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC) {
  137. if (IsZeroBuffer (
  138. Ptr,
  139. sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
  140. ))
  141. {
  142. return;
  143. }
  144. }
  145. ValidatePccGas (Ptr, Context);
  146. }
  147. /**
  148. This function validates interrupt acknowledge address space for
  149. type 4 structure.
  150. @param [in] Ptr Pointer to the start of the field data.
  151. @param [in] Context Pointer to context specific information e.g. this
  152. could be a pointer to the ACPI table header.
  153. **/
  154. STATIC
  155. VOID
  156. EFIAPI
  157. ValidatePccIntAckGas (
  158. IN UINT8 *Ptr,
  159. IN VOID *Context
  160. )
  161. {
  162. // If the subspace does not support interrupts or the interrupt is
  163. // edge driven the register may be omitted. A value of 0x0 on all
  164. // 12 bytes of the GAS structure indicates the register is not
  165. // present.
  166. if (((*PccGlobalFlags & EFI_ACPI_6_4_PCCT_FLAGS_PLATFORM_INTERRUPT) !=
  167. EFI_ACPI_6_4_PCCT_FLAGS_PLATFORM_INTERRUPT) ||
  168. ((*ExtendedPccSubspaceInterruptFlags &
  169. EFI_ACPI_6_4_PCCT_SUBSPACE_PLATFORM_INTERRUPT_FLAGS_MODE) ==
  170. EFI_ACPI_6_4_PCCT_SUBSPACE_PLATFORM_INTERRUPT_FLAGS_MODE))
  171. {
  172. if (IsZeroBuffer (
  173. Ptr,
  174. sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
  175. ))
  176. {
  177. return;
  178. }
  179. }
  180. ValidatePccGas (Ptr, Context);
  181. }
  182. /**
  183. This function validates error status address space for type 4 structure.
  184. @param [in] Ptr Pointer to the start of the field data.
  185. @param [in] Context Pointer to context specific information e.g. this
  186. could be a pointer to the ACPI table header.
  187. **/
  188. STATIC
  189. VOID
  190. EFIAPI
  191. ValidatePccErrStatusGas (
  192. IN UINT8 *Ptr,
  193. IN VOID *Context
  194. )
  195. {
  196. // This field is ignored by the OSPM on slave channels.
  197. if (*PccSubspaceType == EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC) {
  198. return;
  199. }
  200. ValidatePccGas (Ptr, Context);
  201. }
  202. /**
  203. This function validates platform interrupt flags for type 4 structure.
  204. @param [in] Ptr Pointer to the start of the field data.
  205. @param [in] Context Pointer to context specific information e.g. this
  206. could be a pointer to the ACPI table header.
  207. **/
  208. STATIC
  209. VOID
  210. EFIAPI
  211. ValidatePlatInterrupt (
  212. IN UINT8 *Ptr,
  213. IN VOID *Context
  214. )
  215. {
  216. // If a slave subspace is present in the PCCT, then the global Platform
  217. // Interrupt flag must be set to 1.
  218. if ((*PccSubspaceType == EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC) &&
  219. ((*PccGlobalFlags & EFI_ACPI_6_4_PCCT_FLAGS_PLATFORM_INTERRUPT) !=
  220. EFI_ACPI_6_4_PCCT_FLAGS_PLATFORM_INTERRUPT))
  221. {
  222. IncrementErrorCount ();
  223. Print (
  224. L"\nError: Global Platform interrupt flag must be set to 1" \
  225. L" if a PCC type 4 structure is present in PCCT."
  226. );
  227. }
  228. }
  229. /**
  230. An ACPI_PARSER array describing the ACPI PCCT Table.
  231. */
  232. STATIC CONST ACPI_PARSER PcctParser[] = {
  233. PARSE_ACPI_HEADER (&AcpiHdrInfo),
  234. { L"Flags", 4, 36, NULL, NULL, (VOID **)&PccGlobalFlags, NULL, NULL },
  235. { L"Reserved", 8, 40, NULL, NULL, NULL, NULL, NULL }
  236. };
  237. /**
  238. An ACPI_PARSER array describing the platform communications channel subspace
  239. structure header.
  240. */
  241. STATIC CONST ACPI_PARSER PccSubspaceHeaderParser[] = {
  242. PCC_SUBSPACE_HEADER ()
  243. // ... Type Specific Fields ...
  244. };
  245. /**
  246. An ACPI_PARSER array describing the Generic Communications Subspace - Type 0
  247. */
  248. STATIC CONST ACPI_PARSER PccSubspaceType0Parser[] = {
  249. PCC_SUBSPACE_HEADER (),
  250. { L"Reserved", 6, 2, L"%x %x %x %x %x %x", Dump6Chars, NULL, NULL, NULL },
  251. { L"Base Address", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL },
  252. { L"Memory Range Length",8, 16, L"0x%lx", NULL, NULL, ValidateRangeLength8,
  253. NULL },
  254. { L"Doorbell Register",12, 24, NULL, DumpGas, NULL, ValidatePccMemoryIoGas,
  255. NULL },
  256. { L"Doorbell Preserve",8, 36, L"0x%lx", NULL, NULL, NULL, NULL },
  257. { L"Doorbell Write", 8, 44, L"0x%lx", NULL, NULL, NULL, NULL },
  258. { L"Nominal Latency", 4, 52, L"%u", NULL, NULL, NULL, NULL },
  259. { L"Maximum Periodic Access Rate",4, 56, L"%u", NULL, NULL, NULL, NULL },
  260. { L"Minimum Request Turnaround Time",2, 60, L"%u", NULL, NULL, NULL, NULL }
  261. };
  262. /**
  263. An ACPI_PARSER array describing the HW-Reduced Communications Subspace
  264. - Type 1
  265. */
  266. STATIC CONST ACPI_PARSER PccSubspaceType1Parser[] = {
  267. PCC_SUBSPACE_HEADER (),
  268. { L"Platform Interrupt",4, 2, L"0x%x", NULL, NULL, NULL, NULL },
  269. { L"Platform Interrupt Flags",1, 6, L"0x%x", NULL, NULL, NULL, NULL },
  270. { L"Reserved", 1, 7, L"0x%x", NULL, NULL, NULL, NULL },
  271. { L"Base Address", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL },
  272. { L"Memory Range Length",8, 16, L"0x%lx", NULL, NULL, ValidateRangeLength8,
  273. NULL },
  274. { L"Doorbell Register",12, 24, NULL, DumpGas, NULL,
  275. ValidatePccGas, NULL },
  276. { L"Doorbell Preserve",8, 36, L"0x%lx", NULL, NULL, NULL, NULL },
  277. { L"Doorbell Write", 8, 44, L"0x%lx", NULL, NULL, NULL, NULL },
  278. { L"Nominal Latency", 4, 52, L"%u", NULL, NULL, NULL, NULL },
  279. { L"Maximum Periodic Access Rate",4, 56, L"%u", NULL, NULL, NULL, NULL },
  280. { L"Minimum Request Turnaround Time",2, 60, L"%u", NULL, NULL, NULL, NULL }
  281. };
  282. /**
  283. An ACPI_PARSER array describing the HW-Reduced Communications Subspace
  284. - Type 2
  285. */
  286. STATIC CONST ACPI_PARSER PccSubspaceType2Parser[] = {
  287. PCC_SUBSPACE_HEADER (),
  288. { L"Platform Interrupt",4, 2, L"0x%x", NULL, NULL, NULL, NULL },
  289. { L"Platform Interrupt Flags",1, 6, L"0x%x", NULL, NULL, NULL, NULL },
  290. { L"Reserved", 1, 7, L"0x%x", NULL, NULL, NULL, NULL },
  291. { L"Base Address", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL },
  292. { L"Memory Range Length",8, 16, L"0x%lx", NULL, NULL, ValidateRangeLength8,
  293. NULL },
  294. { L"Doorbell Register",12, 24, NULL, DumpGas, NULL,
  295. ValidatePccGas, NULL },
  296. { L"Doorbell Preserve",8, 36, L"0x%lx", NULL, NULL, NULL, NULL },
  297. { L"Doorbell Write", 8, 44, L"0x%lx", NULL, NULL, NULL, NULL },
  298. { L"Nominal Latency", 4, 52, L"%u", NULL, NULL, NULL, NULL },
  299. { L"Maximum Periodic Access Rate",4, 56, L"%u", NULL, NULL, NULL, NULL },
  300. { L"Minimum Request Turnaround Time",2, 60, L"%u", NULL, NULL, NULL, NULL },
  301. { L"Platform Interrupt Ack Register",12, 62, NULL, DumpGas, NULL,
  302. ValidatePccGas, NULL },
  303. { L"Platform Interrupt Ack Preserve",8, 74, L"0x%lx", NULL, NULL, NULL, NULL },
  304. { L"Platform Interrupt Ack Write",8, 82, L"0x%lx", NULL, NULL,
  305. NULL, NULL },
  306. };
  307. /**
  308. An ACPI_PARSER array describing the Extended PCC Subspaces - Type 3/4
  309. */
  310. STATIC CONST ACPI_PARSER PccSubspaceType3Parser[] = {
  311. PCC_SUBSPACE_HEADER (),
  312. { L"Platform Interrupt", 4, 2, L"0x%x", NULL, NULL,
  313. ValidatePlatInterrupt, NULL },
  314. { L"Platform Interrupt Flags", 1, 6, L"0x%x", NULL,
  315. (VOID **)&ExtendedPccSubspaceInterruptFlags,NULL, NULL },
  316. { L"Reserved", 1, 7, L"0x%x", NULL, NULL,NULL, NULL },
  317. { L"Base Address", 8, 8, L"0x%lx", NULL, NULL,NULL, NULL },
  318. { L"Memory Range Length", 4, 16, L"0x%x", NULL, NULL,ValidateRangeLength4,
  319. NULL },
  320. { L"Doorbell Register", 12, 20, NULL, DumpGas, NULL,
  321. ValidatePccDoorbellGas, NULL },
  322. { L"Doorbell Preserve", 8, 32, L"0x%lx", NULL, NULL,NULL, NULL },
  323. { L"Doorbell Write", 8, 40, L"0x%lx", NULL, NULL,NULL, NULL },
  324. { L"Nominal Latency", 4, 48, L"%u", NULL, NULL,NULL, NULL },
  325. { L"Maximum Periodic Access Rate", 4, 52, L"%u", NULL, NULL,NULL, NULL },
  326. { L"Minimum Request Turnaround Time", 4, 56, L"%u", NULL, NULL,NULL, NULL },
  327. { L"Platform Interrupt Ack Register", 12, 60, NULL, DumpGas, NULL,
  328. ValidatePccIntAckGas, NULL },
  329. { L"Platform Interrupt Ack Preserve", 8, 72, L"0x%lx", NULL, NULL,NULL, NULL },
  330. { L"Platform Interrupt Ack Set", 8, 80, L"0x%lx", NULL, NULL,NULL, NULL },
  331. { L"Reserved", 8, 88, L"0x%lx", NULL, NULL,NULL, NULL },
  332. { L"Cmd Complete Check Reg Addr", 12, 96, NULL, DumpGas, NULL,
  333. ValidatePccGas, NULL },
  334. { L"Cmd Complete Check Mask", 8, 108, L"0x%lx", NULL, NULL,NULL, NULL },
  335. { L"Cmd Update Reg Addr", 12, 116, NULL, DumpGas, NULL,
  336. ValidatePccGas, NULL },
  337. { L"Cmd Update Preserve mask", 8, 128, L"0x%lx", NULL, NULL,NULL, NULL },
  338. { L"Cmd Update Set mask", 8, 136, L"0x%lx", NULL, NULL,NULL, NULL },
  339. { L"Error Status Register", 12, 144, NULL, DumpGas, NULL,
  340. ValidatePccErrStatusGas, NULL },
  341. { L"Error Status Mask", 8, 156, L"0x%lx", NULL, NULL,NULL, NULL },
  342. };
  343. /**
  344. An ACPI_PARSER array describing the HW Registers based Communications
  345. Subspace Structure - Type 5
  346. */
  347. STATIC CONST ACPI_PARSER PccSubspaceType5Parser[] = {
  348. PCC_SUBSPACE_HEADER (),
  349. { L"Version", 2, 2, L"0x%x", NULL, NULL, NULL, NULL },
  350. { L"Base Address", 8, 4, L"0x%lx", NULL, NULL, NULL, NULL },
  351. { L"Shared Memory Range Length",8, 12, L"0x%lx", NULL, NULL, NULL, NULL },
  352. { L"Doorbell Register", 12, 20, NULL, DumpGas, NULL,
  353. ValidatePccMemoryIoGas,NULL },
  354. { L"Doorbell Preserve", 8, 32, L"0x%lx", NULL, NULL, NULL, NULL },
  355. { L"Doorbell Write", 8, 40, L"0x%lx", NULL, NULL, NULL, NULL },
  356. { L"Command Complete Check Register",12, 48, NULL, DumpGas, NULL,
  357. ValidatePccMemoryIoGas,NULL },
  358. { L"Command Complete Check Mask",8, 60, L"0x%lx", NULL, NULL, NULL, NULL },
  359. { L"Error Status Register",12, 68, NULL, DumpGas, NULL,
  360. ValidatePccMemoryIoGas,NULL },
  361. { L"Error Status Mask", 8, 80, L"0x%lx", NULL, NULL, NULL, NULL },
  362. { L"Nominal Latency", 4, 88, L"0x%x", NULL, NULL, NULL, NULL },
  363. { L"Minimum Request Turnaround Time",4, 92, L"0x%x", NULL, NULL, NULL, NULL }
  364. };
  365. /**
  366. This function parses the PCC Subspace type 0.
  367. @param [in] Ptr Pointer to the start of Subspace Structure.
  368. @param [in] Length Length of the Subspace Structure.
  369. **/
  370. STATIC
  371. VOID
  372. DumpPccSubspaceType0 (
  373. IN UINT8 *Ptr,
  374. IN UINT8 Length
  375. )
  376. {
  377. ParseAcpi (
  378. TRUE,
  379. 2,
  380. "Subspace Type 0",
  381. Ptr,
  382. Length,
  383. PARSER_PARAMS (PccSubspaceType0Parser)
  384. );
  385. }
  386. /**
  387. This function parses the PCC Subspace type 1.
  388. @param [in] Ptr Pointer to the start of the Subspace Structure.
  389. @param [in] Length Length of the Subspace Structure.
  390. **/
  391. STATIC
  392. VOID
  393. DumpPccSubspaceType1 (
  394. IN UINT8 *Ptr,
  395. IN UINT8 Length
  396. )
  397. {
  398. ParseAcpi (
  399. TRUE,
  400. 2,
  401. "Subspace Type 1",
  402. Ptr,
  403. Length,
  404. PARSER_PARAMS (PccSubspaceType1Parser)
  405. );
  406. }
  407. /**
  408. This function parses the PCC Subspace type 2.
  409. @param [in] Ptr Pointer to the start of the Subspace Structure.
  410. @param [in] Length Length of the Subspace Structure.
  411. **/
  412. STATIC
  413. VOID
  414. DumpPccSubspaceType2 (
  415. IN UINT8 *Ptr,
  416. IN UINT8 Length
  417. )
  418. {
  419. ParseAcpi (
  420. TRUE,
  421. 2,
  422. "Subspace Type 2",
  423. Ptr,
  424. Length,
  425. PARSER_PARAMS (PccSubspaceType2Parser)
  426. );
  427. }
  428. /**
  429. This function parses the PCC Subspace type 3.
  430. @param [in] Ptr Pointer to the start of the Subspace Structure.
  431. @param [in] Length Length of the Subspace Structure.
  432. **/
  433. STATIC
  434. VOID
  435. DumpPccSubspaceType3 (
  436. IN UINT8 *Ptr,
  437. IN UINT8 Length
  438. )
  439. {
  440. ParseAcpi (
  441. TRUE,
  442. 2,
  443. "Subspace Type 3",
  444. Ptr,
  445. Length,
  446. PARSER_PARAMS (PccSubspaceType3Parser)
  447. );
  448. }
  449. /**
  450. This function parses the PCC Subspace type 4.
  451. @param [in] Ptr Pointer to the start of the Subspace Structure.
  452. @param [in] Length Length of the Subspace Structure.
  453. **/
  454. STATIC
  455. VOID
  456. DumpPccSubspaceType4 (
  457. IN UINT8 *Ptr,
  458. IN UINT8 Length
  459. )
  460. {
  461. ParseAcpi (
  462. TRUE,
  463. 2,
  464. "Subspace Type 4",
  465. Ptr,
  466. Length,
  467. PARSER_PARAMS (PccSubspaceType3Parser)
  468. );
  469. }
  470. /**
  471. This function parses the PCC Subspace type 5.
  472. @param [in] Ptr Pointer to the start of the Subspace Structure.
  473. @param [in] Length Length of the Subspace Structure.
  474. **/
  475. STATIC
  476. VOID
  477. DumpPccSubspaceType5 (
  478. IN UINT8 *Ptr,
  479. IN UINT8 Length
  480. )
  481. {
  482. ParseAcpi (
  483. TRUE,
  484. 2,
  485. "Subspace Type 5",
  486. Ptr,
  487. Length,
  488. PARSER_PARAMS (PccSubspaceType5Parser)
  489. );
  490. }
  491. /**
  492. This function parses the ACPI PCCT table including its sub-structures
  493. of type 0 through 4.
  494. When trace is enabled this function parses the PCCT table and
  495. traces the ACPI table fields.
  496. This function also performs validation of the ACPI table fields.
  497. @param [in] Trace If TRUE, trace the ACPI fields.
  498. @param [in] Ptr Pointer to the start of the buffer.
  499. @param [in] AcpiTableLength Length of the ACPI table.
  500. @param [in] AcpiTableRevision Revision of the ACPI table.
  501. **/
  502. VOID
  503. EFIAPI
  504. ParseAcpiPcct (
  505. IN BOOLEAN Trace,
  506. IN UINT8 *Ptr,
  507. IN UINT32 AcpiTableLength,
  508. IN UINT8 AcpiTableRevision
  509. )
  510. {
  511. UINT32 Offset;
  512. UINT8 *PccSubspacePtr;
  513. UINTN SubspaceCount;
  514. if (!Trace) {
  515. return;
  516. }
  517. Offset = ParseAcpi (
  518. TRUE,
  519. 0,
  520. "PCCT",
  521. Ptr,
  522. AcpiTableLength,
  523. PARSER_PARAMS (PcctParser)
  524. );
  525. PccSubspacePtr = Ptr + Offset;
  526. SubspaceCount = 0;
  527. while (Offset < AcpiTableLength) {
  528. // Parse common structure header to obtain Type and Length.
  529. ParseAcpi (
  530. FALSE,
  531. 0,
  532. NULL,
  533. PccSubspacePtr,
  534. AcpiTableLength - Offset,
  535. PARSER_PARAMS (PccSubspaceHeaderParser)
  536. );
  537. // Check if the values used to control the parsing logic have been
  538. // successfully read.
  539. if ((PccSubspaceType == NULL) ||
  540. (PccSubspaceLength == NULL))
  541. {
  542. IncrementErrorCount ();
  543. Print (
  544. L"ERROR: Insufficient remaining table buffer length to read the " \
  545. L"structure header. Length = %u.\n",
  546. AcpiTableLength - Offset
  547. );
  548. return;
  549. }
  550. // Validate Structure length
  551. if ((*PccSubspaceLength == 0) ||
  552. ((Offset + (*PccSubspaceLength)) > AcpiTableLength))
  553. {
  554. IncrementErrorCount ();
  555. Print (
  556. L"ERROR: Invalid Structure length. " \
  557. L"Length = %u. Offset = %u. AcpiTableLength = %u.\n",
  558. *PccSubspaceLength,
  559. Offset,
  560. AcpiTableLength
  561. );
  562. return;
  563. }
  564. switch (*PccSubspaceType) {
  565. case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_GENERIC:
  566. DumpPccSubspaceType0 (
  567. PccSubspacePtr,
  568. *PccSubspaceLength
  569. );
  570. break;
  571. case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_1_HW_REDUCED_COMMUNICATIONS:
  572. DumpPccSubspaceType1 (
  573. PccSubspacePtr,
  574. *PccSubspaceLength
  575. );
  576. break;
  577. case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_2_HW_REDUCED_COMMUNICATIONS:
  578. DumpPccSubspaceType2 (
  579. PccSubspacePtr,
  580. *PccSubspaceLength
  581. );
  582. break;
  583. case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_3_EXTENDED_PCC:
  584. DumpPccSubspaceType3 (
  585. PccSubspacePtr,
  586. *PccSubspaceLength
  587. );
  588. break;
  589. case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC:
  590. DumpPccSubspaceType4 (
  591. PccSubspacePtr,
  592. *PccSubspaceLength
  593. );
  594. break;
  595. case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_5_HW_REGISTERS_COMMUNICATIONS:
  596. DumpPccSubspaceType5 (
  597. PccSubspacePtr,
  598. *PccSubspaceLength
  599. );
  600. break;
  601. default:
  602. IncrementErrorCount ();
  603. Print (
  604. L"ERROR: Unknown PCC subspace structure:"
  605. L" Type = %u, Length = %u\n",
  606. PccSubspaceType,
  607. *PccSubspaceLength
  608. );
  609. }
  610. PccSubspacePtr += *PccSubspaceLength;
  611. Offset += *PccSubspaceLength;
  612. SubspaceCount++;
  613. } // while
  614. if (SubspaceCount > MAX_PCC_SUBSPACES) {
  615. IncrementErrorCount ();
  616. Print (L"ERROR: Too many PCC subspaces.");
  617. }
  618. }