+++ /dev/null
-/** @file\r
-\r
-Processor power management initialization code.\r
-\r
-Copyright (c) 2013-2016 Intel Corporation.\r
-\r
-SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-\r
-**/\r
-\r
-#include "SmmPowerManagement.h"\r
-\r
-//\r
-// Global variables\r
-//\r
-extern EFI_ACPI_SDT_PROTOCOL *mAcpiSdt;\r
-extern EFI_ACPI_TABLE_PROTOCOL *mAcpiTable;\r
-\r
-extern EFI_GUID gPowerManagementAcpiTableStorageGuid;\r
-\r
-/**\r
- This function is the entry of processor power management initialization code.\r
- It initializes the processor's power management features based on the user\r
- configurations and hardware capabilities.\r
-**/\r
-VOID\r
-PpmInit (\r
- VOID\r
- )\r
-{\r
- //\r
- // Processor Power Management Flags\r
- //\r
- mGlobalNvsAreaPtr->Cfgd = PcdGet32(PcdPpmFlags);\r
-\r
- //\r
- // Patch and publish power management related acpi tables\r
- //\r
- PpmPatchAndPublishAcpiTables();\r
-}\r
-\r
-/**\r
- This function is to patch and publish power management related acpi tables.\r
-**/\r
-VOID\r
-PpmPatchAndPublishAcpiTables (\r
- VOID\r
- )\r
-{\r
- //\r
- // Patch FADT table to enable C2,C3\r
- //\r
- PpmPatchFadtTable();\r
-\r
- //\r
- // Load all the power management acpi tables and patch IST table\r
- //\r
- PpmLoadAndPatchPMTables();\r
-}\r
-\r
-/**\r
- This function is to patch PLvl2Lat and PLvl3Lat to enable C2, C3 support in OS.\r
-**/\r
-VOID\r
-PpmPatchFadtTable (\r
- VOID\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_ACPI_DESCRIPTION_HEADER *Table;\r
- EFI_ACPI_SDT_HEADER *CurrentTable;\r
- EFI_ACPI_TABLE_VERSION Version;\r
- UINTN Index;\r
- UINTN Handle;\r
-\r
- //\r
- // Scan all the acpi tables to find FADT 2.0\r
- //\r
- Index = 0;\r
- do {\r
- Status = mAcpiSdt->GetAcpiTable (\r
- Index,\r
- &CurrentTable,\r
- &Version,\r
- &Handle\r
- );\r
- if (Status == EFI_NOT_FOUND) {\r
- break;\r
- }\r
- ASSERT_EFI_ERROR (Status);\r
- Index++;\r
- } while (CurrentTable->Signature != EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE || CurrentTable->Revision != 0x03);\r
-\r
- ASSERT (CurrentTable->Signature == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE);\r
-\r
- Table = NULL;\r
- Status = gBS->AllocatePool (EfiBootServicesData, CurrentTable->Length, (VOID **) &Table);\r
- ASSERT (Table != NULL);\r
- CopyMem (Table, CurrentTable, CurrentTable->Length);\r
-\r
- //\r
- // Update the ACPI table and recalculate checksum\r
- //\r
- Status = mAcpiTable->UninstallAcpiTable (mAcpiTable, Handle);\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // Should not get an error here ever, but abort if we do.\r
- //\r
- return ;\r
- }\r
-\r
- //\r
- // Update the check sum\r
- // It needs to be zeroed before the checksum calculation\r
- //\r
- ((EFI_ACPI_SDT_HEADER *)Table)->Checksum = 0;\r
- ((EFI_ACPI_SDT_HEADER *)Table)->Checksum =\r
- CalculateCheckSum8 ((VOID *)Table, Table->Length);\r
-\r
- //\r
- // Add the table\r
- //\r
- Status = mAcpiTable->InstallAcpiTable (\r
- mAcpiTable,\r
- Table,\r
- Table->Length,\r
- &Handle\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- gBS->FreePool (Table);\r
-}\r
-\r
-VOID\r
-SsdtTableUpdate (\r
- IN OUT EFI_ACPI_DESCRIPTION_HEADER *TableHeader\r
- )\r
-/*++\r
-\r
- Routine Description:\r
-\r
- Update the SSDT table\r
-\r
- Arguments:\r
-\r
- Table - The SSDT table to be patched\r
-\r
- Returns:\r
-\r
- None\r
-\r
---*/\r
-{\r
- UINT8 *CurrPtr;\r
- UINT8 *SsdtPointer;\r
- UINT32 *Signature;\r
-\r
- //\r
- // Loop through the ASL looking for values that we must fix up.\r
- //\r
- CurrPtr = (UINT8 *) TableHeader;\r
- for (SsdtPointer = CurrPtr;\r
- SsdtPointer <= (CurrPtr + ((EFI_ACPI_COMMON_HEADER *) CurrPtr)->Length);\r
- SsdtPointer++\r
- )\r
- {\r
- Signature = (UINT32 *) SsdtPointer;\r
- if ((*Signature) == SIGNATURE_32 ('P', 'M', 'B', 'A')) {\r
- switch (*(Signature+1)) {\r
- case (SIGNATURE_32 ('L', 'V', 'L', '0')):\r
- Signature[0] = PcdGet16(PcdPmbaIoBaseAddress);\r
- Signature[1] = 0;\r
- break;\r
- case (SIGNATURE_32 ('L', 'V', 'L', '2')):\r
- Signature[0] = PcdGet16(PcdPmbaIoLVL2);\r
- Signature[1] = 0;\r
- break;\r
- }\r
- }\r
- }\r
-}\r
-\r
-EFI_STATUS\r
-LocateSupportProtocol (\r
- IN EFI_GUID *Protocol,\r
- OUT VOID **Instance,\r
- IN UINT32 Type\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Locate the first instance of a protocol. If the protocol requested is an\r
- FV protocol, then it will return the first FV that contains the ACPI table\r
- storage file.\r
-\r
-Arguments:\r
-\r
- Protocol The protocol to find.\r
- Instance Return pointer to the first instance of the protocol\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS The function completed successfully.\r
- EFI_NOT_FOUND The protocol could not be located.\r
- EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol.\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- EFI_HANDLE *HandleBuffer;\r
- UINTN NumberOfHandles;\r
- EFI_FV_FILETYPE FileType;\r
- UINT32 FvStatus;\r
- EFI_FV_FILE_ATTRIBUTES Attributes;\r
- UINTN Size;\r
- UINTN i;\r
-\r
- FvStatus = 0;\r
-\r
- //\r
- // Locate protocol.\r
- //\r
- Status = gBS->LocateHandleBuffer (\r
- ByProtocol,\r
- Protocol,\r
- NULL,\r
- &NumberOfHandles,\r
- &HandleBuffer\r
- );\r
- if (EFI_ERROR (Status)) {\r
-\r
- //\r
- // Defined errors at this time are not found and out of resources.\r
- //\r
- return Status;\r
- }\r
-\r
-\r
-\r
- //\r
- // Looking for FV with ACPI storage file\r
- //\r
-\r
- for (i = 0; i < NumberOfHandles; i++) {\r
- //\r
- // Get the protocol on this handle\r
- // This should not fail because of LocateHandleBuffer\r
- //\r
- Status = gBS->HandleProtocol (\r
- HandleBuffer[i],\r
- Protocol,\r
- Instance\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- if (!Type) {\r
- //\r
- // Not looking for the FV protocol, so find the first instance of the\r
- // protocol. There should not be any errors because our handle buffer\r
- // should always contain at least one or LocateHandleBuffer would have\r
- // returned not found.\r
- //\r
- break;\r
- }\r
-\r
- //\r
- // See if it has the ACPI storage file\r
- //\r
-\r
- Status = ((EFI_FIRMWARE_VOLUME2_PROTOCOL*) (*Instance))->ReadFile (*Instance,\r
- &gPowerManagementAcpiTableStorageGuid,\r
- NULL,\r
- &Size,\r
- &FileType,\r
- &Attributes,\r
- &FvStatus\r
- );\r
-\r
- //\r
- // If we found it, then we are done\r
- //\r
- if (Status == EFI_SUCCESS) {\r
- break;\r
- }\r
- }\r
-\r
- //\r
- // Our exit status is determined by the success of the previous operations\r
- // If the protocol was found, Instance already points to it.\r
- //\r
-\r
- //\r
- // Free any allocated buffers\r
- //\r
- gBS->FreePool (HandleBuffer);\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- This function is to load all the power management acpi tables and patch IST table.\r
-**/\r
-VOID\r
-PpmLoadAndPatchPMTables (\r
- VOID\r
- )\r
-{\r
- EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;\r
- EFI_STATUS Status;\r
- INTN Instance;\r
- EFI_ACPI_COMMON_HEADER *CurrentTable;\r
- UINTN TableHandle;\r
- UINT32 FvStatus;\r
- UINTN Size;\r
-\r
- Status = LocateSupportProtocol (&gEfiFirmwareVolume2ProtocolGuid, (VOID**)&FwVol, 1);\r
- if (EFI_ERROR (Status)) {\r
- return;\r
- }\r
-\r
- //\r
- // Read tables from the storage file.\r
- //\r
- Instance = 0;\r
- CurrentTable = NULL;\r
-\r
- while (Status == EFI_SUCCESS) {\r
-\r
- Status = FwVol->ReadSection (\r
- FwVol,\r
- &gPowerManagementAcpiTableStorageGuid,\r
- EFI_SECTION_RAW,\r
- Instance,\r
- (VOID**)&CurrentTable,\r
- &Size,\r
- &FvStatus\r
- );\r
-\r
- if (!EFI_ERROR(Status)) {\r
- SsdtTableUpdate ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable);\r
-\r
- //\r
- // Update the check sum\r
- // It needs to be zeroed before the checksum calculation\r
- //\r
- ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum = 0;\r
- ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum = (UINT8)\r
- CalculateCheckSum8 ((VOID *)CurrentTable, CurrentTable->Length);\r
-\r
- //\r
- // Add the table\r
- //\r
- TableHandle = 0;\r
- Status = mAcpiTable->InstallAcpiTable (\r
- mAcpiTable,\r
- CurrentTable,\r
- CurrentTable->Length,\r
- &TableHandle\r
- );\r
-\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- //\r
- // Increment the instance\r
- //\r
- Instance++;\r
- CurrentTable = NULL;\r
- }\r
- }\r
-\r
-}\r