diff options
Diffstat (limited to 'ReferenceCode/AcpiTables/Cppc/Dxe')
-rw-r--r-- | ReferenceCode/AcpiTables/Cppc/Dxe/Cppc.c | 863 | ||||
-rw-r--r-- | ReferenceCode/AcpiTables/Cppc/Dxe/Cppc.dxs | 35 | ||||
-rw-r--r-- | ReferenceCode/AcpiTables/Cppc/Dxe/Cppc.h | 245 | ||||
-rw-r--r-- | ReferenceCode/AcpiTables/Cppc/Dxe/Cppc.inf | 91 | ||||
-rw-r--r-- | ReferenceCode/AcpiTables/Cppc/Dxe/CppcDxe.cif | 13 | ||||
-rw-r--r-- | ReferenceCode/AcpiTables/Cppc/Dxe/CppcDxe.mak | 96 | ||||
-rw-r--r-- | ReferenceCode/AcpiTables/Cppc/Dxe/CppcDxe.sdl | 30 |
7 files changed, 1373 insertions, 0 deletions
diff --git a/ReferenceCode/AcpiTables/Cppc/Dxe/Cppc.c b/ReferenceCode/AcpiTables/Cppc/Dxe/Cppc.c new file mode 100644 index 0000000..9da9b1a --- /dev/null +++ b/ReferenceCode/AcpiTables/Cppc/Dxe/Cppc.c @@ -0,0 +1,863 @@ +/** @file + This DXE driver configures and supports Collaborative Processor Performance Control (CPPC). + +@copyright + Copyright (c) 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement + +**/ +#include "Cppc.h" + +ACPI_PLATFORM_POLICY_PROTOCOL *mAcpiPlatformPolicyProtocol; + +extern EFI_RUNTIME_SERVICES *gRT; +extern EFI_BOOT_SERVICES *gBS; + +EFI_PHYSICAL_ADDRESS mCppcBaseAddressMem = 0; + +/// +/// Driver entry point +/// +EFI_DRIVER_ENTRY_POINT (InitializeCppc) + +EFI_STATUS +InitializeCppc ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/** +@brief + Cppc DXE support. + + @param[in] ImageHandle - Pointer to the loaded image protocol for this driver + @param[in] SystemTable - Pointer to the EFI System Table + + @retval EFI_SUCCESS - The driver installed/initialized correctly. +**/ +{ + EFI_STATUS Status; + VOID *MemoryPointer; + UINT64 MsrValue; + + gRT = SystemTable->RuntimeServices; + gBS = SystemTable->BootServices; + + /// + /// Initialize the EFI Runtime Library + /// + DxeInitializeDriverLib (ImageHandle, SystemTable); + + /// + /// S3 boot script + /// + INITIALIZE_SCRIPT (ImageHandle, SystemTable); + + /// + /// Locate platform configuration information and copy it to a global variable. + /// + Status = gBS->LocateProtocol ( + &gAcpiPlatformPolicyProtocolGuid, + NULL, + (VOID **) &mAcpiPlatformPolicyProtocol + ); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_ERROR, "CPPC: No Platform Policy Protocol available.\n")); + ASSERT_EFI_ERROR(Status); + return Status; + } else { + DEBUG ((EFI_D_ERROR, "CPPC: Platform Policy Protocol is loaded.\n")); + } + + /// + /// Enable or disable CPPC depending on platform policy. + /// + if (mAcpiPlatformPolicyProtocol->EnableCppc == 0) { + DEBUG ((EFI_D_ERROR, "CPPC is disabled by platform policy. \n")); + return EFI_SUCCESS; + } + + /// + /// Check if Haswell traditional, Haswell ULT or Crystal Well CPU. + /// + if(!(IsCpuSupported())){ + DEBUG ((EFI_D_ERROR, "CPPC not supported in this CPU. \n")); + return EFI_SUCCESS; + } + + /// + /// Check if Mobile CPU. + /// + if(!(IS_SA_DEVICE_ID_MOBILE (McD0PciCfg16 (R_SA_MC_DEVICE_ID)))) { + DEBUG ((EFI_D_ERROR, "CPPC not supported in this CPU. (not mobile) \n")); + return EFI_SUCCESS; + } + + /// + /// Check if processor supports EE Policy capability. + /// + MsrValue = EfiReadMsr (EFI_MSR_POWER_CTL); + if (((UINT32)MsrValue & BIT18) != BIT18) { + DEBUG ((EFI_D_ERROR, "CPPC not supported in this CPU. (no Energy Efficient Policy capability) \n")); + return EFI_SUCCESS; + } + + gST = SystemTable; + gDS = NULL; + Status = EfiGetSystemConfigurationTable (&gEfiDxeServicesTableGuid, (VOID**) &gDS); + + /// + /// Allocate 4kb of runtime memory. + /// + Status = (gBS->AllocatePool) (EfiACPIMemoryNVS, CPPC_SIZE, &MemoryPointer); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "CPPC: No Memory Buffer available.\n")); + ASSERT_EFI_ERROR(Status); + return Status; + } else { + mCppcBaseAddressMem = (EFI_PHYSICAL_ADDRESS) MemoryPointer; + ZeroMem ((VOID *)(UINTN)mCppcBaseAddressMem, CPPC_SIZE); + DEBUG((EFI_D_ERROR, "CPPC: PCCA memory buffer address: %x\n", mCppcBaseAddressMem)); + } + + /// + /// Add the Platform Communications Channel Table signature. + /// + CopyMem ((VOID *)(UINTN)mCppcBaseAddressMem, "PCC" , 3); + + /// + /// Load the SSDT Table for the CPPC ACPI objects. + /// + LoadAcpiTables (); + + /// + /// Load the ACPI 5.0 PCC Table. + /// + LoadAcpiTablesPcct (); + + /// + /// Load the ACPI 5.0 _CPC objects. + /// + LoadAcpiTablesCpc (); + + return EFI_SUCCESS; +} + +VOID +LoadAcpiTables( + VOID + ) +/** +@brief + This procedure loads the CPPC SSDT table. + + @param[in] None + + @retval None + +**/ +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN NumberOfHandles; + UINTN Index; + EFI_FIRMWARE_VOLUME_PROTOCOL *FwVol; + EFI_ACPI_TABLE_PROTOCOL *AcpiTable; + INTN Instance; + EFI_ACPI_COMMON_HEADER *Table; + UINTN Size; + EFI_FV_FILETYPE FileType; + EFI_FV_FILE_ATTRIBUTES Attributes; + UINT32 FvStatus; + EFI_ACPI_DESCRIPTION_HEADER *TableHeader; + UINTN TableHandle; + EFI_ACPI_TABLE_VERSION Version; + BOOLEAN LoadTable; + NAME_LAYOUT *NamePtr; + UINT8 *CurrPtr; + UINT32 *Signature; + UINT8 UpdateCounter; + + FwVol = NULL; + Table = NULL; + + /// + /// Locate FV protocol. + /// + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolumeProtocolGuid, + NULL, + &NumberOfHandles, + &HandleBuffer + ); + ASSERT_EFI_ERROR (Status); + + /// + /// Look for FV with ACPI storage file + /// + for (Index = 0; Index < NumberOfHandles; Index++) { + + /// + /// Get the protocol on this handle + /// This should not fail because of LocateHandleBuffer + /// + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiFirmwareVolumeProtocolGuid, + (VOID **) &FwVol + ); + ASSERT_EFI_ERROR (Status); + + if ((Status == EFI_SUCCESS) && (FwVol != NULL)) { + /// + /// See if it has the ACPI storage file + /// + Size = 0; + FvStatus = 0; + Status = FwVol->ReadFile ( + FwVol, + &gCppcAcpiTableStorageGuid, + 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 + /// + FreePool (HandleBuffer); + + /// + /// Sanity check that we found our data file + /// + ASSERT (FwVol); + if (FwVol == NULL) { + return; + } + + /// + /// By default, a table belongs in all ACPI table versions published. + /// + Version = EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0; + + /// + /// Find the Table protocol + /// + Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable); + + /// + /// Read tables from the storage file. + /// + Instance = 0; + + while (Status == EFI_SUCCESS) { + /// + /// Read the ACPI tables + /// + Status = FwVol->ReadSection ( + FwVol, + &gCppcAcpiTableStorageGuid, + EFI_SECTION_RAW, + Instance, + (VOID **) &Table, + &Size, + &FvStatus + ); + + if (!EFI_ERROR (Status)) { + + LoadTable = FALSE; + TableHeader = (EFI_ACPI_DESCRIPTION_HEADER *) Table; + + switch (((EFI_ACPI_DESCRIPTION_HEADER*) TableHeader)->OemTableId) { + + case EFI_SIGNATURE_64 ('C', 'p', 'p', 'c', 'T', 'a', 'b', 'l'): + /// + /// This is Cppc SSDT. Cppc should be enabled if we reach here so load the table. + /// + LoadTable = TRUE; + DEBUG ((EFI_D_ERROR, "CPPC: Found Cppc SSDT signature.\n")); + + UpdateCounter = 3; // Number of objects to initialize. + for (CurrPtr = (UINT8 *) TableHeader; ((CurrPtr <= ((UINT8 *) TableHeader + TableHeader->Length))) && UpdateCounter !=0; CurrPtr++) { + Signature = (UINT32 *) (CurrPtr + 1); + /// + /// Patch PCCA with the address of the CPPC shared memory buffer. + /// + if ((*CurrPtr == AML_NAME_OP) && (*Signature == EFI_SIGNATURE_32 ('P', 'C', 'C', 'A'))) { + NamePtr = (NAME_LAYOUT *) CurrPtr; + if (mCppcBaseAddressMem != 0){ + NamePtr->Value = (UINT32) mCppcBaseAddressMem; + } + UpdateCounter--; + DEBUG((EFI_D_ERROR, "CPPC: PCCA pointer updated in SSDT: %x\n", mCppcBaseAddressMem)); + } + /// + /// Patch PCCS with the size of the CPPC shared memory buffer. + /// + if ((*CurrPtr == AML_NAME_OP) && (*Signature == EFI_SIGNATURE_32 ('P', 'C', 'C', 'S'))) { + NamePtr = (NAME_LAYOUT *) CurrPtr; + NamePtr->Value = (UINT32) CPPC_SIZE; + UpdateCounter--; + DEBUG((EFI_D_ERROR, "CPPC: PCCS length updated in SSDT: %x\n", CPPC_SIZE)); + } + /// + /// Patch PENB with the CPPC Enable/Disable Flag. + /// + if ((*CurrPtr == AML_NAME_OP) && (*Signature == EFI_SIGNATURE_32 ('P', 'E', 'N', 'B'))) { + NamePtr = (NAME_LAYOUT *) CurrPtr; + NamePtr->Value = (UINT32) mAcpiPlatformPolicyProtocol->EnableCppc; + UpdateCounter--; + DEBUG((EFI_D_ERROR, "CPPC: PENB updated in SSDT: %x\n", (UINT32) mAcpiPlatformPolicyProtocol->EnableCppc)); + } + } + break; + + default: + break; + } + + /// + /// Add the table + /// + if (LoadTable) { + TableHandle = 0; + Status = AcpiTable->InstallAcpiTable ( + AcpiTable, + Table, + Table->Length, + &TableHandle + ); + } + + /// + /// Increment the instance + /// + Instance++; + Table = NULL; + } + } +} + +VOID +LoadAcpiTablesPcct( + VOID + ) +/** +@brief + This procedure loads the ACPI 5.0 PCCT table. + + @param[in] None + + @retval None + +**/ +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN NumberOfHandles; + UINTN Index; + EFI_FIRMWARE_VOLUME_PROTOCOL *FwVol; + EFI_ACPI_TABLE_PROTOCOL *AcpiTable; + INTN Instance; + EFI_ACPI_COMMON_HEADER *Table; + UINTN Size; + EFI_FV_FILETYPE FileType; + EFI_FV_FILE_ATTRIBUTES Attributes; + UINT32 FvStatus; + EFI_ACPI_DESCRIPTION_HEADER *TableHeader; + UINTN TableHandle; + EFI_ACPI_TABLE_VERSION Version; + BOOLEAN LoadTable; + EFI_ACPI_5_0_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER *PcctHeaderPtr; + EFI_ACPI_5_0_PCCT_SUBSPACE_GENERIC *PcctPtr; + UINT8 *CurrPtr; + UINT32 *Signature; + UINT8 UpdateCounter; + + FwVol = NULL; + Table = NULL; + + /// + /// Locate FV protocol. + /// + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolumeProtocolGuid, + NULL, + &NumberOfHandles, + &HandleBuffer + ); + ASSERT_EFI_ERROR (Status); + + /// + /// Look for FV with ACPI storage file + /// + for (Index = 0; Index < NumberOfHandles; Index++) { + + /// + /// Get the protocol on this handle + /// This should not fail because of LocateHandleBuffer + /// + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiFirmwareVolumeProtocolGuid, + (VOID **) &FwVol + ); + ASSERT_EFI_ERROR (Status); + + if ((Status == EFI_SUCCESS) && (FwVol != NULL)) { + /// + /// See if it has the ACPI storage file + /// + Size = 0; + FvStatus = 0; + Status = FwVol->ReadFile ( + FwVol, + &gCppcAcpiTableStorageGuid, + 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 + /// + FreePool (HandleBuffer); + + /// + /// Sanity check that we found our data file + /// + ASSERT (FwVol); + if (FwVol == NULL) { + return; + } + + /// + /// By default, a table belongs in all ACPI table versions published. + /// + Version = EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0; + + /// + /// Find the Table protocol + /// + Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable); + + /// + /// Read tables from the storage file. + /// + Instance = 0; + + while (Status == EFI_SUCCESS) { + /// + /// Read the ACPI tables + /// + Status = FwVol->ReadSection ( + FwVol, + &gCppcAcpiTableStorageGuid, + EFI_SECTION_RAW, + Instance, + (VOID **) &Table, + &Size, + &FvStatus + ); + + if (!EFI_ERROR (Status)) { + + LoadTable = FALSE; + TableHeader = (EFI_ACPI_DESCRIPTION_HEADER *) Table; + + switch (((EFI_ACPI_DESCRIPTION_HEADER*) TableHeader)->OemTableId) { + + case EFI_SIGNATURE_64 ('P', 'c', 'c', 't', 'T', 'a', 'b', 'l'): + /// + /// This is PCCT. Cppc should be enabled if we reach here so load the table. + /// + LoadTable = TRUE; + DEBUG ((EFI_D_ERROR, "PCCT: Found PCCT signature.\n")); + + UpdateCounter = 1; /// Number of objects to initialize. + for (CurrPtr = (UINT8 *) TableHeader; ((CurrPtr <= ((UINT8 *) TableHeader + TableHeader->Length))) && UpdateCounter !=0; CurrPtr++) { + Signature = (UINT32 *) (CurrPtr + 1); + /// + /// Patch the EFI_ACPI_5_0_PCCT_SUBSPACE_GENERIC structure. + /// + if ((*CurrPtr == AML_NAME_OP) && (*Signature == EFI_SIGNATURE_32 ('P', 'C', 'C', 'T'))) { + CurrPtr -= sizeof (EFI_ACPI_DESCRIPTION_HEADER); // backup the current pointer in order to use the PCCT header structure + PcctHeaderPtr = (EFI_ACPI_5_0_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER *) CurrPtr; + PcctHeaderPtr->Flags = (UINT32) mAcpiPlatformPolicyProtocol->EnableCppcPlatformSCI; + PcctHeaderPtr->Reserved = 0; + + CurrPtr += sizeof (EFI_ACPI_5_0_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER); + PcctPtr = (EFI_ACPI_5_0_PCCT_SUBSPACE_GENERIC *) CurrPtr; + PcctPtr->Type = 0x0; + PcctPtr->Length = 62; + PcctPtr->BaseAddress = mCppcBaseAddressMem; /// Shared memory address + PcctPtr->AddressLength = CPPC_SIZE; /// sizeof(Shared memory) in bytes + + PcctPtr->DoorbellRegister.AddressSpaceId = 1; /// IO address type + PcctPtr->DoorbellRegister.RegisterBitWidth = 8; /// byte + PcctPtr->DoorbellRegister.RegisterBitOffset = 0x0; /// offset=0 + PcctPtr->DoorbellRegister.AccessSize = 1; /// byte access + PcctPtr->DoorbellRegister.Address = MmioRead16 (MmPciExpressAddress (0,0, PCI_DEV_NUM_ICH_LPC, 0, R_ACPI_BAR)) &~BIT0; + PcctPtr->DoorbellRegister.Address += R_ACPI_GPE_CNTL; /// PMBASE + GPE_CNTL register offset + PcctPtr->DoorbellPreserve = 0xFD; /// preserve all bits except bit 1 + PcctPtr->DoorbellWrite = 2; /// write bit 1 = 1 to trigger GPE + PcctPtr->NominalLatency = 5000; /// 5ms + PcctPtr->MaximumPeriodicAccessRate = 0x0; + PcctPtr->MinimumRequestTurnaroundTime = 0x0; + + UpdateCounter--; + DEBUG((EFI_D_ERROR, "PCCT: Patch the EFI_ACPI_5_0_PCCT_SUBSPACE_GENERIC structure.\n")); + } + } + break; + + default: + break; + } + + /// + /// Add the table + /// + if (LoadTable) { + TableHandle = 0; + Status = AcpiTable->InstallAcpiTable ( + AcpiTable, + Table, + Table->Length, + &TableHandle + ); + } + + /// + /// Increment the instance + /// + Instance++; + Table = NULL; + } + } +} + +VOID +LoadAcpiTablesCpc( + VOID + ) +/** +@brief + Load ACPI SSDT tables. + + @param[in] None + + @retval None + +**/ +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN NumberOfHandles; + UINTN Index; + EFI_FIRMWARE_VOLUME_PROTOCOL *FwVol; + EFI_ACPI_TABLE_PROTOCOL *AcpiTable; + INTN Instance; + EFI_ACPI_COMMON_HEADER *Table; + UINTN Size; + EFI_FV_FILETYPE FileType; + EFI_FV_FILE_ATTRIBUTES Attributes; + UINT32 FvStatus; + EFI_ACPI_DESCRIPTION_HEADER *TableHeader; + UINTN TableHandle; + EFI_ACPI_TABLE_VERSION Version; + BOOLEAN LoadTable; + + FwVol = NULL; + Table = NULL; + + /// + /// Locate FV protocol. + /// + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolumeProtocolGuid, + NULL, + &NumberOfHandles, + &HandleBuffer + ); + ASSERT_EFI_ERROR (Status); + + /// + /// Look for FV with ACPI storage file + /// + for (Index = 0; Index < NumberOfHandles; Index++) { + + /// + /// Get the protocol on this handle + /// This should not fail because of LocateHandleBuffer + /// + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiFirmwareVolumeProtocolGuid, + (VOID **) &FwVol + ); + ASSERT_EFI_ERROR (Status); + + if ((Status == EFI_SUCCESS) && (FwVol != NULL)) { + /// + /// See if it has the ACPI storage file + /// + Size = 0; + FvStatus = 0; + Status = FwVol->ReadFile ( + FwVol, + &gCppcAcpiTableStorageGuid, + 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 + /// + FreePool (HandleBuffer); + + /// + /// Sanity check that we found our data file + /// + ASSERT (FwVol); + if (FwVol == NULL) { + return; + } + + /// + /// By default, a table belongs in all ACPI table versions published. + /// + Version = EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0; + + /// + /// Find the Table protocol + /// + Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable); + + /// + /// Read tables from the storage file. + /// + Instance = 0; + + while (Status == EFI_SUCCESS) { + /// + /// Read the ACPI tables + /// + Status = FwVol->ReadSection ( + FwVol, + &gCppcAcpiTableStorageGuid, + EFI_SECTION_RAW, + Instance, + (VOID **) &Table, + &Size, + &FvStatus + ); + + if (!EFI_ERROR (Status)) { + + LoadTable = FALSE; + TableHeader = (EFI_ACPI_DESCRIPTION_HEADER *) Table; + + switch (((EFI_ACPI_DESCRIPTION_HEADER*) TableHeader)->OemTableId) { + + case EFI_SIGNATURE_64 ('C', 'p', 'c', '_', 'T', 'a', 'b', 'l'): + /// + /// This is the _CPC SSDT. Cppc should be enabled if we reach here so load the table. + /// + LoadTable = TRUE; + DEBUG ((EFI_D_ERROR, "CPPC: Found _CPC SSDT signature.\n")); + break; + + default: + break; + } + + /// + /// Add the table + /// + if (LoadTable) { + TableHandle = 0; + Status = AcpiTable->InstallAcpiTable ( + AcpiTable, + Table, + Table->Length, + &TableHandle + ); + } + + /// + /// Increment the instance + /// + Instance++; + Table = NULL; + } + } +} + +EFI_STATUS +LocateSupportProtocol ( + IN EFI_GUID *Protocol, + OUT VOID **Instance, + IN BOOLEAN Type + ) +/** + @brief + 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. + + @param[in] The protocol to find. + @param[in] Return pointer to the first instance of the protocol + @param[in] TRUE if the desired protocol is a FV protocol + + @retval EFI_SUCCESS - The function completed successfully. + @retval EFI_NOT_FOUND - The protocol could not be located. + @retval 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; + + /// + /// 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 + /// + Size = 0; + FvStatus = 0; + Status = ((EFI_FIRMWARE_VOLUME_PROTOCOL *) (*Instance))->ReadFile ( + *Instance, + &gCppcAcpiTableStorageGuid, + 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 + /// + FreePool (HandleBuffer); + + return Status; +} diff --git a/ReferenceCode/AcpiTables/Cppc/Dxe/Cppc.dxs b/ReferenceCode/AcpiTables/Cppc/Dxe/Cppc.dxs new file mode 100644 index 0000000..d1df44e --- /dev/null +++ b/ReferenceCode/AcpiTables/Cppc/Dxe/Cppc.dxs @@ -0,0 +1,35 @@ +/** @file + Dependency expression source file. + +@copyright + Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement + +**/ + + +#include "EfiDepex.h" +#include EFI_PROTOCOL_DEPENDENCY (CpuIo) +#include EFI_PROTOCOL_DEPENDENCY (AcpiSupport) +#include EFI_PROTOCOL_DEPENDENCY (AcpiPlatformPolicy) +#include EFI_PROTOCOL_DEPENDENCY (PowerMgmtInitDone) + +DEPENDENCY_START + EFI_CPU_IO_PROTOCOL_GUID AND + EFI_ACPI_SUPPORT_GUID AND + ACPI_PLATFORM_POLICY_PROTOCOL_GUID AND + EFI_POWER_MGMT_INIT_DONE_PROTOCOL_GUID +DEPENDENCY_END diff --git a/ReferenceCode/AcpiTables/Cppc/Dxe/Cppc.h b/ReferenceCode/AcpiTables/Cppc/Dxe/Cppc.h new file mode 100644 index 0000000..289fe93 --- /dev/null +++ b/ReferenceCode/AcpiTables/Cppc/Dxe/Cppc.h @@ -0,0 +1,245 @@ +/** @file + Header file for the Collaborative Processor Performance Control (CPPC) driver. + +@copyright + Copyright (c) 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement +**/ + +#ifndef _CPPC_H_ +#define _CPPC_H_ + +#include "EdkIIGlueBase.h" +#include "EdkIIGlueDxe.h" +#include "EfiScriptLib.h" +#include "Acpi.h" +#include "SaAccess.h" +#include "CpuAccess.h" +#include "CpuPlatformLib.h" +/// +/// Consumed protocols +/// +#include EFI_PROTOCOL_DEPENDENCY (AcpiTable) +#include EFI_PROTOCOL_DEPENDENCY (FirmwareVolume) +#include EFI_PROTOCOL_CONSUMER (PciRootBridgeIo) +#include EFI_PROTOCOL_DEFINITION (AcpiPlatformPolicy) + +#define CPPC_SIZE 0x1000 /// 4kb of runtime memory for CPPC shared memory buffer +#define PCI_DEV_NUM_ICH_LPC 31 /// ICH is Device 31 +#define R_ACPI_BAR 0x40 /// ACPI Base Address Register +#define R_ACPI_GPE_CNTL 0x42 /// GPE control register offset +#define CPUID_FULL_FAMILY_MODEL_HASWELL 0x000306C0 +#define EFI_MSR_POWER_CTL 0x000001FC + +/// +/// SSDT data storage file +/// +#include "CppcAcpiTableStorage.h" + +/// +/// AML parsing definitions +/// +#define AML_NAME_OP 0x08 + +/// +/// ASL NAME structure +/// +#pragma pack(1) +typedef struct { + UINT8 NameOp; // Byte [0]=0x08:NameOp. + UINT32 NameString; // Byte [4:1]=Name of object. + UINT8 DWordPrefix; // Byte [5]=0x0C:DWord Prefix. + UINT32 Value; // Byte [9:6] ; Value of named object. +} NAME_LAYOUT; +#pragma pack() + +/// +/// ACPI 5.0 Generic Address Space definition +/// +#pragma pack(1) +typedef struct { + UINT8 AddressSpaceId; + UINT8 RegisterBitWidth; + UINT8 RegisterBitOffset; + UINT8 AccessSize; + UINT64 Address; +} EFI_ACPI_5_0_GENERIC_ADDRESS_STRUCTURE; +#pragma pack() + +/// +/// Platform Communications Channel Table (PCCT) +/// +#pragma pack(1) +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 Flags; + UINT64 Reserved; +} EFI_ACPI_5_0_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER; +#pragma pack() + +/// +/// Generic Communications Subspace Structure +/// +#pragma pack(1) +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Reserved[6]; + UINT64 BaseAddress; + UINT64 AddressLength; + EFI_ACPI_5_0_GENERIC_ADDRESS_STRUCTURE DoorbellRegister; + UINT64 DoorbellPreserve; + UINT64 DoorbellWrite; + UINT32 NominalLatency; + UINT32 MaximumPeriodicAccessRate; + UINT16 MinimumRequestTurnaroundTime; +} EFI_ACPI_5_0_PCCT_SUBSPACE_GENERIC; +#pragma pack() + +/// +/// UINT64 workaround +/// +/// The MS compiler doesn't handle QWORDs very well. I'm breaking +/// them into DWORDs to circumvent the problems. Converting back +/// shouldn't be a big deal. +/// +#pragma pack(1) +typedef union _MSR_REGISTER { + UINT64 Qword; + + struct _DWORDS { + UINT32 Low; + UINT32 High; + } Dwords; + + struct _BYTES { + UINT8 FirstByte; + UINT8 SecondByte; + UINT8 ThirdByte; + UINT8 FouthByte; + UINT8 FifthByte; + UINT8 SixthByte; + UINT8 SeventhByte; + UINT8 EighthByte; + } Bytes; + +} MSR_REGISTER; +#pragma pack() + +#ifndef BIT63 +#define BIT0 0x0001 +#define BIT1 0x0002 +#define BIT2 0x0004 +#define BIT3 0x0008 +#define BIT4 0x0010 +#define BIT5 0x0020 +#define BIT6 0x0040 +#define BIT7 0x0080 +#define BIT8 0x0100 +#define BIT9 0x0200 +#define BIT10 0x0400 +#define BIT11 0x0800 +#define BIT12 0x1000 +#define BIT13 0x2000 +#define BIT14 0x4000 +#define BIT15 0x8000 +#define BIT16 0x00010000 +#define BIT17 0x00020000 +#define BIT18 0x00040000 +#define BIT19 0x00080000 +#define BIT20 0x00100000 +#define BIT21 0x00200000 +#define BIT22 0x00400000 +#define BIT23 0x00800000 +#define BIT24 0x01000000 +#define BIT25 0x02000000 +#define BIT26 0x04000000 +#define BIT27 0x08000000 +#define BIT28 0x10000000 +#define BIT29 0x20000000 +#define BIT30 0x40000000 +#define BIT31 0x80000000 +#define BIT32 0x100000000 +#define BIT33 0x200000000 +#define BIT34 0x400000000 +#define BIT35 0x800000000 +#define BIT36 0x1000000000 +#define BIT37 0x2000000000 +#define BIT38 0x4000000000 +#define BIT39 0x8000000000 +#define BIT40 0x10000000000 +#define BIT41 0x20000000000 +#define BIT42 0x40000000000 +#define BIT43 0x80000000000 +#define BIT44 0x100000000000 +#define BIT45 0x200000000000 +#define BIT46 0x400000000000 +#define BIT47 0x800000000000 +#define BIT48 0x1000000000000 +#define BIT49 0x2000000000000 +#define BIT50 0x4000000000000 +#define BIT51 0x8000000000000 +#define BIT52 0x10000000000000 +#define BIT53 0x20000000000000 +#define BIT54 0x40000000000000 +#define BIT55 0x80000000000000 +#define BIT56 0x100000000000000 +#define BIT57 0x200000000000000 +#define BIT58 0x400000000000000 +#define BIT59 0x800000000000000 +#define BIT60 0x1000000000000000 +#define BIT61 0x2000000000000000 +#define BIT62 0x4000000000000000 +#define BIT63 0x8000000000000000 +#endif + +#define MmPciExpressAddress(Segment, Bus, Device, Function, Register) \ + ( (UINTN) (PciRead32 (PCI_LIB_ADDRESS (0,0,0,0x60)) & 0xFC000000) + \ + (UINTN) (Bus << 20) + \ + (UINTN) (Device << 15) + \ + (UINTN) (Function << 12) + \ + (UINTN) (Register) \ + ) + +EFI_STATUS +InitializeCppc ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +VOID +LoadAcpiTables( + VOID + ); + +VOID +LoadAcpiTablesPcct( + VOID + ); + +VOID +LoadAcpiTablesCpc( + VOID + ); + +EFI_STATUS +LocateSupportProtocol ( + IN EFI_GUID *Protocol, + OUT VOID **Instance, + IN BOOLEAN Type + ); + +#endif diff --git a/ReferenceCode/AcpiTables/Cppc/Dxe/Cppc.inf b/ReferenceCode/AcpiTables/Cppc/Dxe/Cppc.inf new file mode 100644 index 0000000..731cf82 --- /dev/null +++ b/ReferenceCode/AcpiTables/Cppc/Dxe/Cppc.inf @@ -0,0 +1,91 @@ +## @file +# Component description file for Cppc module +# +#@copyright +# Copyright (c) 2012 Intel Corporation. All rights reserved +# This software and associated documentation (if any) is furnished +# under a license and may only be used or copied in accordance +# with the terms of the license. Except as permitted by such +# license, no part of this software or documentation may be +# reproduced, stored in a retrieval system, or transmitted in any +# form or by any means without the express written consent of +# Intel Corporation. +# +# This file contains an 'Intel Peripheral Driver' and uniquely +# identified as "Intel Reference Module" and is +# licensed for Intel CPUs and chipsets under the terms of your +# license agreement with Intel or your vendor. This file may +# be modified by the user, subject to additional terms of the +# license agreement +# + + +[defines] +BASE_NAME = Cppc +FILE_GUID = C07A1EB5-5C04-4100-817B-0A11BB5F15DC +COMPONENT_TYPE = RT_DRIVER + +[sources.common] + Cppc.h + Cppc.c + +[includes.common] + $(EFI_SOURCE)/$(PROJECT_ACPI_ROOT) + $(EFI_SOURCE)/$(PROJECT_ACPI_ROOT)/Cppc + $(EFI_SOURCE)/$(PROJECT_ACPI_ROOT)/Cppc/Guid/AcpiTableStorage + . + $(EDK_SOURCE)/Sample/Chipset/PcCompatible + $(EDK_SOURCE)/Foundation + $(EDK_SOURCE)/Foundation/Include + $(EDK_SOURCE)/Foundation/Efi + $(EDK_SOURCE)/Foundation/Efi/Include + $(EDK_SOURCE)/Foundation/Framework + $(EDK_SOURCE)/Foundation/Framework/Include + $(EDK_SOURCE)/Include/IndustryStandard + $(EDK_SOURCE)/Foundation/Include/IndustryStandard + $(EDK_SOURCE)/Foundation/Core/Dxe + $(EDK_SOURCE)/Foundation/Core/Dxe/ArchProtocol/Cpu + $(EDK_SOURCE)/Foundation/Library/Dxe/Include + $(EFI_SOURCE) + $(EFI_SOURCE)/Framework + $(EFI_SOURCE)/Include + $(EFI_SOURCE)/Include/IndustryStandard + $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include/Pcd + $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include + $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include/Library + $(EDK_SOURCE)/Foundation/Cpu/Pentium/Include + $(EFI_SOURCE)/$(PROJECT_CPU_ROOT) + $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include + $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include/Library + $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Library/CpuPlatformLib + $(EFI_SOURCE)/$(PROJECT_SA_ROOT)/Include + +[libraries.common] + EdkIIGlueDxeMemoryAllocationLib + EdkIIGlueBaseLib + EdkIIGlueDxeReportStatusCodeLib + EdkIIGlueDxeDebugLibReportStatusCode + EdkProtocolLib + EfiProtocolLib + EfiDriverLib + ArchProtocolLib + EdkFrameworkProtocolLib + EdkIIGlueBasePciExpressLib + EdkIIGlueUefiLib + EfiScriptLib + AcpiProtocolLib + CpuProtocolLib + CpuPlatformLib + CppcGuidLib + +[nmake.common] + IMAGE_ENTRY_POINT = InitializeCppc + DPX_SOURCE = Cppc.dxs +# +# Module Entry Point +# + C_FLAGS = $(C_FLAGS) -D"__EDKII_GLUE_MODULE_ENTRY_POINT__=InitializeCppc" \ + -D __EDKII_GLUE_BASE_LIB__ \ + -D __EDKII_GLUE_DXE_REPORT_STATUS_CODE_LIB__ \ + -D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ + diff --git a/ReferenceCode/AcpiTables/Cppc/Dxe/CppcDxe.cif b/ReferenceCode/AcpiTables/Cppc/Dxe/CppcDxe.cif new file mode 100644 index 0000000..5379e0e --- /dev/null +++ b/ReferenceCode/AcpiTables/Cppc/Dxe/CppcDxe.cif @@ -0,0 +1,13 @@ +<component> + name = "CppcDxe" + category = ModulePart + LocalRoot = "ReferenceCode\AcpiTables\Cppc\Dxe\" + RefName = "CppcDxe" +[files] +"CppcDxe.sdl" +"CppcDxe.mak" +"Cppc.c" +"Cppc.dxs" +"Cppc.h" +"Cppc.inf" +<endComponent> diff --git a/ReferenceCode/AcpiTables/Cppc/Dxe/CppcDxe.mak b/ReferenceCode/AcpiTables/Cppc/Dxe/CppcDxe.mak new file mode 100644 index 0000000..a318f31 --- /dev/null +++ b/ReferenceCode/AcpiTables/Cppc/Dxe/CppcDxe.mak @@ -0,0 +1,96 @@ +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2012, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* + +#************************************************************************* +#<AMI_FHDR_START> +# +# Name: CppcDxe.mak +# +# Description: Make file to build Intel CPPC components +# +#<AMI_FHDR_END> +#************************************************************************* +EDK : CppcDxe + +CppcDxe : $(BUILD_DIR)\CppcDxe.mak CppcDxeBin + +CppcDxe_OBJECTS = \ +$(BUILD_DIR)\$(INTEL_CPPC_DXE_DIR)\Cppc.obj + +$(BUILD_DIR)\CppcDxe.mak : $(INTEL_CPPC_DXE_DIR)\$(@B).cif $(INTEL_CPPC_DXE_DIR)\$(@B).mak $(BUILD_RULES) + $(CIF2MAK) $(INTEL_CPPC_DXE_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) + +CppcDxe_LIBS =\ + $(EdkIIGlueDxeMemoryAllocationLib_LIB)\ + $(EDKPROTOCOLLIB)\ + $(EFIPROTOCOLLIB)\ + $(ARCHPROTOCOLLIB)\ + $(EDKFRAMEWORKPROTOCOLLIB)\ + $(EFISCRIPTLIB)\ + $(EdkIIGlueBaseLib_LIB)\ + $(EdkIIGlueBasePciExpressLib_LIB)\ + $(EdkIIGlueUefiLib_LIB)\ +!IF "$(x64_BUILD)"=="1" + $(EdkIIGlueBaseLibX64_LIB)\ +!ELSE + $(EdkIIGlueBaseLibIA32_LIB)\ +!ENDIF + $(EdkIIGlueDxeReportStatusCodeLib_LIB)\ + $(EdkIIGlueDxeServicesTableLib_LIB)\ + $(EdkIIGlueDxeDebugLibReportStatusCode_LIB)\ + $(EdkIIGlueDxeHobLib_LIB)\ + $(EdkIIGlueBasePciLibPciExpress_LIB)\ + $(EFIDRIVERLIB)\ + $(AcpiProtocolLib_LIB)\ + $(CppcGuidLib_LIB)\ + $(CpuProtocolLib_LIB)\ + $(CpuPlatformLib_LIB)\ + $(PchPlatformDxeLib_LIB)\ + +CppcDxe_INCLUDES= $(EDK_INCLUDES)\ + $(IndustryStandard_INCLUDES)\ + $(EdkIIGlueLib_INCLUDES)\ + $(CPPC_INCLUDES)\ + /I ReferenceCode\AcpiTables\ + /I$(ArchProtocolLib_DIR)\Cpu\ + $(PROJECT_CPU_INCLUDES)\ + /I$(PROJECT_CPU_ROOT)\Library\CpuPlatformLib\ + /I$(INTEL_SYSTEM_AGENT_DIR)\Include\ + +CppcDxeBin: $(CppcDxe_LIBS) + $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\ + /f $(BUILD_DIR)\CppcDxe.mak all \ + NAME=CppcDxe\ + MAKEFILE=$(BUILD_DIR)\CppcDxe.mak \ + "MY_INCLUDES=$(CppcDxe_INCLUDES)"\ + GUID=C07A1EB5-5C04-4100-817B-0A11BB5F15DC\ + ENTRY_POINT=InitializeCppc \ + TYPE=RT_DRIVER\ + "OBJECTS=$(CppcDxe_OBJECTS)"\ + DEPEX1=$(INTEL_CPPC_DXE_DIR)\Cppc.dxs\ + DEPEX1_TYPE=EFI_SECTION_DXE_DEPEX\ + COMPRESS=1 +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2012, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#*************************************************************************
\ No newline at end of file diff --git a/ReferenceCode/AcpiTables/Cppc/Dxe/CppcDxe.sdl b/ReferenceCode/AcpiTables/Cppc/Dxe/CppcDxe.sdl new file mode 100644 index 0000000..164ab26 --- /dev/null +++ b/ReferenceCode/AcpiTables/Cppc/Dxe/CppcDxe.sdl @@ -0,0 +1,30 @@ +TOKEN + Name = "CppcDxe_SUPPORT" + Value = "1" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes + Help = "Main switch to enable CppcDxe support in Project" +End + +MODULE + Help = "Includes CppcDxe.mak to Project" + File = "CppcDxe.mak" +End + +PATH + Name = "INTEL_CPPC_DXE_DIR" +End + +ELINK + Name = "/I$(INTEL_CPPC_DXE_DIR)" + Parent = "CPPC_INCLUDES" + InvokeOrder = AfterParent +End + +ELINK + Name = "$(BUILD_DIR)\CppcDxe.ffs" + Parent = "FV_MAIN" + InvokeOrder = AfterParent +End |