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
)) {
149 /** A helper function to build and install multiple ACPI tables.
151 This is a helper function that invokes the Table generator interface
152 for building an ACPI table. It uses the AcpiTableProtocol to install the
153 table, then frees the resources allocated for generating it.
155 @param [in] TableFactoryProtocol Pointer to the Table Factory Protocol
157 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
159 @param [in] Generator Pointer to the AcpiTable generator.
160 @param [in] AcpiTableProtocol Pointer to the AcpiTable protocol.
161 @param [in] AcpiTableInfo Pointer to the ACPI table Info.
163 @retval EFI_SUCCESS Success.
164 @retval EFI_INVALID_PARAMETER A parameter is invalid.
165 @retval EFI_NOT_FOUND Required object is not found.
166 @retval EFI_BAD_BUFFER_SIZE Size returned by the Configuration Manager
167 is less than the Object size for the
173 BuildAndInstallMultipleAcpiTable (
174 IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL
*CONST TableFactoryProtocol
,
175 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL
*CONST CfgMgrProtocol
,
176 IN CONST ACPI_TABLE_GENERATOR
*CONST Generator
,
177 IN EFI_ACPI_TABLE_PROTOCOL
*AcpiTableProtocol
,
178 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO
*CONST AcpiTableInfo
183 EFI_ACPI_DESCRIPTION_HEADER
**AcpiTable
;
190 Status
= Generator
->BuildAcpiTableEx (
197 if (EFI_ERROR (Status
)) {
200 "ERROR: Failed to Build Table." \
201 " TableGeneratorId = 0x%x. Status = %r\n",
202 AcpiTableInfo
->TableGeneratorId
,
205 // Free any allocated resources.
209 if ((AcpiTable
== NULL
) || (TableCount
== 0)) {
210 Status
= EFI_NOT_FOUND
;
214 for (Index
= 0; Index
< TableCount
; Index
++) {
215 // Dump ACPI Table Header
216 DUMP_ACPI_TABLE_HEADER (AcpiTable
[Index
]);
217 // Install ACPI table
218 Status
= AcpiTableProtocol
->InstallAcpiTable (
221 AcpiTable
[Index
]->Length
,
224 if (EFI_ERROR (Status
)) {
227 "ERROR: Failed to Install ACPI Table. Status = %r\n",
230 // Free any allocated resources.
236 "INFO: ACPI Table installed. Status = %r\n",
242 // Free any resources allocated for generating the tables.
243 if (Generator
->FreeTableResourcesEx
!= NULL
) {
244 Status1
= Generator
->FreeTableResourcesEx (
251 if (EFI_ERROR (Status1
)) {
254 "ERROR: Failed to Free Table Resources." \
255 "TableGeneratorId = 0x%x. Status = %r\n",
256 AcpiTableInfo
->TableGeneratorId
,
261 // Return the first error status in case of failure
262 if (!EFI_ERROR (Status
)) {
270 /** A helper function to invoke a Table generator
272 This is a helper function that invokes the Table generator interface
273 for building an ACPI table. It uses the AcpiTableProtocol to install the
274 table, then frees the resources allocated for generating it.
276 @param [in] TableFactoryProtocol Pointer to the Table Factory Protocol
278 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
280 @param [in] AcpiTableProtocol Pointer to the AcpiTable protocol.
281 @param [in] AcpiTableInfo Pointer to the ACPI table Info.
283 @retval EFI_SUCCESS Success.
284 @retval EFI_INVALID_PARAMETER A parameter is invalid.
285 @retval EFI_NOT_FOUND Required object is not found.
286 @retval EFI_BAD_BUFFER_SIZE Size returned by the Configuration Manager
287 is less than the Object size for the
293 BuildAndInstallAcpiTable (
294 IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL
*CONST TableFactoryProtocol
,
295 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL
*CONST CfgMgrProtocol
,
296 IN EFI_ACPI_TABLE_PROTOCOL
*AcpiTableProtocol
,
297 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO
*CONST AcpiTableInfo
301 CONST ACPI_TABLE_GENERATOR
*Generator
;
303 ASSERT (TableFactoryProtocol
!= NULL
);
304 ASSERT (CfgMgrProtocol
!= NULL
);
305 ASSERT (AcpiTableProtocol
!= NULL
);
306 ASSERT (AcpiTableInfo
!= NULL
);
310 "INFO: EStdObjAcpiTableList: Address = 0x%p," \
311 " TableGeneratorId = 0x%x\n",
313 AcpiTableInfo
->TableGeneratorId
317 Status
= TableFactoryProtocol
->GetAcpiTableGenerator (
318 TableFactoryProtocol
,
319 AcpiTableInfo
->TableGeneratorId
,
322 if (EFI_ERROR (Status
)) {
325 "ERROR: Table Generator not found." \
326 " TableGeneratorId = 0x%x. Status = %r\n",
327 AcpiTableInfo
->TableGeneratorId
,
333 if (Generator
== NULL
) {
334 return EFI_NOT_FOUND
;
339 "INFO: Generator found : %s\n",
340 Generator
->Description
343 if (Generator
->BuildAcpiTableEx
!= NULL
) {
344 Status
= BuildAndInstallMultipleAcpiTable (
345 TableFactoryProtocol
,
351 if (EFI_ERROR (Status
)) {
354 "ERROR: Failed to find build and install ACPI Table." \
359 } else if (Generator
->BuildAcpiTable
!= NULL
) {
360 Status
= BuildAndInstallSingleAcpiTable (
361 TableFactoryProtocol
,
367 if (EFI_ERROR (Status
)) {
370 "ERROR: Failed to find build and install ACPI Table." \
376 Status
= EFI_INVALID_PARAMETER
;
379 "ERROR: Table Generator does not implement the" \
380 " ACPI_TABLE_GENERATOR_BUILD_TABLE interface." \
381 " TableGeneratorId = 0x%x. Status = %r\n",
382 AcpiTableInfo
->TableGeneratorId
,
390 /** The function checks if the Configuration Manager has provided the
391 mandatory ACPI tables for installation.
393 @param [in] AcpiTableInfo Pointer to the ACPI Table Info list.
394 @param [in] AcpiTableCount Count of ACPI Table Info.
396 @retval EFI_SUCCESS Success.
397 @retval EFI_NOT_FOUND If mandatory table is not found.
402 VerifyMandatoryTablesArePresent (
403 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO
*CONST AcpiTableInfo
,
404 IN UINT32 AcpiTableCount
415 Status
= EFI_SUCCESS
;
422 ASSERT (AcpiTableInfo
!= NULL
);
424 while (AcpiTableCount
-- != 0) {
425 switch (AcpiTableInfo
[AcpiTableCount
].AcpiTableSignature
) {
426 case EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE
:
429 case EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE
:
432 case EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE
:
435 case EFI_ACPI_6_2_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
:
438 case EFI_ACPI_6_2_DEBUG_PORT_2_TABLE_SIGNATURE
:
441 case EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE
:
449 // We need at least the FADT, MADT, GTDT and the DSDT tables to boot
451 DEBUG ((DEBUG_ERROR
, "ERROR: FADT Table not found\n"));
452 Status
= EFI_NOT_FOUND
;
456 DEBUG ((DEBUG_ERROR
, "ERROR: MADT Table not found.\n"));
457 Status
= EFI_NOT_FOUND
;
461 DEBUG ((DEBUG_ERROR
, "ERROR: GTDT Table not found.\n"));
462 Status
= EFI_NOT_FOUND
;
466 DEBUG ((DEBUG_ERROR
, "ERROR: DSDT Table not found.\n"));
467 Status
= EFI_NOT_FOUND
;
471 DEBUG ((DEBUG_WARN
, "WARNING: DBG2 Table not found.\n"));
475 DEBUG ((DEBUG_WARN
, "WARNING: SPCR Table not found.\n"));
481 /** Generate and install ACPI tables.
483 The function gathers the information necessary for installing the
484 ACPI tables from the Configuration Manager, invokes the generators
485 and installs them (via BuildAndInstallAcpiTable).
487 @param [in] TableFactoryProtocol Pointer to the Table Factory Protocol
489 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
492 @retval EFI_SUCCESS Success.
493 @retval EFI_NOT_FOUND If a mandatory table or a generator is not found.
499 IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL
*CONST TableFactoryProtocol
,
500 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL
*CONST CfgMgrProtocol
504 EFI_ACPI_TABLE_PROTOCOL
*AcpiTableProtocol
;
505 CM_STD_OBJ_ACPI_TABLE_INFO
*AcpiTableInfo
;
506 UINT32 AcpiTableCount
;
509 ASSERT (TableFactoryProtocol
!= NULL
);
510 ASSERT (CfgMgrProtocol
!= NULL
);
512 // Find the AcpiTable protocol
513 Status
= gBS
->LocateProtocol (
514 &gEfiAcpiTableProtocolGuid
,
516 (VOID
**)&AcpiTableProtocol
518 if (EFI_ERROR (Status
)) {
521 "ERROR: Failed to find AcpiTable protocol. Status = %r\n",
527 Status
= GetEStdObjAcpiTableList (
533 if (EFI_ERROR (Status
)) {
536 "ERROR: Failed to get ACPI Table List. Status = %r\n",
542 if (0 == AcpiTableCount
) {
545 "ERROR: EStdObjAcpiTableList: AcpiTableCount = %d\n",
548 return EFI_NOT_FOUND
;
553 "INFO: EStdObjAcpiTableList: AcpiTableCount = %d\n",
557 // Check if mandatory ACPI tables are present.
558 Status
= VerifyMandatoryTablesArePresent (
562 if (EFI_ERROR (Status
)) {
565 "ERROR: Failed to find mandatory ACPI Table(s)."
572 // Add the FADT Table first.
573 for (Idx
= 0; Idx
< AcpiTableCount
; Idx
++) {
574 if (CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdFadt
) ==
575 AcpiTableInfo
[Idx
].TableGeneratorId
)
577 Status
= BuildAndInstallAcpiTable (
578 TableFactoryProtocol
,
583 if (EFI_ERROR (Status
)) {
586 "ERROR: Failed to find build and install ACPI FADT Table." \
597 // Add remaining ACPI Tables
598 for (Idx
= 0; Idx
< AcpiTableCount
; Idx
++) {
601 "INFO: AcpiTableInfo[%d].TableGeneratorId = 0x%x\n",
603 AcpiTableInfo
[Idx
].TableGeneratorId
606 // Skip FADT Table since we have already added
607 if (CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdFadt
) ==
608 AcpiTableInfo
[Idx
].TableGeneratorId
)
613 // Skip the Reserved table Generator ID for standard generators
614 if ((IS_GENERATOR_NAMESPACE_STD (AcpiTableInfo
[Idx
].TableGeneratorId
)) &&
615 ((CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdReserved
) >=
616 AcpiTableInfo
[Idx
].TableGeneratorId
) ||
617 (CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdMax
) <=
618 AcpiTableInfo
[Idx
].TableGeneratorId
)))
622 "WARNING: Invalid ACPI Generator table ID = 0x%x, Skipping...\n",
623 AcpiTableInfo
[Idx
].TableGeneratorId
628 Status
= BuildAndInstallAcpiTable (
629 TableFactoryProtocol
,
634 if (EFI_ERROR (Status
)) {
637 "ERROR: Failed to find, build, and install ACPI Table." \
648 /** Entrypoint of Dynamic Table Manager Dxe.
650 The Dynamic Table Manager uses the Configuration Manager Protocol
651 to get the list of ACPI and SMBIOS tables to install. For each table
652 in the list it requests the corresponding ACPI/SMBIOS table factory for
653 a generator capable of building the ACPI/SMBIOS table.
654 If a suitable table generator is found, it invokes the generator interface
655 to build the table. The Dynamic Table Manager then installs the
656 table and invokes another generator interface to free any resources
657 allocated for building the table.
662 @retval EFI_SUCCESS Success.
663 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
664 @retval EFI_NOT_FOUND Required interface/object was not found.
665 @retval EFI_INVALID_PARAMETER Some parameter is incorrect/invalid.
669 DynamicTableManagerDxeInitialize (
670 IN EFI_HANDLE ImageHandle
,
671 IN EFI_SYSTEM_TABLE
*SystemTable
675 EDKII_CONFIGURATION_MANAGER_PROTOCOL
*CfgMgrProtocol
;
676 CM_STD_OBJ_CONFIGURATION_MANAGER_INFO
*CfgMfrInfo
;
677 EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL
*TableFactoryProtocol
;
679 // Locate the Dynamic Table Factory
680 Status
= gBS
->LocateProtocol (
681 &gEdkiiDynamicTableFactoryProtocolGuid
,
683 (VOID
**)&TableFactoryProtocol
685 if (EFI_ERROR (Status
)) {
688 "ERROR: Failed to find Dynamic Table Factory protocol." \
695 // Locate the Configuration Manager for the Platform
696 Status
= gBS
->LocateProtocol (
697 &gEdkiiConfigurationManagerProtocolGuid
,
699 (VOID
**)&CfgMgrProtocol
701 if (EFI_ERROR (Status
)) {
704 "ERROR: Failed to find Configuration Manager protocol. Status = %r\n",
710 Status
= GetCgfMgrInfo (CfgMgrProtocol
, &CfgMfrInfo
);
711 if (EFI_ERROR (Status
)) {
714 "ERROR: Failed to get Configuration Manager info. Status = %r\n",
722 "INFO: Configuration Manager Version = 0x%x, OemID = %c%c%c%c%c%c\n",
723 CfgMfrInfo
->Revision
,
724 CfgMfrInfo
->OemId
[0],
725 CfgMfrInfo
->OemId
[1],
726 CfgMfrInfo
->OemId
[2],
727 CfgMfrInfo
->OemId
[3],
728 CfgMfrInfo
->OemId
[4],
732 Status
= ProcessAcpiTables (TableFactoryProtocol
, CfgMgrProtocol
);
733 if (EFI_ERROR (Status
)) {
736 "ERROR: ACPI Table processing failure. Status = %r\n",