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