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