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