2 Dynamic Table Manager Dxe
4 Copyright (c) 2017 - 2019, ARM Limited. All rights reserved.
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include <Library/DebugLib.h>
17 #include <Library/PcdLib.h>
18 #include <Library/UefiBootServicesTableLib.h>
19 #include <Protocol/AcpiTable.h>
21 // Module specific include files.
22 #include <AcpiTableGenerator.h>
23 #include <ConfigurationManagerObject.h>
24 #include <ConfigurationManagerHelper.h>
25 #include <DeviceTreeTableGenerator.h>
26 #include <Library/TableHelperLib.h>
27 #include <Protocol/ConfigurationManagerProtocol.h>
28 #include <Protocol/DynamicTableFactoryProtocol.h>
29 #include <SmbiosTableGenerator.h>
31 /** This macro expands to a function that retrieves the ACPI Table
32 List from the Configuration Manager.
35 EObjNameSpaceStandard
,
37 CM_STD_OBJ_ACPI_TABLE_INFO
40 /** A helper function to build and install a single ACPI table.
42 This is a helper function that invokes the Table generator interface
43 for building an ACPI table. It uses the AcpiTableProtocol to install the
44 table, then frees the resources allocated for generating it.
46 @param [in] TableFactoryProtocol Pointer to the Table Factory Protocol
48 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
50 @param [in] Generator Pointer to the AcpiTable generator.
51 @param [in] AcpiTableProtocol Pointer to the AcpiTable protocol.
52 @param [in] AcpiTableInfo Pointer to the ACPI table Info.
54 @retval EFI_SUCCESS Success.
55 @retval EFI_INVALID_PARAMETER A parameter is invalid.
56 @retval EFI_NOT_FOUND Required object is not found.
57 @retval EFI_BAD_BUFFER_SIZE Size returned by the Configuration Manager
58 is less than the Object size for the
64 BuildAndInstallSingleAcpiTable (
65 IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL
* CONST TableFactoryProtocol
,
66 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL
* CONST CfgMgrProtocol
,
67 IN CONST ACPI_TABLE_GENERATOR
* CONST Generator
,
68 IN EFI_ACPI_TABLE_PROTOCOL
* AcpiTableProtocol
,
69 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO
* CONST AcpiTableInfo
74 EFI_ACPI_DESCRIPTION_HEADER
* AcpiTable
;
78 Status
= Generator
->BuildAcpiTable (
84 if (EFI_ERROR (Status
)) {
87 "ERROR: Failed to Build Table." \
88 " TableGeneratorId = 0x%x. Status = %r\n",
89 AcpiTableInfo
->TableGeneratorId
,
92 // Free any allocated resources.
96 if (AcpiTable
== NULL
) {
97 Status
= EFI_NOT_FOUND
;
101 // Dump ACPI Table Header
102 DUMP_ACPI_TABLE_HEADER (AcpiTable
);
104 // Install ACPI table
105 Status
= AcpiTableProtocol
->InstallAcpiTable (
111 if (EFI_ERROR (Status
)) {
114 "ERROR: Failed to Install ACPI Table. Status = %r\n",
117 // Free any allocated resources.
123 "INFO: ACPI Table installed. Status = %r\n",
128 // Free any resources allocated for generating the tables.
129 if (Generator
->FreeTableResources
!= NULL
) {
130 Status1
= Generator
->FreeTableResources (
136 if (EFI_ERROR (Status1
)) {
139 "ERROR: Failed to Free Table Resources." \
140 "TableGeneratorId = 0x%x. Status = %r\n",
141 AcpiTableInfo
->TableGeneratorId
,
146 // Return the first error status in case of failure
147 if (!EFI_ERROR (Status
)) {
154 /** A helper function to build and install multiple ACPI tables.
156 This is a helper function that invokes the Table generator interface
157 for building an ACPI table. It uses the AcpiTableProtocol to install the
158 table, then frees the resources allocated for generating it.
160 @param [in] TableFactoryProtocol Pointer to the Table Factory Protocol
162 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
164 @param [in] Generator Pointer to the AcpiTable generator.
165 @param [in] AcpiTableProtocol Pointer to the AcpiTable protocol.
166 @param [in] AcpiTableInfo Pointer to the ACPI table Info.
168 @retval EFI_SUCCESS Success.
169 @retval EFI_INVALID_PARAMETER A parameter is invalid.
170 @retval EFI_NOT_FOUND Required object is not found.
171 @retval EFI_BAD_BUFFER_SIZE Size returned by the Configuration Manager
172 is less than the Object size for the
178 BuildAndInstallMultipleAcpiTable (
179 IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL
* CONST TableFactoryProtocol
,
180 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL
* CONST CfgMgrProtocol
,
181 IN CONST ACPI_TABLE_GENERATOR
* CONST Generator
,
182 IN EFI_ACPI_TABLE_PROTOCOL
* AcpiTableProtocol
,
183 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO
* CONST AcpiTableInfo
188 EFI_ACPI_DESCRIPTION_HEADER
** AcpiTable
;
195 Status
= Generator
->BuildAcpiTableEx (
202 if (EFI_ERROR (Status
)) {
205 "ERROR: Failed to Build Table." \
206 " TableGeneratorId = 0x%x. Status = %r\n",
207 AcpiTableInfo
->TableGeneratorId
,
210 // Free any allocated resources.
214 if ((AcpiTable
== NULL
) || (TableCount
== 0)) {
215 Status
= EFI_NOT_FOUND
;
219 for (Index
= 0; Index
< TableCount
; Index
++) {
220 // Dump ACPI Table Header
221 DUMP_ACPI_TABLE_HEADER (AcpiTable
[Index
]);
222 // Install ACPI table
223 Status
= AcpiTableProtocol
->InstallAcpiTable (
226 AcpiTable
[Index
]->Length
,
229 if (EFI_ERROR (Status
)) {
232 "ERROR: Failed to Install ACPI Table. Status = %r\n",
235 // Free any allocated resources.
241 "INFO: ACPI Table installed. Status = %r\n",
247 // Free any resources allocated for generating the tables.
248 if (Generator
->FreeTableResourcesEx
!= NULL
) {
249 Status1
= Generator
->FreeTableResourcesEx (
256 if (EFI_ERROR (Status1
)) {
259 "ERROR: Failed to Free Table Resources." \
260 "TableGeneratorId = 0x%x. Status = %r\n",
261 AcpiTableInfo
->TableGeneratorId
,
266 // Return the first error status in case of failure
267 if (!EFI_ERROR (Status
)) {
274 /** A helper function to invoke a Table generator
276 This is a helper function that invokes the Table generator interface
277 for building an ACPI table. It uses the AcpiTableProtocol to install the
278 table, then frees the resources allocated for generating it.
280 @param [in] TableFactoryProtocol Pointer to the Table Factory Protocol
282 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
284 @param [in] AcpiTableProtocol Pointer to the AcpiTable protocol.
285 @param [in] AcpiTableInfo Pointer to the ACPI table Info.
287 @retval EFI_SUCCESS Success.
288 @retval EFI_INVALID_PARAMETER A parameter is invalid.
289 @retval EFI_NOT_FOUND Required object is not found.
290 @retval EFI_BAD_BUFFER_SIZE Size returned by the Configuration Manager
291 is less than the Object size for the
297 BuildAndInstallAcpiTable (
298 IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL
* CONST TableFactoryProtocol
,
299 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL
* CONST CfgMgrProtocol
,
300 IN EFI_ACPI_TABLE_PROTOCOL
* AcpiTableProtocol
,
301 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO
* CONST AcpiTableInfo
305 CONST ACPI_TABLE_GENERATOR
* Generator
;
307 ASSERT (TableFactoryProtocol
!= NULL
);
308 ASSERT (CfgMgrProtocol
!= NULL
);
309 ASSERT (AcpiTableProtocol
!= NULL
);
310 ASSERT (AcpiTableInfo
!= NULL
);
314 "INFO: EStdObjAcpiTableList: Address = 0x%p," \
315 " TableGeneratorId = 0x%x\n",
317 AcpiTableInfo
->TableGeneratorId
321 Status
= TableFactoryProtocol
->GetAcpiTableGenerator (
322 TableFactoryProtocol
,
323 AcpiTableInfo
->TableGeneratorId
,
326 if (EFI_ERROR (Status
)) {
329 "ERROR: Table Generator not found." \
330 " TableGeneratorId = 0x%x. Status = %r\n",
331 AcpiTableInfo
->TableGeneratorId
,
337 if (Generator
== NULL
) {
338 return EFI_NOT_FOUND
;
343 "INFO: Generator found : %s\n",
344 Generator
->Description
347 if (Generator
->BuildAcpiTableEx
!= NULL
) {
348 Status
= BuildAndInstallMultipleAcpiTable (
349 TableFactoryProtocol
,
355 if (EFI_ERROR (Status
)) {
358 "ERROR: Failed to find build and install ACPI Table." \
363 } else if (Generator
->BuildAcpiTable
!= NULL
) {
364 Status
= BuildAndInstallSingleAcpiTable (
365 TableFactoryProtocol
,
371 if (EFI_ERROR (Status
)) {
374 "ERROR: Failed to find build and install ACPI Table." \
380 Status
= EFI_INVALID_PARAMETER
;
383 "ERROR: Table Generator does not implement the" \
384 " ACPI_TABLE_GENERATOR_BUILD_TABLE interface." \
385 " TableGeneratorId = 0x%x. Status = %r\n",
386 AcpiTableInfo
->TableGeneratorId
,
394 /** The function checks if the Configuration Manager has provided the
395 mandatory ACPI tables for installation.
397 @param [in] AcpiTableInfo Pointer to the ACPI Table Info list.
398 @param [in] AcpiTableCount Count of ACPI Table Info.
400 @retval EFI_SUCCESS Success.
401 @retval EFI_NOT_FOUND If mandatory table is not found.
406 VerifyMandatoryTablesArePresent (
407 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO
* CONST AcpiTableInfo
,
408 IN UINT32 AcpiTableCount
419 Status
= EFI_SUCCESS
;
426 ASSERT (AcpiTableInfo
!= NULL
);
428 while (AcpiTableCount
-- != 0) {
429 switch (AcpiTableInfo
[AcpiTableCount
].AcpiTableSignature
) {
430 case EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE
:
433 case EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE
:
436 case EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE
:
439 case EFI_ACPI_6_2_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
:
442 case EFI_ACPI_6_2_DEBUG_PORT_2_TABLE_SIGNATURE
:
445 case EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE
:
453 // We need at least the FADT, MADT, GTDT and the DSDT tables to boot
455 DEBUG ((DEBUG_ERROR
,"ERROR: FADT Table not found\n"));
456 Status
= EFI_NOT_FOUND
;
459 DEBUG ((DEBUG_ERROR
, "ERROR: MADT Table not found.\n"));
460 Status
= EFI_NOT_FOUND
;
463 DEBUG ((DEBUG_ERROR
, "ERROR: GTDT Table not found.\n"));
464 Status
= EFI_NOT_FOUND
;
467 DEBUG ((DEBUG_ERROR
, "ERROR: DSDT Table not found.\n"));
468 Status
= EFI_NOT_FOUND
;
471 DEBUG ((DEBUG_WARN
, "WARNING: DBG2 Table not found.\n"));
474 DEBUG ((DEBUG_WARN
, "WARNING: SPCR Table not found.\n"));
479 /** Generate and install ACPI tables.
481 The function gathers the information necessary for installing the
482 ACPI tables from the Configuration Manager, invokes the generators
483 and installs them (via BuildAndInstallAcpiTable).
485 @param [in] TableFactoryProtocol Pointer to the Table Factory Protocol
487 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
490 @retval EFI_SUCCESS Success.
491 @retval EFI_NOT_FOUND If a mandatory table or a generator is not found.
497 IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL
* CONST TableFactoryProtocol
,
498 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL
* CONST CfgMgrProtocol
502 EFI_ACPI_TABLE_PROTOCOL
* AcpiTableProtocol
;
503 CM_STD_OBJ_ACPI_TABLE_INFO
* AcpiTableInfo
;
504 UINT32 AcpiTableCount
;
507 ASSERT (TableFactoryProtocol
!= NULL
);
508 ASSERT (CfgMgrProtocol
!= NULL
);
510 // Find the AcpiTable protocol
511 Status
= gBS
->LocateProtocol (
512 &gEfiAcpiTableProtocolGuid
,
514 (VOID
**)&AcpiTableProtocol
516 if (EFI_ERROR (Status
)) {
519 "ERROR: Failed to find AcpiTable protocol. Status = %r\n",
525 Status
= GetEStdObjAcpiTableList (
531 if (EFI_ERROR (Status
)) {
534 "ERROR: Failed to get ACPI Table List. Status = %r\n",
540 if (0 == AcpiTableCount
) {
543 "ERROR: EStdObjAcpiTableList: AcpiTableCount = %d\n",
546 return EFI_NOT_FOUND
;
551 "INFO: EStdObjAcpiTableList: AcpiTableCount = %d\n",
555 // Check if mandatory ACPI tables are present.
556 Status
= VerifyMandatoryTablesArePresent (
560 if (EFI_ERROR (Status
)) {
563 "ERROR: Failed to find mandatory ACPI Table(s)."
570 // Add the FADT Table first.
571 for (Idx
= 0; Idx
< AcpiTableCount
; Idx
++) {
572 if (CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdFadt
) ==
573 AcpiTableInfo
[Idx
].TableGeneratorId
) {
574 Status
= BuildAndInstallAcpiTable (
575 TableFactoryProtocol
,
580 if (EFI_ERROR (Status
)) {
583 "ERROR: Failed to find build and install ACPI FADT Table." \
593 // Add remaining ACPI Tables
594 for (Idx
= 0; Idx
< AcpiTableCount
; Idx
++) {
597 "INFO: AcpiTableInfo[%d].TableGeneratorId = 0x%x\n",
599 AcpiTableInfo
[Idx
].TableGeneratorId
602 // Skip FADT Table since we have already added
603 if (CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdFadt
) ==
604 AcpiTableInfo
[Idx
].TableGeneratorId
) {
608 // Skip the Reserved table Generator ID for standard generators
609 if ((IS_GENERATOR_NAMESPACE_STD (AcpiTableInfo
[Idx
].TableGeneratorId
)) &&
610 ((CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdReserved
) >=
611 AcpiTableInfo
[Idx
].TableGeneratorId
) ||
612 (CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdMax
) <=
613 AcpiTableInfo
[Idx
].TableGeneratorId
))) {
616 "WARNING: Invalid ACPI Generator table ID = 0x%x, Skipping...\n",
617 AcpiTableInfo
[Idx
].TableGeneratorId
622 Status
= BuildAndInstallAcpiTable (
623 TableFactoryProtocol
,
628 if (EFI_ERROR (Status
)) {
631 "ERROR: Failed to find, build, and install ACPI Table." \
642 /** Entrypoint of Dynamic Table Manager Dxe.
644 The Dynamic Table Manager uses the Configuration Manager Protocol
645 to get the list of ACPI and SMBIOS tables to install. For each table
646 in the list it requests the corresponding ACPI/SMBIOS table factory for
647 a generator capable of building the ACPI/SMBIOS table.
648 If a suitable table generator is found, it invokes the generator interface
649 to build the table. The Dynamic Table Manager then installs the
650 table and invokes another generator interface to free any resources
651 allocated for building the table.
656 @retval EFI_SUCCESS Success.
657 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
658 @retval EFI_NOT_FOUND Required interface/object was not found.
659 @retval EFI_INVALID_PARAMETER Some parameter is incorrect/invalid.
663 DynamicTableManagerDxeInitialize (
664 IN CONST EFI_HANDLE ImageHandle
,
665 IN EFI_SYSTEM_TABLE
* CONST SystemTable
669 EDKII_CONFIGURATION_MANAGER_PROTOCOL
* CfgMgrProtocol
;
670 CM_STD_OBJ_CONFIGURATION_MANAGER_INFO
* CfgMfrInfo
;
671 EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL
* TableFactoryProtocol
;
673 // Locate the Dynamic Table Factory
674 Status
= gBS
->LocateProtocol (
675 &gEdkiiDynamicTableFactoryProtocolGuid
,
677 (VOID
**)&TableFactoryProtocol
679 if (EFI_ERROR (Status
)) {
682 "ERROR: Failed to find Dynamic Table Factory protocol." \
689 // Locate the Configuration Manager for the Platform
690 Status
= gBS
->LocateProtocol (
691 &gEdkiiConfigurationManagerProtocolGuid
,
693 (VOID
**)&CfgMgrProtocol
695 if (EFI_ERROR (Status
)) {
698 "ERROR: Failed to find Configuration Manager protocol. Status = %r\n",
704 Status
= GetCgfMgrInfo (CfgMgrProtocol
, &CfgMfrInfo
);
705 if (EFI_ERROR (Status
)) {
708 "ERROR: Failed to get Configuration Manager info. Status = %r\n",
716 "INFO: Configuration Manager Version = 0x%x, OemID = %c%c%c%c%c%c\n",
717 CfgMfrInfo
->Revision
,
718 CfgMfrInfo
->OemId
[0],
719 CfgMfrInfo
->OemId
[1],
720 CfgMfrInfo
->OemId
[2],
721 CfgMfrInfo
->OemId
[3],
722 CfgMfrInfo
->OemId
[4],
726 Status
= ProcessAcpiTables (TableFactoryProtocol
, CfgMgrProtocol
);
727 if (EFI_ERROR (Status
)) {
730 "ERROR: ACPI Table processing failure. Status = %r\n",