3 Processor power management initialization code.
5 Copyright (c) 2013-2015 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
;
82 EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE
*FadtPointer
;
85 // Scan all the acpi tables to find FADT 2.0
89 Status
= mAcpiSdt
->GetAcpiTable (
95 if (Status
== EFI_NOT_FOUND
) {
98 ASSERT_EFI_ERROR (Status
);
100 } while (CurrentTable
->Signature
!= EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE
|| CurrentTable
->Revision
!= 0x03);
102 ASSERT (CurrentTable
->Signature
== EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE
);
105 Status
= gBS
->AllocatePool (EfiBootServicesData
, CurrentTable
->Length
, (VOID
**) &Table
);
106 ASSERT (Table
!= NULL
);
107 CopyMem (Table
, CurrentTable
, CurrentTable
->Length
);
109 FadtPointer
= (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE
*) Table
;
112 // Update the ACPI table and recalculate checksum
114 Status
= mAcpiTable
->UninstallAcpiTable (mAcpiTable
, Handle
);
115 if (EFI_ERROR (Status
)) {
117 // Should not get an error here ever, but abort if we do.
123 // Update the check sum
124 // It needs to be zeroed before the checksum calculation
126 ((EFI_ACPI_SDT_HEADER
*)Table
)->Checksum
= 0;
127 ((EFI_ACPI_SDT_HEADER
*)Table
)->Checksum
=
128 CalculateCheckSum8 ((VOID
*)Table
, Table
->Length
);
133 Status
= mAcpiTable
->InstallAcpiTable (
139 ASSERT_EFI_ERROR (Status
);
140 gBS
->FreePool (Table
);
145 IN OUT EFI_ACPI_DESCRIPTION_HEADER
*TableHeader
151 Update the SSDT table
155 Table - The SSDT table to be patched
168 // Loop through the ASL looking for values that we must fix up.
170 CurrPtr
= (UINT8
*) TableHeader
;
171 for (SsdtPointer
= CurrPtr
;
172 SsdtPointer
<= (CurrPtr
+ ((EFI_ACPI_COMMON_HEADER
*) CurrPtr
)->Length
);
176 Signature
= (UINT32
*) SsdtPointer
;
177 if ((*Signature
) == SIGNATURE_32 ('P', 'M', 'B', 'A')) {
178 switch (*(Signature
+1)) {
179 case (SIGNATURE_32 ('L', 'V', 'L', '0')):
180 Signature
[0] = PcdGet16(PcdPmbaIoBaseAddress
);
183 case (SIGNATURE_32 ('L', 'V', 'L', '2')):
184 Signature
[0] = PcdGet16(PcdPmbaIoLVL2
);
193 LocateSupportProtocol (
194 IN EFI_GUID
*Protocol
,
202 Locate the first instance of a protocol. If the protocol requested is an
203 FV protocol, then it will return the first FV that contains the ACPI table
208 Protocol The protocol to find.
209 Instance Return pointer to the first instance of the protocol
213 EFI_SUCCESS The function completed successfully.
214 EFI_NOT_FOUND The protocol could not be located.
215 EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol.
220 EFI_HANDLE
*HandleBuffer
;
221 UINTN NumberOfHandles
;
222 EFI_FV_FILETYPE FileType
;
224 EFI_FV_FILE_ATTRIBUTES Attributes
;
233 Status
= gBS
->LocateHandleBuffer (
240 if (EFI_ERROR (Status
)) {
243 // Defined errors at this time are not found and out of resources.
251 // Looking for FV with ACPI storage file
254 for (i
= 0; i
< NumberOfHandles
; i
++) {
256 // Get the protocol on this handle
257 // This should not fail because of LocateHandleBuffer
259 Status
= gBS
->HandleProtocol (
264 ASSERT_EFI_ERROR (Status
);
268 // Not looking for the FV protocol, so find the first instance of the
269 // protocol. There should not be any errors because our handle buffer
270 // should always contain at least one or LocateHandleBuffer would have
271 // returned not found.
277 // See if it has the ACPI storage file
280 Status
= ((EFI_FIRMWARE_VOLUME2_PROTOCOL
*) (*Instance
))->ReadFile (*Instance
,
281 &gPowerManagementAcpiTableStorageGuid
,
290 // If we found it, then we are done
292 if (Status
== EFI_SUCCESS
) {
298 // Our exit status is determined by the success of the previous operations
299 // If the protocol was found, Instance already points to it.
303 // Free any allocated buffers
305 gBS
->FreePool (HandleBuffer
);
311 This function is to load all the power management acpi tables and patch IST table.
314 PpmLoadAndPatchPMTables (
318 EFI_FIRMWARE_VOLUME2_PROTOCOL
*FwVol
;
321 EFI_ACPI_COMMON_HEADER
*CurrentTable
;
325 EFI_ACPI_TABLE_VERSION Version
;
327 Status
= LocateSupportProtocol (&gEfiFirmwareVolume2ProtocolGuid
, (VOID
**)&FwVol
, 1);
328 if (EFI_ERROR (Status
)) {
333 // Read tables from the storage file.
338 while (Status
== EFI_SUCCESS
) {
340 Status
= FwVol
->ReadSection (
342 &gPowerManagementAcpiTableStorageGuid
,
345 (VOID
**)&CurrentTable
,
350 if (!EFI_ERROR(Status
)) {
351 Version
= EFI_ACPI_TABLE_VERSION_1_0B
| EFI_ACPI_TABLE_VERSION_2_0
| EFI_ACPI_TABLE_VERSION_3_0
;
353 if(((EFI_ACPI_DESCRIPTION_HEADER
*) CurrentTable
)->OemTableId
== SIGNATURE_64 ('C', 'p', 'u', '0', 'I', 's', 't', 0)) {
354 Version
= EFI_ACPI_TABLE_VERSION_NONE
;
355 } else if(((EFI_ACPI_DESCRIPTION_HEADER
*) CurrentTable
)->OemTableId
== SIGNATURE_64 ('C', 'p', 'u', '1', 'I', 's', 't', 0)) {
356 Version
= EFI_ACPI_TABLE_VERSION_NONE
;
359 SsdtTableUpdate ((EFI_ACPI_DESCRIPTION_HEADER
*) CurrentTable
);
362 // Update the check sum
363 // It needs to be zeroed before the checksum calculation
365 ((EFI_ACPI_SDT_HEADER
*)CurrentTable
)->Checksum
= 0;
366 ((EFI_ACPI_SDT_HEADER
*)CurrentTable
)->Checksum
= (UINT8
)
367 CalculateCheckSum8 ((VOID
*)CurrentTable
, CurrentTable
->Length
);
373 Status
= mAcpiTable
->InstallAcpiTable (
376 CurrentTable
->Length
,
380 ASSERT_EFI_ERROR (Status
);
383 // Increment the instance