ShellPkg: Add acpiview tool to dump ACPI tables
[mirror_edk2.git] / ShellPkg / Library / UefiShellAcpiViewCommandLib / Parsers / Srat / SratParser.c
1 /**\r
2   SRAT table parser\r
3 \r
4   Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.\r
5   This program and the accompanying materials\r
6   are licensed and made available under the terms and conditions of the BSD License\r
7   which accompanies this distribution.  The full text of the license may be found at\r
8   http://opensource.org/licenses/bsd-license.php\r
9 \r
10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12 \r
13   @par Reference(s):\r
14     - ACPI 6.2 Specification - Errata A, September 2017\r
15 **/\r
16 \r
17 #include <IndustryStandard/Acpi.h>\r
18 #include <Library/PrintLib.h>\r
19 #include <Library/UefiLib.h>\r
20 #include "AcpiParser.h"\r
21 #include "AcpiTableParser.h"\r
22 \r
23 // Local Variables\r
24 STATIC CONST UINT8* SratRAType;\r
25 STATIC CONST UINT8* SratRALength;\r
26 STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;\r
27 \r
28 /** This function validates the Reserved field in the SRAT table header.\r
29 \r
30   @param [in] Ptr     Pointer to the start of the field data.\r
31   @param [in] Context Pointer to context specific information e.g. this\r
32                       could be a pointer to the ACPI table header.\r
33 */\r
34 STATIC\r
35 VOID\r
36 EFIAPI\r
37 ValidateSratReserved (\r
38   IN UINT8* Ptr,\r
39   IN VOID*  Context\r
40   );\r
41 \r
42 /** This function traces the APIC Proximity Domain field.\r
43 \r
44   @param [in] Format  Format string for tracing the data.\r
45   @param [in] Ptr     Pointer to the start of the buffer.\r
46 */\r
47 STATIC\r
48 VOID\r
49 DumpSratApicProximity (\r
50   IN  CONST CHAR16*  Format,\r
51   IN  UINT8*         Ptr\r
52   );\r
53 \r
54 /** An ACPI_PARSER array describing the SRAT Table.\r
55 */\r
56 STATIC CONST ACPI_PARSER SratParser[] = {\r
57   PARSE_ACPI_HEADER (&AcpiHdrInfo),\r
58   {L"Reserved", 4, 36, L"0x%x", NULL, NULL, ValidateSratReserved, NULL},\r
59   {L"Reserved", 8, 40, L"0x%lx", NULL, NULL, NULL, NULL}\r
60 };\r
61 \r
62 /** An ACPI_PARSER array describing the Resource Allocation\r
63     structure header.\r
64 */\r
65 STATIC CONST ACPI_PARSER SratResourceAllocationParser[] = {\r
66   {L"Type", 1, 0, NULL, NULL, (VOID**)&SratRAType, NULL, NULL},\r
67   {L"Length", 1, 1, NULL, NULL, (VOID**)&SratRALength, NULL, NULL}\r
68 };\r
69 \r
70 /** An ACPI_PARSER array describing the GICC Affinity structure.\r
71 */\r
72 STATIC CONST ACPI_PARSER SratGicCAffinityParser[] = {\r
73   {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},\r
74   {L"Length", 1, 1, L"0x%x", NULL, NULL, NULL, NULL},\r
75 \r
76   {L"Proximity Domain", 4, 2, L"0x%x", NULL, NULL, NULL, NULL},\r
77   {L"ACPI Processor UID", 4, 6, L"0x%x", NULL, NULL, NULL, NULL},\r
78   {L"Flags", 4, 10, L"0x%x", NULL, NULL, NULL, NULL},\r
79   {L"Clock Domain", 4, 14, L"0x%x", NULL, NULL, NULL, NULL}\r
80 };\r
81 \r
82 /** An ACPI_PARSER array describing the GIC ITS Affinity structure.\r
83 */\r
84 STATIC CONST ACPI_PARSER SratGicITSAffinityParser[] = {\r
85   {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},\r
86   {L"Length", 1, 1, L"0x%x", NULL, NULL, NULL, NULL},\r
87 \r
88   {L"Proximity Domain", 4, 2, L"0x%x", NULL, NULL, NULL, NULL},\r
89   {L"Reserved", 2, 6, L"0x%x", NULL, NULL, NULL, NULL},\r
90   {L"ITS Id", 4, 8, L"0x%x", NULL, NULL, NULL, NULL},\r
91 };\r
92 \r
93 /** An ACPI_PARSER array describing the Memory Affinity structure.\r
94 */\r
95 STATIC CONST ACPI_PARSER SratMemAffinityParser[] = {\r
96   {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},\r
97   {L"Length", 1, 1, L"0x%x", NULL, NULL, NULL, NULL},\r
98 \r
99   {L"Proximity Domain", 4, 2, L"0x%x", NULL, NULL, NULL, NULL},\r
100   {L"Reserved", 2, 6, L"0x%x", NULL, NULL, NULL, NULL},\r
101   {L"Base Address Low", 4, 8, L"0x%x", NULL, NULL, NULL, NULL},\r
102   {L"Base Address High", 4, 12, L"0x%x", NULL, NULL, NULL, NULL},\r
103   {L"Length Low", 4, 16, L"0x%x", NULL, NULL, NULL, NULL},\r
104   {L"Length High", 4, 20, L"0x%x", NULL, NULL, NULL, NULL},\r
105   {L"Reserved", 4, 24, L"0x%x", NULL, NULL, NULL, NULL},\r
106   {L"Flags", 4, 28, L"0x%x", NULL, NULL, NULL, NULL},\r
107   {L"Reserved", 8, 32, L"0x%lx", NULL, NULL, NULL, NULL}\r
108 };\r
109 \r
110 /** An ACPI_PARSER array describing the APIC/SAPIC Affinity structure.\r
111 */\r
112 STATIC CONST ACPI_PARSER SratApciSapicAffinityParser[] = {\r
113   {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},\r
114   {L"Length", 1, 1, L"0x%x", NULL, NULL, NULL, NULL},\r
115 \r
116   {L"Proximity Domain [7:0]", 1, 2, L"0x%x", NULL, NULL, NULL, NULL},\r
117   {L"APIC ID", 1, 3, L"0x%x", NULL, NULL, NULL, NULL},\r
118   {L"Flags", 4, 4, L"0x%x", NULL, NULL, NULL, NULL},\r
119   {L"Local SAPIC EID", 1, 8, L"0x%x", NULL, NULL, NULL, NULL},\r
120   {L"Proximity Domain [31:8]", 3, 9, L"0x%x", DumpSratApicProximity,\r
121    NULL, NULL, NULL},\r
122   {L"Clock Domain", 4, 12, L"0x%x", NULL, NULL, NULL, NULL}\r
123 };\r
124 \r
125 /** An ACPI_PARSER array describing the Processor Local x2APIC\r
126     Affinity structure.\r
127 */\r
128 STATIC CONST ACPI_PARSER SratX2ApciAffinityParser[] = {\r
129   {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},\r
130   {L"Length", 1, 1, L"0x%x", NULL, NULL, NULL, NULL},\r
131 \r
132   {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL},\r
133   {L"Proximity Domain", 4, 4, L"0x%x", NULL, NULL, NULL, NULL},\r
134   {L"X2APIC ID", 4, 8, L"0x%x", NULL, NULL, NULL, NULL},\r
135   {L"Flags", 4, 12, L"0x%x", NULL, NULL, NULL, NULL},\r
136   {L"Clock Domain", 4, 16, L"0x%x", NULL, NULL, NULL, NULL},\r
137   {L"Reserved", 4, 20, L"0x%x", NULL, NULL, NULL, NULL}\r
138 };\r
139 \r
140 /** This function validates the Reserved field in the SRAT table header.\r
141 \r
142   @param [in] Ptr     Pointer to the start of the field data.\r
143   @param [in] Context Pointer to context specific information e.g. this\r
144                       could be a pointer to the ACPI table header.\r
145 */\r
146 STATIC\r
147 VOID\r
148 EFIAPI\r
149 ValidateSratReserved (\r
150   IN UINT8* Ptr,\r
151   IN VOID*  Context\r
152   )\r
153 {\r
154   if (*(UINT32*)Ptr != 1) {\r
155     IncrementErrorCount ();\r
156     Print (L"\nERROR: Reserved should be 1 for backward compatibility.\n");\r
157   }\r
158 }\r
159 \r
160 /** This function traces the APIC Proximity Domain field.\r
161 \r
162   @param [in] Format  Format string for tracing the data.\r
163   @param [in] Ptr     Pointer to the start of the buffer.\r
164 */\r
165 STATIC\r
166 VOID\r
167 DumpSratApicProximity (\r
168  IN CONST CHAR16* Format,\r
169  IN UINT8*        Ptr\r
170  )\r
171 {\r
172   UINT32 ProximityDomain = Ptr[0] | (Ptr[1] << 8) | (Ptr[2] << 16);\r
173   Print (Format, ProximityDomain);\r
174 }\r
175 \r
176 /** This function parses the ACPI SRAT table.\r
177   When trace is enabled this function parses the SRAT table and\r
178   traces the ACPI table fields.\r
179 \r
180   This function parses the following Resource Allocation Structures:\r
181     - Processor Local APIC/SAPIC Affinity Structure\r
182     - Memory Affinity Structure\r
183     - Processor Local x2APIC Affinity Structure\r
184     - GICC Affinity Structure\r
185 \r
186   This function also performs validation of the ACPI table fields.\r
187 \r
188   @param [in] Trace              If TRUE, trace the ACPI fields.\r
189   @param [in] Ptr                Pointer to the start of the buffer.\r
190   @param [in] AcpiTableLength    Length of the ACPI table.\r
191   @param [in] AcpiTableRevision  Revision of the ACPI table.\r
192 */\r
193 VOID\r
194 EFIAPI\r
195 ParseAcpiSrat (\r
196   IN BOOLEAN Trace,\r
197   IN UINT8*  Ptr,\r
198   IN UINT32  AcpiTableLength,\r
199   IN UINT8   AcpiTableRevision\r
200   )\r
201 {\r
202   UINT32 Offset;\r
203   UINT8* ResourcePtr;\r
204   UINT32 GicCAffinityIndex = 0;\r
205   UINT32 GicITSAffinityIndex = 0;\r
206   UINT32 MemoryAffinityIndex = 0;\r
207   UINT32 ApicSapicAffinityIndex = 0;\r
208   UINT32 X2ApicAffinityIndex = 0;\r
209   CHAR8  Buffer[80];  // Used for AsciiName param of ParseAcpi\r
210 \r
211   if (!Trace) {\r
212     return;\r
213   }\r
214 \r
215   Offset = ParseAcpi (\r
216              TRUE,\r
217              0,\r
218              "SRAT",\r
219              Ptr,\r
220              AcpiTableLength,\r
221              PARSER_PARAMS (SratParser)\r
222              );\r
223   ResourcePtr = Ptr + Offset;\r
224 \r
225   while (Offset < AcpiTableLength) {\r
226     ParseAcpi (\r
227       FALSE,\r
228       0,\r
229       NULL,\r
230       ResourcePtr,\r
231       2,  // The length is 1 byte at offset 1\r
232       PARSER_PARAMS (SratResourceAllocationParser)\r
233       );\r
234 \r
235     switch (*SratRAType) {\r
236       case EFI_ACPI_6_2_GICC_AFFINITY:\r
237         AsciiSPrint (\r
238           Buffer,\r
239           sizeof (Buffer),\r
240           "GICC Affinity Structure [%d]",\r
241           GicCAffinityIndex++\r
242           );\r
243         ParseAcpi (\r
244           TRUE,\r
245           2,\r
246           Buffer,\r
247           ResourcePtr,\r
248           *SratRALength,\r
249           PARSER_PARAMS (SratGicCAffinityParser)\r
250           );\r
251         break;\r
252 \r
253       case EFI_ACPI_6_2_GIC_ITS_AFFINITY:\r
254         AsciiSPrint (\r
255           Buffer,\r
256           sizeof (Buffer),\r
257           "GIC ITS Affinity Structure [%d]",\r
258           GicITSAffinityIndex++\r
259         );\r
260         ParseAcpi (\r
261           TRUE,\r
262           2,\r
263           Buffer,\r
264           ResourcePtr,\r
265           *SratRALength,\r
266           PARSER_PARAMS (SratGicITSAffinityParser)\r
267         );\r
268         break;\r
269 \r
270       case EFI_ACPI_6_2_MEMORY_AFFINITY:\r
271         AsciiSPrint (\r
272           Buffer,\r
273           sizeof (Buffer),\r
274           "Memory Affinity Structure [%d]",\r
275           MemoryAffinityIndex++\r
276           );\r
277         ParseAcpi (\r
278           TRUE,\r
279           2,\r
280           Buffer,\r
281           ResourcePtr,\r
282           *SratRALength,\r
283           PARSER_PARAMS (SratMemAffinityParser)\r
284           );\r
285         break;\r
286 \r
287       case EFI_ACPI_6_2_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY:\r
288         AsciiSPrint (\r
289           Buffer,\r
290           sizeof (Buffer),\r
291           "APIC/SAPIC Affinity Structure [%d]",\r
292           ApicSapicAffinityIndex++\r
293           );\r
294         ParseAcpi (\r
295           TRUE,\r
296           2,\r
297           Buffer,\r
298           ResourcePtr,\r
299           *SratRALength,\r
300           PARSER_PARAMS (SratApciSapicAffinityParser)\r
301           );\r
302         break;\r
303 \r
304       case EFI_ACPI_6_2_PROCESSOR_LOCAL_X2APIC_AFFINITY:\r
305         AsciiSPrint (\r
306           Buffer,\r
307           sizeof (Buffer),\r
308           "X2APIC Affinity Structure [%d]",\r
309           X2ApicAffinityIndex++\r
310           );\r
311         ParseAcpi (\r
312           TRUE,\r
313           2,\r
314           Buffer,\r
315           ResourcePtr,\r
316           *SratRALength,\r
317           PARSER_PARAMS (SratX2ApciAffinityParser)\r
318           );\r
319         break;\r
320 \r
321       default:\r
322         IncrementErrorCount ();\r
323         Print (L"ERROR: Unknown SRAT Affinity type = 0x%x\n", *SratRAType);\r
324         break;\r
325     }\r
326 \r
327     ResourcePtr += (*SratRALength);\r
328     Offset += (*SratRALength);\r
329   }\r
330 }\r