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