3 Processor power management initialization code.
5 Copyright (c) 2013-2016 Intel Corporation.
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include "SmmPowerManagement.h"
23 extern EFI_ACPI_SDT_PROTOCOL
*mAcpiSdt
;
24 extern EFI_ACPI_TABLE_PROTOCOL
*mAcpiTable
;
26 extern EFI_GUID gPowerManagementAcpiTableStorageGuid
;
29 This function is the entry of processor power management initialization code.
30 It initializes the processor's power management features based on the user
31 configurations and hardware capabilities.
39 // Processor Power Management Flags
41 mGlobalNvsAreaPtr
->Cfgd
= PcdGet32(PcdPpmFlags
);
44 // Patch and publish power management related acpi tables
46 PpmPatchAndPublishAcpiTables();
50 This function is to patch and publish power management related acpi tables.
53 PpmPatchAndPublishAcpiTables (
58 // Patch FADT table to enable C2,C3
63 // Load all the power management acpi tables and patch IST table
65 PpmLoadAndPatchPMTables();
69 This function is to patch PLvl2Lat and PLvl3Lat to enable C2, C3 support in OS.
77 EFI_ACPI_DESCRIPTION_HEADER
*Table
;
78 EFI_ACPI_SDT_HEADER
*CurrentTable
;
79 EFI_ACPI_TABLE_VERSION Version
;
84 // Scan all the acpi tables to find FADT 2.0
88 Status
= mAcpiSdt
->GetAcpiTable (
94 if (Status
== EFI_NOT_FOUND
) {
97 ASSERT_EFI_ERROR (Status
);
99 } while (CurrentTable
->Signature
!= EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE
|| CurrentTable
->Revision
!= 0x03);
101 ASSERT (CurrentTable
->Signature
== EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE
);
104 Status
= gBS
->AllocatePool (EfiBootServicesData
, CurrentTable
->Length
, (VOID
**) &Table
);
105 ASSERT (Table
!= NULL
);
106 CopyMem (Table
, CurrentTable
, CurrentTable
->Length
);
109 // Update the ACPI table and recalculate checksum
111 Status
= mAcpiTable
->UninstallAcpiTable (mAcpiTable
, Handle
);
112 if (EFI_ERROR (Status
)) {
114 // Should not get an error here ever, but abort if we do.
120 // Update the check sum
121 // It needs to be zeroed before the checksum calculation
123 ((EFI_ACPI_SDT_HEADER
*)Table
)->Checksum
= 0;
124 ((EFI_ACPI_SDT_HEADER
*)Table
)->Checksum
=
125 CalculateCheckSum8 ((VOID
*)Table
, Table
->Length
);
130 Status
= mAcpiTable
->InstallAcpiTable (
136 ASSERT_EFI_ERROR (Status
);
137 gBS
->FreePool (Table
);
142 IN OUT EFI_ACPI_DESCRIPTION_HEADER
*TableHeader
148 Update the SSDT table
152 Table - The SSDT table to be patched
165 // Loop through the ASL looking for values that we must fix up.
167 CurrPtr
= (UINT8
*) TableHeader
;
168 for (SsdtPointer
= CurrPtr
;
169 SsdtPointer
<= (CurrPtr
+ ((EFI_ACPI_COMMON_HEADER
*) CurrPtr
)->Length
);
173 Signature
= (UINT32
*) SsdtPointer
;
174 if ((*Signature
) == SIGNATURE_32 ('P', 'M', 'B', 'A')) {
175 switch (*(Signature
+1)) {
176 case (SIGNATURE_32 ('L', 'V', 'L', '0')):
177 Signature
[0] = PcdGet16(PcdPmbaIoBaseAddress
);
180 case (SIGNATURE_32 ('L', 'V', 'L', '2')):
181 Signature
[0] = PcdGet16(PcdPmbaIoLVL2
);
190 LocateSupportProtocol (
191 IN EFI_GUID
*Protocol
,
199 Locate the first instance of a protocol. If the protocol requested is an
200 FV protocol, then it will return the first FV that contains the ACPI table
205 Protocol The protocol to find.
206 Instance Return pointer to the first instance of the protocol
210 EFI_SUCCESS The function completed successfully.
211 EFI_NOT_FOUND The protocol could not be located.
212 EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol.
217 EFI_HANDLE
*HandleBuffer
;
218 UINTN NumberOfHandles
;
219 EFI_FV_FILETYPE FileType
;
221 EFI_FV_FILE_ATTRIBUTES Attributes
;
230 Status
= gBS
->LocateHandleBuffer (
237 if (EFI_ERROR (Status
)) {
240 // Defined errors at this time are not found and out of resources.
248 // Looking for FV with ACPI storage file
251 for (i
= 0; i
< NumberOfHandles
; i
++) {
253 // Get the protocol on this handle
254 // This should not fail because of LocateHandleBuffer
256 Status
= gBS
->HandleProtocol (
261 ASSERT_EFI_ERROR (Status
);
265 // Not looking for the FV protocol, so find the first instance of the
266 // protocol. There should not be any errors because our handle buffer
267 // should always contain at least one or LocateHandleBuffer would have
268 // returned not found.
274 // See if it has the ACPI storage file
277 Status
= ((EFI_FIRMWARE_VOLUME2_PROTOCOL
*) (*Instance
))->ReadFile (*Instance
,
278 &gPowerManagementAcpiTableStorageGuid
,
287 // If we found it, then we are done
289 if (Status
== EFI_SUCCESS
) {
295 // Our exit status is determined by the success of the previous operations
296 // If the protocol was found, Instance already points to it.
300 // Free any allocated buffers
302 gBS
->FreePool (HandleBuffer
);
308 This function is to load all the power management acpi tables and patch IST table.
311 PpmLoadAndPatchPMTables (
315 EFI_FIRMWARE_VOLUME2_PROTOCOL
*FwVol
;
318 EFI_ACPI_COMMON_HEADER
*CurrentTable
;
323 Status
= LocateSupportProtocol (&gEfiFirmwareVolume2ProtocolGuid
, (VOID
**)&FwVol
, 1);
324 if (EFI_ERROR (Status
)) {
329 // Read tables from the storage file.
334 while (Status
== EFI_SUCCESS
) {
336 Status
= FwVol
->ReadSection (
338 &gPowerManagementAcpiTableStorageGuid
,
341 (VOID
**)&CurrentTable
,
346 if (!EFI_ERROR(Status
)) {
347 SsdtTableUpdate ((EFI_ACPI_DESCRIPTION_HEADER
*) CurrentTable
);
350 // Update the check sum
351 // It needs to be zeroed before the checksum calculation
353 ((EFI_ACPI_SDT_HEADER
*)CurrentTable
)->Checksum
= 0;
354 ((EFI_ACPI_SDT_HEADER
*)CurrentTable
)->Checksum
= (UINT8
)
355 CalculateCheckSum8 ((VOID
*)CurrentTable
, CurrentTable
->Length
);
361 Status
= mAcpiTable
->InstallAcpiTable (
364 CurrentTable
->Length
,
368 ASSERT_EFI_ERROR (Status
);
371 // Increment the instance