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