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