]> git.proxmox.com Git - mirror_edk2.git/blob - DynamicTablesPkg/Library/Acpi/Arm/AcpiSratLibArm/SratGenerator.c
DynamicTablesPkg: Apply uncrustify changes
[mirror_edk2.git] / DynamicTablesPkg / Library / Acpi / Arm / AcpiSratLibArm / SratGenerator.c
1 /** @file
2 SRAT Table Generator
3
4 Copyright (c) 2019 - 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 @par Glossary:
11 - Cm or CM - Configuration Manager
12 - Obj or OBJ - Object
13 **/
14
15 #include <Library/AcpiLib.h>
16 #include <Library/BaseLib.h>
17 #include <Library/DebugLib.h>
18 #include <Library/MemoryAllocationLib.h>
19 #include <Protocol/AcpiTable.h>
20
21 // Module specific include files.
22 #include <AcpiTableGenerator.h>
23 #include <ConfigurationManagerObject.h>
24 #include <ConfigurationManagerHelper.h>
25 #include <Library/TableHelperLib.h>
26 #include <Protocol/ConfigurationManagerProtocol.h>
27
28 /**
29 ARM standard SRAT Generator
30
31 Requirements:
32 The following Configuration Manager Object(s) are used by this Generator:
33 - EArmObjGicCInfo (REQUIRED)
34 - EArmObjGicItsInfo (OPTIONAL)
35 - EArmObjMemoryAffinityInfo (OPTIONAL)
36 - EArmObjGenericInitiatorAffinityInfo (OPTIONAL)
37 - EArmObjDeviceHandleAcpi (OPTIONAL)
38 - EArmObjDeviceHandlePci (OPTIONAL)
39 */
40
41 /** This macro expands to a function that retrieves the GIC
42 CPU interface Information from the Configuration Manager.
43 */
44 GET_OBJECT_LIST (
45 EObjNameSpaceArm,
46 EArmObjGicCInfo,
47 CM_ARM_GICC_INFO
48 );
49
50 /** This macro expands to a function that retrieves the GIC
51 Interrupt Translation Service Information from the
52 Configuration Manager.
53 */
54 GET_OBJECT_LIST (
55 EObjNameSpaceArm,
56 EArmObjGicItsInfo,
57 CM_ARM_GIC_ITS_INFO
58 );
59
60 /**
61 This macro expands to a function that retrieves the Memory Affinity
62 information from the Configuration Manager.
63 */
64 GET_OBJECT_LIST (
65 EObjNameSpaceArm,
66 EArmObjMemoryAffinityInfo,
67 CM_ARM_MEMORY_AFFINITY_INFO
68 );
69
70 /**
71 This macro expands to a function that retrieves the Generic Initiator Affinity
72 information from the Configuration Manager.
73 */
74 GET_OBJECT_LIST (
75 EObjNameSpaceArm,
76 EArmObjGenericInitiatorAffinityInfo,
77 CM_ARM_GENERIC_INITIATOR_AFFINITY_INFO
78 );
79
80 /**
81 This macro expands to a function that retrieves the ACPI Device Handle
82 information from the Configuration Manager.
83 */
84 GET_OBJECT_LIST (
85 EObjNameSpaceArm,
86 EArmObjDeviceHandleAcpi,
87 CM_ARM_DEVICE_HANDLE_ACPI
88 );
89
90 /**
91 This macro expands to a function that retrieves the PCI Device Handle
92 information from the Configuration Manager.
93 */
94 GET_OBJECT_LIST (
95 EObjNameSpaceArm,
96 EArmObjDeviceHandlePci,
97 CM_ARM_DEVICE_HANDLE_PCI
98 );
99
100 /** Return the PCI Device information in BDF format
101
102 PCI Bus Number - Max 256 busses (Bits 15:8 of BDF)
103 PCI Device Number - Max 32 devices (Bits 7:3 of BDF)
104 PCI Function Number - Max 8 functions (Bits 2:0 of BDF)
105
106 @param [in] DeviceHandlePci Pointer to the PCI Device Handle.
107
108 @retval BDF value corresponding to the PCI Device Handle.
109 **/
110 STATIC
111 UINT16
112 GetBdf (
113 IN CONST CM_ARM_DEVICE_HANDLE_PCI *DeviceHandlePci
114 )
115 {
116 UINT16 Bdf;
117
118 Bdf = (UINT16)DeviceHandlePci->BusNumber << 8;
119 Bdf |= (DeviceHandlePci->DeviceNumber & 0x1F) << 3;
120 Bdf |= DeviceHandlePci->FunctionNumber & 0x7;
121 return Bdf;
122 }
123
124 /** Add the GICC Affinity Structures in the SRAT Table.
125
126 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
127 Protocol Interface.
128 @param [in] Srat Pointer to the SRAT Table.
129 @param [in] GicCAffOffset Offset of the GICC Affinity
130 information in the SRAT Table.
131 @param [in] GicCInfo Pointer to the GIC CPU Information list.
132 @param [in] GicCCount Count of GIC CPU Interfaces.
133
134 @retval EFI_SUCCESS Table generated successfully.
135 **/
136 STATIC
137 EFI_STATUS
138 AddGICCAffinity (
139 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
140 IN EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER *CONST Srat,
141 IN CONST UINT32 GicCAffOffset,
142 IN CONST CM_ARM_GICC_INFO *GicCInfo,
143 IN UINT32 GicCCount
144 )
145 {
146 EFI_ACPI_6_3_GICC_AFFINITY_STRUCTURE *GicCAff;
147
148 ASSERT (Srat != NULL);
149 ASSERT (GicCInfo != NULL);
150
151 GicCAff = (EFI_ACPI_6_3_GICC_AFFINITY_STRUCTURE *)((UINT8 *)Srat +
152 GicCAffOffset);
153
154 while (GicCCount-- != 0) {
155 DEBUG ((DEBUG_INFO, "SRAT: GicCAff = 0x%p\n", GicCAff));
156
157 GicCAff->Type = EFI_ACPI_6_3_GICC_AFFINITY;
158 GicCAff->Length = sizeof (EFI_ACPI_6_3_GICC_AFFINITY_STRUCTURE);
159 GicCAff->ProximityDomain = GicCInfo->ProximityDomain;
160 GicCAff->AcpiProcessorUid = GicCInfo->AcpiProcessorUid;
161 GicCAff->Flags = GicCInfo->AffinityFlags;
162 GicCAff->ClockDomain = GicCInfo->ClockDomain;
163
164 // Next
165 GicCAff++;
166 GicCInfo++;
167 }// while
168
169 return EFI_SUCCESS;
170 }
171
172 /** Add the GIC ITS Affinity Structures in the SRAT Table.
173
174 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
175 Protocol Interface.
176 @param [in] Srat Pointer to the SRAT Table.
177 @param [in] GicItsAffOffset Offset of the GIC ITS Affinity
178 information in the SRAT Table.
179 @param [in] GicItsInfo Pointer to the GIC ITS Information list.
180 @param [in] GicItsCount Count of GIC ITS.
181
182 @retval EFI_SUCCESS Table generated successfully.
183 **/
184 STATIC
185 EFI_STATUS
186 AddGICItsAffinity (
187 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
188 IN EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER *CONST Srat,
189 IN CONST UINT32 GicItsAffOffset,
190 IN CONST CM_ARM_GIC_ITS_INFO *GicItsInfo,
191 IN UINT32 GicItsCount
192 )
193 {
194 EFI_ACPI_6_3_GIC_ITS_AFFINITY_STRUCTURE *GicItsAff;
195
196 ASSERT (Srat != NULL);
197 ASSERT (GicItsInfo != NULL);
198
199 GicItsAff = (EFI_ACPI_6_3_GIC_ITS_AFFINITY_STRUCTURE *)((UINT8 *)Srat +
200 GicItsAffOffset);
201
202 while (GicItsCount-- != 0) {
203 DEBUG ((DEBUG_INFO, "SRAT: GicItsAff = 0x%p\n", GicItsAff));
204
205 GicItsAff->Type = EFI_ACPI_6_3_GIC_ITS_AFFINITY;
206 GicItsAff->Length = sizeof (EFI_ACPI_6_3_GIC_ITS_AFFINITY_STRUCTURE);
207 GicItsAff->ProximityDomain = GicItsInfo->ProximityDomain;
208 GicItsAff->Reserved[0] = EFI_ACPI_RESERVED_BYTE;
209 GicItsAff->Reserved[1] = EFI_ACPI_RESERVED_BYTE;
210 GicItsAff->ItsId = GicItsInfo->GicItsId;
211
212 // Next
213 GicItsAff++;
214 GicItsInfo++;
215 }// while
216
217 return EFI_SUCCESS;
218 }
219
220 /** Add the Memory Affinity Structures in the SRAT Table.
221
222 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
223 Protocol Interface.
224 @param [in] Srat Pointer to the SRAT Table.
225 @param [in] MemAffOffset Offset of the Memory Affinity
226 information in the SRAT Table.
227 @param [in] MemAffInfo Pointer to the Memory Affinity Information list.
228 @param [in] MemAffCount Count of Memory Affinity objects.
229
230 @retval EFI_SUCCESS Table generated successfully.
231 **/
232 STATIC
233 EFI_STATUS
234 AddMemoryAffinity (
235 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
236 IN EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER *CONST Srat,
237 IN CONST UINT32 MemAffOffset,
238 IN CONST CM_ARM_MEMORY_AFFINITY_INFO *MemAffInfo,
239 IN UINT32 MemAffCount
240 )
241 {
242 EFI_ACPI_6_3_MEMORY_AFFINITY_STRUCTURE *MemAff;
243
244 ASSERT (Srat != NULL);
245 ASSERT (MemAffInfo != NULL);
246
247 MemAff = (EFI_ACPI_6_3_MEMORY_AFFINITY_STRUCTURE *)((UINT8 *)Srat +
248 MemAffOffset);
249
250 while (MemAffCount-- != 0) {
251 DEBUG ((DEBUG_INFO, "SRAT: MemAff = 0x%p\n", MemAff));
252
253 MemAff->Type = EFI_ACPI_6_3_MEMORY_AFFINITY;
254 MemAff->Length = sizeof (EFI_ACPI_6_3_MEMORY_AFFINITY_STRUCTURE);
255 MemAff->ProximityDomain = MemAffInfo->ProximityDomain;
256 MemAff->Reserved1 = EFI_ACPI_RESERVED_WORD;
257 MemAff->AddressBaseLow = (UINT32)(MemAffInfo->BaseAddress & MAX_UINT32);
258 MemAff->AddressBaseHigh = (UINT32)(MemAffInfo->BaseAddress >> 32);
259 MemAff->LengthLow = (UINT32)(MemAffInfo->Length & MAX_UINT32);
260 MemAff->LengthHigh = (UINT32)(MemAffInfo->Length >> 32);
261 MemAff->Reserved2 = EFI_ACPI_RESERVED_DWORD;
262 MemAff->Flags = MemAffInfo->Flags;
263 MemAff->Reserved3 = EFI_ACPI_RESERVED_QWORD;
264
265 // Next
266 MemAff++;
267 MemAffInfo++;
268 }// while
269
270 return EFI_SUCCESS;
271 }
272
273 /** Add the Generic Initiator Affinity Structures in the SRAT Table.
274
275 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
276 Protocol Interface.
277 @param [in] Srat Pointer to the SRAT Table.
278 @param [in] GenInitAffOff Offset of the Generic Initiator Affinity
279 information in the SRAT Table.
280 @param [in] GenInitAffInfo Pointer to the Generic Initiator Affinity
281 Information list.
282 @param [in] GenInitAffCount Count of Generic Initiator Affinity
283 objects.
284
285 @retval EFI_SUCCESS Table generated successfully.
286 @retval EFI_INVALID_PARAMETER A parameter is invalid.
287 @retval EFI_NOT_FOUND The required object information is not found.
288 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
289 Manager is less than the Object size for the
290 requested object.
291 **/
292 STATIC
293 EFI_STATUS
294 AddGenericInitiatorAffinity (
295 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
296 IN EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER *CONST Srat,
297 IN CONST UINT32 GenInitAffOff,
298 IN CONST CM_ARM_GENERIC_INITIATOR_AFFINITY_INFO *GenInitAffInfo,
299 IN UINT32 GenInitAffCount
300 )
301 {
302 EFI_STATUS Status;
303 EFI_ACPI_6_3_GENERIC_INITIATOR_AFFINITY_STRUCTURE *GenInitAff;
304 CM_ARM_DEVICE_HANDLE_ACPI *DeviceHandleAcpi;
305 CM_ARM_DEVICE_HANDLE_PCI *DeviceHandlePci;
306 UINT32 DeviceHandleCount;
307
308 ASSERT (Srat != NULL);
309 ASSERT (GenInitAffInfo != NULL);
310
311 GenInitAff = (EFI_ACPI_6_3_GENERIC_INITIATOR_AFFINITY_STRUCTURE *)(
312 (UINT8 *)Srat + GenInitAffOff);
313
314 while (GenInitAffCount-- != 0) {
315 DEBUG ((DEBUG_INFO, "SRAT: GenInitAff = 0x%p\n", GenInitAff));
316
317 GenInitAff->Type = EFI_ACPI_6_3_GENERIC_INITIATOR_AFFINITY;
318 GenInitAff->Length =
319 sizeof (EFI_ACPI_6_3_GENERIC_INITIATOR_AFFINITY_STRUCTURE);
320 GenInitAff->Reserved1 = EFI_ACPI_RESERVED_WORD;
321 GenInitAff->DeviceHandleType = GenInitAffInfo->DeviceHandleType;
322 GenInitAff->ProximityDomain = GenInitAffInfo->ProximityDomain;
323
324 if (GenInitAffInfo->DeviceHandleToken == CM_NULL_TOKEN) {
325 DEBUG ((
326 DEBUG_ERROR,
327 "ERROR: SRAT: Invalid Device Handle Token.\n"
328 ));
329 ASSERT (0);
330 return EFI_INVALID_PARAMETER;
331 }
332
333 if (GenInitAffInfo->DeviceHandleType == EFI_ACPI_6_3_ACPI_DEVICE_HANDLE) {
334 Status = GetEArmObjDeviceHandleAcpi (
335 CfgMgrProtocol,
336 GenInitAffInfo->DeviceHandleToken,
337 &DeviceHandleAcpi,
338 &DeviceHandleCount
339 );
340 if (EFI_ERROR (Status)) {
341 DEBUG ((
342 DEBUG_ERROR,
343 "ERROR: SRAT: Failed to get ACPI Device Handle Inf."
344 " DeviceHandleToken = %p."
345 " Status = %r\n",
346 GenInitAffInfo->DeviceHandleToken,
347 Status
348 ));
349 return Status;
350 }
351
352 // We are expecting only one device handle.
353 ASSERT (DeviceHandleCount == 1);
354
355 // Populate the ACPI device handle information.
356 GenInitAff->DeviceHandle.Acpi.AcpiHid = DeviceHandleAcpi->Hid;
357 GenInitAff->DeviceHandle.Acpi.AcpiUid = DeviceHandleAcpi->Uid;
358 GenInitAff->DeviceHandle.Acpi.Reserved[0] = EFI_ACPI_RESERVED_BYTE;
359 GenInitAff->DeviceHandle.Acpi.Reserved[1] = EFI_ACPI_RESERVED_BYTE;
360 GenInitAff->DeviceHandle.Acpi.Reserved[2] = EFI_ACPI_RESERVED_BYTE;
361 GenInitAff->DeviceHandle.Acpi.Reserved[3] = EFI_ACPI_RESERVED_BYTE;
362 } else if (GenInitAffInfo->DeviceHandleType ==
363 EFI_ACPI_6_3_PCI_DEVICE_HANDLE)
364 {
365 Status = GetEArmObjDeviceHandlePci (
366 CfgMgrProtocol,
367 GenInitAffInfo->DeviceHandleToken,
368 &DeviceHandlePci,
369 &DeviceHandleCount
370 );
371 if (EFI_ERROR (Status)) {
372 DEBUG ((
373 DEBUG_ERROR,
374 "ERROR: SRAT: Failed to get ACPI Device Handle Inf."
375 " DeviceHandleToken = %p."
376 " Status = %r\n",
377 GenInitAffInfo->DeviceHandleToken,
378 Status
379 ));
380 return Status;
381 }
382
383 // We are expecting only one device handle
384 ASSERT (DeviceHandleCount == 1);
385
386 // Populate the ACPI device handle information.
387 GenInitAff->DeviceHandle.Pci.PciSegment = DeviceHandlePci->SegmentNumber;
388 GenInitAff->DeviceHandle.Pci.PciBdfNumber = GetBdf (DeviceHandlePci);
389
390 GenInitAff->DeviceHandle.Pci.Reserved[0] = EFI_ACPI_RESERVED_BYTE;
391 GenInitAff->DeviceHandle.Pci.Reserved[1] = EFI_ACPI_RESERVED_BYTE;
392 GenInitAff->DeviceHandle.Pci.Reserved[2] = EFI_ACPI_RESERVED_BYTE;
393 GenInitAff->DeviceHandle.Pci.Reserved[3] = EFI_ACPI_RESERVED_BYTE;
394 GenInitAff->DeviceHandle.Pci.Reserved[4] = EFI_ACPI_RESERVED_BYTE;
395 GenInitAff->DeviceHandle.Pci.Reserved[5] = EFI_ACPI_RESERVED_BYTE;
396 GenInitAff->DeviceHandle.Pci.Reserved[6] = EFI_ACPI_RESERVED_BYTE;
397 GenInitAff->DeviceHandle.Pci.Reserved[7] = EFI_ACPI_RESERVED_BYTE;
398 GenInitAff->DeviceHandle.Pci.Reserved[8] = EFI_ACPI_RESERVED_BYTE;
399 GenInitAff->DeviceHandle.Pci.Reserved[9] = EFI_ACPI_RESERVED_BYTE;
400 GenInitAff->DeviceHandle.Pci.Reserved[10] = EFI_ACPI_RESERVED_BYTE;
401 GenInitAff->DeviceHandle.Pci.Reserved[11] = EFI_ACPI_RESERVED_BYTE;
402 } else {
403 DEBUG ((
404 DEBUG_ERROR,
405 "ERROR: SRAT: Invalid Device Handle Type.\n"
406 ));
407 ASSERT (0);
408 return EFI_INVALID_PARAMETER;
409 }
410
411 GenInitAff->Flags = GenInitAffInfo->Flags;
412 GenInitAff->Reserved2[0] = EFI_ACPI_RESERVED_BYTE;
413 GenInitAff->Reserved2[1] = EFI_ACPI_RESERVED_BYTE;
414
415 // Next
416 GenInitAff++;
417 GenInitAffInfo++;
418 }// while
419
420 return EFI_SUCCESS;
421 }
422
423 /** Construct the SRAT ACPI table.
424
425 Called by the Dynamic Table Manager, this function invokes the
426 Configuration Manager protocol interface to get the required hardware
427 information for generating the ACPI table.
428
429 If this function allocates any resources then they must be freed
430 in the FreeXXXXTableResources function.
431
432 @param [in] This Pointer to the table generator.
433 @param [in] AcpiTableInfo Pointer to the ACPI Table Info.
434 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
435 Protocol Interface.
436 @param [out] Table Pointer to the constructed ACPI Table.
437
438 @retval EFI_SUCCESS Table generated successfully.
439 @retval EFI_INVALID_PARAMETER A parameter is invalid.
440 @retval EFI_NOT_FOUND The required object was not found.
441 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
442 Manager is less than the Object size for the
443 requested object.
444 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
445 **/
446 STATIC
447 EFI_STATUS
448 EFIAPI
449 BuildSratTable (
450 IN CONST ACPI_TABLE_GENERATOR *CONST This,
451 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,
452 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
453 OUT EFI_ACPI_DESCRIPTION_HEADER **CONST Table
454 )
455 {
456 EFI_STATUS Status;
457 UINT32 TableSize;
458 UINT32 GicCCount;
459 UINT32 GicItsCount;
460 UINT32 MemAffCount;
461 UINT32 GenInitiatorAffCount;
462
463 UINT32 GicCAffOffset;
464 UINT32 GicItsAffOffset;
465 UINT32 MemAffOffset;
466 UINT32 GenInitiatorAffOffset;
467
468 CM_ARM_GICC_INFO *GicCInfo;
469 CM_ARM_GIC_ITS_INFO *GicItsInfo;
470 CM_ARM_MEMORY_AFFINITY_INFO *MemAffInfo;
471 CM_ARM_GENERIC_INITIATOR_AFFINITY_INFO *GenInitiatorAffInfo;
472
473 EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER *Srat;
474
475 ASSERT (
476 (This != NULL) &&
477 (AcpiTableInfo != NULL) &&
478 (CfgMgrProtocol != NULL) &&
479 (Table != NULL) &&
480 (AcpiTableInfo->TableGeneratorId == This->GeneratorID) &&
481 (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature)
482 );
483
484 if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) ||
485 (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision))
486 {
487 DEBUG ((
488 DEBUG_ERROR,
489 "ERROR: SRAT: Requested table revision = %d is not supported. "
490 "Supported table revisions: Minimum = %d. Maximum = %d\n",
491 AcpiTableInfo->AcpiTableRevision,
492 This->MinAcpiTableRevision,
493 This->AcpiTableRevision
494 ));
495 return EFI_INVALID_PARAMETER;
496 }
497
498 *Table = NULL;
499
500 Status = GetEArmObjGicCInfo (
501 CfgMgrProtocol,
502 CM_NULL_TOKEN,
503 &GicCInfo,
504 &GicCCount
505 );
506 if (EFI_ERROR (Status)) {
507 DEBUG ((
508 DEBUG_ERROR,
509 "ERROR: SRAT: Failed to get GICC Info. Status = %r\n",
510 Status
511 ));
512 goto error_handler;
513 }
514
515 if (GicCCount == 0) {
516 DEBUG ((
517 DEBUG_ERROR,
518 "ERROR: SRAT: GIC CPU Interface information not provided.\n"
519 ));
520 ASSERT (0);
521 Status = EFI_INVALID_PARAMETER;
522 goto error_handler;
523 }
524
525 Status = GetEArmObjGicItsInfo (
526 CfgMgrProtocol,
527 CM_NULL_TOKEN,
528 &GicItsInfo,
529 &GicItsCount
530 );
531 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
532 DEBUG ((
533 DEBUG_ERROR,
534 "ERROR: SRAT: Failed to get GIC ITS Info. Status = %r\n",
535 Status
536 ));
537 goto error_handler;
538 }
539
540 Status = GetEArmObjMemoryAffinityInfo (
541 CfgMgrProtocol,
542 CM_NULL_TOKEN,
543 &MemAffInfo,
544 &MemAffCount
545 );
546 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
547 DEBUG ((
548 DEBUG_ERROR,
549 "ERROR: SRAT: Failed to get Memory Affinity Info. Status = %r\n",
550 Status
551 ));
552 goto error_handler;
553 }
554
555 Status = GetEArmObjGenericInitiatorAffinityInfo (
556 CfgMgrProtocol,
557 CM_NULL_TOKEN,
558 &GenInitiatorAffInfo,
559 &GenInitiatorAffCount
560 );
561 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
562 DEBUG ((
563 DEBUG_ERROR,
564 "ERROR: SRAT: Failed to get Generic Initiator Affinity Info."
565 " Status = %r\n",
566 Status
567 ));
568 goto error_handler;
569 }
570
571 // Calculate the size of the SRAT table
572 TableSize = sizeof (EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER);
573
574 GicCAffOffset = TableSize;
575 TableSize += (sizeof (EFI_ACPI_6_3_GICC_AFFINITY_STRUCTURE) * GicCCount);
576
577 if (GicItsCount != 0) {
578 GicItsAffOffset = TableSize;
579 TableSize += (sizeof (EFI_ACPI_6_3_GIC_ITS_AFFINITY_STRUCTURE) *
580 GicItsCount);
581 }
582
583 if (MemAffCount != 0) {
584 MemAffOffset = TableSize;
585 TableSize += (sizeof (EFI_ACPI_6_3_MEMORY_AFFINITY_STRUCTURE) *
586 MemAffCount);
587 }
588
589 if (GenInitiatorAffCount != 0) {
590 GenInitiatorAffOffset = TableSize;
591 TableSize += (sizeof (EFI_ACPI_6_3_GENERIC_INITIATOR_AFFINITY_STRUCTURE) *
592 GenInitiatorAffCount);
593 }
594
595 // Allocate the Buffer for SRAT table
596 *Table = (EFI_ACPI_DESCRIPTION_HEADER *)AllocateZeroPool (TableSize);
597 if (*Table == NULL) {
598 Status = EFI_OUT_OF_RESOURCES;
599 DEBUG ((
600 DEBUG_ERROR,
601 "ERROR: SRAT: Failed to allocate memory for SRAT Table, Size = %d," \
602 " Status = %r\n",
603 TableSize,
604 Status
605 ));
606 goto error_handler;
607 }
608
609 Srat = (EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER *)*Table;
610
611 DEBUG ((
612 DEBUG_INFO,
613 "SRAT: Srat = 0x%p TableSize = 0x%x\n",
614 Srat,
615 TableSize
616 ));
617
618 Status = AddAcpiHeader (
619 CfgMgrProtocol,
620 This,
621 &Srat->Header,
622 AcpiTableInfo,
623 TableSize
624 );
625 if (EFI_ERROR (Status)) {
626 DEBUG ((
627 DEBUG_ERROR,
628 "ERROR: SRAT: Failed to add ACPI header. Status = %r\n",
629 Status
630 ));
631 goto error_handler;
632 }
633
634 // Setup the Reserved fields
635 // Reserved1 must be set to 1 for backward compatibility
636 Srat->Reserved1 = 1;
637 Srat->Reserved2 = EFI_ACPI_RESERVED_QWORD;
638
639 Status = AddGICCAffinity (
640 CfgMgrProtocol,
641 Srat,
642 GicCAffOffset,
643 GicCInfo,
644 GicCCount
645 );
646 if (EFI_ERROR (Status)) {
647 DEBUG ((
648 DEBUG_ERROR,
649 "ERROR: SRAT: Failed to add GICC Affinity structures. Status = %r\n",
650 Status
651 ));
652 goto error_handler;
653 }
654
655 if (GicItsCount != 0) {
656 Status = AddGICItsAffinity (
657 CfgMgrProtocol,
658 Srat,
659 GicItsAffOffset,
660 GicItsInfo,
661 GicItsCount
662 );
663 if (EFI_ERROR (Status)) {
664 DEBUG ((
665 DEBUG_ERROR,
666 "ERROR: SRAT: Failed to add GIC ITS Affinity structures. Status = %r\n",
667 Status
668 ));
669 goto error_handler;
670 }
671 }
672
673 if (MemAffCount != 0) {
674 Status = AddMemoryAffinity (
675 CfgMgrProtocol,
676 Srat,
677 MemAffOffset,
678 MemAffInfo,
679 MemAffCount
680 );
681 if (EFI_ERROR (Status)) {
682 DEBUG ((
683 DEBUG_ERROR,
684 "ERROR: SRAT: Failed to add Memory Affinity structures. Status = %r\n",
685 Status
686 ));
687 goto error_handler;
688 }
689 }
690
691 if (GenInitiatorAffCount != 0) {
692 Status = AddGenericInitiatorAffinity (
693 CfgMgrProtocol,
694 Srat,
695 GenInitiatorAffOffset,
696 GenInitiatorAffInfo,
697 GenInitiatorAffCount
698 );
699 if (EFI_ERROR (Status)) {
700 DEBUG ((
701 DEBUG_ERROR,
702 "ERROR: SRAT: Failed to add Generic Initiator Affinity structures."
703 " Status = %r\n",
704 Status
705 ));
706 goto error_handler;
707 }
708 }
709
710 return Status;
711
712 error_handler:
713
714 if (*Table != NULL) {
715 FreePool (*Table);
716 *Table = NULL;
717 }
718
719 return Status;
720 }
721
722 /** Free any resources allocated for constructing the SRAT.
723
724 @param [in] This Pointer to the table generator.
725 @param [in] AcpiTableInfo Pointer to the ACPI Table Info.
726 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
727 Protocol Interface.
728 @param [in, out] Table Pointer to the ACPI Table.
729
730 @retval EFI_SUCCESS The resources were freed successfully.
731 @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
732 **/
733 STATIC
734 EFI_STATUS
735 FreeSratTableResources (
736 IN CONST ACPI_TABLE_GENERATOR *CONST This,
737 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,
738 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
739 IN OUT EFI_ACPI_DESCRIPTION_HEADER **CONST Table
740 )
741 {
742 ASSERT (
743 (This != NULL) &&
744 (AcpiTableInfo != NULL) &&
745 (CfgMgrProtocol != NULL) &&
746 (AcpiTableInfo->TableGeneratorId == This->GeneratorID) &&
747 (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature)
748 );
749
750 if ((Table == NULL) || (*Table == NULL)) {
751 DEBUG ((DEBUG_ERROR, "ERROR: SRAT: Invalid Table Pointer\n"));
752 ASSERT (0);
753 return EFI_INVALID_PARAMETER;
754 }
755
756 FreePool (*Table);
757 *Table = NULL;
758 return EFI_SUCCESS;
759 }
760
761 /** The SRAT Table Generator revision.
762 */
763 #define SRAT_GENERATOR_REVISION CREATE_REVISION (1, 0)
764
765 /** The interface for the SRAT Table Generator.
766 */
767 STATIC
768 CONST
769 ACPI_TABLE_GENERATOR SratGenerator = {
770 // Generator ID
771 CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSrat),
772 // Generator Description
773 L"ACPI.STD.SRAT.GENERATOR",
774 // ACPI Table Signature
775 EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_SIGNATURE,
776 // ACPI Table Revision supported by this Generator
777 EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_REVISION,
778 // Minimum supported ACPI Table Revision
779 EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_REVISION,
780 // Creator ID
781 TABLE_GENERATOR_CREATOR_ID_ARM,
782 // Creator Revision
783 SRAT_GENERATOR_REVISION,
784 // Build Table function
785 BuildSratTable,
786 // Free Resource function
787 FreeSratTableResources,
788 // Extended build function not needed
789 NULL,
790 // Extended build function not implemented by the generator.
791 // Hence extended free resource function is not required.
792 NULL
793 };
794
795 /** Register the Generator with the ACPI Table Factory.
796
797 @param [in] ImageHandle The handle to the image.
798 @param [in] SystemTable Pointer to the System Table.
799
800 @retval EFI_SUCCESS The Generator is registered.
801 @retval EFI_INVALID_PARAMETER A parameter is invalid.
802 @retval EFI_ALREADY_STARTED The Generator for the Table ID
803 is already registered.
804 **/
805 EFI_STATUS
806 EFIAPI
807 AcpiSratLibConstructor (
808 IN EFI_HANDLE ImageHandle,
809 IN EFI_SYSTEM_TABLE *SystemTable
810 )
811 {
812 EFI_STATUS Status;
813
814 Status = RegisterAcpiTableGenerator (&SratGenerator);
815 DEBUG ((DEBUG_INFO, "SRAT: Register Generator. Status = %r\n", Status));
816 ASSERT_EFI_ERROR (Status);
817 return Status;
818 }
819
820 /** Deregister the Generator from the ACPI Table Factory.
821
822 @param [in] ImageHandle The handle to the image.
823 @param [in] SystemTable Pointer to the System Table.
824
825 @retval EFI_SUCCESS The Generator is deregistered.
826 @retval EFI_INVALID_PARAMETER A parameter is invalid.
827 @retval EFI_NOT_FOUND The Generator is not registered.
828 **/
829 EFI_STATUS
830 EFIAPI
831 AcpiSratLibDestructor (
832 IN EFI_HANDLE ImageHandle,
833 IN EFI_SYSTEM_TABLE *SystemTable
834 )
835 {
836 EFI_STATUS Status;
837
838 Status = DeregisterAcpiTableGenerator (&SratGenerator);
839 DEBUG ((DEBUG_INFO, "SRAT: Deregister Generator. Status = %r\n", Status));
840 ASSERT_EFI_ERROR (Status);
841 return Status;
842 }