4 Copyright (c) 2016 - 2019, ARM Limited. All rights reserved.
5 SPDX-License-Identifier: BSD-2-Clause-Patent
8 - ACPI 6.3 Specification - January 2019
11 #include <IndustryStandard/Acpi.h>
12 #include <Library/PrintLib.h>
13 #include <Library/UefiLib.h>
14 #include "AcpiParser.h"
15 #include "AcpiTableParser.h"
18 STATIC CONST UINT8
* SratRAType
;
19 STATIC CONST UINT8
* SratRALength
;
20 STATIC CONST UINT8
* SratDeviceHandleType
;
21 STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo
;
24 This function validates the Reserved field in the SRAT table header.
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.
33 ValidateSratReserved (
38 if (*(UINT32
*)Ptr
!= 1) {
39 IncrementErrorCount ();
40 Print (L
"\nERROR: Reserved should be 1 for backward compatibility.\n");
45 This function validates the Device Handle Type field in the Generic Initiator
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.
55 ValidateSratDeviceHandleType (
60 UINT8 DeviceHandleType
;
62 DeviceHandleType
= *Ptr
;
64 if (DeviceHandleType
> EFI_ACPI_6_3_PCI_DEVICE_HANDLE
) {
65 IncrementErrorCount ();
67 L
"\nERROR: Invalid Device Handle Type: %d. Must be between 0 and %d.",
69 EFI_ACPI_6_3_PCI_DEVICE_HANDLE
75 This function traces the PCI BDF Number field inside Device Handle - PCI
77 @param [in] Format Format string for tracing the data.
78 @param [in] Ptr Pointer to the start of the buffer.
83 DumpSratPciBdfNumber (
84 IN CONST CHAR16
* Format
,
88 CHAR16 Buffer
[OUTPUT_FIELD_COLUMN_WIDTH
];
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:
100 +-----+------+------+
103 // Print PCI Bus Number (Bits 7:0 of Byte 2)
109 PrintFieldName (4, Buffer
);
117 // Print PCI Device Number (Bits 7:3 of Byte 3)
123 PrintFieldName (4, Buffer
);
126 (*Ptr
& (BIT7
| BIT6
| BIT5
| BIT4
| BIT3
)) >> 3
129 // PCI Function Number (Bits 2:0 of Byte 3)
133 L
"PCI Function Number"
135 PrintFieldName (4, Buffer
);
138 *Ptr
& (BIT2
| BIT1
| BIT0
)
143 An ACPI_PARSER array describing the Device Handle - ACPI
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
}
152 An ACPI_PARSER array describing the Device Handle - PCI
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
,
162 This function traces the Device Handle field inside Generic Initiator
165 @param [in] Format Format string for tracing the data.
166 @param [in] Ptr Pointer to the start of the buffer.
171 DumpSratDeviceHandle (
172 IN CONST CHAR16
* Format
,
176 if (SratDeviceHandleType
== NULL
) {
177 IncrementErrorCount ();
178 Print (L
"\nERROR: Device Handle Type read incorrectly.\n");
184 if (*SratDeviceHandleType
== EFI_ACPI_6_3_ACPI_DEVICE_HANDLE
) {
190 sizeof (EFI_ACPI_6_3_DEVICE_HANDLE_ACPI
),
191 PARSER_PARAMS (SratDeviceHandleAcpiParser
)
193 } else if (*SratDeviceHandleType
== EFI_ACPI_6_3_PCI_DEVICE_HANDLE
) {
199 sizeof (EFI_ACPI_6_3_DEVICE_HANDLE_PCI
),
200 PARSER_PARAMS (SratDeviceHandlePciParser
)
206 This function traces the APIC Proximity Domain field.
208 @param [in] Format Format string for tracing the data.
209 @param [in] Ptr Pointer to the start of the buffer.
214 DumpSratApicProximity (
215 IN CONST CHAR16
* Format
,
219 UINT32 ProximityDomain
;
221 ProximityDomain
= Ptr
[0] | (Ptr
[1] << 8) | (Ptr
[2] << 16);
223 Print (Format
, ProximityDomain
);
227 An ACPI_PARSER array describing the SRAT Table.
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
}
236 An ACPI_PARSER array describing the Resource Allocation structure header.
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
}
244 An ACPI_PARSER array describing the GICC Affinity structure.
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
},
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
}
257 An ACPI_PARSER array describing the GIC ITS Affinity structure.
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
},
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
},
269 An ACPI_PARSER array describing the Generic Initiator Affinity Structure
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
},
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
}
285 An ACPI_PARSER array describing the Memory Affinity structure.
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
},
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
}
303 An ACPI_PARSER array describing the APIC/SAPIC Affinity structure.
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
},
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
,
315 {L
"Clock Domain", 4, 12, L
"0x%x", NULL
, NULL
, NULL
, NULL
}
319 An ACPI_PARSER array describing the Processor Local x2APIC Affinity structure.
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
},
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
}
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.
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
344 This function also performs validation of the ACPI table fields.
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.
356 IN UINT32 AcpiTableLength
,
357 IN UINT8 AcpiTableRevision
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
370 GicCAffinityIndex
= 0;
371 GicITSAffinityIndex
= 0;
372 GenericInitiatorAffinityIndex
= 0;
373 MemoryAffinityIndex
= 0;
374 ApicSapicAffinityIndex
= 0;
375 X2ApicAffinityIndex
= 0;
387 PARSER_PARAMS (SratParser
)
390 ResourcePtr
= Ptr
+ Offset
;
392 while (Offset
< AcpiTableLength
) {
398 AcpiTableLength
- Offset
,
399 PARSER_PARAMS (SratResourceAllocationParser
)
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 ();
408 L
"ERROR: Insufficient remaining table buffer length to read the " \
409 L
"Static Resource Allocation structure header. Length = %d.\n",
410 AcpiTableLength
- Offset
415 // Make sure the SRAT structure lies inside the table
416 if ((Offset
+ *SratRALength
) > AcpiTableLength
) {
417 IncrementErrorCount ();
419 L
"ERROR: Invalid SRAT structure length. SratRALength = %d. " \
420 L
"RemainingTableBufferLength = %d. SRAT parsing aborted.\n",
422 AcpiTableLength
- Offset
427 switch (*SratRAType
) {
428 case EFI_ACPI_6_3_GICC_AFFINITY
:
432 "GICC Affinity Structure [%d]",
441 PARSER_PARAMS (SratGicCAffinityParser
)
445 case EFI_ACPI_6_3_GIC_ITS_AFFINITY
:
449 "GIC ITS Affinity Structure [%d]",
450 GicITSAffinityIndex
++
458 PARSER_PARAMS (SratGicITSAffinityParser
)
462 case EFI_ACPI_6_3_GENERIC_INITIATOR_AFFINITY
:
466 "Generic Initiator Affinity Structure [%d]",
467 GenericInitiatorAffinityIndex
++
475 PARSER_PARAMS (SratGenericInitiatorAffinityParser
)
479 case EFI_ACPI_6_3_MEMORY_AFFINITY
:
483 "Memory Affinity Structure [%d]",
484 MemoryAffinityIndex
++
492 PARSER_PARAMS (SratMemAffinityParser
)
496 case EFI_ACPI_6_3_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY
:
500 "APIC/SAPIC Affinity Structure [%d]",
501 ApicSapicAffinityIndex
++
509 PARSER_PARAMS (SratApciSapicAffinityParser
)
513 case EFI_ACPI_6_3_PROCESSOR_LOCAL_X2APIC_AFFINITY
:
517 "X2APIC Affinity Structure [%d]",
518 X2ApicAffinityIndex
++
526 PARSER_PARAMS (SratX2ApciAffinityParser
)
531 IncrementErrorCount ();
532 Print (L
"ERROR: Unknown SRAT Affinity type = 0x%x\n", *SratRAType
);
536 ResourcePtr
+= (*SratRALength
);
537 Offset
+= (*SratRALength
);