4 Copyright (c) 2017 - 2019, ARM Limited. All rights reserved.
5 SPDX-License-Identifier: BSD-2-Clause-Patent
8 - ACPI 6.3 Specification - January 2019
12 #include <Library/AcpiLib.h>
13 #include <Library/DebugLib.h>
14 #include <Library/MemoryAllocationLib.h>
15 #include <Protocol/AcpiTable.h>
17 // Module specific include files.
18 #include <AcpiTableGenerator.h>
19 #include <ConfigurationManagerObject.h>
20 #include <ConfigurationManagerHelper.h>
21 #include <Library/TableHelperLib.h>
22 #include <Protocol/ConfigurationManagerProtocol.h>
24 /** ARM standard MADT Generator
27 The following Configuration Manager Object(s) are required by
31 - EArmObjGicMsiFrameInfo (OPTIONAL)
32 - EArmObjGicRedistributorInfo (OPTIONAL)
33 - EArmObjGicItsInfo (OPTIONAL)
36 /** This macro expands to a function that retrieves the GIC
37 CPU interface Information from the Configuration Manager.
45 /** This macro expands to a function that retrieves the GIC
46 Distributor Information from the Configuration Manager.
55 /** This macro expands to a function that retrieves the GIC
56 MSI Frame Information from the Configuration Manager.
60 EArmObjGicMsiFrameInfo
,
61 CM_ARM_GIC_MSI_FRAME_INFO
64 /** This macro expands to a function that retrieves the GIC
65 Redistributor Information from the Configuration Manager.
70 EArmObjGicRedistributorInfo
,
71 CM_ARM_GIC_REDIST_INFO
74 /** This macro expands to a function that retrieves the GIC
75 Interrupt Translation Service Information from the
76 Configuration Manager.
84 /** This function updates the GIC CPU Interface Information in the
85 EFI_ACPI_6_3_GIC_STRUCTURE structure.
87 @param [in] Gicc Pointer to GIC CPU Interface structure.
88 @param [in] GicCInfo Pointer to the GIC CPU Interface Information.
89 @param [in] MadtRev MADT table revision.
94 IN EFI_ACPI_6_3_GIC_STRUCTURE
* CONST Gicc
,
95 IN CONST CM_ARM_GICC_INFO
* CONST GicCInfo
,
96 IN CONST UINT8 MadtRev
99 ASSERT (Gicc
!= NULL
);
100 ASSERT (GicCInfo
!= NULL
);
103 Gicc
->Type
= EFI_ACPI_6_3_GIC
;
105 Gicc
->Length
= sizeof (EFI_ACPI_6_3_GIC_STRUCTURE
);
107 Gicc
->Reserved
= EFI_ACPI_RESERVED_WORD
;
109 // UINT32 CPUInterfaceNumber
110 Gicc
->CPUInterfaceNumber
= GicCInfo
->CPUInterfaceNumber
;
111 // UINT32 AcpiProcessorUid
112 Gicc
->AcpiProcessorUid
= GicCInfo
->AcpiProcessorUid
;
114 Gicc
->Flags
= GicCInfo
->Flags
;
115 // UINT32 ParkingProtocolVersion
116 Gicc
->ParkingProtocolVersion
= GicCInfo
->ParkingProtocolVersion
;
117 // UINT32 PerformanceInterruptGsiv
118 Gicc
->PerformanceInterruptGsiv
= GicCInfo
->PerformanceInterruptGsiv
;
119 // UINT64 ParkedAddress
120 Gicc
->ParkedAddress
= GicCInfo
->ParkedAddress
;
122 // UINT64 PhysicalBaseAddress
123 Gicc
->PhysicalBaseAddress
= GicCInfo
->PhysicalBaseAddress
;
125 Gicc
->GICV
= GicCInfo
->GICV
;
127 Gicc
->GICH
= GicCInfo
->GICH
;
129 // UINT32 VGICMaintenanceInterrupt
130 Gicc
->VGICMaintenanceInterrupt
= GicCInfo
->VGICMaintenanceInterrupt
;
131 // UINT64 GICRBaseAddress
132 Gicc
->GICRBaseAddress
= GicCInfo
->GICRBaseAddress
;
135 Gicc
->MPIDR
= GicCInfo
->MPIDR
;
136 // UINT8 ProcessorPowerEfficiencyClass
137 Gicc
->ProcessorPowerEfficiencyClass
=
138 GicCInfo
->ProcessorPowerEfficiencyClass
;
140 Gicc
->Reserved2
= EFI_ACPI_RESERVED_BYTE
;
142 // UINT16 SpeOverflowInterrupt
143 if (MadtRev
> EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
) {
144 Gicc
->SpeOverflowInterrupt
= GicCInfo
->SpeOverflowInterrupt
;
146 // Setting SpeOverflowInterrupt to 0 ensures backward compatibility with
147 // ACPI 6.2 by also clearing the Reserved2[1] and Reserved2[2] fields
148 // in EFI_ACPI_6_2_GIC_STRUCTURE.
149 Gicc
->SpeOverflowInterrupt
= 0;
154 Function to test if two GIC CPU Interface information structures have the
155 same ACPI Processor UID.
157 @param [in] GicCInfo1 Pointer to the first GICC info structure.
158 @param [in] GicCInfo2 Pointer to the second GICC info structure.
159 @param [in] Index1 Index of GicCInfo1 in the shared list of GIC
160 CPU Interface Info structures.
161 @param [in] Index2 Index of GicCInfo2 in the shared list of GIC
162 CPU Interface Info structures.
164 @retval TRUE GicCInfo1 and GicCInfo2 have the same UID.
165 @retval FALSE GicCInfo1 and GicCInfo2 have different UIDs.
170 IN CONST VOID
* GicCInfo1
,
171 IN CONST VOID
* GicCInfo2
,
179 ASSERT ((GicCInfo1
!= NULL
) && (GicCInfo2
!= NULL
));
181 Uid1
= ((CM_ARM_GICC_INFO
*)GicCInfo1
)->AcpiProcessorUid
;
182 Uid2
= ((CM_ARM_GICC_INFO
*)GicCInfo2
)->AcpiProcessorUid
;
187 "ERROR: MADT: GICC Info Structures %d and %d have the same ACPI " \
188 "Processor UID: 0x%x.\n",
199 /** Add the GIC CPU Interface Information to the MADT Table.
201 This function also checks for duplicate ACPI Processor UIDs.
203 @param [in] Gicc Pointer to GIC CPU Interface structure list.
204 @param [in] GicCInfo Pointer to the GIC CPU Information list.
205 @param [in] GicCCount Count of GIC CPU Interfaces.
206 @param [in] MadtRev MADT table revision.
208 @retval EFI_SUCCESS GIC CPU Interface Information was added
210 @retval EFI_INVALID_PARAMETER One or more invalid GIC CPU Info values were
211 provided and the generator failed to add the
212 information to the table.
217 IN EFI_ACPI_6_3_GIC_STRUCTURE
* Gicc
,
218 IN CONST CM_ARM_GICC_INFO
* GicCInfo
,
220 IN CONST UINT8 MadtRev
223 BOOLEAN IsAcpiProcUidDuplicated
;
225 ASSERT (Gicc
!= NULL
);
226 ASSERT (GicCInfo
!= NULL
);
228 IsAcpiProcUidDuplicated
= FindDuplicateValue (
231 sizeof (CM_ARM_GICC_INFO
),
234 // Duplicate ACPI Processor UID was found so the GICC info provided
236 if (IsAcpiProcUidDuplicated
) {
237 return EFI_INVALID_PARAMETER
;
240 while (GicCCount
-- != 0) {
241 AddGICC (Gicc
++, GicCInfo
++, MadtRev
);
247 /** Update the GIC Distributor Information in the MADT Table.
249 @param [in] Gicd Pointer to GIC Distributor structure.
250 @param [in] GicDInfo Pointer to the GIC Distributor Information.
255 EFI_ACPI_6_3_GIC_DISTRIBUTOR_STRUCTURE
* CONST Gicd
,
256 CONST CM_ARM_GICD_INFO
* CONST GicDInfo
259 ASSERT (Gicd
!= NULL
);
260 ASSERT (GicDInfo
!= NULL
);
263 Gicd
->Type
= EFI_ACPI_6_3_GICD
;
265 Gicd
->Length
= sizeof (EFI_ACPI_6_3_GIC_DISTRIBUTOR_STRUCTURE
);
267 Gicd
->Reserved1
= EFI_ACPI_RESERVED_WORD
;
269 // One, and only one, GIC distributor structure must be present
270 // in the MADT for an ARM based system
272 // UINT64 PhysicalBaseAddress
273 Gicd
->PhysicalBaseAddress
= GicDInfo
->PhysicalBaseAddress
;
275 Gicd
->SystemVectorBase
= EFI_ACPI_RESERVED_DWORD
;
277 Gicd
->GicVersion
= GicDInfo
->GicVersion
;
278 // UINT8 Reserved2[3]
279 Gicd
->Reserved2
[0] = EFI_ACPI_RESERVED_BYTE
;
280 Gicd
->Reserved2
[1] = EFI_ACPI_RESERVED_BYTE
;
281 Gicd
->Reserved2
[2] = EFI_ACPI_RESERVED_BYTE
;
284 /** Update the GIC MSI Frame Information.
286 @param [in] GicMsiFrame Pointer to GIC MSI Frame structure.
287 @param [in] GicMsiFrameInfo Pointer to the GIC MSI Frame Information.
292 IN EFI_ACPI_6_3_GIC_MSI_FRAME_STRUCTURE
* CONST GicMsiFrame
,
293 IN CONST CM_ARM_GIC_MSI_FRAME_INFO
* CONST GicMsiFrameInfo
296 ASSERT (GicMsiFrame
!= NULL
);
297 ASSERT (GicMsiFrameInfo
!= NULL
);
299 GicMsiFrame
->Type
= EFI_ACPI_6_3_GIC_MSI_FRAME
;
300 GicMsiFrame
->Length
= sizeof (EFI_ACPI_6_3_GIC_MSI_FRAME_STRUCTURE
);
301 GicMsiFrame
->Reserved1
= EFI_ACPI_RESERVED_WORD
;
302 GicMsiFrame
->GicMsiFrameId
= GicMsiFrameInfo
->GicMsiFrameId
;
303 GicMsiFrame
->PhysicalBaseAddress
= GicMsiFrameInfo
->PhysicalBaseAddress
;
305 GicMsiFrame
->Flags
= GicMsiFrameInfo
->Flags
;
306 GicMsiFrame
->SPICount
= GicMsiFrameInfo
->SPICount
;
307 GicMsiFrame
->SPIBase
= GicMsiFrameInfo
->SPIBase
;
310 /** Add the GIC MSI Frame Information to the MADT Table.
312 @param [in] GicMsiFrame Pointer to GIC MSI Frame structure list.
313 @param [in] GicMsiFrameInfo Pointer to the GIC MSI Frame info list.
314 @param [in] GicMsiFrameCount Count of GIC MSI Frames.
318 AddGICMsiFrameInfoList (
319 IN EFI_ACPI_6_3_GIC_MSI_FRAME_STRUCTURE
* GicMsiFrame
,
320 IN CONST CM_ARM_GIC_MSI_FRAME_INFO
* GicMsiFrameInfo
,
321 IN UINT32 GicMsiFrameCount
324 ASSERT (GicMsiFrame
!= NULL
);
325 ASSERT (GicMsiFrameInfo
!= NULL
);
327 while (GicMsiFrameCount
-- != 0) {
328 AddGICMsiFrame (GicMsiFrame
++, GicMsiFrameInfo
++);
332 /** Update the GIC Redistributor Information.
334 @param [in] Gicr Pointer to GIC Redistributor structure.
335 @param [in] GicRedisributorInfo Pointer to the GIC Redistributor Info.
339 AddGICRedistributor (
340 IN EFI_ACPI_6_3_GICR_STRUCTURE
* CONST Gicr
,
341 IN CONST CM_ARM_GIC_REDIST_INFO
* CONST GicRedisributorInfo
344 ASSERT (Gicr
!= NULL
);
345 ASSERT (GicRedisributorInfo
!= NULL
);
347 Gicr
->Type
= EFI_ACPI_6_3_GICR
;
348 Gicr
->Length
= sizeof (EFI_ACPI_6_3_GICR_STRUCTURE
);
349 Gicr
->Reserved
= EFI_ACPI_RESERVED_WORD
;
350 Gicr
->DiscoveryRangeBaseAddress
=
351 GicRedisributorInfo
->DiscoveryRangeBaseAddress
;
352 Gicr
->DiscoveryRangeLength
= GicRedisributorInfo
->DiscoveryRangeLength
;
355 /** Add the GIC Redistributor Information to the MADT Table.
357 @param [in] Gicr Pointer to GIC Redistributor structure list.
358 @param [in] GicRInfo Pointer to the GIC Distributor info list.
359 @param [in] GicRCount Count of GIC Distributors.
363 AddGICRedistributorList (
364 IN EFI_ACPI_6_3_GICR_STRUCTURE
* Gicr
,
365 IN CONST CM_ARM_GIC_REDIST_INFO
* GicRInfo
,
369 ASSERT (Gicr
!= NULL
);
370 ASSERT (GicRInfo
!= NULL
);
372 while (GicRCount
-- != 0) {
373 AddGICRedistributor (Gicr
++, GicRInfo
++);
377 /** Update the GIC Interrupt Translation Service Information
379 @param [in] GicIts Pointer to GIC ITS structure.
380 @param [in] GicItsInfo Pointer to the GIC ITS Information.
384 AddGICInterruptTranslationService (
385 IN EFI_ACPI_6_3_GIC_ITS_STRUCTURE
* CONST GicIts
,
386 IN CONST CM_ARM_GIC_ITS_INFO
* CONST GicItsInfo
389 ASSERT (GicIts
!= NULL
);
390 ASSERT (GicItsInfo
!= NULL
);
392 GicIts
->Type
= EFI_ACPI_6_3_GIC_ITS
;
393 GicIts
->Length
= sizeof (EFI_ACPI_6_3_GIC_ITS_STRUCTURE
);
394 GicIts
->Reserved
= EFI_ACPI_RESERVED_WORD
;
395 GicIts
->GicItsId
= GicItsInfo
->GicItsId
;
396 GicIts
->PhysicalBaseAddress
= GicItsInfo
->PhysicalBaseAddress
;
397 GicIts
->Reserved2
= EFI_ACPI_RESERVED_DWORD
;
400 /** Add the GIC Interrupt Translation Service Information
403 @param [in] GicIts Pointer to GIC ITS structure list.
404 @param [in] GicItsInfo Pointer to the GIC ITS list.
405 @param [in] GicItsCount Count of GIC ITS.
410 IN EFI_ACPI_6_3_GIC_ITS_STRUCTURE
* GicIts
,
411 IN CONST CM_ARM_GIC_ITS_INFO
* GicItsInfo
,
412 IN UINT32 GicItsCount
415 ASSERT (GicIts
!= NULL
);
416 ASSERT (GicItsInfo
!= NULL
);
418 while (GicItsCount
-- != 0) {
419 AddGICInterruptTranslationService (GicIts
++, GicItsInfo
++);
423 /** Construct the MADT ACPI table.
425 This function invokes the Configuration Manager protocol interface
426 to get the required hardware information for generating the ACPI
429 If this function allocates any resources then they must be freed
430 in the FreeXXXXTableResources function.
432 @param [in] This Pointer to the table generator.
433 @param [in] AcpiTableInfo Pointer to the ACPI Table Info.
434 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
436 @param [out] Table Pointer to the constructed ACPI Table.
438 @retval EFI_SUCCESS Table generated successfully.
439 @retval EFI_INVALID_PARAMETER A parameter is invalid.
440 @retval EFI_NOT_FOUND The required object was not found.
441 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
442 Manager is less than the Object size for the
449 IN CONST ACPI_TABLE_GENERATOR
* CONST This
,
450 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO
* CONST AcpiTableInfo
,
451 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL
* CONST CfgMgrProtocol
,
452 OUT EFI_ACPI_DESCRIPTION_HEADER
** CONST Table
460 UINT32 GicRedistCount
;
462 CM_ARM_GICC_INFO
* GicCInfo
;
463 CM_ARM_GICD_INFO
* GicDInfo
;
464 CM_ARM_GIC_MSI_FRAME_INFO
* GicMSIInfo
;
465 CM_ARM_GIC_REDIST_INFO
* GicRedistInfo
;
466 CM_ARM_GIC_ITS_INFO
* GicItsInfo
;
470 UINT32 GicRedistOffset
;
473 EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER
* Madt
;
475 ASSERT (This
!= NULL
);
476 ASSERT (AcpiTableInfo
!= NULL
);
477 ASSERT (CfgMgrProtocol
!= NULL
);
478 ASSERT (Table
!= NULL
);
479 ASSERT (AcpiTableInfo
->TableGeneratorId
== This
->GeneratorID
);
480 ASSERT (AcpiTableInfo
->AcpiTableSignature
== This
->AcpiTableSignature
);
482 if ((AcpiTableInfo
->AcpiTableRevision
< This
->MinAcpiTableRevision
) ||
483 (AcpiTableInfo
->AcpiTableRevision
> This
->AcpiTableRevision
)) {
486 "ERROR: MADT: Requested table revision = %d, is not supported."
487 "Supported table revision: Minimum = %d, Maximum = %d\n",
488 AcpiTableInfo
->AcpiTableRevision
,
489 This
->MinAcpiTableRevision
,
490 This
->AcpiTableRevision
492 return EFI_INVALID_PARAMETER
;
497 Status
= GetEArmObjGicCInfo (
503 if (EFI_ERROR (Status
)) {
506 "ERROR: MADT: Failed to get GICC Info. Status = %r\n",
512 if (GicCCount
== 0) {
515 "ERROR: MADT: GIC CPU Interface information not provided.\n"
517 ASSERT (GicCCount
!= 0);
518 Status
= EFI_INVALID_PARAMETER
;
522 Status
= GetEArmObjGicDInfo (
528 if (EFI_ERROR (Status
)) {
531 "ERROR: MADT: Failed to get GICD Info. Status = %r\n",
537 if (GicDCount
== 0) {
540 "ERROR: MADT: GIC Distributor information not provided.\n"
542 ASSERT (GicDCount
!= 0);
543 Status
= EFI_INVALID_PARAMETER
;
550 "ERROR: MADT: One, and only one, GIC distributor must be present."
554 ASSERT (GicDCount
<= 1);
555 Status
= EFI_INVALID_PARAMETER
;
559 Status
= GetEArmObjGicMsiFrameInfo (
565 if (EFI_ERROR (Status
) && (Status
!= EFI_NOT_FOUND
)) {
568 "ERROR: MADT: Failed to get GIC MSI Info. Status = %r\n",
574 Status
= GetEArmObjGicRedistributorInfo (
580 if (EFI_ERROR (Status
) && (Status
!= EFI_NOT_FOUND
)) {
583 "ERROR: MADT: Failed to get GIC Redistributor Info. Status = %r\n",
589 Status
= GetEArmObjGicItsInfo (
595 if (EFI_ERROR (Status
) && (Status
!= EFI_NOT_FOUND
)) {
598 "ERROR: MADT: Failed to get GIC ITS Info. Status = %r\n",
604 TableSize
= sizeof (EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER
);
606 GicCOffset
= TableSize
;
607 TableSize
+= (sizeof (EFI_ACPI_6_3_GIC_STRUCTURE
) * GicCCount
);
609 GicDOffset
= TableSize
;
610 TableSize
+= (sizeof (EFI_ACPI_6_3_GIC_DISTRIBUTOR_STRUCTURE
) * GicDCount
);
612 GicMSIOffset
= TableSize
;
613 TableSize
+= (sizeof (EFI_ACPI_6_3_GIC_MSI_FRAME_STRUCTURE
) * GicMSICount
);
615 GicRedistOffset
= TableSize
;
616 TableSize
+= (sizeof (EFI_ACPI_6_3_GICR_STRUCTURE
) * GicRedistCount
);
618 GicItsOffset
= TableSize
;
619 TableSize
+= (sizeof (EFI_ACPI_6_3_GIC_ITS_STRUCTURE
) * GicItsCount
);
621 // Allocate the Buffer for MADT table
622 *Table
= (EFI_ACPI_DESCRIPTION_HEADER
*)AllocateZeroPool (TableSize
);
623 if (*Table
== NULL
) {
624 Status
= EFI_OUT_OF_RESOURCES
;
627 "ERROR: MADT: Failed to allocate memory for MADT Table, Size = %d," \
635 Madt
= (EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER
*)*Table
;
639 "MADT: Madt = 0x%p TableSize = 0x%x\n",
644 Status
= AddAcpiHeader (
651 if (EFI_ERROR (Status
)) {
654 "ERROR: MADT: Failed to add ACPI header. Status = %r\n",
660 Status
= AddGICCList (
661 (EFI_ACPI_6_3_GIC_STRUCTURE
*)((UINT8
*)Madt
+ GicCOffset
),
664 Madt
->Header
.Revision
666 if (EFI_ERROR (Status
)) {
669 "ERROR: MADT: Failed to add GICC structures. Status = %r\n",
676 (EFI_ACPI_6_3_GIC_DISTRIBUTOR_STRUCTURE
*)((UINT8
*)Madt
+ GicDOffset
),
680 if (GicMSICount
!= 0) {
681 AddGICMsiFrameInfoList (
682 (EFI_ACPI_6_3_GIC_MSI_FRAME_STRUCTURE
*)((UINT8
*)Madt
+ GicMSIOffset
),
688 if (GicRedistCount
!= 0) {
689 AddGICRedistributorList (
690 (EFI_ACPI_6_3_GICR_STRUCTURE
*)((UINT8
*)Madt
+ GicRedistOffset
),
696 if (GicItsCount
!= 0) {
698 (EFI_ACPI_6_3_GIC_ITS_STRUCTURE
*)((UINT8
*)Madt
+ GicItsOffset
),
707 if (*Table
!= NULL
) {
714 /** Free any resources allocated for constructing the MADT
716 @param [in] This Pointer to the table generator.
717 @param [in] AcpiTableInfo Pointer to the ACPI Table Info.
718 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
720 @param [in, out] Table Pointer to the ACPI Table.
722 @retval EFI_SUCCESS The resources were freed successfully.
723 @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
727 FreeMadtTableResources (
728 IN CONST ACPI_TABLE_GENERATOR
* CONST This
,
729 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO
* CONST AcpiTableInfo
,
730 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL
* CONST CfgMgrProtocol
,
731 IN OUT EFI_ACPI_DESCRIPTION_HEADER
** CONST Table
734 ASSERT (This
!= NULL
);
735 ASSERT (AcpiTableInfo
!= NULL
);
736 ASSERT (CfgMgrProtocol
!= NULL
);
737 ASSERT (AcpiTableInfo
->TableGeneratorId
== This
->GeneratorID
);
738 ASSERT (AcpiTableInfo
->AcpiTableSignature
== This
->AcpiTableSignature
);
740 if ((Table
== NULL
) || (*Table
== NULL
)) {
741 DEBUG ((DEBUG_ERROR
, "ERROR: MADT: Invalid Table Pointer\n"));
742 ASSERT ((Table
!= NULL
) && (*Table
!= NULL
));
743 return EFI_INVALID_PARAMETER
;
751 /** The MADT Table Generator revision.
753 #define MADT_GENERATOR_REVISION CREATE_REVISION (1, 0)
755 /** The interface for the MADT Table Generator.
759 ACPI_TABLE_GENERATOR MadtGenerator
= {
761 CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdMadt
),
762 // Generator Description
763 L
"ACPI.STD.MADT.GENERATOR",
764 // ACPI Table Signature
765 EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE
,
766 // ACPI Table Revision supported by this Generator
767 EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
,
768 // Minimum supported ACPI Table Revision
769 EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
,
771 TABLE_GENERATOR_CREATOR_ID_ARM
,
773 MADT_GENERATOR_REVISION
,
774 // Build Table function
776 // Free Resource function
777 FreeMadtTableResources
,
778 // Extended build function not needed
780 // Extended build function not implemented by the generator.
781 // Hence extended free resource function is not required.
785 /** Register the Generator with the ACPI Table Factory.
787 @param [in] ImageHandle The handle to the image.
788 @param [in] SystemTable Pointer to the System Table.
790 @retval EFI_SUCCESS The Generator is registered.
791 @retval EFI_INVALID_PARAMETER A parameter is invalid.
792 @retval EFI_ALREADY_STARTED The Generator for the Table ID
793 is already registered.
797 AcpiMadtLibConstructor (
798 IN CONST EFI_HANDLE ImageHandle
,
799 IN EFI_SYSTEM_TABLE
* CONST SystemTable
803 Status
= RegisterAcpiTableGenerator (&MadtGenerator
);
804 DEBUG ((DEBUG_INFO
, "MADT: Register Generator. Status = %r\n", Status
));
805 ASSERT_EFI_ERROR (Status
);
809 /** Deregister the Generator from the ACPI Table Factory.
811 @param [in] ImageHandle The handle to the image.
812 @param [in] SystemTable Pointer to the System Table.
814 @retval EFI_SUCCESS The Generator is deregistered.
815 @retval EFI_INVALID_PARAMETER A parameter is invalid.
816 @retval EFI_NOT_FOUND The Generator is not registered.
820 AcpiMadtLibDestructor (
821 IN CONST EFI_HANDLE ImageHandle
,
822 IN EFI_SYSTEM_TABLE
* CONST SystemTable
826 Status
= DeregisterAcpiTableGenerator (&MadtGenerator
);
827 DEBUG ((DEBUG_INFO
, "MADT: Deregister Generator. Status = %r\n", Status
));
828 ASSERT_EFI_ERROR (Status
);