]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Srat/SratParser.c
SecurityPkg: Apply uncrustify changes
[mirror_edk2.git] / ShellPkg / Library / UefiShellAcpiViewCommandLib / Parsers / Srat / SratParser.c
... / ...
CommitLineData
1/** @file\r
2 SRAT table parser\r
3\r
4 Copyright (c) 2016 - 2020, 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.3 Specification - January 2019\r
9**/\r
10\r
11#include <IndustryStandard/Acpi.h>\r
12#include <Library/PrintLib.h>\r
13#include <Library/UefiLib.h>\r
14#include "AcpiParser.h"\r
15#include "AcpiTableParser.h"\r
16#include "AcpiViewConfig.h"\r
17\r
18// Local Variables\r
19STATIC CONST UINT8* SratRAType;\r
20STATIC CONST UINT8* SratRALength;\r
21STATIC CONST UINT8* SratDeviceHandleType;\r
22STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;\r
23\r
24/**\r
25 This function validates the Reserved field in the SRAT table header.\r
26\r
27 @param [in] Ptr Pointer to the start of the field data.\r
28 @param [in] Context Pointer to context specific information e.g. this\r
29 could be a pointer to the ACPI table header.\r
30**/\r
31STATIC\r
32VOID\r
33EFIAPI\r
34ValidateSratReserved (\r
35 IN UINT8* Ptr,\r
36 IN VOID* Context\r
37 )\r
38{\r
39 if (*(UINT32*)Ptr != 1) {\r
40 IncrementErrorCount ();\r
41 Print (L"\nERROR: Reserved should be 1 for backward compatibility.\n");\r
42 }\r
43}\r
44\r
45/**\r
46 This function validates the Device Handle Type field in the Generic Initiator\r
47 Affinity Structure.\r
48\r
49 @param [in] Ptr Pointer to the start of the field data.\r
50 @param [in] Context Pointer to context specific information e.g. this\r
51 could be a pointer to the ACPI table header.\r
52**/\r
53STATIC\r
54VOID\r
55EFIAPI\r
56ValidateSratDeviceHandleType (\r
57 IN UINT8* Ptr,\r
58 IN VOID* Context\r
59 )\r
60{\r
61 UINT8 DeviceHandleType;\r
62\r
63 DeviceHandleType = *Ptr;\r
64\r
65 if (DeviceHandleType > EFI_ACPI_6_3_PCI_DEVICE_HANDLE) {\r
66 IncrementErrorCount ();\r
67 Print (\r
68 L"\nERROR: Invalid Device Handle Type: %d. Must be between 0 and %d.",\r
69 DeviceHandleType,\r
70 EFI_ACPI_6_3_PCI_DEVICE_HANDLE\r
71 );\r
72 }\r
73}\r
74\r
75/**\r
76 This function traces the PCI BDF Number field inside Device Handle - PCI\r
77\r
78 @param [in] Format Format string for tracing the data.\r
79 @param [in] Ptr Pointer to the start of the buffer.\r
80**/\r
81STATIC\r
82VOID\r
83EFIAPI\r
84DumpSratPciBdfNumber (\r
85 IN CONST CHAR16* Format,\r
86 IN UINT8* Ptr\r
87 )\r
88{\r
89 CHAR16 Buffer[OUTPUT_FIELD_COLUMN_WIDTH];\r
90\r
91 Print (L"\n");\r
92\r
93 /*\r
94 The PCI BDF Number subfields are printed in the order specified in the ACPI\r
95 specification. The format of the 16-bit PCI BDF Number field is as follows:\r
96\r
97 +-----+------+------+\r
98 |DEV | FUNC | BUS |\r
99 +-----+------+------+\r
100 |15:11| 10:8 | 7:0 |\r
101 +-----+------+------+\r
102 */\r
103\r
104 // Print PCI Bus Number (Bits 7:0 of Byte 2)\r
105 UnicodeSPrint (\r
106 Buffer,\r
107 sizeof (Buffer),\r
108 L"PCI Bus Number"\r
109 );\r
110 PrintFieldName (4, Buffer);\r
111 Print (\r
112 L"0x%x\n",\r
113 *Ptr\r
114 );\r
115\r
116 Ptr++;\r
117\r
118 // Print PCI Device Number (Bits 7:3 of Byte 3)\r
119 UnicodeSPrint (\r
120 Buffer,\r
121 sizeof (Buffer),\r
122 L"PCI Device Number"\r
123 );\r
124 PrintFieldName (4, Buffer);\r
125 Print (\r
126 L"0x%x\n",\r
127 (*Ptr & (BIT7 | BIT6 | BIT5 | BIT4 | BIT3)) >> 3\r
128 );\r
129\r
130 // PCI Function Number (Bits 2:0 of Byte 3)\r
131 UnicodeSPrint (\r
132 Buffer,\r
133 sizeof (Buffer),\r
134 L"PCI Function Number"\r
135 );\r
136 PrintFieldName (4, Buffer);\r
137 Print (\r
138 L"0x%x\n",\r
139 *Ptr & (BIT2 | BIT1 | BIT0)\r
140 );\r
141}\r
142\r
143/**\r
144 An ACPI_PARSER array describing the Device Handle - ACPI\r
145**/\r
146STATIC CONST ACPI_PARSER SratDeviceHandleAcpiParser[] = {\r
147 {L"ACPI_HID", 8, 0, L"0x%lx", NULL, NULL, NULL, NULL},\r
148 {L"ACPI_UID", 4, 8, L"0x%x", NULL, NULL, NULL, NULL},\r
149 {L"Reserved", 4, 12, L"0x%x", NULL, NULL, NULL, NULL}\r
150};\r
151\r
152/**\r
153 An ACPI_PARSER array describing the Device Handle - PCI\r
154**/\r
155STATIC CONST ACPI_PARSER SratDeviceHandlePciParser[] = {\r
156 {L"PCI Segment", 2, 0, L"0x%x", NULL, NULL, NULL, NULL},\r
157 {L"PCI BDF Number", 2, 2, NULL, DumpSratPciBdfNumber, NULL, NULL, NULL},\r
158 {L"Reserved", 12, 4, L"%x %x %x %x - %x %x %x %x - %x %x %x %x", Dump12Chars,\r
159 NULL, NULL, NULL}\r
160};\r
161\r
162/**\r
163 This function traces the Device Handle field inside Generic Initiator\r
164 Affinity Structure.\r
165\r
166 @param [in] Format Format string for tracing the data.\r
167 @param [in] Ptr Pointer to the start of the buffer.\r
168**/\r
169STATIC\r
170VOID\r
171EFIAPI\r
172DumpSratDeviceHandle (\r
173 IN CONST CHAR16* Format,\r
174 IN UINT8* Ptr\r
175 )\r
176{\r
177 if (SratDeviceHandleType == NULL) {\r
178 IncrementErrorCount ();\r
179 Print (L"\nERROR: Device Handle Type read incorrectly.\n");\r
180 return;\r
181 }\r
182\r
183 Print (L"\n");\r
184\r
185 if (*SratDeviceHandleType == EFI_ACPI_6_3_ACPI_DEVICE_HANDLE) {\r
186 ParseAcpi (\r
187 TRUE,\r
188 2,\r
189 NULL,\r
190 Ptr,\r
191 sizeof (EFI_ACPI_6_3_DEVICE_HANDLE_ACPI),\r
192 PARSER_PARAMS (SratDeviceHandleAcpiParser)\r
193 );\r
194 } else if (*SratDeviceHandleType == EFI_ACPI_6_3_PCI_DEVICE_HANDLE) {\r
195 ParseAcpi (\r
196 TRUE,\r
197 2,\r
198 NULL,\r
199 Ptr,\r
200 sizeof (EFI_ACPI_6_3_DEVICE_HANDLE_PCI),\r
201 PARSER_PARAMS (SratDeviceHandlePciParser)\r
202 );\r
203 }\r
204}\r
205\r
206/**\r
207 This function traces the APIC Proximity Domain field.\r
208\r
209 @param [in] Format Format string for tracing the data.\r
210 @param [in] Ptr Pointer to the start of the buffer.\r
211**/\r
212STATIC\r
213VOID\r
214EFIAPI\r
215DumpSratApicProximity (\r
216 IN CONST CHAR16* Format,\r
217 IN UINT8* Ptr\r
218 )\r
219{\r
220 UINT32 ProximityDomain;\r
221\r
222 ProximityDomain = Ptr[0] | (Ptr[1] << 8) | (Ptr[2] << 16);\r
223\r
224 Print (Format, ProximityDomain);\r
225}\r
226\r
227/**\r
228 An ACPI_PARSER array describing the SRAT Table.\r
229**/\r
230STATIC CONST ACPI_PARSER SratParser[] = {\r
231 PARSE_ACPI_HEADER (&AcpiHdrInfo),\r
232 {L"Reserved", 4, 36, L"0x%x", NULL, NULL, ValidateSratReserved, NULL},\r
233 {L"Reserved", 8, 40, L"0x%lx", NULL, NULL, NULL, NULL}\r
234};\r
235\r
236/**\r
237 An ACPI_PARSER array describing the Resource Allocation structure header.\r
238**/\r
239STATIC CONST ACPI_PARSER SratResourceAllocationParser[] = {\r
240 {L"Type", 1, 0, NULL, NULL, (VOID**)&SratRAType, NULL, NULL},\r
241 {L"Length", 1, 1, NULL, NULL, (VOID**)&SratRALength, NULL, NULL}\r
242};\r
243\r
244/**\r
245 An ACPI_PARSER array describing the GICC Affinity structure.\r
246**/\r
247STATIC CONST ACPI_PARSER SratGicCAffinityParser[] = {\r
248 {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},\r
249 {L"Length", 1, 1, L"0x%x", NULL, NULL, NULL, NULL},\r
250\r
251 {L"Proximity Domain", 4, 2, L"0x%x", NULL, NULL, NULL, NULL},\r
252 {L"ACPI Processor UID", 4, 6, L"0x%x", NULL, NULL, NULL, NULL},\r
253 {L"Flags", 4, 10, L"0x%x", NULL, NULL, NULL, NULL},\r
254 {L"Clock Domain", 4, 14, L"0x%x", NULL, NULL, NULL, NULL}\r
255};\r
256\r
257/**\r
258 An ACPI_PARSER array describing the GIC ITS Affinity structure.\r
259**/\r
260STATIC CONST ACPI_PARSER SratGicITSAffinityParser[] = {\r
261 {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},\r
262 {L"Length", 1, 1, L"0x%x", NULL, NULL, NULL, NULL},\r
263\r
264 {L"Proximity Domain", 4, 2, L"0x%x", NULL, NULL, NULL, NULL},\r
265 {L"Reserved", 2, 6, L"0x%x", NULL, NULL, NULL, NULL},\r
266 {L"ITS Id", 4, 8, L"0x%x", NULL, NULL, NULL, NULL},\r
267};\r
268\r
269/**\r
270 An ACPI_PARSER array describing the Generic Initiator Affinity Structure\r
271**/\r
272STATIC CONST ACPI_PARSER SratGenericInitiatorAffinityParser[] = {\r
273 {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},\r
274 {L"Length", 1, 1, L"0x%x", NULL, NULL, NULL, NULL},\r
275\r
276 {L"Reserved", 1, 2, L"0x%x", NULL, NULL, NULL, NULL},\r
277 {L"Device Handle Type", 1, 3, L"%d", NULL, (VOID**)&SratDeviceHandleType,\r
278 ValidateSratDeviceHandleType, NULL},\r
279 {L"Proximity Domain", 4, 4, L"0x%x", NULL, NULL, NULL, NULL},\r
280 {L"Device Handle", 16, 8, L"%s", DumpSratDeviceHandle, NULL, NULL, NULL},\r
281 {L"Flags", 4, 24, L"0x%x", NULL, NULL, NULL, NULL},\r
282 {L"Reserved", 4, 28, L"0x%x", NULL, NULL, NULL, NULL}\r
283};\r
284\r
285/**\r
286 An ACPI_PARSER array describing the Memory Affinity structure.\r
287**/\r
288STATIC CONST ACPI_PARSER SratMemAffinityParser[] = {\r
289 {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},\r
290 {L"Length", 1, 1, L"0x%x", NULL, NULL, NULL, NULL},\r
291\r
292 {L"Proximity Domain", 4, 2, L"0x%x", NULL, NULL, NULL, NULL},\r
293 {L"Reserved", 2, 6, L"0x%x", NULL, NULL, NULL, NULL},\r
294 {L"Base Address Low", 4, 8, L"0x%x", NULL, NULL, NULL, NULL},\r
295 {L"Base Address High", 4, 12, L"0x%x", NULL, NULL, NULL, NULL},\r
296 {L"Length Low", 4, 16, L"0x%x", NULL, NULL, NULL, NULL},\r
297 {L"Length High", 4, 20, L"0x%x", NULL, NULL, NULL, NULL},\r
298 {L"Reserved", 4, 24, L"0x%x", NULL, NULL, NULL, NULL},\r
299 {L"Flags", 4, 28, L"0x%x", NULL, NULL, NULL, NULL},\r
300 {L"Reserved", 8, 32, L"0x%lx", NULL, NULL, NULL, NULL}\r
301};\r
302\r
303/**\r
304 An ACPI_PARSER array describing the APIC/SAPIC Affinity structure.\r
305**/\r
306STATIC CONST ACPI_PARSER SratApciSapicAffinityParser[] = {\r
307 {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},\r
308 {L"Length", 1, 1, L"0x%x", NULL, NULL, NULL, NULL},\r
309\r
310 {L"Proximity Domain [7:0]", 1, 2, L"0x%x", NULL, NULL, NULL, NULL},\r
311 {L"APIC ID", 1, 3, L"0x%x", NULL, NULL, NULL, NULL},\r
312 {L"Flags", 4, 4, L"0x%x", NULL, NULL, NULL, NULL},\r
313 {L"Local SAPIC EID", 1, 8, L"0x%x", NULL, NULL, NULL, NULL},\r
314 {L"Proximity Domain [31:8]", 3, 9, L"0x%x", DumpSratApicProximity,\r
315 NULL, NULL, NULL},\r
316 {L"Clock Domain", 4, 12, L"0x%x", NULL, NULL, NULL, NULL}\r
317};\r
318\r
319/**\r
320 An ACPI_PARSER array describing the Processor Local x2APIC Affinity structure.\r
321**/\r
322STATIC CONST ACPI_PARSER SratX2ApciAffinityParser[] = {\r
323 {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},\r
324 {L"Length", 1, 1, L"0x%x", NULL, NULL, NULL, NULL},\r
325\r
326 {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL},\r
327 {L"Proximity Domain", 4, 4, L"0x%x", NULL, NULL, NULL, NULL},\r
328 {L"X2APIC ID", 4, 8, L"0x%x", NULL, NULL, NULL, NULL},\r
329 {L"Flags", 4, 12, L"0x%x", NULL, NULL, NULL, NULL},\r
330 {L"Clock Domain", 4, 16, L"0x%x", NULL, NULL, NULL, NULL},\r
331 {L"Reserved", 4, 20, L"0x%x", NULL, NULL, NULL, NULL}\r
332};\r
333\r
334/**\r
335 This function parses the ACPI SRAT table.\r
336 When trace is enabled this function parses the SRAT table and\r
337 traces the ACPI table fields.\r
338\r
339 This function parses the following Resource Allocation Structures:\r
340 - Processor Local APIC/SAPIC Affinity Structure\r
341 - Memory Affinity Structure\r
342 - Processor Local x2APIC Affinity Structure\r
343 - GICC Affinity Structure\r
344\r
345 This function also performs validation of the ACPI table fields.\r
346\r
347 @param [in] Trace If TRUE, trace the ACPI fields.\r
348 @param [in] Ptr Pointer to the start of the buffer.\r
349 @param [in] AcpiTableLength Length of the ACPI table.\r
350 @param [in] AcpiTableRevision Revision of the ACPI table.\r
351**/\r
352VOID\r
353EFIAPI\r
354ParseAcpiSrat (\r
355 IN BOOLEAN Trace,\r
356 IN UINT8* Ptr,\r
357 IN UINT32 AcpiTableLength,\r
358 IN UINT8 AcpiTableRevision\r
359 )\r
360{\r
361 UINT32 Offset;\r
362 UINT8* ResourcePtr;\r
363 UINT32 GicCAffinityIndex;\r
364 UINT32 GicITSAffinityIndex;\r
365 UINT32 GenericInitiatorAffinityIndex;\r
366 UINT32 MemoryAffinityIndex;\r
367 UINT32 ApicSapicAffinityIndex;\r
368 UINT32 X2ApicAffinityIndex;\r
369 CHAR8 Buffer[80]; // Used for AsciiName param of ParseAcpi\r
370\r
371 GicCAffinityIndex = 0;\r
372 GicITSAffinityIndex = 0;\r
373 GenericInitiatorAffinityIndex = 0;\r
374 MemoryAffinityIndex = 0;\r
375 ApicSapicAffinityIndex = 0;\r
376 X2ApicAffinityIndex = 0;\r
377\r
378 if (!Trace) {\r
379 return;\r
380 }\r
381\r
382 Offset = ParseAcpi (\r
383 TRUE,\r
384 0,\r
385 "SRAT",\r
386 Ptr,\r
387 AcpiTableLength,\r
388 PARSER_PARAMS (SratParser)\r
389 );\r
390\r
391 ResourcePtr = Ptr + Offset;\r
392\r
393 while (Offset < AcpiTableLength) {\r
394 ParseAcpi (\r
395 FALSE,\r
396 0,\r
397 NULL,\r
398 ResourcePtr,\r
399 AcpiTableLength - Offset,\r
400 PARSER_PARAMS (SratResourceAllocationParser)\r
401 );\r
402\r
403 // Check if the values used to control the parsing logic have been\r
404 // successfully read.\r
405 if ((SratRAType == NULL) ||\r
406 (SratRALength == NULL)) {\r
407 IncrementErrorCount ();\r
408 Print (\r
409 L"ERROR: Insufficient remaining table buffer length to read the " \\r
410 L"Static Resource Allocation structure header. Length = %d.\n",\r
411 AcpiTableLength - Offset\r
412 );\r
413 return;\r
414 }\r
415\r
416 // Validate Static Resource Allocation Structure length\r
417 if ((*SratRALength == 0) ||\r
418 ((Offset + (*SratRALength)) > AcpiTableLength)) {\r
419 IncrementErrorCount ();\r
420 Print (\r
421 L"ERROR: Invalid Static Resource Allocation Structure length. " \\r
422 L"Length = %d. Offset = %d. AcpiTableLength = %d.\n",\r
423 *SratRALength,\r
424 Offset,\r
425 AcpiTableLength\r
426 );\r
427 return;\r
428 }\r
429\r
430 switch (*SratRAType) {\r
431 case EFI_ACPI_6_3_GICC_AFFINITY:\r
432 AsciiSPrint (\r
433 Buffer,\r
434 sizeof (Buffer),\r
435 "GICC Affinity Structure [%d]",\r
436 GicCAffinityIndex++\r
437 );\r
438 ParseAcpi (\r
439 TRUE,\r
440 2,\r
441 Buffer,\r
442 ResourcePtr,\r
443 *SratRALength,\r
444 PARSER_PARAMS (SratGicCAffinityParser)\r
445 );\r
446 break;\r
447\r
448 case EFI_ACPI_6_3_GIC_ITS_AFFINITY:\r
449 AsciiSPrint (\r
450 Buffer,\r
451 sizeof (Buffer),\r
452 "GIC ITS Affinity Structure [%d]",\r
453 GicITSAffinityIndex++\r
454 );\r
455 ParseAcpi (\r
456 TRUE,\r
457 2,\r
458 Buffer,\r
459 ResourcePtr,\r
460 *SratRALength,\r
461 PARSER_PARAMS (SratGicITSAffinityParser)\r
462 );\r
463 break;\r
464\r
465 case EFI_ACPI_6_3_GENERIC_INITIATOR_AFFINITY:\r
466 AsciiSPrint (\r
467 Buffer,\r
468 sizeof (Buffer),\r
469 "Generic Initiator Affinity Structure [%d]",\r
470 GenericInitiatorAffinityIndex++\r
471 );\r
472 ParseAcpi (\r
473 TRUE,\r
474 2,\r
475 Buffer,\r
476 ResourcePtr,\r
477 *SratRALength,\r
478 PARSER_PARAMS (SratGenericInitiatorAffinityParser)\r
479 );\r
480 break;\r
481\r
482 case EFI_ACPI_6_3_MEMORY_AFFINITY:\r
483 AsciiSPrint (\r
484 Buffer,\r
485 sizeof (Buffer),\r
486 "Memory Affinity Structure [%d]",\r
487 MemoryAffinityIndex++\r
488 );\r
489 ParseAcpi (\r
490 TRUE,\r
491 2,\r
492 Buffer,\r
493 ResourcePtr,\r
494 *SratRALength,\r
495 PARSER_PARAMS (SratMemAffinityParser)\r
496 );\r
497 break;\r
498\r
499 case EFI_ACPI_6_3_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY:\r
500 AsciiSPrint (\r
501 Buffer,\r
502 sizeof (Buffer),\r
503 "APIC/SAPIC Affinity Structure [%d]",\r
504 ApicSapicAffinityIndex++\r
505 );\r
506 ParseAcpi (\r
507 TRUE,\r
508 2,\r
509 Buffer,\r
510 ResourcePtr,\r
511 *SratRALength,\r
512 PARSER_PARAMS (SratApciSapicAffinityParser)\r
513 );\r
514 break;\r
515\r
516 case EFI_ACPI_6_3_PROCESSOR_LOCAL_X2APIC_AFFINITY:\r
517 AsciiSPrint (\r
518 Buffer,\r
519 sizeof (Buffer),\r
520 "X2APIC Affinity Structure [%d]",\r
521 X2ApicAffinityIndex++\r
522 );\r
523 ParseAcpi (\r
524 TRUE,\r
525 2,\r
526 Buffer,\r
527 ResourcePtr,\r
528 *SratRALength,\r
529 PARSER_PARAMS (SratX2ApciAffinityParser)\r
530 );\r
531 break;\r
532\r
533 default:\r
534 IncrementErrorCount ();\r
535 Print (L"ERROR: Unknown SRAT Affinity type = 0x%x\n", *SratRAType);\r
536 break;\r
537 }\r
538\r
539 ResourcePtr += (*SratRALength);\r
540 Offset += (*SratRALength);\r
541 }\r
542}\r