HmatParser.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667
  1. /** @file
  2. HMAT table parser
  3. Copyright (c) 2020, Arm Limited.
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. @par Reference(s):
  6. - ACPI 6.3 Specification - January 2019
  7. @par Glossary:
  8. - MPDA - Memory Proximity Domain Attributes
  9. - SLLBI - System Locality Latency and Bandwidth Information
  10. - MSCI - Memory Side Cache Information
  11. - Dom - Domain
  12. **/
  13. #include <Library/PrintLib.h>
  14. #include <Library/BaseLib.h>
  15. #include <Library/UefiLib.h>
  16. #include "AcpiParser.h"
  17. #include "AcpiView.h"
  18. // Maximum Memory Domain matrix print size.
  19. #define MAX_MEMORY_DOMAIN_TARGET_PRINT_MATRIX 10
  20. // Local variables
  21. STATIC CONST UINT16 *HmatStructureType;
  22. STATIC CONST UINT32 *HmatStructureLength;
  23. STATIC CONST UINT32 *NumberInitiatorProximityDomain;
  24. STATIC CONST UINT32 *NumberTargetProximityDomain;
  25. STATIC CONST
  26. EFI_ACPI_6_4_HMAT_STRUCTURE_SYSTEM_LOCALITY_LATENCY_AND_BANDWIDTH_INFO_FLAGS *
  27. SllbiFlags;
  28. STATIC CONST UINT8 *SllbiDataType;
  29. STATIC CONST UINT16 *NumberSMBIOSHandles;
  30. STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;
  31. /**
  32. Names of System Locality Latency Bandwidth Information (SLLBI) data types
  33. **/
  34. STATIC CONST CHAR16 *SllbiNames[] = {
  35. L"Access %sLatency%s",
  36. L"Read %sLatency%s",
  37. L"Write %sLatency%s",
  38. L"Access %sBandwidth%s",
  39. L"Read %sBandwidth%s",
  40. L"Write %sBandwidth%s"
  41. };
  42. /**
  43. This function validates the Cache Attributes field.
  44. @param [in] Ptr Pointer to the start of the field data.
  45. @param [in] Context Pointer to context specific information e.g. this
  46. could be a pointer to the ACPI table header.
  47. **/
  48. STATIC
  49. VOID
  50. EFIAPI
  51. ValidateCacheAttributes (
  52. IN UINT8 *Ptr,
  53. IN VOID *Context
  54. )
  55. {
  56. EFI_ACPI_6_4_HMAT_STRUCTURE_MEMORY_SIDE_CACHE_INFO_CACHE_ATTRIBUTES *
  57. Attributes;
  58. Attributes =
  59. (EFI_ACPI_6_4_HMAT_STRUCTURE_MEMORY_SIDE_CACHE_INFO_CACHE_ATTRIBUTES *)Ptr;
  60. if (Attributes->TotalCacheLevels > 0x3) {
  61. IncrementErrorCount ();
  62. Print (
  63. L"\nERROR: Attributes bits [3:0] have invalid value: 0x%x",
  64. Attributes->TotalCacheLevels
  65. );
  66. }
  67. if (Attributes->CacheLevel > 0x3) {
  68. IncrementErrorCount ();
  69. Print (
  70. L"\nERROR: Attributes bits [7:4] have invalid value: 0x%x",
  71. Attributes->CacheLevel
  72. );
  73. }
  74. if (Attributes->CacheAssociativity > 0x2) {
  75. IncrementErrorCount ();
  76. Print (
  77. L"\nERROR: Attributes bits [11:8] have invalid value: 0x%x",
  78. Attributes->CacheAssociativity
  79. );
  80. }
  81. if (Attributes->WritePolicy > 0x2) {
  82. IncrementErrorCount ();
  83. Print (
  84. L"\nERROR: Attributes bits [15:12] have invalid value: 0x%x",
  85. Attributes->WritePolicy
  86. );
  87. }
  88. }
  89. /**
  90. Dumps the cache attributes field
  91. @param [in] Format Optional format string for tracing the data.
  92. @param [in] Ptr Pointer to the start of the buffer.
  93. **/
  94. STATIC
  95. VOID
  96. EFIAPI
  97. DumpCacheAttributes (
  98. IN CONST CHAR16 *Format OPTIONAL,
  99. IN UINT8 *Ptr
  100. )
  101. {
  102. EFI_ACPI_6_4_HMAT_STRUCTURE_MEMORY_SIDE_CACHE_INFO_CACHE_ATTRIBUTES *
  103. Attributes;
  104. Attributes =
  105. (EFI_ACPI_6_4_HMAT_STRUCTURE_MEMORY_SIDE_CACHE_INFO_CACHE_ATTRIBUTES *)Ptr;
  106. Print (L"\n");
  107. PrintFieldName (4, L"Total Cache Levels");
  108. Print (L"%d\n", Attributes->TotalCacheLevels);
  109. PrintFieldName (4, L"Cache Level");
  110. Print (L"%d\n", Attributes->CacheLevel);
  111. PrintFieldName (4, L"Cache Associativity");
  112. Print (L"%d\n", Attributes->CacheAssociativity);
  113. PrintFieldName (4, L"Write Policy");
  114. Print (L"%d\n", Attributes->WritePolicy);
  115. PrintFieldName (4, L"Cache Line Size");
  116. Print (L"%d\n", Attributes->CacheLineSize);
  117. }
  118. /**
  119. An ACPI_PARSER array describing the ACPI HMAT Table.
  120. */
  121. STATIC CONST ACPI_PARSER HmatParser[] = {
  122. PARSE_ACPI_HEADER (&AcpiHdrInfo),
  123. { L"Reserved", 4,36, NULL, NULL, NULL, NULL, NULL }
  124. };
  125. /**
  126. An ACPI_PARSER array describing the HMAT structure header.
  127. */
  128. STATIC CONST ACPI_PARSER HmatStructureHeaderParser[] = {
  129. { L"Type", 2, 0, NULL, NULL, (VOID **)&HmatStructureType, NULL, NULL },
  130. { L"Reserved", 2, 2, NULL, NULL, NULL, NULL, NULL },
  131. { L"Length", 4, 4, NULL, NULL, (VOID **)&HmatStructureLength, NULL, NULL }
  132. };
  133. /**
  134. An ACPI PARSER array describing the Memory Proximity Domain Attributes
  135. Structure - Type 0.
  136. */
  137. STATIC CONST ACPI_PARSER MemProximityDomainAttributeParser[] = {
  138. { L"Type", 2, 0, L"0x%x", NULL, NULL, NULL, NULL },
  139. { L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL },
  140. { L"Length", 4, 4, L"%d", NULL, NULL, NULL, NULL },
  141. { L"Flags", 2, 8, L"0x%x", NULL, NULL, NULL, NULL },
  142. { L"Reserved", 2, 10, L"0x%x", NULL, NULL, NULL, NULL },
  143. { L"Proximity Dom for initiator", 4, 12, L"0x%x", NULL, NULL, NULL, NULL },
  144. { L"Proximity Dom for memory", 4, 16, L"0x%x", NULL, NULL, NULL, NULL },
  145. { L"Reserved", 4, 20, L"0x%x", NULL, NULL, NULL, NULL },
  146. { L"Reserved", 8, 24, L"0x%lx", NULL, NULL, NULL, NULL },
  147. { L"Reserved", 8, 32, L"0x%lx", NULL, NULL, NULL, NULL }
  148. };
  149. /**
  150. An ACPI PARSER array describing the System Locality Latency and Bandwidth
  151. Information Structure - Type 1.
  152. */
  153. STATIC CONST ACPI_PARSER SllbiParser[] = {
  154. { L"Type", 2, 0, L"0x%x", NULL, NULL, NULL, NULL },
  155. { L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL },
  156. { L"Length", 4, 4, L"%d", NULL, NULL, NULL, NULL },
  157. { L"Flags", 1, 8, L"0x%x", NULL, (VOID **)&SllbiFlags, NULL, NULL },
  158. { L"Data type", 1, 9, L"0x%x", NULL, (VOID **)&SllbiDataType, NULL, NULL },
  159. { L"Min Transfer Size", 1, 10, L"%d", NULL, NULL, NULL, NULL },
  160. { L"Reserved", 1, 11, L"0x%x", NULL, NULL, NULL, NULL },
  161. { L"Initiator Proximity Dom Count", 4, 12, L"%d", NULL,
  162. (VOID **)&NumberInitiatorProximityDomain, NULL, NULL },
  163. { L"Target Proximity Dom Count", 4, 16, L"%d", NULL,
  164. (VOID **)&NumberTargetProximityDomain, NULL, NULL },
  165. { L"Reserved", 4, 20, L"0x%x", NULL, NULL, NULL, NULL },
  166. { L"Entry Base Unit", 8, 24, L"0x%lx", NULL, NULL, NULL, NULL }
  167. // initiator Proximity Domain list ...
  168. // target Proximity Domain list ...
  169. // Latency/Bandwidth matrix ...
  170. };
  171. /**
  172. An ACPI PARSER array describing the Memory Side Cache Information
  173. Structure - Type 2.
  174. */
  175. STATIC CONST ACPI_PARSER MemSideCacheInfoParser[] = {
  176. { L"Type", 2, 0, L"0x%x", NULL, NULL, NULL, NULL },
  177. { L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL },
  178. { L"Length", 4, 4, L"%d", NULL, NULL, NULL, NULL },
  179. { L"Proximity Dom for memory", 4, 8, L"0x%x", NULL, NULL, NULL, NULL },
  180. { L"Reserved", 4, 12, L"0x%x", NULL, NULL, NULL, NULL },
  181. { L"Memory Side Cache Size", 8, 16, L"0x%lx", NULL, NULL, NULL, NULL },
  182. { L"Cache Attributes", 4, 24, NULL, DumpCacheAttributes, NULL,
  183. ValidateCacheAttributes, NULL },
  184. { L"Reserved", 2, 28, L"0x%x", NULL, NULL, NULL, NULL },
  185. { L"SMBIOS Handle Count", 2, 30, L"%d", NULL,
  186. (VOID **)&NumberSMBIOSHandles, NULL, NULL }
  187. // SMBIOS handles List ...
  188. };
  189. /**
  190. This function parses the Memory Proximity Domain Attributes
  191. Structure (Type 0).
  192. @param [in] Ptr Pointer to the start of the Memory Proximity Domain
  193. Attributes Structure data.
  194. @param [in] Length Length of the Memory Proximity Domain Attributes
  195. Structure.
  196. **/
  197. STATIC
  198. VOID
  199. DumpMpda (
  200. IN UINT8 *Ptr,
  201. IN UINT32 Length
  202. )
  203. {
  204. ParseAcpi (
  205. TRUE,
  206. 2,
  207. "Memory Proximity Domain Attributes Structure",
  208. Ptr,
  209. Length,
  210. PARSER_PARAMS (MemProximityDomainAttributeParser)
  211. );
  212. }
  213. /**
  214. This function parses the System Locality Latency and Bandwidth Information
  215. Structure (Type 1).
  216. @param [in] Ptr Pointer to the start of the System Locality Latency and
  217. Bandwidth Information Structure data.
  218. @param [in] Length Length of the System Locality Latency and Bandwidth
  219. Information Structure.
  220. **/
  221. STATIC
  222. VOID
  223. DumpSllbi (
  224. IN UINT8 *Ptr,
  225. IN UINT32 Length
  226. )
  227. {
  228. CONST UINT32 *InitiatorProximityDomainList;
  229. CONST UINT32 *TargetProximityDomainList;
  230. CONST UINT16 *LatencyBandwidthMatrix;
  231. UINT32 Offset;
  232. CHAR16 Buffer[OUTPUT_FIELD_COLUMN_WIDTH];
  233. CHAR16 SecondBuffer[OUTPUT_FIELD_COLUMN_WIDTH];
  234. UINT32 RequiredTableSize;
  235. UINT32 Index;
  236. UINT32 IndexInitiator;
  237. UINT32 IndexTarget;
  238. UINT32 TargetStartOffset;
  239. Offset = ParseAcpi (
  240. TRUE,
  241. 2,
  242. "System Locality Latency and Bandwidth Information Structure",
  243. Ptr,
  244. Length,
  245. PARSER_PARAMS (SllbiParser)
  246. );
  247. // Check if the values used to control the parsing logic have been
  248. // successfully read.
  249. if ((SllbiFlags == NULL) ||
  250. (SllbiDataType == NULL) ||
  251. (NumberInitiatorProximityDomain == NULL) ||
  252. (NumberTargetProximityDomain == NULL))
  253. {
  254. IncrementErrorCount ();
  255. Print (
  256. L"ERROR: Insufficient remaining table buffer length to read the " \
  257. L"SLLBI structure header. Length = %d.\n",
  258. Length
  259. );
  260. return;
  261. }
  262. RequiredTableSize = (*NumberInitiatorProximityDomain * sizeof (UINT32)) +
  263. (*NumberTargetProximityDomain * sizeof (UINT32)) +
  264. (*NumberInitiatorProximityDomain *
  265. *NumberTargetProximityDomain * sizeof (UINT16)) +
  266. Offset;
  267. if (RequiredTableSize > Length) {
  268. IncrementErrorCount ();
  269. Print (
  270. L"ERROR: Insufficient System Locality Latency and Bandwidth" \
  271. L"Information Structure length. TableLength = %d. " \
  272. L"RequiredTableLength = %d.\n",
  273. Length,
  274. RequiredTableSize
  275. );
  276. return;
  277. }
  278. InitiatorProximityDomainList = (UINT32 *)(Ptr + Offset);
  279. TargetProximityDomainList = InitiatorProximityDomainList +
  280. *NumberInitiatorProximityDomain;
  281. LatencyBandwidthMatrix = (UINT16 *)(TargetProximityDomainList +
  282. *NumberTargetProximityDomain);
  283. // Display each element of the Initiator Proximity Domain list
  284. for (Index = 0; Index < *NumberInitiatorProximityDomain; Index++) {
  285. UnicodeSPrint (
  286. Buffer,
  287. sizeof (Buffer),
  288. L"Initiator Proximity Dom [%d]",
  289. Index
  290. );
  291. PrintFieldName (4, Buffer);
  292. Print (
  293. L"0x%x\n",
  294. InitiatorProximityDomainList[Index]
  295. );
  296. }
  297. // Display each element of the Target Proximity Domain list
  298. for (Index = 0; Index < *NumberTargetProximityDomain; Index++) {
  299. UnicodeSPrint (
  300. Buffer,
  301. sizeof (Buffer),
  302. L"Target Proximity Dom [%d]",
  303. Index
  304. );
  305. PrintFieldName (4, Buffer);
  306. Print (
  307. L"0x%x\n",
  308. TargetProximityDomainList[Index]
  309. );
  310. }
  311. // Create base name depending on Data Type in this Structure
  312. if (*SllbiDataType >= ARRAY_SIZE (SllbiNames)) {
  313. IncrementErrorCount ();
  314. Print (L"Error: Unkown Data Type. DataType = 0x%x.\n", *SllbiDataType);
  315. return;
  316. }
  317. StrCpyS (Buffer, sizeof (Buffer), SllbiNames[*SllbiDataType]);
  318. // Adjust base name depending on Memory Hierarchy in this Structure
  319. switch (SllbiFlags->MemoryHierarchy) {
  320. case 0:
  321. UnicodeSPrint (
  322. SecondBuffer,
  323. sizeof (SecondBuffer),
  324. Buffer,
  325. L"",
  326. L"%s"
  327. );
  328. break;
  329. case 1:
  330. case 2:
  331. case 3:
  332. UnicodeSPrint (
  333. SecondBuffer,
  334. sizeof (SecondBuffer),
  335. Buffer,
  336. L"Hit ",
  337. L"%s"
  338. );
  339. break;
  340. default:
  341. IncrementErrorCount ();
  342. Print (
  343. L"Error: Invalid Memory Hierarchy. MemoryHierarchy = %d.\n",
  344. SllbiFlags->MemoryHierarchy
  345. );
  346. return;
  347. } // switch
  348. if (*NumberTargetProximityDomain <= MAX_MEMORY_DOMAIN_TARGET_PRINT_MATRIX) {
  349. // Display the latency/bandwidth matrix as a matrix
  350. UnicodeSPrint (
  351. Buffer,
  352. sizeof (Buffer),
  353. SecondBuffer,
  354. L""
  355. );
  356. PrintFieldName (4, Buffer);
  357. Print (L"\n Target : X-axis (Horizontal)");
  358. Print (L"\n Initiator : Y-axis (Vertical)");
  359. Print (L"\n |");
  360. for (IndexTarget = 0;
  361. IndexTarget < *NumberTargetProximityDomain;
  362. IndexTarget++)
  363. {
  364. Print (L" %2d", IndexTarget);
  365. }
  366. Print (L"\n ---+");
  367. for (IndexTarget = 0;
  368. IndexTarget < *NumberTargetProximityDomain;
  369. IndexTarget++)
  370. {
  371. Print (L"------");
  372. }
  373. Print (L"\n");
  374. TargetStartOffset = 0;
  375. for (IndexInitiator = 0;
  376. IndexInitiator < *NumberInitiatorProximityDomain;
  377. IndexInitiator++)
  378. {
  379. Print (L" %2d |", IndexInitiator);
  380. for (IndexTarget = 0;
  381. IndexTarget < *NumberTargetProximityDomain;
  382. IndexTarget++)
  383. {
  384. Print (
  385. L" %5d",
  386. LatencyBandwidthMatrix[TargetStartOffset + IndexTarget]
  387. );
  388. } // for Target
  389. Print (L"\n");
  390. TargetStartOffset += (*NumberTargetProximityDomain);
  391. } // for Initiator
  392. Print (L"\n");
  393. } else {
  394. // Display the latency/bandwidth matrix as a list
  395. UnicodeSPrint (
  396. Buffer,
  397. sizeof (Buffer),
  398. SecondBuffer,
  399. L" [%d][%d]"
  400. );
  401. TargetStartOffset = 0;
  402. for (IndexInitiator = 0;
  403. IndexInitiator < *NumberInitiatorProximityDomain;
  404. IndexInitiator++)
  405. {
  406. for (IndexTarget = 0;
  407. IndexTarget < *NumberTargetProximityDomain;
  408. IndexTarget++)
  409. {
  410. UnicodeSPrint (
  411. SecondBuffer,
  412. sizeof (SecondBuffer),
  413. Buffer,
  414. IndexInitiator,
  415. IndexTarget
  416. );
  417. PrintFieldName (4, SecondBuffer);
  418. Print (
  419. L"%d\n",
  420. LatencyBandwidthMatrix[TargetStartOffset + IndexTarget]
  421. );
  422. } // for Target
  423. TargetStartOffset += (*NumberTargetProximityDomain);
  424. } // for Initiator
  425. }
  426. }
  427. /**
  428. This function parses the Memory Side Cache Information Structure (Type 2).
  429. @param [in] Ptr Pointer to the start of the Memory Side Cache Information
  430. Structure data.
  431. @param [in] Length Length of the Memory Side Cache Information Structure.
  432. **/
  433. STATIC
  434. VOID
  435. DumpMsci (
  436. IN UINT8 *Ptr,
  437. IN UINT32 Length
  438. )
  439. {
  440. CONST UINT16 *SMBIOSHandlesList;
  441. CHAR16 Buffer[OUTPUT_FIELD_COLUMN_WIDTH];
  442. UINT32 Offset;
  443. UINT16 Index;
  444. Offset = ParseAcpi (
  445. TRUE,
  446. 2,
  447. "Memory Side Cache Information Structure",
  448. Ptr,
  449. Length,
  450. PARSER_PARAMS (MemSideCacheInfoParser)
  451. );
  452. // Check if the values used to control the parsing logic have been
  453. // successfully read.
  454. if (NumberSMBIOSHandles == NULL) {
  455. IncrementErrorCount ();
  456. Print (
  457. L"ERROR: Insufficient remaining table buffer length to read the " \
  458. L"MSCI structure header. Length = %d.\n",
  459. Length
  460. );
  461. return;
  462. }
  463. if ((*NumberSMBIOSHandles * sizeof (UINT16)) > (Length - Offset)) {
  464. IncrementErrorCount ();
  465. Print (
  466. L"ERROR: Invalid Number of SMBIOS Handles. SMBIOSHandlesCount = %d." \
  467. L"RemainingBufferLength = %d.\n",
  468. *NumberSMBIOSHandles,
  469. Length - Offset
  470. );
  471. return;
  472. }
  473. SMBIOSHandlesList = (UINT16 *)(Ptr + Offset);
  474. for (Index = 0; Index < *NumberSMBIOSHandles; Index++) {
  475. UnicodeSPrint (
  476. Buffer,
  477. sizeof (Buffer),
  478. L"SMBIOS Handles [%d]",
  479. Index
  480. );
  481. PrintFieldName (4, Buffer);
  482. Print (
  483. L"0x%x\n",
  484. SMBIOSHandlesList[Index]
  485. );
  486. }
  487. }
  488. /**
  489. This function parses the ACPI HMAT table.
  490. When trace is enabled this function parses the HMAT table and
  491. traces the ACPI table fields.
  492. This function parses the following HMAT structures:
  493. - Memory Proximity Domain Attributes Structure (Type 0)
  494. - System Locality Latency and Bandwidth Info Structure (Type 1)
  495. - Memory Side Cache Info structure (Type 2)
  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. ParseAcpiHmat (
  505. IN BOOLEAN Trace,
  506. IN UINT8 *Ptr,
  507. IN UINT32 AcpiTableLength,
  508. IN UINT8 AcpiTableRevision
  509. )
  510. {
  511. UINT32 Offset;
  512. UINT8 *HmatStructurePtr;
  513. if (!Trace) {
  514. return;
  515. }
  516. Offset = ParseAcpi (
  517. Trace,
  518. 0,
  519. "HMAT",
  520. Ptr,
  521. AcpiTableLength,
  522. PARSER_PARAMS (HmatParser)
  523. );
  524. HmatStructurePtr = Ptr + Offset;
  525. while (Offset < AcpiTableLength) {
  526. // Parse HMAT Structure Header to obtain Type and Length.
  527. ParseAcpi (
  528. FALSE,
  529. 0,
  530. NULL,
  531. HmatStructurePtr,
  532. AcpiTableLength - Offset,
  533. PARSER_PARAMS (HmatStructureHeaderParser)
  534. );
  535. // Check if the values used to control the parsing logic have been
  536. // successfully read.
  537. if ((HmatStructureType == NULL) ||
  538. (HmatStructureLength == NULL))
  539. {
  540. IncrementErrorCount ();
  541. Print (
  542. L"ERROR: Insufficient remaining table buffer length to read the " \
  543. L"HMAT structure header. Length = %d.\n",
  544. AcpiTableLength - Offset
  545. );
  546. return;
  547. }
  548. // Validate HMAT Structure length.
  549. if ((*HmatStructureLength == 0) ||
  550. ((Offset + (*HmatStructureLength)) > AcpiTableLength))
  551. {
  552. IncrementErrorCount ();
  553. Print (
  554. L"ERROR: Invalid HMAT Structure length. " \
  555. L"Length = %d. Offset = %d. AcpiTableLength = %d.\n",
  556. *HmatStructureLength,
  557. Offset,
  558. AcpiTableLength
  559. );
  560. return;
  561. }
  562. switch (*HmatStructureType) {
  563. case EFI_ACPI_6_4_HMAT_TYPE_MEMORY_PROXIMITY_DOMAIN_ATTRIBUTES:
  564. DumpMpda (
  565. HmatStructurePtr,
  566. *HmatStructureLength
  567. );
  568. break;
  569. case EFI_ACPI_6_4_HMAT_TYPE_SYSTEM_LOCALITY_LATENCY_AND_BANDWIDTH_INFO:
  570. DumpSllbi (
  571. HmatStructurePtr,
  572. *HmatStructureLength
  573. );
  574. break;
  575. case EFI_ACPI_6_4_HMAT_TYPE_MEMORY_SIDE_CACHE_INFO:
  576. DumpMsci (
  577. HmatStructurePtr,
  578. *HmatStructureLength
  579. );
  580. break;
  581. default:
  582. IncrementErrorCount ();
  583. Print (
  584. L"ERROR: Unknown HMAT structure:"
  585. L" Type = %d, Length = %d\n",
  586. *HmatStructureType,
  587. *HmatStructureLength
  588. );
  589. break;
  590. } // switch
  591. HmatStructurePtr += *HmatStructureLength;
  592. Offset += *HmatStructureLength;
  593. } // while
  594. }