]> git.proxmox.com Git - mirror_edk2.git/blame - DynamicTablesPkg/Library/Acpi/Arm/AcpiMcfgLibArm/McfgGenerator.c
DynamicTablesPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / DynamicTablesPkg / Library / Acpi / Arm / AcpiMcfgLibArm / McfgGenerator.c
CommitLineData
7e79e051
SM
1/** @file\r
2 MCFG Table Generator\r
3\r
4 Copyright (c) 2017 - 2019, ARM Limited. All rights reserved.\r
9cd9bdc6 5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
7e79e051
SM
6\r
7 @par Reference(s):\r
8 - PCI Firmware Specification - Revision 3.2, January 26, 2015.\r
9\r
10**/\r
11\r
12#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>\r
13#include <Library/AcpiLib.h>\r
14#include <Library/DebugLib.h>\r
15#include <Library/MemoryAllocationLib.h>\r
16#include <Protocol/AcpiTable.h>\r
17\r
18// Module specific include files.\r
19#include <AcpiTableGenerator.h>\r
20#include <ConfigurationManagerObject.h>\r
21#include <ConfigurationManagerHelper.h>\r
22#include <Library/TableHelperLib.h>\r
23#include <Protocol/ConfigurationManagerProtocol.h>\r
24\r
25/** ARM standard MCFG Generator\r
26\r
27Requirements:\r
28 The following Configuration Manager Object(s) are required by\r
29 this Generator:\r
30 - EArmObjPciConfigSpaceInfo\r
31*/\r
32\r
33#pragma pack(1)\r
34\r
35/** This typedef is used to shorten the name of the MCFG Table\r
36 header structure.\r
37*/\r
38typedef\r
39 EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER\r
40 MCFG_TABLE;\r
41\r
42/** This typedef is used to shorten the name of the Enhanced\r
43 Configuration Space address structure.\r
44*/\r
45typedef\r
46 EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE\r
47 MCFG_CFG_SPACE_ADDR;\r
48\r
49#pragma pack()\r
50\r
51/** Retrieve the PCI Configuration Space Information.\r
52*/\r
53GET_OBJECT_LIST (\r
54 EObjNameSpaceArm,\r
55 EArmObjPciConfigSpaceInfo,\r
56 CM_ARM_PCI_CONFIG_SPACE_INFO\r
57 );\r
58\r
59/** Add the PCI Enhanced Configuration Space Information to the MCFG Table.\r
60\r
61 @param [in] Mcfg Pointer to MCFG Table.\r
62 @param [in] PciCfgSpaceOffset Offset for the PCI Configuration Space\r
63 Info structure in the MCFG Table.\r
64 @param [in] PciCfgSpaceInfoList Pointer to the PCI Configuration Space\r
65 Info List.\r
66 @param [in] PciCfgSpaceCount Count of PCI Configuration Space Info.\r
67**/\r
68STATIC\r
69VOID\r
70AddPciConfigurationSpaceList (\r
71 IN MCFG_TABLE * CONST Mcfg,\r
72 IN CONST UINT32 PciCfgSpaceOffset,\r
73 IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO * PciCfgSpaceInfoList,\r
74 IN UINT32 PciCfgSpaceCount\r
75)\r
76{\r
77 MCFG_CFG_SPACE_ADDR * PciCfgSpace;\r
78\r
79 ASSERT (Mcfg != NULL);\r
80 ASSERT (PciCfgSpaceInfoList != NULL);\r
81\r
82 PciCfgSpace = (MCFG_CFG_SPACE_ADDR *)((UINT8*)Mcfg + PciCfgSpaceOffset);\r
83\r
84 while (PciCfgSpaceCount-- != 0) {\r
85 // Add PCI Configuration Space entry\r
86 PciCfgSpace->BaseAddress = PciCfgSpaceInfoList->BaseAddress;\r
87 PciCfgSpace->PciSegmentGroupNumber =\r
88 PciCfgSpaceInfoList->PciSegmentGroupNumber;\r
89 PciCfgSpace->StartBusNumber = PciCfgSpaceInfoList->StartBusNumber;\r
90 PciCfgSpace->EndBusNumber = PciCfgSpaceInfoList->EndBusNumber;\r
91 PciCfgSpace->Reserved = EFI_ACPI_RESERVED_DWORD;\r
92 PciCfgSpace++;\r
93 PciCfgSpaceInfoList++;\r
94 }\r
95}\r
96\r
97/** Construct the MCFG ACPI table.\r
98\r
99 This function invokes the Configuration Manager protocol interface\r
100 to get the required hardware information for generating the ACPI\r
101 table.\r
102\r
103 If this function allocates any resources then they must be freed\r
104 in the FreeXXXXTableResources function.\r
105\r
106 @param [in] This Pointer to the table generator.\r
107 @param [in] AcpiTableInfo Pointer to the ACPI Table Info.\r
108 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
109 Protocol Interface.\r
110 @param [out] Table Pointer to the constructed ACPI Table.\r
111\r
112 @retval EFI_SUCCESS Table generated successfully.\r
113 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
114 @retval EFI_NOT_FOUND The required object was not found.\r
115 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration\r
116 Manager is less than the Object size for the\r
117 requested object.\r
118**/\r
119STATIC\r
120EFI_STATUS\r
121EFIAPI\r
122BuildMcfgTable (\r
123 IN CONST ACPI_TABLE_GENERATOR * CONST This,\r
124 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo,\r
125 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,\r
126 OUT EFI_ACPI_DESCRIPTION_HEADER ** CONST Table\r
127 )\r
128{\r
129 EFI_STATUS Status;\r
130 UINT32 TableSize;\r
131 UINT32 ConfigurationSpaceCount;\r
132 CM_ARM_PCI_CONFIG_SPACE_INFO * PciConfigSpaceInfoList;\r
133 MCFG_TABLE * Mcfg;\r
134\r
135 ASSERT (This != NULL);\r
136 ASSERT (AcpiTableInfo != NULL);\r
137 ASSERT (CfgMgrProtocol != NULL);\r
138 ASSERT (Table != NULL);\r
139 ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);\r
140 ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);\r
141\r
142 if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) ||\r
143 (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision)) {\r
144 DEBUG ((\r
145 DEBUG_ERROR,\r
146 "ERROR: MCFG: Requested table revision = %d, is not supported."\r
147 "Supported table revision: Minimum = %d, Maximum = %d\n",\r
148 AcpiTableInfo->AcpiTableRevision,\r
149 This->MinAcpiTableRevision,\r
150 This->AcpiTableRevision\r
151 ));\r
152 return EFI_INVALID_PARAMETER;\r
153 }\r
154\r
155 *Table = NULL;\r
156 Status = GetEArmObjPciConfigSpaceInfo (\r
157 CfgMgrProtocol,\r
158 CM_NULL_TOKEN,\r
159 &PciConfigSpaceInfoList,\r
160 &ConfigurationSpaceCount\r
161 );\r
162 if (EFI_ERROR (Status)) {\r
163 DEBUG ((DEBUG_ERROR,\r
164 "ERROR: MCFG: Failed to get PCI Configuration Space Information." \\r
165 " Status = %r\n",\r
166 Status\r
167 ));\r
168 goto error_handler;\r
169 }\r
170\r
171 if (ConfigurationSpaceCount == 0) {\r
172 DEBUG ((\r
173 DEBUG_ERROR,\r
174 "ERROR: MCFG: Configuration Space Count = %d\n",\r
175 ConfigurationSpaceCount\r
176 ));\r
177 Status = EFI_INVALID_PARAMETER;\r
178 ASSERT (ConfigurationSpaceCount != 0);\r
179 goto error_handler;\r
180 }\r
181\r
182 DEBUG ((\r
183 DEBUG_INFO,\r
184 "MCFG: Configuration Space Count = %d\n",\r
185 ConfigurationSpaceCount\r
186 ));\r
187\r
188 // Calculate the MCFG Table Size\r
189 TableSize = sizeof (MCFG_TABLE) +\r
190 ((sizeof (MCFG_CFG_SPACE_ADDR) * ConfigurationSpaceCount));\r
191\r
192 *Table = (EFI_ACPI_DESCRIPTION_HEADER*)AllocateZeroPool (TableSize);\r
193 if (*Table == NULL) {\r
194 Status = EFI_OUT_OF_RESOURCES;\r
195 DEBUG ((\r
196 DEBUG_ERROR,\r
197 "ERROR: MCFG: Failed to allocate memory for MCFG Table, Size = %d," \\r
198 " Status = %r\n",\r
199 TableSize,\r
200 Status\r
201 ));\r
202 goto error_handler;\r
203 }\r
204\r
205 Mcfg = (MCFG_TABLE*)*Table;\r
206 DEBUG ((\r
207 DEBUG_INFO,\r
208 "MCFG: Mcfg = 0x%p TableSize = 0x%x\n",\r
209 Mcfg,\r
210 TableSize\r
211 ));\r
212\r
213 Status = AddAcpiHeader (\r
214 CfgMgrProtocol,\r
215 This,\r
216 &Mcfg->Header,\r
e12bdeb1 217 AcpiTableInfo,\r
7e79e051
SM
218 TableSize\r
219 );\r
220 if (EFI_ERROR (Status)) {\r
221 DEBUG ((\r
222 DEBUG_ERROR,\r
223 "ERROR: MCFG: Failed to add ACPI header. Status = %r\n",\r
224 Status\r
225 ));\r
226 goto error_handler;\r
227 }\r
228\r
229 Mcfg->Reserved = EFI_ACPI_RESERVED_QWORD;\r
230\r
231 AddPciConfigurationSpaceList (\r
232 Mcfg,\r
233 sizeof (MCFG_TABLE),\r
234 PciConfigSpaceInfoList,\r
235 ConfigurationSpaceCount\r
236 );\r
237\r
238 return EFI_SUCCESS;\r
239\r
240error_handler:\r
241 if (*Table != NULL) {\r
242 FreePool (*Table);\r
243 *Table = NULL;\r
244 }\r
245 return Status;\r
246}\r
247\r
248/** Free any resources allocated for constructing the MCFG\r
249\r
250 @param [in] This Pointer to the table generator.\r
251 @param [in] AcpiTableInfo Pointer to the ACPI Table Info.\r
252 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
253 Protocol Interface.\r
254 @param [in, out] Table Pointer to the ACPI Table.\r
255\r
256 @retval EFI_SUCCESS The resources were freed successfully.\r
257 @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.\r
258**/\r
259STATIC\r
260EFI_STATUS\r
261FreeMcfgTableResources (\r
262 IN CONST ACPI_TABLE_GENERATOR * CONST This,\r
263 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo,\r
264 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,\r
265 IN OUT EFI_ACPI_DESCRIPTION_HEADER ** CONST Table\r
266 )\r
267{\r
268 ASSERT (This != NULL);\r
269 ASSERT (AcpiTableInfo != NULL);\r
270 ASSERT (CfgMgrProtocol != NULL);\r
271 ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);\r
272 ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);\r
273\r
274 if ((Table == NULL) || (*Table == NULL)) {\r
275 DEBUG ((DEBUG_ERROR, "ERROR: MCFG: Invalid Table Pointer\n"));\r
276 ASSERT ((Table != NULL) && (*Table != NULL));\r
277 return EFI_INVALID_PARAMETER;\r
278 }\r
279\r
280 FreePool (*Table);\r
281 *Table = NULL;\r
282 return EFI_SUCCESS;\r
283}\r
284\r
285/** This macro defines the MCFG Table Generator revision.\r
286*/\r
287#define MCFG_GENERATOR_REVISION CREATE_REVISION (1, 0)\r
288\r
289/** The interface for the MCFG Table Generator.\r
290*/\r
291STATIC\r
292CONST\r
293ACPI_TABLE_GENERATOR McfgGenerator = {\r
294 // Generator ID\r
295 CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdMcfg),\r
296 // Generator Description\r
297 L"ACPI.STD.MCFG.GENERATOR",\r
298 // ACPI Table Signature\r
299 EFI_ACPI_6_2_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE,\r
300 // ACPI Table Revision supported by this Generator\r
301 EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION,\r
302 // Minimum supported ACPI Table Revision\r
303 EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION,\r
304 // Creator ID\r
305 TABLE_GENERATOR_CREATOR_ID_ARM,\r
306 // Creator Revision\r
307 MCFG_GENERATOR_REVISION,\r
308 // Build Table function\r
309 BuildMcfgTable,\r
310 // Free Resource function\r
311 FreeMcfgTableResources,\r
312 // Extended build function not needed\r
313 NULL,\r
314 // Extended build function not implemented by the generator.\r
315 // Hence extended free resource function is not required.\r
316 NULL\r
317};\r
318\r
319/** Register the Generator with the ACPI Table Factory.\r
320\r
321 @param [in] ImageHandle The handle to the image.\r
322 @param [in] SystemTable Pointer to the System Table.\r
323\r
324 @retval EFI_SUCCESS The Generator is registered.\r
325 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
326 @retval EFI_ALREADY_STARTED The Generator for the Table ID\r
327 is already registered.\r
328**/\r
329EFI_STATUS\r
330EFIAPI\r
331AcpiMcfgLibConstructor (\r
332 IN CONST EFI_HANDLE ImageHandle,\r
333 IN EFI_SYSTEM_TABLE * CONST SystemTable\r
334 )\r
335{\r
336 EFI_STATUS Status;\r
337 Status = RegisterAcpiTableGenerator (&McfgGenerator);\r
338 DEBUG ((DEBUG_INFO, "MCFG: Register Generator. Status = %r\n", Status));\r
339 ASSERT_EFI_ERROR (Status);\r
340 return Status;\r
341}\r
342\r
343/** Deregister the Generator from the ACPI Table Factory.\r
344\r
345 @param [in] ImageHandle The handle to the image.\r
346 @param [in] SystemTable Pointer to the System Table.\r
347\r
348 @retval EFI_SUCCESS The Generator is deregistered.\r
349 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
350 @retval EFI_NOT_FOUND The Generator is not registered.\r
351**/\r
352EFI_STATUS\r
353EFIAPI\r
354AcpiMcfgLibDestructor (\r
355 IN CONST EFI_HANDLE ImageHandle,\r
356 IN EFI_SYSTEM_TABLE * CONST SystemTable\r
357 )\r
358{\r
359 EFI_STATUS Status;\r
360 Status = DeregisterAcpiTableGenerator (&McfgGenerator);\r
361 DEBUG ((DEBUG_INFO, "MCFG: Deregister Generator. Status = %r\n", Status));\r
362 ASSERT_EFI_ERROR (Status);\r
363 return Status;\r
364}\r