]>
Commit | Line | Data |
---|---|---|
d4d2fdf2 KK |
1 | /** @file\r |
2 | PPTT table parser\r | |
3 | \r | |
a50b65ce | 4 | Copyright (c) 2019 - 2021, ARM Limited. All rights reserved.\r |
56ba3746 | 5 | SPDX-License-Identifier: BSD-2-Clause-Patent\r |
d4d2fdf2 KK |
6 | \r |
7 | @par Reference(s):\r | |
a50b65ce | 8 | - ACPI 6.4 Specification - January 2021\r |
5a27f7a2 | 9 | - ARM Architecture Reference Manual ARMv8 (D.a)\r |
d4d2fdf2 KK |
10 | **/\r |
11 | \r | |
12 | #include <Library/PrintLib.h>\r | |
13 | #include <Library/UefiLib.h>\r | |
14 | #include "AcpiParser.h"\r | |
5a27f7a2 | 15 | #include "AcpiView.h"\r |
e18ac66d | 16 | #include "AcpiViewConfig.h"\r |
5a27f7a2 | 17 | #include "PpttParser.h"\r |
d4d2fdf2 KK |
18 | \r |
19 | // Local variables\r | |
8cf2bdfc CJ |
20 | STATIC CONST UINT8 *ProcessorTopologyStructureType;\r |
21 | STATIC CONST UINT8 *ProcessorTopologyStructureLength;\r | |
22 | STATIC CONST UINT32 *NumberOfPrivateResources;\r | |
23 | STATIC CONST EFI_ACPI_6_4_PPTT_STRUCTURE_CACHE_FLAGS *CacheFlags;\r | |
24 | STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;\r | |
25 | \r | |
26 | #if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)\r | |
27 | \r | |
28 | /**\r | |
29 | Increment the error count and print an error that a required flag is missing.\r | |
30 | \r | |
31 | @param [in] FlagName Name of the missing flag.\r | |
32 | **/\r | |
33 | STATIC\r | |
34 | VOID\r | |
35 | EFIAPI\r | |
36 | LogCacheFlagError (\r | |
37 | IN CONST CHAR16 *FlagName\r | |
38 | )\r | |
39 | {\r | |
40 | IncrementErrorCount ();\r | |
41 | Print (\r | |
42 | L"\nERROR: On Arm based systems, all cache properties must be"\r | |
6fb09da8 CJ |
43 | L" provided in the cache type structure."\r |
44 | L" Missing '%s' flag.",\r | |
45 | FlagName\r | |
8cf2bdfc CJ |
46 | );\r |
47 | }\r | |
48 | \r | |
49 | #endif\r | |
50 | \r | |
51 | /**\r | |
52 | This function validates the Cache Type Structure (Type 1) Cache Flags field.\r | |
53 | \r | |
54 | @param [in] Ptr Pointer to the start of the field data.\r | |
55 | @param [in] Context Pointer to context specific information e.g. this\r | |
56 | could be a pointer to the ACPI table header.\r | |
57 | **/\r | |
58 | STATIC\r | |
59 | VOID\r | |
60 | EFIAPI\r | |
61 | ValidateCacheFlags (\r | |
62 | IN UINT8 *Ptr,\r | |
63 | IN VOID *Context\r | |
64 | )\r | |
65 | {\r | |
66 | #if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)\r | |
67 | CacheFlags = (EFI_ACPI_6_4_PPTT_STRUCTURE_CACHE_FLAGS *)Ptr;\r | |
68 | \r | |
69 | if (CacheFlags == NULL) {\r | |
70 | IncrementErrorCount ();\r | |
71 | Print (L"\nERROR: Cache Structure Flags were not successfully read.");\r | |
72 | return;\r | |
73 | }\r | |
74 | \r | |
75 | if (CacheFlags->SizePropertyValid == EFI_ACPI_6_4_PPTT_CACHE_SIZE_INVALID) {\r | |
76 | LogCacheFlagError (L"Size Property Valid");\r | |
77 | }\r | |
78 | \r | |
79 | if (CacheFlags->NumberOfSetsValid == EFI_ACPI_6_4_PPTT_NUMBER_OF_SETS_INVALID) {\r | |
80 | LogCacheFlagError (L"Number Of Sets Valid");\r | |
81 | }\r | |
82 | \r | |
83 | if (CacheFlags->AssociativityValid == EFI_ACPI_6_4_PPTT_ASSOCIATIVITY_INVALID) {\r | |
84 | LogCacheFlagError (L"Associativity Valid");\r | |
85 | }\r | |
86 | \r | |
87 | if (CacheFlags->AllocationTypeValid == EFI_ACPI_6_4_PPTT_ALLOCATION_TYPE_INVALID) {\r | |
88 | LogCacheFlagError (L"Allocation Type Valid");\r | |
89 | }\r | |
90 | \r | |
91 | if (CacheFlags->CacheTypeValid == EFI_ACPI_6_4_PPTT_CACHE_TYPE_INVALID) {\r | |
92 | LogCacheFlagError (L"Cache Type Valid");\r | |
93 | }\r | |
94 | \r | |
95 | if (CacheFlags->WritePolicyValid == EFI_ACPI_6_4_PPTT_WRITE_POLICY_INVALID) {\r | |
96 | LogCacheFlagError (L"Write Policy Valid");\r | |
97 | }\r | |
98 | \r | |
99 | if (CacheFlags->LineSizeValid == EFI_ACPI_6_4_PPTT_LINE_SIZE_INVALID) {\r | |
100 | LogCacheFlagError (L"Line Size Valid");\r | |
101 | }\r | |
102 | \r | |
103 | // Cache ID was only introduced in revision 3\r | |
104 | if (*(AcpiHdrInfo.Revision) >= 3) {\r | |
105 | if (CacheFlags->CacheIdValid == EFI_ACPI_6_4_PPTT_CACHE_ID_INVALID) {\r | |
106 | LogCacheFlagError (L"Cache Id Valid");\r | |
107 | }\r | |
108 | }\r | |
109 | \r | |
110 | #endif\r | |
111 | }\r | |
d4d2fdf2 KK |
112 | \r |
113 | /**\r | |
5a27f7a2 KK |
114 | This function validates the Cache Type Structure (Type 1) 'Number of sets'\r |
115 | field.\r | |
116 | \r | |
117 | @param [in] Ptr Pointer to the start of the field data.\r | |
118 | @param [in] Context Pointer to context specific information e.g. this\r | |
119 | could be a pointer to the ACPI table header.\r | |
d4d2fdf2 | 120 | **/\r |
5a27f7a2 KK |
121 | STATIC\r |
122 | VOID\r | |
123 | EFIAPI\r | |
124 | ValidateCacheNumberOfSets (\r | |
47d20b54 MK |
125 | IN UINT8 *Ptr,\r |
126 | IN VOID *Context\r | |
5a27f7a2 KK |
127 | )\r |
128 | {\r | |
47d20b54 MK |
129 | UINT32 NumberOfSets;\r |
130 | \r | |
131 | NumberOfSets = *(UINT32 *)Ptr;\r | |
5a27f7a2 KK |
132 | \r |
133 | if (NumberOfSets == 0) {\r | |
134 | IncrementErrorCount ();\r | |
135 | Print (L"\nERROR: Cache number of sets must be greater than 0");\r | |
136 | return;\r | |
137 | }\r | |
138 | \r | |
47d20b54 | 139 | #if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)\r |
5a27f7a2 KK |
140 | if (NumberOfSets > PPTT_ARM_CCIDX_CACHE_NUMBER_OF_SETS_MAX) {\r |
141 | IncrementErrorCount ();\r | |
142 | Print (\r | |
143 | L"\nERROR: When ARMv8.3-CCIDX is implemented the maximum cache number of "\r | |
47d20b54 | 144 | L"sets must be less than or equal to %d",\r |
5a27f7a2 KK |
145 | PPTT_ARM_CCIDX_CACHE_NUMBER_OF_SETS_MAX\r |
146 | );\r | |
147 | return;\r | |
148 | }\r | |
149 | \r | |
150 | if (NumberOfSets > PPTT_ARM_CACHE_NUMBER_OF_SETS_MAX) {\r | |
151 | IncrementWarningCount ();\r | |
152 | Print (\r | |
153 | L"\nWARNING: Without ARMv8.3-CCIDX, the maximum cache number of sets "\r | |
47d20b54 MK |
154 | L"must be less than or equal to %d. Ignore this message if "\r |
155 | L"ARMv8.3-CCIDX is implemented",\r | |
5a27f7a2 KK |
156 | PPTT_ARM_CACHE_NUMBER_OF_SETS_MAX\r |
157 | );\r | |
158 | return;\r | |
159 | }\r | |
5a27f7a2 | 160 | \r |
47d20b54 | 161 | #endif\r |
5a27f7a2 KK |
162 | }\r |
163 | \r | |
164 | /**\r | |
165 | This function validates the Cache Type Structure (Type 1) 'Associativity'\r | |
166 | field.\r | |
167 | \r | |
168 | @param [in] Ptr Pointer to the start of the field data.\r | |
169 | @param [in] Context Pointer to context specific information e.g. this\r | |
170 | could be a pointer to the ACPI table header.\r | |
171 | **/\r | |
172 | STATIC\r | |
173 | VOID\r | |
174 | EFIAPI\r | |
175 | ValidateCacheAssociativity (\r | |
47d20b54 MK |
176 | IN UINT8 *Ptr,\r |
177 | IN VOID *Context\r | |
5a27f7a2 KK |
178 | )\r |
179 | {\r | |
47d20b54 MK |
180 | UINT8 Associativity;\r |
181 | \r | |
182 | Associativity = *(UINT8 *)Ptr;\r | |
5a27f7a2 KK |
183 | \r |
184 | if (Associativity == 0) {\r | |
185 | IncrementErrorCount ();\r | |
186 | Print (L"\nERROR: Cache associativity must be greater than 0");\r | |
187 | return;\r | |
188 | }\r | |
189 | }\r | |
d4d2fdf2 KK |
190 | \r |
191 | /**\r | |
192 | This function validates the Cache Type Structure (Type 1) Line size field.\r | |
193 | \r | |
194 | @param [in] Ptr Pointer to the start of the field data.\r | |
195 | @param [in] Context Pointer to context specific information e.g. this\r | |
196 | could be a pointer to the ACPI table header.\r | |
197 | **/\r | |
198 | STATIC\r | |
199 | VOID\r | |
200 | EFIAPI\r | |
201 | ValidateCacheLineSize (\r | |
47d20b54 MK |
202 | IN UINT8 *Ptr,\r |
203 | IN VOID *Context\r | |
d4d2fdf2 KK |
204 | )\r |
205 | {\r | |
47d20b54 | 206 | #if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)\r |
d4d2fdf2 KK |
207 | // Reference: ARM Architecture Reference Manual ARMv8 (D.a)\r |
208 | // Section D12.2.25: CCSIDR_EL1, Current Cache Size ID Register\r | |
209 | // LineSize, bits [2:0]\r | |
210 | // (Log2(Number of bytes in cache line)) - 4.\r | |
211 | \r | |
47d20b54 MK |
212 | UINT16 LineSize;\r |
213 | LineSize = *(UINT16 *)Ptr;\r | |
d4d2fdf2 | 214 | \r |
5a27f7a2 | 215 | if ((LineSize < PPTT_ARM_CACHE_LINE_SIZE_MIN) ||\r |
47d20b54 MK |
216 | (LineSize > PPTT_ARM_CACHE_LINE_SIZE_MAX))\r |
217 | {\r | |
d4d2fdf2 KK |
218 | IncrementErrorCount ();\r |
219 | Print (\r | |
5a27f7a2 | 220 | L"\nERROR: The cache line size must be between %d and %d bytes"\r |
47d20b54 | 221 | L" on ARM Platforms.",\r |
5a27f7a2 KK |
222 | PPTT_ARM_CACHE_LINE_SIZE_MIN,\r |
223 | PPTT_ARM_CACHE_LINE_SIZE_MAX\r | |
d4d2fdf2 KK |
224 | );\r |
225 | return;\r | |
226 | }\r | |
227 | \r | |
228 | if ((LineSize & (LineSize - 1)) != 0) {\r | |
229 | IncrementErrorCount ();\r | |
230 | Print (L"\nERROR: The cache line size is not a power of 2.");\r | |
231 | }\r | |
47d20b54 MK |
232 | \r |
233 | #endif\r | |
d4d2fdf2 KK |
234 | }\r |
235 | \r | |
8cf2bdfc CJ |
236 | /**\r |
237 | This function validates the Cache Type Structure (Type 1) Cache ID field.\r | |
238 | \r | |
239 | @param [in] Ptr Pointer to the start of the field data.\r | |
240 | @param [in] Context Pointer to context specific information e.g. this\r | |
241 | could be a pointer to the ACPI table header.\r | |
242 | **/\r | |
243 | STATIC\r | |
244 | VOID\r | |
245 | EFIAPI\r | |
246 | ValidateCacheId (\r | |
247 | IN UINT8 *Ptr,\r | |
248 | IN VOID *Context\r | |
249 | )\r | |
250 | {\r | |
251 | UINT32 CacheId;\r | |
252 | \r | |
253 | CacheId = *(UINT32 *)Ptr;\r | |
254 | \r | |
255 | // Cache ID was only introduced in revision 3\r | |
256 | if (*(AcpiHdrInfo.Revision) < 3) {\r | |
257 | return;\r | |
258 | }\r | |
259 | \r | |
260 | if (CacheFlags == NULL) {\r | |
261 | IncrementErrorCount ();\r | |
262 | Print (L"\nERROR: Cache Structure Flags were not successfully read.");\r | |
263 | return;\r | |
264 | }\r | |
265 | \r | |
266 | if (CacheFlags->CacheIdValid == EFI_ACPI_6_4_PPTT_CACHE_ID_VALID) {\r | |
267 | if (CacheId == 0) {\r | |
268 | IncrementErrorCount ();\r | |
269 | Print (L"\nERROR: 0 is not a valid Cache ID.");\r | |
270 | return;\r | |
271 | }\r | |
272 | }\r | |
273 | }\r | |
274 | \r | |
d4d2fdf2 KK |
275 | /**\r |
276 | This function validates the Cache Type Structure (Type 1) Attributes field.\r | |
277 | \r | |
278 | @param [in] Ptr Pointer to the start of the field data.\r | |
279 | @param [in] Context Pointer to context specific information e.g. this\r | |
280 | could be a pointer to the ACPI table header.\r | |
281 | **/\r | |
282 | STATIC\r | |
283 | VOID\r | |
284 | EFIAPI\r | |
285 | ValidateCacheAttributes (\r | |
47d20b54 MK |
286 | IN UINT8 *Ptr,\r |
287 | IN VOID *Context\r | |
d4d2fdf2 KK |
288 | )\r |
289 | {\r | |
d4d2fdf2 | 290 | // Reference: Advanced Configuration and Power Interface (ACPI) Specification\r |
a50b65ce CJ |
291 | // Version 6.4, January 2021\r |
292 | // Table 5-140: Cache Type Structure\r | |
47d20b54 MK |
293 | UINT8 Attributes;\r |
294 | \r | |
295 | Attributes = *(UINT8 *)Ptr;\r | |
d4d2fdf2 KK |
296 | \r |
297 | if ((Attributes & 0xE0) != 0) {\r | |
298 | IncrementErrorCount ();\r | |
299 | Print (\r | |
300 | L"\nERROR: Attributes bits [7:5] are reserved and must be zero.",\r | |
301 | Attributes\r | |
302 | );\r | |
303 | return;\r | |
304 | }\r | |
d4d2fdf2 KK |
305 | }\r |
306 | \r | |
5a27f7a2 KK |
307 | /**\r |
308 | An ACPI_PARSER array describing the ACPI PPTT Table.\r | |
309 | **/\r | |
47d20b54 | 310 | STATIC CONST ACPI_PARSER PpttParser[] = {\r |
5a27f7a2 KK |
311 | PARSE_ACPI_HEADER (&AcpiHdrInfo)\r |
312 | };\r | |
313 | \r | |
d4d2fdf2 KK |
314 | /**\r |
315 | An ACPI_PARSER array describing the processor topology structure header.\r | |
316 | **/\r | |
47d20b54 MK |
317 | STATIC CONST ACPI_PARSER ProcessorTopologyStructureHeaderParser[] = {\r |
318 | { L"Type", 1, 0, NULL, NULL, (VOID **)&ProcessorTopologyStructureType,\r | |
319 | NULL, NULL },\r | |
320 | { L"Length", 1, 1, NULL, NULL, (VOID **)&ProcessorTopologyStructureLength,\r | |
321 | NULL, NULL },\r | |
322 | { L"Reserved", 2, 2, NULL, NULL, NULL, NULL,NULL }\r | |
d4d2fdf2 KK |
323 | };\r |
324 | \r | |
325 | /**\r | |
326 | An ACPI_PARSER array describing the Processor Hierarchy Node Structure - Type 0.\r | |
327 | **/\r | |
47d20b54 MK |
328 | STATIC CONST ACPI_PARSER ProcessorHierarchyNodeStructureParser[] = {\r |
329 | { L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL },\r | |
330 | { L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL },\r | |
331 | { L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL },\r | |
332 | \r | |
333 | { L"Flags", 4, 4, L"0x%x", NULL, NULL, NULL, NULL },\r | |
334 | { L"Parent", 4, 8, L"0x%x", NULL, NULL, NULL, NULL },\r | |
335 | { L"ACPI Processor ID", 4, 12, L"0x%x", NULL, NULL, NULL, NULL },\r | |
336 | { L"Number of private resources", 4, 16, L"%d", NULL,\r | |
337 | (VOID **)&NumberOfPrivateResources, NULL, NULL }\r | |
d4d2fdf2 KK |
338 | };\r |
339 | \r | |
340 | /**\r | |
341 | An ACPI_PARSER array describing the Cache Type Structure - Type 1.\r | |
342 | **/\r | |
47d20b54 | 343 | STATIC CONST ACPI_PARSER CacheTypeStructureParser[] = {\r |
8cf2bdfc CJ |
344 | { L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL },\r |
345 | { L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL },\r | |
346 | { L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL },\r | |
347 | \r | |
348 | { L"Flags", 4, 4, L"0x%x", NULL, (VOID **)&CacheFlags, ValidateCacheFlags,\r | |
349 | NULL },\r | |
350 | { L"Next Level of Cache", 4, 8, L"0x%x", NULL, NULL, NULL, NULL },\r | |
351 | { L"Size", 4, 12, L"0x%x", NULL, NULL, NULL, NULL },\r | |
352 | { L"Number of sets", 4, 16, L"%d", NULL, NULL, ValidateCacheNumberOfSets, NULL },\r | |
353 | { L"Associativity", 1, 20, L"%d", NULL, NULL, ValidateCacheAssociativity, NULL },\r | |
354 | { L"Attributes", 1, 21, L"0x%x", NULL, NULL, ValidateCacheAttributes, NULL },\r | |
355 | { L"Line size", 2, 22, L"%d", NULL, NULL, ValidateCacheLineSize, NULL },\r | |
356 | { L"Cache ID", 4, 24, L"%d", NULL, NULL, ValidateCacheId, NULL }\r | |
d4d2fdf2 KK |
357 | };\r |
358 | \r | |
d4d2fdf2 KK |
359 | /**\r |
360 | This function parses the Processor Hierarchy Node Structure (Type 0).\r | |
361 | \r | |
362 | @param [in] Ptr Pointer to the start of the Processor Hierarchy Node\r | |
363 | Structure data.\r | |
364 | @param [in] Length Length of the Processor Hierarchy Node Structure.\r | |
365 | **/\r | |
366 | STATIC\r | |
367 | VOID\r | |
368 | DumpProcessorHierarchyNodeStructure (\r | |
47d20b54 | 369 | IN UINT8 *Ptr,\r |
d4d2fdf2 KK |
370 | IN UINT8 Length\r |
371 | )\r | |
372 | {\r | |
47d20b54 MK |
373 | UINT32 Offset;\r |
374 | UINT32 Index;\r | |
375 | CHAR16 Buffer[OUTPUT_FIELD_COLUMN_WIDTH];\r | |
d4d2fdf2 KK |
376 | \r |
377 | Offset = ParseAcpi (\r | |
378 | TRUE,\r | |
379 | 2,\r | |
380 | "Processor Hierarchy Node Structure",\r | |
381 | Ptr,\r | |
382 | Length,\r | |
383 | PARSER_PARAMS (ProcessorHierarchyNodeStructureParser)\r | |
384 | );\r | |
385 | \r | |
84a534b4 KK |
386 | // Check if the values used to control the parsing logic have been\r |
387 | // successfully read.\r | |
388 | if (NumberOfPrivateResources == NULL) {\r | |
389 | IncrementErrorCount ();\r | |
390 | Print (\r | |
391 | L"ERROR: Insufficient Processor Hierarchy Node length. Length = %d.\n",\r | |
392 | Length\r | |
393 | );\r | |
394 | return;\r | |
395 | }\r | |
396 | \r | |
5f066122 KK |
397 | // Make sure the Private Resource array lies inside this structure\r |
398 | if (Offset + (*NumberOfPrivateResources * sizeof (UINT32)) > Length) {\r | |
399 | IncrementErrorCount ();\r | |
400 | Print (\r | |
401 | L"ERROR: Invalid Number of Private Resources. " \\r | |
47d20b54 MK |
402 | L"PrivateResourceCount = %d. RemainingBufferLength = %d. " \\r |
403 | L"Parsing of this structure aborted.\n",\r | |
5f066122 KK |
404 | *NumberOfPrivateResources,\r |
405 | Length - Offset\r | |
406 | );\r | |
407 | return;\r | |
408 | }\r | |
409 | \r | |
d4d2fdf2 | 410 | Index = 0;\r |
5f066122 KK |
411 | \r |
412 | // Parse the specified number of private resource references or the Processor\r | |
413 | // Hierarchy Node length. Whichever is minimum.\r | |
d4d2fdf2 KK |
414 | while (Index < *NumberOfPrivateResources) {\r |
415 | UnicodeSPrint (\r | |
416 | Buffer,\r | |
417 | sizeof (Buffer),\r | |
418 | L"Private resources [%d]",\r | |
419 | Index\r | |
420 | );\r | |
421 | \r | |
422 | PrintFieldName (4, Buffer);\r | |
423 | Print (\r | |
424 | L"0x%x\n",\r | |
47d20b54 | 425 | *((UINT32 *)(Ptr + Offset))\r |
d4d2fdf2 KK |
426 | );\r |
427 | \r | |
5f066122 | 428 | Offset += sizeof (UINT32);\r |
d4d2fdf2 KK |
429 | Index++;\r |
430 | }\r | |
431 | }\r | |
432 | \r | |
433 | /**\r | |
434 | This function parses the Cache Type Structure (Type 1).\r | |
435 | \r | |
436 | @param [in] Ptr Pointer to the start of the Cache Type Structure data.\r | |
437 | @param [in] Length Length of the Cache Type Structure.\r | |
438 | **/\r | |
439 | STATIC\r | |
440 | VOID\r | |
441 | DumpCacheTypeStructure (\r | |
47d20b54 | 442 | IN UINT8 *Ptr,\r |
d4d2fdf2 KK |
443 | IN UINT8 Length\r |
444 | )\r | |
445 | {\r | |
446 | ParseAcpi (\r | |
447 | TRUE,\r | |
448 | 2,\r | |
449 | "Cache Type Structure",\r | |
450 | Ptr,\r | |
451 | Length,\r | |
452 | PARSER_PARAMS (CacheTypeStructureParser)\r | |
453 | );\r | |
454 | }\r | |
455 | \r | |
d4d2fdf2 KK |
456 | /**\r |
457 | This function parses the ACPI PPTT table.\r | |
458 | When trace is enabled this function parses the PPTT table and\r | |
459 | traces the ACPI table fields.\r | |
460 | \r | |
461 | This function parses the following processor topology structures:\r | |
462 | - Processor hierarchy node structure (Type 0)\r | |
463 | - Cache Type Structure (Type 1)\r | |
d4d2fdf2 KK |
464 | \r |
465 | This function also performs validation of the ACPI table fields.\r | |
466 | \r | |
467 | @param [in] Trace If TRUE, trace the ACPI fields.\r | |
468 | @param [in] Ptr Pointer to the start of the buffer.\r | |
469 | @param [in] AcpiTableLength Length of the ACPI table.\r | |
470 | @param [in] AcpiTableRevision Revision of the ACPI table.\r | |
471 | **/\r | |
472 | VOID\r | |
473 | EFIAPI\r | |
474 | ParseAcpiPptt (\r | |
47d20b54 MK |
475 | IN BOOLEAN Trace,\r |
476 | IN UINT8 *Ptr,\r | |
477 | IN UINT32 AcpiTableLength,\r | |
478 | IN UINT8 AcpiTableRevision\r | |
d4d2fdf2 KK |
479 | )\r |
480 | {\r | |
47d20b54 MK |
481 | UINT32 Offset;\r |
482 | UINT8 *ProcessorTopologyStructurePtr;\r | |
d4d2fdf2 KK |
483 | \r |
484 | if (!Trace) {\r | |
485 | return;\r | |
486 | }\r | |
487 | \r | |
488 | Offset = ParseAcpi (\r | |
489 | TRUE,\r | |
490 | 0,\r | |
491 | "PPTT",\r | |
492 | Ptr,\r | |
493 | AcpiTableLength,\r | |
494 | PARSER_PARAMS (PpttParser)\r | |
495 | );\r | |
84a534b4 | 496 | \r |
d4d2fdf2 KK |
497 | ProcessorTopologyStructurePtr = Ptr + Offset;\r |
498 | \r | |
499 | while (Offset < AcpiTableLength) {\r | |
500 | // Parse Processor Hierarchy Node Structure to obtain Type and Length.\r | |
501 | ParseAcpi (\r | |
502 | FALSE,\r | |
503 | 0,\r | |
504 | NULL,\r | |
505 | ProcessorTopologyStructurePtr,\r | |
5f066122 | 506 | AcpiTableLength - Offset,\r |
d4d2fdf2 KK |
507 | PARSER_PARAMS (ProcessorTopologyStructureHeaderParser)\r |
508 | );\r | |
509 | \r | |
84a534b4 KK |
510 | // Check if the values used to control the parsing logic have been\r |
511 | // successfully read.\r | |
512 | if ((ProcessorTopologyStructureType == NULL) ||\r | |
47d20b54 MK |
513 | (ProcessorTopologyStructureLength == NULL))\r |
514 | {\r | |
84a534b4 KK |
515 | IncrementErrorCount ();\r |
516 | Print (\r | |
517 | L"ERROR: Insufficient remaining table buffer length to read the " \\r | |
47d20b54 | 518 | L"processor topology structure header. Length = %d.\n",\r |
84a534b4 KK |
519 | AcpiTableLength - Offset\r |
520 | );\r | |
521 | return;\r | |
522 | }\r | |
523 | \r | |
b8504826 KK |
524 | // Validate Processor Topology Structure length\r |
525 | if ((*ProcessorTopologyStructureLength == 0) ||\r | |
47d20b54 MK |
526 | ((Offset + (*ProcessorTopologyStructureLength)) > AcpiTableLength))\r |
527 | {\r | |
d4d2fdf2 KK |
528 | IncrementErrorCount ();\r |
529 | Print (\r | |
b8504826 | 530 | L"ERROR: Invalid Processor Topology Structure length. " \\r |
47d20b54 | 531 | L"Length = %d. Offset = %d. AcpiTableLength = %d.\n",\r |
5f066122 | 532 | *ProcessorTopologyStructureLength,\r |
b8504826 KK |
533 | Offset,\r |
534 | AcpiTableLength\r | |
d4d2fdf2 | 535 | );\r |
5f066122 | 536 | return;\r |
d4d2fdf2 KK |
537 | }\r |
538 | \r | |
539 | PrintFieldName (2, L"* Structure Offset *");\r | |
540 | Print (L"0x%x\n", Offset);\r | |
541 | \r | |
542 | switch (*ProcessorTopologyStructureType) {\r | |
a50b65ce | 543 | case EFI_ACPI_6_4_PPTT_TYPE_PROCESSOR:\r |
d4d2fdf2 KK |
544 | DumpProcessorHierarchyNodeStructure (\r |
545 | ProcessorTopologyStructurePtr,\r | |
546 | *ProcessorTopologyStructureLength\r | |
547 | );\r | |
548 | break;\r | |
a50b65ce | 549 | case EFI_ACPI_6_4_PPTT_TYPE_CACHE:\r |
d4d2fdf2 KK |
550 | DumpCacheTypeStructure (\r |
551 | ProcessorTopologyStructurePtr,\r | |
552 | *ProcessorTopologyStructureLength\r | |
553 | );\r | |
554 | break;\r | |
a50b65ce CJ |
555 | case EFI_ACPI_6_3_PPTT_TYPE_ID:\r |
556 | IncrementErrorCount ();\r | |
557 | Print (\r | |
558 | L"ERROR: PPTT Type 2 - Processor ID has been removed and must not be"\r | |
559 | L"used.\n"\r | |
d4d2fdf2 KK |
560 | );\r |
561 | break;\r | |
562 | default:\r | |
563 | IncrementErrorCount ();\r | |
564 | Print (\r | |
565 | L"ERROR: Unknown processor topology structure:"\r | |
47d20b54 | 566 | L" Type = %d, Length = %d\n",\r |
d4d2fdf2 KK |
567 | *ProcessorTopologyStructureType,\r |
568 | *ProcessorTopologyStructureLength\r | |
569 | );\r | |
570 | }\r | |
571 | \r | |
572 | ProcessorTopologyStructurePtr += *ProcessorTopologyStructureLength;\r | |
47d20b54 | 573 | Offset += *ProcessorTopologyStructureLength;\r |
d4d2fdf2 KK |
574 | } // while\r |
575 | }\r |