4 Copyright (c) 2016 - 2020, 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"
16 #include "AcpiViewConfig.h"
19 STATIC CONST UINT8
*SratRAType
;
20 STATIC CONST UINT8
*SratRALength
;
21 STATIC CONST UINT8
*SratDeviceHandleType
;
22 STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo
;
25 This function validates the Reserved field in the SRAT table header.
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.
34 ValidateSratReserved (
39 if (*(UINT32
*)Ptr
!= 1) {
40 IncrementErrorCount ();
41 Print (L
"\nERROR: Reserved should be 1 for backward compatibility.\n");
46 This function validates the Device Handle Type field in the Generic Initiator
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.
56 ValidateSratDeviceHandleType (
61 UINT8 DeviceHandleType
;
63 DeviceHandleType
= *Ptr
;
65 if (DeviceHandleType
> EFI_ACPI_6_3_PCI_DEVICE_HANDLE
) {
66 IncrementErrorCount ();
68 L
"\nERROR: Invalid Device Handle Type: %d. Must be between 0 and %d.",
70 EFI_ACPI_6_3_PCI_DEVICE_HANDLE
76 This function traces the PCI BDF Number field inside Device Handle - PCI
78 @param [in] Format Format string for tracing the data.
79 @param [in] Ptr Pointer to the start of the buffer.
84 DumpSratPciBdfNumber (
85 IN CONST CHAR16
*Format
,
89 CHAR16 Buffer
[OUTPUT_FIELD_COLUMN_WIDTH
];
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:
101 +-----+------+------+
104 // Print PCI Bus Number (Bits 7:0 of Byte 2)
110 PrintFieldName (4, Buffer
);
118 // Print PCI Device Number (Bits 7:3 of Byte 3)
124 PrintFieldName (4, Buffer
);
127 (*Ptr
& (BIT7
| BIT6
| BIT5
| BIT4
| BIT3
)) >> 3
130 // PCI Function Number (Bits 2:0 of Byte 3)
134 L
"PCI Function Number"
136 PrintFieldName (4, Buffer
);
139 *Ptr
& (BIT2
| BIT1
| BIT0
)
144 An ACPI_PARSER array describing the Device Handle - ACPI
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
}
153 An ACPI_PARSER array describing the Device Handle - PCI
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
,
163 This function traces the Device Handle field inside Generic Initiator
166 @param [in] Format Format string for tracing the data.
167 @param [in] Ptr Pointer to the start of the buffer.
172 DumpSratDeviceHandle (
173 IN CONST CHAR16
*Format
,
177 if (SratDeviceHandleType
== NULL
) {
178 IncrementErrorCount ();
179 Print (L
"\nERROR: Device Handle Type read incorrectly.\n");
185 if (*SratDeviceHandleType
== EFI_ACPI_6_3_ACPI_DEVICE_HANDLE
) {
191 sizeof (EFI_ACPI_6_3_DEVICE_HANDLE_ACPI
),
192 PARSER_PARAMS (SratDeviceHandleAcpiParser
)
194 } else if (*SratDeviceHandleType
== EFI_ACPI_6_3_PCI_DEVICE_HANDLE
) {
200 sizeof (EFI_ACPI_6_3_DEVICE_HANDLE_PCI
),
201 PARSER_PARAMS (SratDeviceHandlePciParser
)
207 This function traces the APIC Proximity Domain field.
209 @param [in] Format Format string for tracing the data.
210 @param [in] Ptr Pointer to the start of the buffer.
215 DumpSratApicProximity (
216 IN CONST CHAR16
*Format
,
220 UINT32 ProximityDomain
;
222 ProximityDomain
= Ptr
[0] | (Ptr
[1] << 8) | (Ptr
[2] << 16);
224 Print (Format
, ProximityDomain
);
228 An ACPI_PARSER array describing the SRAT Table.
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
}
237 An ACPI_PARSER array describing the Resource Allocation structure header.
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
}
245 An ACPI_PARSER array describing the GICC Affinity structure.
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
},
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
}
258 An ACPI_PARSER array describing the GIC ITS Affinity structure.
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
},
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
},
270 An ACPI_PARSER array describing the Generic Initiator Affinity Structure
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
},
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
}
286 An ACPI_PARSER array describing the Memory Affinity structure.
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
},
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
}
304 An ACPI_PARSER array describing the APIC/SAPIC Affinity structure.
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
},
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
,
316 { L
"Clock Domain", 4, 12, L
"0x%x", NULL
, NULL
, NULL
, NULL
}
320 An ACPI_PARSER array describing the Processor Local x2APIC Affinity structure.
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
},
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
}
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.
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
345 This function also performs validation of the ACPI table fields.
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.
357 IN UINT32 AcpiTableLength
,
358 IN UINT8 AcpiTableRevision
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
371 GicCAffinityIndex
= 0;
372 GicITSAffinityIndex
= 0;
373 GenericInitiatorAffinityIndex
= 0;
374 MemoryAffinityIndex
= 0;
375 ApicSapicAffinityIndex
= 0;
376 X2ApicAffinityIndex
= 0;
388 PARSER_PARAMS (SratParser
)
391 ResourcePtr
= Ptr
+ Offset
;
393 while (Offset
< AcpiTableLength
) {
399 AcpiTableLength
- Offset
,
400 PARSER_PARAMS (SratResourceAllocationParser
)
403 // Check if the values used to control the parsing logic have been
404 // successfully read.
405 if ((SratRAType
== NULL
) ||
406 (SratRALength
== NULL
))
408 IncrementErrorCount ();
410 L
"ERROR: Insufficient remaining table buffer length to read the " \
411 L
"Static Resource Allocation structure header. Length = %d.\n",
412 AcpiTableLength
- Offset
417 // Validate Static Resource Allocation Structure length
418 if ((*SratRALength
== 0) ||
419 ((Offset
+ (*SratRALength
)) > AcpiTableLength
))
421 IncrementErrorCount ();
423 L
"ERROR: Invalid Static Resource Allocation Structure length. " \
424 L
"Length = %d. Offset = %d. AcpiTableLength = %d.\n",
432 switch (*SratRAType
) {
433 case EFI_ACPI_6_3_GICC_AFFINITY
:
437 "GICC Affinity Structure [%d]",
446 PARSER_PARAMS (SratGicCAffinityParser
)
450 case EFI_ACPI_6_3_GIC_ITS_AFFINITY
:
454 "GIC ITS Affinity Structure [%d]",
455 GicITSAffinityIndex
++
463 PARSER_PARAMS (SratGicITSAffinityParser
)
467 case EFI_ACPI_6_3_GENERIC_INITIATOR_AFFINITY
:
471 "Generic Initiator Affinity Structure [%d]",
472 GenericInitiatorAffinityIndex
++
480 PARSER_PARAMS (SratGenericInitiatorAffinityParser
)
484 case EFI_ACPI_6_3_MEMORY_AFFINITY
:
488 "Memory Affinity Structure [%d]",
489 MemoryAffinityIndex
++
497 PARSER_PARAMS (SratMemAffinityParser
)
501 case EFI_ACPI_6_3_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY
:
505 "APIC/SAPIC Affinity Structure [%d]",
506 ApicSapicAffinityIndex
++
514 PARSER_PARAMS (SratApciSapicAffinityParser
)
518 case EFI_ACPI_6_3_PROCESSOR_LOCAL_X2APIC_AFFINITY
:
522 "X2APIC Affinity Structure [%d]",
523 X2ApicAffinityIndex
++
531 PARSER_PARAMS (SratX2ApciAffinityParser
)
536 IncrementErrorCount ();
537 Print (L
"ERROR: Unknown SRAT Affinity type = 0x%x\n", *SratRAType
);
541 ResourcePtr
+= (*SratRALength
);
542 Offset
+= (*SratRALength
);