ShellPkg: Display VENDOR_ID in ASCII when parsing PPTT
[mirror_edk2.git] / ShellPkg / Library / UefiShellAcpiViewCommandLib / Parsers / Pptt / PpttParser.c
1 /** @file\r
2   PPTT table parser\r
3 \r
4   Copyright (c) 2019, ARM Limited. All rights reserved.\r
5   SPDX-License-Identifier: BSD-2-Clause-Patent\r
6 \r
7   @par Reference(s):\r
8     - ACPI 6.2 Specification - Errata A, September 2017\r
9 **/\r
10 \r
11 #include <Library/PrintLib.h>\r
12 #include <Library/UefiLib.h>\r
13 #include "AcpiParser.h"\r
14 \r
15 // Local variables\r
16 STATIC CONST UINT8*  ProcessorTopologyStructureType;\r
17 STATIC CONST UINT8*  ProcessorTopologyStructureLength;\r
18 STATIC CONST UINT32* NumberOfPrivateResources;\r
19 STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;\r
20 \r
21 /**\r
22   An ACPI_PARSER array describing the ACPI PPTT Table.\r
23 **/\r
24 STATIC CONST ACPI_PARSER PpttParser[] = {\r
25   PARSE_ACPI_HEADER (&AcpiHdrInfo)\r
26 };\r
27 \r
28 /**\r
29   This function validates the Cache Type Structure (Type 1) Line size field.\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 ValidateCacheLineSize (\r
39   IN UINT8* Ptr,\r
40   IN VOID*  Context\r
41   )\r
42 {\r
43 #if defined(MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)\r
44   // Reference: ARM Architecture Reference Manual ARMv8 (D.a)\r
45   // Section D12.2.25: CCSIDR_EL1, Current Cache Size ID Register\r
46   //   LineSize, bits [2:0]\r
47   //     (Log2(Number of bytes in cache line)) - 4.\r
48 \r
49   UINT16 LineSize;\r
50   LineSize = *(UINT16*)Ptr;\r
51 \r
52   if ((LineSize < 16) || (LineSize > 2048)) {\r
53     IncrementErrorCount ();\r
54     Print (\r
55       L"\nERROR: The cache line size must be between 16 and 2048 bytes"\r
56         L" on ARM Platforms."\r
57       );\r
58     return;\r
59   }\r
60 \r
61   if ((LineSize & (LineSize - 1)) != 0) {\r
62     IncrementErrorCount ();\r
63     Print (L"\nERROR: The cache line size is not a power of 2.");\r
64   }\r
65 #endif\r
66 }\r
67 \r
68 /**\r
69   This function validates the Cache Type Structure (Type 1) Attributes field.\r
70 \r
71   @param [in] Ptr     Pointer to the start of the field data.\r
72   @param [in] Context Pointer to context specific information e.g. this\r
73                       could be a pointer to the ACPI table header.\r
74 **/\r
75 STATIC\r
76 VOID\r
77 EFIAPI\r
78 ValidateCacheAttributes (\r
79   IN UINT8* Ptr,\r
80   IN VOID*  Context\r
81   )\r
82 {\r
83   // Reference: Advanced Configuration and Power Interface (ACPI) Specification\r
84   //            Version 6.2 Errata A, September 2017\r
85   // Table 5-153: Cache Type Structure\r
86   UINT8 Attributes;\r
87   Attributes = *(UINT8*)Ptr;\r
88 \r
89   if ((Attributes & 0xE0) != 0) {\r
90     IncrementErrorCount ();\r
91     Print (\r
92       L"\nERROR: Attributes bits [7:5] are reserved and must be zero.",\r
93       Attributes\r
94       );\r
95     return;\r
96   }\r
97 }\r
98 \r
99 /**\r
100   An ACPI_PARSER array describing the processor topology structure header.\r
101 **/\r
102 STATIC CONST ACPI_PARSER ProcessorTopologyStructureHeaderParser[] = {\r
103   {L"Type", 1, 0, NULL, NULL, (VOID**)&ProcessorTopologyStructureType,\r
104    NULL, NULL},\r
105   {L"Length", 1, 1, NULL, NULL, (VOID**)&ProcessorTopologyStructureLength,\r
106    NULL, NULL},\r
107   {L"Reserved", 2, 2, NULL, NULL, NULL, NULL, NULL}\r
108 };\r
109 \r
110 /**\r
111   An ACPI_PARSER array describing the Processor Hierarchy Node Structure - Type 0.\r
112 **/\r
113 STATIC CONST ACPI_PARSER ProcessorHierarchyNodeStructureParser[] = {\r
114   {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},\r
115   {L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL},\r
116   {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL},\r
117 \r
118   {L"Flags", 4, 4, L"0x%x", NULL, NULL, NULL, NULL},\r
119   {L"Parent", 4, 8, L"0x%x", NULL, NULL, NULL, NULL},\r
120   {L"ACPI Processor ID", 4, 12, L"0x%x", NULL, NULL, NULL, NULL},\r
121   {L"Number of private resources", 4, 16, L"%d", NULL,\r
122    (VOID**)&NumberOfPrivateResources, NULL, NULL}\r
123 };\r
124 \r
125 /**\r
126   An ACPI_PARSER array describing the Cache Type Structure - Type 1.\r
127 **/\r
128 STATIC CONST ACPI_PARSER CacheTypeStructureParser[] = {\r
129   {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},\r
130   {L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL},\r
131   {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL},\r
132 \r
133   {L"Flags", 4, 4, L"0x%x", NULL, NULL, NULL, NULL},\r
134   {L"Next Level of Cache", 4, 8, L"0x%x", NULL, NULL, NULL, NULL},\r
135   {L"Size", 4, 12, L"0x%x", NULL, NULL, NULL, NULL},\r
136   {L"Number of sets", 4, 16, L"%d", NULL, NULL, NULL, NULL},\r
137   {L"Associativity", 1, 20, L"%d", NULL, NULL, NULL, NULL},\r
138   {L"Attributes", 1, 21, L"0x%x", NULL, NULL, ValidateCacheAttributes, NULL},\r
139   {L"Line size", 2, 22, L"%d", NULL, NULL, ValidateCacheLineSize, NULL}\r
140 };\r
141 \r
142 /**\r
143   An ACPI_PARSER array describing the ID Type Structure - Type 2.\r
144 **/\r
145 STATIC CONST ACPI_PARSER IdStructureParser[] = {\r
146   {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},\r
147   {L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL},\r
148   {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL},\r
149 \r
150   {L"VENDOR_ID", 4, 4, NULL, Dump4Chars, NULL, NULL, NULL},\r
151   {L"LEVEL_1_ID", 8, 8, L"0x%x", NULL, NULL, NULL, NULL},\r
152   {L"LEVEL_2_ID", 8, 16, L"0x%x", NULL, NULL, NULL, NULL},\r
153   {L"MAJOR_REV", 2, 24, L"0x%x", NULL, NULL, NULL, NULL},\r
154   {L"MINOR_REV", 2, 26, L"0x%x", NULL, NULL, NULL, NULL},\r
155   {L"SPIN_REV", 2, 28, L"0x%x", NULL, NULL, NULL, NULL},\r
156 };\r
157 \r
158 /**\r
159   This function parses the Processor Hierarchy Node Structure (Type 0).\r
160 \r
161   @param [in] Ptr     Pointer to the start of the Processor Hierarchy Node\r
162                       Structure data.\r
163   @param [in] Length  Length of the Processor Hierarchy Node Structure.\r
164 **/\r
165 STATIC\r
166 VOID\r
167 DumpProcessorHierarchyNodeStructure (\r
168   IN UINT8* Ptr,\r
169   IN UINT8  Length\r
170   )\r
171 {\r
172   UINT32 Offset;\r
173   UINT8* PrivateResourcePtr;\r
174   UINT32 Index;\r
175   CHAR16 Buffer[OUTPUT_FIELD_COLUMN_WIDTH];\r
176 \r
177   Offset = ParseAcpi (\r
178              TRUE,\r
179              2,\r
180              "Processor Hierarchy Node Structure",\r
181              Ptr,\r
182              Length,\r
183              PARSER_PARAMS (ProcessorHierarchyNodeStructureParser)\r
184              );\r
185 \r
186   PrivateResourcePtr = Ptr + Offset;\r
187   Index = 0;\r
188   while (Index < *NumberOfPrivateResources) {\r
189     UnicodeSPrint (\r
190       Buffer,\r
191       sizeof (Buffer),\r
192       L"Private resources [%d]",\r
193       Index\r
194       );\r
195 \r
196     PrintFieldName (4, Buffer);\r
197     Print (\r
198       L"0x%x\n",\r
199       *((UINT32*) PrivateResourcePtr)\r
200       );\r
201 \r
202     PrivateResourcePtr += sizeof(UINT32);\r
203     Index++;\r
204   }\r
205 }\r
206 \r
207 /**\r
208   This function parses the Cache Type Structure (Type 1).\r
209 \r
210   @param [in] Ptr     Pointer to the start of the Cache Type Structure data.\r
211   @param [in] Length  Length of the Cache Type Structure.\r
212 **/\r
213 STATIC\r
214 VOID\r
215 DumpCacheTypeStructure (\r
216   IN UINT8* Ptr,\r
217   IN UINT8  Length\r
218   )\r
219 {\r
220   ParseAcpi (\r
221     TRUE,\r
222     2,\r
223     "Cache Type Structure",\r
224     Ptr,\r
225     Length,\r
226     PARSER_PARAMS (CacheTypeStructureParser)\r
227     );\r
228 }\r
229 \r
230 /**\r
231   This function parses the ID Structure (Type 2).\r
232 \r
233   @param [in] Ptr     Pointer to the start of the ID Structure data.\r
234   @param [in] Length  Length of the ID Structure.\r
235 **/\r
236 STATIC\r
237 VOID\r
238 DumpIDStructure (\r
239   IN UINT8* Ptr,\r
240   IN UINT8 Length\r
241   )\r
242 {\r
243   ParseAcpi (\r
244     TRUE,\r
245     2,\r
246     "ID Structure",\r
247     Ptr,\r
248     Length,\r
249     PARSER_PARAMS (IdStructureParser)\r
250     );\r
251 }\r
252 \r
253 /**\r
254   This function parses the ACPI PPTT table.\r
255   When trace is enabled this function parses the PPTT table and\r
256   traces the ACPI table fields.\r
257 \r
258   This function parses the following processor topology structures:\r
259     - Processor hierarchy node structure (Type 0)\r
260     - Cache Type Structure (Type 1)\r
261     - ID structure (Type 2)\r
262 \r
263   This function also performs validation of the ACPI table fields.\r
264 \r
265   @param [in] Trace              If TRUE, trace the ACPI fields.\r
266   @param [in] Ptr                Pointer to the start of the buffer.\r
267   @param [in] AcpiTableLength    Length of the ACPI table.\r
268   @param [in] AcpiTableRevision  Revision of the ACPI table.\r
269 **/\r
270 VOID\r
271 EFIAPI\r
272 ParseAcpiPptt (\r
273   IN BOOLEAN Trace,\r
274   IN UINT8*  Ptr,\r
275   IN UINT32  AcpiTableLength,\r
276   IN UINT8   AcpiTableRevision\r
277   )\r
278 {\r
279   UINT32 Offset;\r
280   UINT8* ProcessorTopologyStructurePtr;\r
281 \r
282   if (!Trace) {\r
283     return;\r
284   }\r
285 \r
286   Offset = ParseAcpi (\r
287              TRUE,\r
288              0,\r
289              "PPTT",\r
290              Ptr,\r
291              AcpiTableLength,\r
292              PARSER_PARAMS (PpttParser)\r
293              );\r
294   ProcessorTopologyStructurePtr = Ptr + Offset;\r
295 \r
296   while (Offset < AcpiTableLength) {\r
297     // Parse Processor Hierarchy Node Structure to obtain Type and Length.\r
298     ParseAcpi (\r
299       FALSE,\r
300       0,\r
301       NULL,\r
302       ProcessorTopologyStructurePtr,\r
303       4,  // Length of the processor topology structure header is 4 bytes\r
304       PARSER_PARAMS (ProcessorTopologyStructureHeaderParser)\r
305       );\r
306 \r
307     if ((Offset + (*ProcessorTopologyStructureLength)) > AcpiTableLength) {\r
308       IncrementErrorCount ();\r
309       Print (\r
310         L"ERROR: Invalid processor topology structure length:"\r
311           L" Type = %d, Length = %d\n",\r
312         *ProcessorTopologyStructureType,\r
313         *ProcessorTopologyStructureLength\r
314         );\r
315       break;\r
316     }\r
317 \r
318     PrintFieldName (2, L"* Structure Offset *");\r
319     Print (L"0x%x\n", Offset);\r
320 \r
321     switch (*ProcessorTopologyStructureType) {\r
322       case EFI_ACPI_6_2_PPTT_TYPE_PROCESSOR:\r
323         DumpProcessorHierarchyNodeStructure (\r
324           ProcessorTopologyStructurePtr,\r
325           *ProcessorTopologyStructureLength\r
326           );\r
327         break;\r
328       case EFI_ACPI_6_2_PPTT_TYPE_CACHE:\r
329         DumpCacheTypeStructure (\r
330           ProcessorTopologyStructurePtr,\r
331           *ProcessorTopologyStructureLength\r
332           );\r
333         break;\r
334       case EFI_ACPI_6_2_PPTT_TYPE_ID:\r
335         DumpIDStructure (\r
336           ProcessorTopologyStructurePtr,\r
337           *ProcessorTopologyStructureLength\r
338           );\r
339         break;\r
340       default:\r
341         IncrementErrorCount ();\r
342         Print (\r
343           L"ERROR: Unknown processor topology structure:"\r
344             L" Type = %d, Length = %d\n",\r
345           *ProcessorTopologyStructureType,\r
346           *ProcessorTopologyStructureLength\r
347           );\r
348     }\r
349 \r
350     ProcessorTopologyStructurePtr += *ProcessorTopologyStructureLength;\r
351     Offset += *ProcessorTopologyStructureLength;\r
352   } // while\r
353 }\r