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