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