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