diff options
Diffstat (limited to 'ReferenceCode/AcpiTables/Cppc/Dxe/Cppc.c')
-rw-r--r-- | ReferenceCode/AcpiTables/Cppc/Dxe/Cppc.c | 863 |
1 files changed, 863 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; +} |