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