2 Dynamic Table Manager Dxe
4 Copyright (c) 2017 - 2019, ARM Limited. All rights reserved.
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include <Library/DebugLib.h>
11 #include <Library/PcdLib.h>
12 #include <Library/UefiBootServicesTableLib.h>
13 #include <Protocol/AcpiTable.h>
15 // Module specific include files.
16 #include <AcpiTableGenerator.h>
17 #include <ConfigurationManagerObject.h>
18 #include <ConfigurationManagerHelper.h>
19 #include <DeviceTreeTableGenerator.h>
20 #include <Library/TableHelperLib.h>
21 #include <Protocol/ConfigurationManagerProtocol.h>
22 #include <Protocol/DynamicTableFactoryProtocol.h>
23 #include <SmbiosTableGenerator.h>
25 /** This macro expands to a function that retrieves the ACPI Table
26 List from the Configuration Manager.
29 EObjNameSpaceStandard
,
31 CM_STD_OBJ_ACPI_TABLE_INFO
34 /** A helper function to build and install a single ACPI table.
36 This is a helper function that invokes the Table generator interface
37 for building an ACPI table. It uses the AcpiTableProtocol to install the
38 table, then frees the resources allocated for generating it.
40 @param [in] TableFactoryProtocol Pointer to the Table Factory Protocol
42 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
44 @param [in] Generator Pointer to the AcpiTable generator.
45 @param [in] AcpiTableProtocol Pointer to the AcpiTable protocol.
46 @param [in] AcpiTableInfo Pointer to the ACPI table Info.
48 @retval EFI_SUCCESS Success.
49 @retval EFI_INVALID_PARAMETER A parameter is invalid.
50 @retval EFI_NOT_FOUND Required object is not found.
51 @retval EFI_BAD_BUFFER_SIZE Size returned by the Configuration Manager
52 is less than the Object size for the
58 BuildAndInstallSingleAcpiTable (
59 IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL
* CONST TableFactoryProtocol
,
60 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL
* CONST CfgMgrProtocol
,
61 IN CONST ACPI_TABLE_GENERATOR
* CONST Generator
,
62 IN EFI_ACPI_TABLE_PROTOCOL
* AcpiTableProtocol
,
63 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO
* CONST AcpiTableInfo
68 EFI_ACPI_DESCRIPTION_HEADER
* AcpiTable
;
72 Status
= Generator
->BuildAcpiTable (
78 if (EFI_ERROR (Status
)) {
81 "ERROR: Failed to Build Table." \
82 " TableGeneratorId = 0x%x. Status = %r\n",
83 AcpiTableInfo
->TableGeneratorId
,
86 // Free any allocated resources.
90 if (AcpiTable
== NULL
) {
91 Status
= EFI_NOT_FOUND
;
95 // Dump ACPI Table Header
96 DUMP_ACPI_TABLE_HEADER (AcpiTable
);
99 Status
= AcpiTableProtocol
->InstallAcpiTable (
105 if (EFI_ERROR (Status
)) {
108 "ERROR: Failed to Install ACPI Table. Status = %r\n",
111 // Free any allocated resources.
117 "INFO: ACPI Table installed. Status = %r\n",
122 // Free any resources allocated for generating the tables.
123 if (Generator
->FreeTableResources
!= NULL
) {
124 Status1
= Generator
->FreeTableResources (
130 if (EFI_ERROR (Status1
)) {
133 "ERROR: Failed to Free Table Resources." \
134 "TableGeneratorId = 0x%x. Status = %r\n",
135 AcpiTableInfo
->TableGeneratorId
,
140 // Return the first error status in case of failure
141 if (!EFI_ERROR (Status
)) {
148 /** A helper function to build and install multiple ACPI tables.
150 This is a helper function that invokes the Table generator interface
151 for building an ACPI table. It uses the AcpiTableProtocol to install the
152 table, then frees the resources allocated for generating it.
154 @param [in] TableFactoryProtocol Pointer to the Table Factory Protocol
156 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
158 @param [in] Generator Pointer to the AcpiTable generator.
159 @param [in] AcpiTableProtocol Pointer to the AcpiTable protocol.
160 @param [in] AcpiTableInfo Pointer to the ACPI table Info.
162 @retval EFI_SUCCESS Success.
163 @retval EFI_INVALID_PARAMETER A parameter is invalid.
164 @retval EFI_NOT_FOUND Required object is not found.
165 @retval EFI_BAD_BUFFER_SIZE Size returned by the Configuration Manager
166 is less than the Object size for the
172 BuildAndInstallMultipleAcpiTable (
173 IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL
* CONST TableFactoryProtocol
,
174 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL
* CONST CfgMgrProtocol
,
175 IN CONST ACPI_TABLE_GENERATOR
* CONST Generator
,
176 IN EFI_ACPI_TABLE_PROTOCOL
* AcpiTableProtocol
,
177 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO
* CONST AcpiTableInfo
182 EFI_ACPI_DESCRIPTION_HEADER
** AcpiTable
;
189 Status
= Generator
->BuildAcpiTableEx (
196 if (EFI_ERROR (Status
)) {
199 "ERROR: Failed to Build Table." \
200 " TableGeneratorId = 0x%x. Status = %r\n",
201 AcpiTableInfo
->TableGeneratorId
,
204 // Free any allocated resources.
208 if ((AcpiTable
== NULL
) || (TableCount
== 0)) {
209 Status
= EFI_NOT_FOUND
;
213 for (Index
= 0; Index
< TableCount
; Index
++) {
214 // Dump ACPI Table Header
215 DUMP_ACPI_TABLE_HEADER (AcpiTable
[Index
]);
216 // Install ACPI table
217 Status
= AcpiTableProtocol
->InstallAcpiTable (
220 AcpiTable
[Index
]->Length
,
223 if (EFI_ERROR (Status
)) {
226 "ERROR: Failed to Install ACPI Table. Status = %r\n",
229 // Free any allocated resources.
235 "INFO: ACPI Table installed. Status = %r\n",
241 // Free any resources allocated for generating the tables.
242 if (Generator
->FreeTableResourcesEx
!= NULL
) {
243 Status1
= Generator
->FreeTableResourcesEx (
250 if (EFI_ERROR (Status1
)) {
253 "ERROR: Failed to Free Table Resources." \
254 "TableGeneratorId = 0x%x. Status = %r\n",
255 AcpiTableInfo
->TableGeneratorId
,
260 // Return the first error status in case of failure
261 if (!EFI_ERROR (Status
)) {
268 /** A helper function to invoke a Table generator
270 This is a helper function that invokes the Table generator interface
271 for building an ACPI table. It uses the AcpiTableProtocol to install the
272 table, then frees the resources allocated for generating it.
274 @param [in] TableFactoryProtocol Pointer to the Table Factory Protocol
276 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
278 @param [in] AcpiTableProtocol Pointer to the AcpiTable protocol.
279 @param [in] AcpiTableInfo Pointer to the ACPI table Info.
281 @retval EFI_SUCCESS Success.
282 @retval EFI_INVALID_PARAMETER A parameter is invalid.
283 @retval EFI_NOT_FOUND Required object is not found.
284 @retval EFI_BAD_BUFFER_SIZE Size returned by the Configuration Manager
285 is less than the Object size for the
291 BuildAndInstallAcpiTable (
292 IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL
* CONST TableFactoryProtocol
,
293 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL
* CONST CfgMgrProtocol
,
294 IN EFI_ACPI_TABLE_PROTOCOL
* AcpiTableProtocol
,
295 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO
* CONST AcpiTableInfo
299 CONST ACPI_TABLE_GENERATOR
* Generator
;
301 ASSERT (TableFactoryProtocol
!= NULL
);
302 ASSERT (CfgMgrProtocol
!= NULL
);
303 ASSERT (AcpiTableProtocol
!= NULL
);
304 ASSERT (AcpiTableInfo
!= NULL
);
308 "INFO: EStdObjAcpiTableList: Address = 0x%p," \
309 " TableGeneratorId = 0x%x\n",
311 AcpiTableInfo
->TableGeneratorId
315 Status
= TableFactoryProtocol
->GetAcpiTableGenerator (
316 TableFactoryProtocol
,
317 AcpiTableInfo
->TableGeneratorId
,
320 if (EFI_ERROR (Status
)) {
323 "ERROR: Table Generator not found." \
324 " TableGeneratorId = 0x%x. Status = %r\n",
325 AcpiTableInfo
->TableGeneratorId
,
331 if (Generator
== NULL
) {
332 return EFI_NOT_FOUND
;
337 "INFO: Generator found : %s\n",
338 Generator
->Description
341 if (Generator
->BuildAcpiTableEx
!= NULL
) {
342 Status
= BuildAndInstallMultipleAcpiTable (
343 TableFactoryProtocol
,
349 if (EFI_ERROR (Status
)) {
352 "ERROR: Failed to find build and install ACPI Table." \
357 } else if (Generator
->BuildAcpiTable
!= NULL
) {
358 Status
= BuildAndInstallSingleAcpiTable (
359 TableFactoryProtocol
,
365 if (EFI_ERROR (Status
)) {
368 "ERROR: Failed to find build and install ACPI Table." \
374 Status
= EFI_INVALID_PARAMETER
;
377 "ERROR: Table Generator does not implement the" \
378 " ACPI_TABLE_GENERATOR_BUILD_TABLE interface." \
379 " TableGeneratorId = 0x%x. Status = %r\n",
380 AcpiTableInfo
->TableGeneratorId
,
388 /** The function checks if the Configuration Manager has provided the
389 mandatory ACPI tables for installation.
391 @param [in] AcpiTableInfo Pointer to the ACPI Table Info list.
392 @param [in] AcpiTableCount Count of ACPI Table Info.
394 @retval EFI_SUCCESS Success.
395 @retval EFI_NOT_FOUND If mandatory table is not found.
400 VerifyMandatoryTablesArePresent (
401 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO
* CONST AcpiTableInfo
,
402 IN UINT32 AcpiTableCount
413 Status
= EFI_SUCCESS
;
420 ASSERT (AcpiTableInfo
!= NULL
);
422 while (AcpiTableCount
-- != 0) {
423 switch (AcpiTableInfo
[AcpiTableCount
].AcpiTableSignature
) {
424 case EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE
:
427 case EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE
:
430 case EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE
:
433 case EFI_ACPI_6_2_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
:
436 case EFI_ACPI_6_2_DEBUG_PORT_2_TABLE_SIGNATURE
:
439 case EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE
:
447 // We need at least the FADT, MADT, GTDT and the DSDT tables to boot
449 DEBUG ((DEBUG_ERROR
,"ERROR: FADT Table not found\n"));
450 Status
= EFI_NOT_FOUND
;
453 DEBUG ((DEBUG_ERROR
, "ERROR: MADT Table not found.\n"));
454 Status
= EFI_NOT_FOUND
;
457 DEBUG ((DEBUG_ERROR
, "ERROR: GTDT Table not found.\n"));
458 Status
= EFI_NOT_FOUND
;
461 DEBUG ((DEBUG_ERROR
, "ERROR: DSDT Table not found.\n"));
462 Status
= EFI_NOT_FOUND
;
465 DEBUG ((DEBUG_WARN
, "WARNING: DBG2 Table not found.\n"));
468 DEBUG ((DEBUG_WARN
, "WARNING: SPCR Table not found.\n"));
473 /** Generate and install ACPI tables.
475 The function gathers the information necessary for installing the
476 ACPI tables from the Configuration Manager, invokes the generators
477 and installs them (via BuildAndInstallAcpiTable).
479 @param [in] TableFactoryProtocol Pointer to the Table Factory Protocol
481 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
484 @retval EFI_SUCCESS Success.
485 @retval EFI_NOT_FOUND If a mandatory table or a generator is not found.
491 IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL
* CONST TableFactoryProtocol
,
492 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL
* CONST CfgMgrProtocol
496 EFI_ACPI_TABLE_PROTOCOL
* AcpiTableProtocol
;
497 CM_STD_OBJ_ACPI_TABLE_INFO
* AcpiTableInfo
;
498 UINT32 AcpiTableCount
;
501 ASSERT (TableFactoryProtocol
!= NULL
);
502 ASSERT (CfgMgrProtocol
!= NULL
);
504 // Find the AcpiTable protocol
505 Status
= gBS
->LocateProtocol (
506 &gEfiAcpiTableProtocolGuid
,
508 (VOID
**)&AcpiTableProtocol
510 if (EFI_ERROR (Status
)) {
513 "ERROR: Failed to find AcpiTable protocol. Status = %r\n",
519 Status
= GetEStdObjAcpiTableList (
525 if (EFI_ERROR (Status
)) {
528 "ERROR: Failed to get ACPI Table List. Status = %r\n",
534 if (0 == AcpiTableCount
) {
537 "ERROR: EStdObjAcpiTableList: AcpiTableCount = %d\n",
540 return EFI_NOT_FOUND
;
545 "INFO: EStdObjAcpiTableList: AcpiTableCount = %d\n",
549 // Check if mandatory ACPI tables are present.
550 Status
= VerifyMandatoryTablesArePresent (
554 if (EFI_ERROR (Status
)) {
557 "ERROR: Failed to find mandatory ACPI Table(s)."
564 // Add the FADT Table first.
565 for (Idx
= 0; Idx
< AcpiTableCount
; Idx
++) {
566 if (CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdFadt
) ==
567 AcpiTableInfo
[Idx
].TableGeneratorId
) {
568 Status
= BuildAndInstallAcpiTable (
569 TableFactoryProtocol
,
574 if (EFI_ERROR (Status
)) {
577 "ERROR: Failed to find build and install ACPI FADT Table." \
587 // Add remaining ACPI Tables
588 for (Idx
= 0; Idx
< AcpiTableCount
; Idx
++) {
591 "INFO: AcpiTableInfo[%d].TableGeneratorId = 0x%x\n",
593 AcpiTableInfo
[Idx
].TableGeneratorId
596 // Skip FADT Table since we have already added
597 if (CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdFadt
) ==
598 AcpiTableInfo
[Idx
].TableGeneratorId
) {
602 // Skip the Reserved table Generator ID for standard generators
603 if ((IS_GENERATOR_NAMESPACE_STD (AcpiTableInfo
[Idx
].TableGeneratorId
)) &&
604 ((CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdReserved
) >=
605 AcpiTableInfo
[Idx
].TableGeneratorId
) ||
606 (CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdMax
) <=
607 AcpiTableInfo
[Idx
].TableGeneratorId
))) {
610 "WARNING: Invalid ACPI Generator table ID = 0x%x, Skipping...\n",
611 AcpiTableInfo
[Idx
].TableGeneratorId
616 Status
= BuildAndInstallAcpiTable (
617 TableFactoryProtocol
,
622 if (EFI_ERROR (Status
)) {
625 "ERROR: Failed to find, build, and install ACPI Table." \
636 /** Entrypoint of Dynamic Table Manager Dxe.
638 The Dynamic Table Manager uses the Configuration Manager Protocol
639 to get the list of ACPI and SMBIOS tables to install. For each table
640 in the list it requests the corresponding ACPI/SMBIOS table factory for
641 a generator capable of building the ACPI/SMBIOS table.
642 If a suitable table generator is found, it invokes the generator interface
643 to build the table. The Dynamic Table Manager then installs the
644 table and invokes another generator interface to free any resources
645 allocated for building the table.
650 @retval EFI_SUCCESS Success.
651 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
652 @retval EFI_NOT_FOUND Required interface/object was not found.
653 @retval EFI_INVALID_PARAMETER Some parameter is incorrect/invalid.
657 DynamicTableManagerDxeInitialize (
658 IN CONST EFI_HANDLE ImageHandle
,
659 IN EFI_SYSTEM_TABLE
* CONST SystemTable
663 EDKII_CONFIGURATION_MANAGER_PROTOCOL
* CfgMgrProtocol
;
664 CM_STD_OBJ_CONFIGURATION_MANAGER_INFO
* CfgMfrInfo
;
665 EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL
* TableFactoryProtocol
;
667 // Locate the Dynamic Table Factory
668 Status
= gBS
->LocateProtocol (
669 &gEdkiiDynamicTableFactoryProtocolGuid
,
671 (VOID
**)&TableFactoryProtocol
673 if (EFI_ERROR (Status
)) {
676 "ERROR: Failed to find Dynamic Table Factory protocol." \
683 // Locate the Configuration Manager for the Platform
684 Status
= gBS
->LocateProtocol (
685 &gEdkiiConfigurationManagerProtocolGuid
,
687 (VOID
**)&CfgMgrProtocol
689 if (EFI_ERROR (Status
)) {
692 "ERROR: Failed to find Configuration Manager protocol. Status = %r\n",
698 Status
= GetCgfMgrInfo (CfgMgrProtocol
, &CfgMfrInfo
);
699 if (EFI_ERROR (Status
)) {
702 "ERROR: Failed to get Configuration Manager info. Status = %r\n",
710 "INFO: Configuration Manager Version = 0x%x, OemID = %c%c%c%c%c%c\n",
711 CfgMfrInfo
->Revision
,
712 CfgMfrInfo
->OemId
[0],
713 CfgMfrInfo
->OemId
[1],
714 CfgMfrInfo
->OemId
[2],
715 CfgMfrInfo
->OemId
[3],
716 CfgMfrInfo
->OemId
[4],
720 Status
= ProcessAcpiTables (TableFactoryProtocol
, CfgMgrProtocol
);
721 if (EFI_ERROR (Status
)) {
724 "ERROR: ACPI Table processing failure. Status = %r\n",