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
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.
14 - PCI Firmware Specification - Revision 3.2, January 26, 2015.
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>
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>
31 /** ARM standard MCFG Generator
34 The following Configuration Manager Object(s) are required by
36 - EArmObjPciConfigSpaceInfo
41 /** This typedef is used to shorten the name of the MCFG Table
45 EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER
48 /** This typedef is used to shorten the name of the Enhanced
49 Configuration Space address structure.
52 EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE
57 /** Retrieve the PCI Configuration Space Information.
61 EArmObjPciConfigSpaceInfo
,
62 CM_ARM_PCI_CONFIG_SPACE_INFO
65 /** Add the PCI Enhanced Configuration Space Information to the MCFG Table.
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
72 @param [in] PciCfgSpaceCount Count of PCI Configuration Space Info.
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
83 MCFG_CFG_SPACE_ADDR
* PciCfgSpace
;
85 ASSERT (Mcfg
!= NULL
);
86 ASSERT (PciCfgSpaceInfoList
!= NULL
);
88 PciCfgSpace
= (MCFG_CFG_SPACE_ADDR
*)((UINT8
*)Mcfg
+ PciCfgSpaceOffset
);
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
;
99 PciCfgSpaceInfoList
++;
103 /** Construct the MCFG ACPI table.
105 This function invokes the Configuration Manager protocol interface
106 to get the required hardware information for generating the ACPI
109 If this function allocates any resources then they must be freed
110 in the FreeXXXXTableResources function.
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
116 @param [out] Table Pointer to the constructed ACPI Table.
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
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
137 UINT32 ConfigurationSpaceCount
;
138 CM_ARM_PCI_CONFIG_SPACE_INFO
* PciConfigSpaceInfoList
;
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
);
148 if ((AcpiTableInfo
->AcpiTableRevision
< This
->MinAcpiTableRevision
) ||
149 (AcpiTableInfo
->AcpiTableRevision
> This
->AcpiTableRevision
)) {
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
158 return EFI_INVALID_PARAMETER
;
162 Status
= GetEArmObjPciConfigSpaceInfo (
165 &PciConfigSpaceInfoList
,
166 &ConfigurationSpaceCount
168 if (EFI_ERROR (Status
)) {
170 "ERROR: MCFG: Failed to get PCI Configuration Space Information." \
177 if (ConfigurationSpaceCount
== 0) {
180 "ERROR: MCFG: Configuration Space Count = %d\n",
181 ConfigurationSpaceCount
183 Status
= EFI_INVALID_PARAMETER
;
184 ASSERT (ConfigurationSpaceCount
!= 0);
190 "MCFG: Configuration Space Count = %d\n",
191 ConfigurationSpaceCount
194 // Calculate the MCFG Table Size
195 TableSize
= sizeof (MCFG_TABLE
) +
196 ((sizeof (MCFG_CFG_SPACE_ADDR
) * ConfigurationSpaceCount
));
198 *Table
= (EFI_ACPI_DESCRIPTION_HEADER
*)AllocateZeroPool (TableSize
);
199 if (*Table
== NULL
) {
200 Status
= EFI_OUT_OF_RESOURCES
;
203 "ERROR: MCFG: Failed to allocate memory for MCFG Table, Size = %d," \
211 Mcfg
= (MCFG_TABLE
*)*Table
;
214 "MCFG: Mcfg = 0x%p TableSize = 0x%x\n",
219 Status
= AddAcpiHeader (
226 if (EFI_ERROR (Status
)) {
229 "ERROR: MCFG: Failed to add ACPI header. Status = %r\n",
235 Mcfg
->Reserved
= EFI_ACPI_RESERVED_QWORD
;
237 AddPciConfigurationSpaceList (
240 PciConfigSpaceInfoList
,
241 ConfigurationSpaceCount
247 if (*Table
!= NULL
) {
254 /** Free any resources allocated for constructing the MCFG
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
260 @param [in, out] Table Pointer to the ACPI Table.
262 @retval EFI_SUCCESS The resources were freed successfully.
263 @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
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
274 ASSERT (This
!= NULL
);
275 ASSERT (AcpiTableInfo
!= NULL
);
276 ASSERT (CfgMgrProtocol
!= NULL
);
277 ASSERT (AcpiTableInfo
->TableGeneratorId
== This
->GeneratorID
);
278 ASSERT (AcpiTableInfo
->AcpiTableSignature
== This
->AcpiTableSignature
);
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
;
291 /** This macro defines the MCFG Table Generator revision.
293 #define MCFG_GENERATOR_REVISION CREATE_REVISION (1, 0)
295 /** The interface for the MCFG Table Generator.
299 ACPI_TABLE_GENERATOR McfgGenerator
= {
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
,
311 TABLE_GENERATOR_CREATOR_ID_ARM
,
313 MCFG_GENERATOR_REVISION
,
314 // Build Table function
316 // Free Resource function
317 FreeMcfgTableResources
,
318 // Extended build function not needed
320 // Extended build function not implemented by the generator.
321 // Hence extended free resource function is not required.
325 /** Register the Generator with the ACPI Table Factory.
327 @param [in] ImageHandle The handle to the image.
328 @param [in] SystemTable Pointer to the System Table.
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.
337 AcpiMcfgLibConstructor (
338 IN CONST EFI_HANDLE ImageHandle
,
339 IN EFI_SYSTEM_TABLE
* CONST SystemTable
343 Status
= RegisterAcpiTableGenerator (&McfgGenerator
);
344 DEBUG ((DEBUG_INFO
, "MCFG: Register Generator. Status = %r\n", Status
));
345 ASSERT_EFI_ERROR (Status
);
349 /** Deregister the Generator from the ACPI Table Factory.
351 @param [in] ImageHandle The handle to the image.
352 @param [in] SystemTable Pointer to the System Table.
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.
360 AcpiMcfgLibDestructor (
361 IN CONST EFI_HANDLE ImageHandle
,
362 IN EFI_SYSTEM_TABLE
* CONST SystemTable
366 Status
= DeregisterAcpiTableGenerator (&McfgGenerator
);
367 DEBUG ((DEBUG_INFO
, "MCFG: Deregister Generator. Status = %r\n", Status
));
368 ASSERT_EFI_ERROR (Status
);