From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
To: Dandan Bi <dandan.bi@intel.com>,
Leif Lindholm <leif.lindholm@linaro.org>
Cc: "edk2-devel@lists.01.org" <edk2-devel@lists.01.org>,
Star Zeng <star.zeng@intel.com>,
Liming Gao <liming.gao@intel.com>,
Matt Sealey <neko@bakuhatsu.net>
Subject: Re: [PATCH v2 3/8] MdeModulePkg/DxeCorePerformanceLib:Track FPDT record in DXE phase
Date: Tue, 1 May 2018 18:26:55 +0200 [thread overview]
Message-ID: <CAKv+Gu8eUd7S4or41HAiUfb49ROVzJ+xaZG3nq8C_EKktNc=gA@mail.gmail.com> (raw)
In-Reply-To: <1517320437-11688-4-git-send-email-dandan.bi@intel.com>
On 30 January 2018 at 14:53, Dandan Bi <dandan.bi@intel.com> wrote:
> V2:
> Update DxecorePerformanceLib to report the boot performance table
> address instead of records contents.
>
> Updated to convert Pref entry to FPDT record in DXE phase and then
> allocate boot performance table to save the record and report
> the address of boot performance table to FirmwarePerformanceDxe.
>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Star Zeng <star.zeng@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Dandan Bi <dandan.bi@intel.com>
> ---
> .../DxeCorePerformanceLib/DxeCorePerformanceLib.c | 1389 +++++++++++++++-----
> .../DxeCorePerformanceLib.inf | 20 +-
> .../DxeCorePerformanceLibInternal.h | 17 +-
> 3 files changed, 1108 insertions(+), 318 deletions(-)
>
> diff --git a/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c b/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c
> index 7c0e207..c6f8a16 100644
> --- a/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c
> +++ b/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c
> @@ -8,11 +8,11 @@
> which are consumed by DxePerformanceLib to logging performance data in DXE phase.
>
> This library is mainly used by DxeCore to start performance logging to ensure that
> Performance Protocol is installed at the very beginning of DXE phase.
>
> -Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
> (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
> This program and the accompanying materials
> are licensed and made available under the terms and conditions of the BSD License
> which accompanies this distribution. The full text of the license may be found at
> http://opensource.org/licenses/bsd-license.php
> @@ -23,27 +23,65 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> **/
>
>
> #include "DxeCorePerformanceLibInternal.h"
>
> -
> //
> -// The data structure to hold global performance data.
> +// Data for FPDT performance records.
> //
> -GAUGE_DATA_HEADER *mGaugeData;
> +#define SMM_BOOT_RECORD_COMM_SIZE (OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data) + sizeof(SMM_BOOT_RECORD_COMMUNICATE))
> +#define STRING_SIZE (EDKII_STRING_EVENT_RECORD_NAME_LENGTH * sizeof (CHAR8))
> +#define MAX_RECORD_SIZE (sizeof (DYNAMIC_STRING_EVENT_RECORD) + STRING_SIZE)
> +#define FIRMWARE_RECORD_BUFFER 0x10000
> +#define CACHE_HANDLE_GUID_COUNT 0x1000
> +
> +BOOT_PERFORMANCE_TABLE *mAcpiBootPerformanceTable = NULL;
> +BOOT_PERFORMANCE_TABLE mBootPerformanceTableTemplate = {
> + {
> + EFI_ACPI_5_0_FPDT_BOOT_PERFORMANCE_TABLE_SIGNATURE,
> + sizeof (BOOT_PERFORMANCE_TABLE)
> + },
> + {
> + {
> + EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_TYPE_FIRMWARE_BASIC_BOOT, // Type
> + sizeof (EFI_ACPI_5_0_FPDT_FIRMWARE_BASIC_BOOT_RECORD), // Length
> + EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_REVISION_FIRMWARE_BASIC_BOOT // Revision
> + },
> + 0, // Reserved
> + //
> + // These values will be updated at runtime.
> + //
> + 0, // ResetEnd
> + 0, // OsLoaderLoadImageStart
> + 0, // OsLoaderStartImageStart
> + 0, // ExitBootServicesEntry
> + 0 // ExitBootServicesExit
> + }
> +};
>
> -//
> -// The current maximum number of logging entries. If current number of
> -// entries exceeds this value, it will re-allocate a larger array and
> -// migration the old data to the larger array.
> -//
> -UINT32 mMaxGaugeRecords;
> +typedef struct {
> + EFI_HANDLE Handle;
> + CHAR8 NameString[EDKII_STRING_EVENT_RECORD_NAME_LENGTH];
> + EFI_GUID ModuleGuid;
> +} HANDLE_GUID_MAP;
>
> -//
> -// The handle to install Performance Protocol instance.
> -//
> -EFI_HANDLE mHandle = NULL;
> +HANDLE_GUID_MAP mCacheHandleGuidTable[CACHE_HANDLE_GUID_COUNT];
> +UINTN mCachePairCount = 0;
> +
> +UINT32 mLoadImageCount = 0;
> +UINT32 mPerformanceLength = 0;
> +UINT32 mMaxPerformanceLength = 0;
> +UINT32 mBootRecordSize = 0;
> +UINT32 mBootRecordMaxSize = 0;
> +
> +BOOLEAN mFpdtBufferIsReported = FALSE;
> +BOOLEAN mLackSpaceIsReported = FALSE;
> +CHAR8 *mPlatformLanguage = NULL;
> +UINT8 *mPerformancePointer = NULL;
> +UINT8 *mBootRecordBuffer = NULL;
> +
> +EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *mDevicePathToText = NULL;
>
> //
> // Interfaces for Performance Protocol.
> //
> PERFORMANCE_PROTOCOL mPerformanceInterface = {
> @@ -61,179 +99,1069 @@ PERFORMANCE_EX_PROTOCOL mPerformanceExInterface = {
> GetGaugeEx
> };
>
> PERFORMANCE_PROPERTY mPerformanceProperty;
>
> -//
> -// Gauge record lock to avoid data corruption or even memory overflow
> -//
> -STATIC EFI_LOCK mPerfRecordLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);
> +/**
> +Check whether the Token is a known one which is uesed by core.
> +
> +@param Token Pointer to a Null-terminated ASCII string
> +
> +@retval TRUE Is a known one used by core.
> +@retval FALSE Not a known one.
> +
> +**/
> +BOOLEAN
> +IsKnownTokens (
> + IN CONST CHAR8 *Token
> + )
> +{
> + if (AsciiStrCmp (Token, SEC_TOK) == 0 ||
> + AsciiStrCmp (Token, PEI_TOK) == 0 ||
> + AsciiStrCmp (Token, DXE_TOK) == 0 ||
> + AsciiStrCmp (Token, BDS_TOK) == 0 ||
> + AsciiStrCmp (Token, DRIVERBINDING_START_TOK) == 0 ||
> + AsciiStrCmp (Token, DRIVERBINDING_SUPPORT_TOK) == 0 ||
> + AsciiStrCmp (Token, DRIVERBINDING_STOP_TOK) == 0 ||
> + AsciiStrCmp (Token, LOAD_IMAGE_TOK) == 0 ||
> + AsciiStrCmp (Token, START_IMAGE_TOK) == 0 ||
> + AsciiStrCmp (Token, PEIM_TOK) == 0) {
> + return TRUE;
> + } else {
> + return FALSE;
> + }
> +}
> +
> +/**
> +Check whether the ID is a known one which map to the known Token.
> +
> +@param Identifier 32-bit identifier.
> +
> +@retval TRUE Is a known one used by core.
> +@retval FALSE Not a known one.
> +
> +**/
> +BOOLEAN
> +IsKnownID (
> + IN UINT32 Identifier
> + )
> +{
> + if (Identifier == MODULE_START_ID ||
> + Identifier == MODULE_END_ID ||
> + Identifier == MODULE_LOADIMAGE_START_ID ||
> + Identifier == MODULE_LOADIMAGE_END_ID ||
> + Identifier == MODULE_DB_START_ID ||
> + Identifier == MODULE_DB_END_ID ||
> + Identifier == MODULE_DB_SUPPORT_START_ID ||
> + Identifier == MODULE_DB_SUPPORT_END_ID ||
> + Identifier == MODULE_DB_STOP_START_ID ||
> + Identifier == MODULE_DB_STOP_END_ID) {
> + return TRUE;
> + } else {
> + return FALSE;
> + }
> +}
>
> /**
> - Searches in the gauge array with keyword Handle, Token, Module and Identifier.
> + Allocate EfiReservedMemoryType below 4G memory address.
> +
> + This function allocates EfiReservedMemoryType below 4G memory address.
> +
> + @param[in] Size Size of memory to allocate.
> +
> + @return Allocated address for output.
> +
> +**/
> +VOID *
> +FpdtAllocateReservedMemoryBelow4G (
> + IN UINTN Size
> + )
> +{
> + UINTN Pages;
> + EFI_PHYSICAL_ADDRESS Address;
> + EFI_STATUS Status;
> + VOID *Buffer;
> +
> + Buffer = NULL;
> + Pages = EFI_SIZE_TO_PAGES (Size);
> + Address = 0xffffffff;
> +
> + Status = gBS->AllocatePages (
> + AllocateMaxAddress,
> + EfiReservedMemoryType,
> + Pages,
> + &Address
> + );
> + ASSERT_EFI_ERROR (Status);
This code is breaking DEBUG builds on ARM systems that have no memory
below 4 GB.
> +
> + if (!EFI_ERROR (Status)) {
> + Buffer = (VOID *) (UINTN) Address;
> + ZeroMem (Buffer, Size);
> + }
> +
> + return Buffer;
> +}
> +
> +/**
> + Allocate buffer for Boot Performance table.
> +
> + @return Status code.
> +
> +**/
> +EFI_STATUS
> +AllocateBootPerformanceTable (
> + )
> +{
> + EFI_STATUS Status;
> + UINTN Size;
> + UINT8 *SmmBootRecordCommBuffer;
> + EFI_SMM_COMMUNICATE_HEADER *SmmCommBufferHeader;
> + SMM_BOOT_RECORD_COMMUNICATE *SmmCommData;
> + UINTN CommSize;
> + UINTN BootPerformanceDataSize;
> + UINT8 *BootPerformanceData;
> + EFI_SMM_COMMUNICATION_PROTOCOL *Communication;
> + FIRMWARE_PERFORMANCE_VARIABLE PerformanceVariable;
> + EDKII_PI_SMM_COMMUNICATION_REGION_TABLE *SmmCommRegionTable;
> + EFI_MEMORY_DESCRIPTOR *SmmCommMemRegion;
> + UINTN Index;
> + VOID *SmmBootRecordData;
> + UINTN SmmBootRecordDataSize;
> + UINTN ReservedMemSize;
> +
> + //
> + // Collect boot records from SMM drivers.
> + //
> + SmmBootRecordCommBuffer = NULL;
> + SmmCommData = NULL;
> + SmmBootRecordData = NULL;
> + SmmBootRecordDataSize = 0;
> + ReservedMemSize = 0;
> + Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &Communication);
> + if (!EFI_ERROR (Status)) {
> + //
> + // Initialize communicate buffer
> + // Get the prepared Reserved Memory Range
> + //
> + Status = EfiGetSystemConfigurationTable (
> + &gEdkiiPiSmmCommunicationRegionTableGuid,
> + (VOID **) &SmmCommRegionTable
> + );
> + if (!EFI_ERROR (Status)) {
> + ASSERT (SmmCommRegionTable != NULL);
> + SmmCommMemRegion = (EFI_MEMORY_DESCRIPTOR *) (SmmCommRegionTable + 1);
> + for (Index = 0; Index < SmmCommRegionTable->NumberOfEntries; Index ++) {
> + if (SmmCommMemRegion->Type == EfiConventionalMemory) {
> + break;
> + }
> + SmmCommMemRegion = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) SmmCommMemRegion + SmmCommRegionTable->DescriptorSize);
> + }
> + ASSERT (Index < SmmCommRegionTable->NumberOfEntries);
> + ASSERT (SmmCommMemRegion->PhysicalStart > 0);
> + ASSERT (SmmCommMemRegion->NumberOfPages > 0);
> + ReservedMemSize = (UINTN) SmmCommMemRegion->NumberOfPages * EFI_PAGE_SIZE;
> +
> + //
> + // Check enough reserved memory space
> + //
> + if (ReservedMemSize > SMM_BOOT_RECORD_COMM_SIZE) {
> + SmmBootRecordCommBuffer = (VOID *) (UINTN) SmmCommMemRegion->PhysicalStart;
> + SmmCommBufferHeader = (EFI_SMM_COMMUNICATE_HEADER*)SmmBootRecordCommBuffer;
> + SmmCommData = (SMM_BOOT_RECORD_COMMUNICATE*)SmmCommBufferHeader->Data;
> + ZeroMem((UINT8*)SmmCommData, sizeof(SMM_BOOT_RECORD_COMMUNICATE));
> +
> + CopyGuid (&SmmCommBufferHeader->HeaderGuid, &gEfiFirmwarePerformanceGuid);
> + SmmCommBufferHeader->MessageLength = sizeof(SMM_BOOT_RECORD_COMMUNICATE);
> + CommSize = SMM_BOOT_RECORD_COMM_SIZE;
> +
> + //
> + // Get the size of boot records.
> + //
> + SmmCommData->Function = SMM_FPDT_FUNCTION_GET_BOOT_RECORD_SIZE;
> + SmmCommData->BootRecordData = NULL;
> + Status = Communication->Communicate (Communication, SmmBootRecordCommBuffer, &CommSize);
> + ASSERT_EFI_ERROR (Status);
> +
> + if (!EFI_ERROR (SmmCommData->ReturnStatus) && SmmCommData->BootRecordSize != 0) {
> + //
> + // Get all boot records
> + //
> + SmmCommData->Function = SMM_FPDT_FUNCTION_GET_BOOT_RECORD_DATA_BY_OFFSET;
> + SmmBootRecordDataSize = SmmCommData->BootRecordSize;
> + SmmBootRecordData = AllocateZeroPool(SmmBootRecordDataSize);
> + ASSERT (SmmBootRecordData != NULL);
> + SmmCommData->BootRecordOffset = 0;
> + SmmCommData->BootRecordData = (VOID *) ((UINTN) SmmCommMemRegion->PhysicalStart + SMM_BOOT_RECORD_COMM_SIZE);
> + SmmCommData->BootRecordSize = ReservedMemSize - SMM_BOOT_RECORD_COMM_SIZE;
> + while (SmmCommData->BootRecordOffset < SmmBootRecordDataSize) {
> + Status = Communication->Communicate (Communication, SmmBootRecordCommBuffer, &CommSize);
> + ASSERT_EFI_ERROR (Status);
> + ASSERT_EFI_ERROR(SmmCommData->ReturnStatus);
> + if (SmmCommData->BootRecordOffset + SmmCommData->BootRecordSize > SmmBootRecordDataSize) {
> + CopyMem ((UINT8 *) SmmBootRecordData + SmmCommData->BootRecordOffset, SmmCommData->BootRecordData, SmmBootRecordDataSize - SmmCommData->BootRecordOffset);
> + } else {
> + CopyMem ((UINT8 *) SmmBootRecordData + SmmCommData->BootRecordOffset, SmmCommData->BootRecordData, SmmCommData->BootRecordSize);
> + }
> + SmmCommData->BootRecordOffset = SmmCommData->BootRecordOffset + SmmCommData->BootRecordSize;
> + }
> + }
> + }
> + }
> + }
> +
> + //
> + // Prepare memory for Boot Performance table.
> + // Boot Performance table includes BasicBoot record, and one or more appended Boot Records.
> + //
> + BootPerformanceDataSize = sizeof (BOOT_PERFORMANCE_TABLE) + mPerformanceLength + PcdGet32 (PcdExtFpdtBootRecordPadSize);
> + if (SmmCommData != NULL) {
> + BootPerformanceDataSize += SmmBootRecordDataSize;
> + }
> +
> + //
> + // Try to allocate the same runtime buffer as last time boot.
> + //
> + ZeroMem (&PerformanceVariable, sizeof (PerformanceVariable));
> + Size = sizeof (PerformanceVariable);
> + Status = gRT->GetVariable (
> + EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME,
> + &gEfiFirmwarePerformanceGuid,
> + NULL,
> + &Size,
> + &PerformanceVariable
> + );
> + if (!EFI_ERROR (Status)) {
> + Status = gBS->AllocatePages (
> + AllocateAddress,
> + EfiReservedMemoryType,
> + EFI_SIZE_TO_PAGES (BootPerformanceDataSize),
> + &PerformanceVariable.BootPerformanceTablePointer
> + );
> + if (!EFI_ERROR (Status)) {
> + mAcpiBootPerformanceTable = (BOOT_PERFORMANCE_TABLE *) (UINTN) PerformanceVariable.BootPerformanceTablePointer;
> + }
> + }
> +
> + if (mAcpiBootPerformanceTable == NULL) {
> + //
> + // Fail to allocate at specified address, continue to allocate at any address.
> + //
> + mAcpiBootPerformanceTable = (BOOT_PERFORMANCE_TABLE *) FpdtAllocateReservedMemoryBelow4G (BootPerformanceDataSize);
Why does this allocation need to live below 4 GB?
If there is no good reason, can we please get rid of this?
If there is a good reason, can we please document it in the code?
> + }
> + DEBUG ((DEBUG_INFO, "DxeCorePerformanceLib: ACPI Boot Performance Table address = 0x%x\n", mAcpiBootPerformanceTable));
> +
> + if (mAcpiBootPerformanceTable == NULL) {
> + if (SmmCommData != NULL && SmmBootRecordData != NULL) {
> + FreePool (SmmBootRecordData);
> + }
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + //
> + // Prepare Boot Performance Table.
> + //
> + BootPerformanceData = (UINT8 *) mAcpiBootPerformanceTable;
> + //
> + // Fill Basic Boot record to Boot Performance Table.
> + //
> + CopyMem (mAcpiBootPerformanceTable, &mBootPerformanceTableTemplate, sizeof (mBootPerformanceTableTemplate));
> + BootPerformanceData = BootPerformanceData + mAcpiBootPerformanceTable->Header.Length;
> + //
> + // Fill Boot records from boot drivers.
> + //
> + if (mPerformancePointer != NULL) {
> + CopyMem (BootPerformanceData, mPerformancePointer, mPerformanceLength);
> + mAcpiBootPerformanceTable->Header.Length += mPerformanceLength;
> + BootPerformanceData = BootPerformanceData + mPerformanceLength;
> + }
> + if (SmmCommData != NULL && SmmBootRecordData != NULL) {
> + //
> + // Fill Boot records from SMM drivers.
> + //
> + CopyMem (BootPerformanceData, SmmBootRecordData, SmmBootRecordDataSize);
> + FreePool (SmmBootRecordData);
> + mAcpiBootPerformanceTable->Header.Length = (UINT32) (mAcpiBootPerformanceTable->Header.Length + SmmBootRecordDataSize);
> + BootPerformanceData = BootPerformanceData + SmmBootRecordDataSize;
> + }
> +
> + //
> + // Save Boot Performance Table address to Variable for use in S4 resume.
> + //
> + PerformanceVariable.BootPerformanceTablePointer = (EFI_PHYSICAL_ADDRESS) (UINTN) mAcpiBootPerformanceTable;
> +
> + //
> + // Save Runtime Performance Table pointers to Variable.
> + // Don't check SetVariable return status. It doesn't impact FPDT table generation.
> + //
> + gRT->SetVariable (
> + EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME,
> + &gEfiFirmwarePerformanceGuid,
> + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
> + sizeof (PerformanceVariable),
> + &PerformanceVariable
> + );
> +
> + mBootRecordBuffer = (UINT8 *) mAcpiBootPerformanceTable;
> + mBootRecordSize = mAcpiBootPerformanceTable->Header.Length;
> + mBootRecordMaxSize = mBootRecordSize + PcdGet32 (PcdExtFpdtBootRecordPadSize);
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Get a human readable module name and module guid for the given image handle.
> + If module name can't be found, "" string will return.
> + If module guid can't be found, Zero Guid will return.
> +
> + @param Handle Image handle or Controller handle.
> + @param NameString The ascii string will be filled into it. If not found, null string will return.
> + @param BufferSize Size of the input NameString buffer.
> + @param ModuleGuid Point to the guid buffer to store the got module guid value.
> +
> + @retval EFI_SUCCESS Successfully get module name and guid.
> + @retval EFI_INVALID_PARAMETER The input parameter NameString is NULL.
> + @retval other value Module Name can't be got.
> +**/
> +EFI_STATUS
> +GetModuleInfoFromHandle (
> + IN EFI_HANDLE Handle,
> + OUT CHAR8 *NameString,
> + IN UINTN BufferSize,
> + OUT EFI_GUID *ModuleGuid OPTIONAL
> + )
> +{
> + EFI_STATUS Status;
> + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
> + EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
> + CHAR8 *PdbFileName;
> + EFI_GUID *TempGuid;
> + UINTN StartIndex;
> + UINTN Index;
> + INTN Count;
> + BOOLEAN ModuleGuidIsGet;
> + UINTN StringSize;
> + CHAR16 *StringPtr;
> + EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2;
> + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFilePath;
> +
> + if (NameString == NULL || BufferSize == 0) {
> + return EFI_INVALID_PARAMETER;
> + }
> + //
> + // Try to get the ModuleGuid and name string form the caached array.
> + //
> + if (mCachePairCount > 0) {
> + for (Count = mCachePairCount -1; Count >= 0; Count--) {
> + if (Handle == mCacheHandleGuidTable[Count].Handle) {
> + CopyGuid (ModuleGuid, &mCacheHandleGuidTable[Count].ModuleGuid);
> + AsciiStrCpyS (NameString, EDKII_STRING_EVENT_RECORD_NAME_LENGTH, mCacheHandleGuidTable[Count].NameString);
> + return EFI_SUCCESS;
> + }
> + }
> + }
> +
> + Status = EFI_INVALID_PARAMETER;
> + LoadedImage = NULL;
> + ModuleGuidIsGet = FALSE;
> +
> + //
> + // Initialize GUID as zero value.
> + //
> + TempGuid = &gZeroGuid;
> + //
> + // Initialize it as "" string.
> + //
> + NameString[0] = 0;
> +
> + if (Handle != NULL) {
> + //
> + // Try Handle as ImageHandle.
> + //
> + Status = gBS->HandleProtocol (
> + Handle,
> + &gEfiLoadedImageProtocolGuid,
> + (VOID**) &LoadedImage
> + );
> +
> + if (EFI_ERROR (Status)) {
> + //
> + // Try Handle as Controller Handle
> + //
> + Status = gBS->OpenProtocol (
> + Handle,
> + &gEfiDriverBindingProtocolGuid,
> + (VOID **) &DriverBinding,
> + NULL,
> + NULL,
> + EFI_OPEN_PROTOCOL_GET_PROTOCOL
> + );
> + if (!EFI_ERROR (Status)) {
> + //
> + // Get Image protocol from ImageHandle
> + //
> + Status = gBS->HandleProtocol (
> + DriverBinding->ImageHandle,
> + &gEfiLoadedImageProtocolGuid,
> + (VOID**) &LoadedImage
> + );
> + }
> + }
> + }
> +
> + if (!EFI_ERROR (Status) && LoadedImage != NULL) {
> + //
> + // Get Module Guid from DevicePath.
> + //
> + if (LoadedImage->FilePath != NULL &&
> + LoadedImage->FilePath->Type == MEDIA_DEVICE_PATH &&
> + LoadedImage->FilePath->SubType == MEDIA_PIWG_FW_FILE_DP
> + ) {
> + //
> + // Determine GUID associated with module logging performance
> + //
> + ModuleGuidIsGet = TRUE;
> + FvFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LoadedImage->FilePath;
> + TempGuid = &FvFilePath->FvFileName;
> + }
> +
> + //
> + // Method 1 Get Module Name from PDB string.
> + //
> + PdbFileName = PeCoffLoaderGetPdbPointer (LoadedImage->ImageBase);
> + if (PdbFileName != NULL && BufferSize > 0) {
> + StartIndex = 0;
> + for (Index = 0; PdbFileName[Index] != 0; Index++) {
> + if ((PdbFileName[Index] == '\\') || (PdbFileName[Index] == '/')) {
> + StartIndex = Index + 1;
> + }
> + }
> + //
> + // Copy the PDB file name to our temporary string.
> + // If the length is bigger than BufferSize, trim the redudant characters to avoid overflow in array boundary.
> + //
> + for (Index = 0; Index < BufferSize - 1; Index++) {
> + NameString[Index] = PdbFileName[Index + StartIndex];
> + if (NameString[Index] == 0 || NameString[Index] == '.') {
> + NameString[Index] = 0;
> + break;
> + }
> + }
>
> - This internal function searches for the gauge entry in the gauge array.
> - If there is an entry that exactly matches the given keywords
> - and its end time stamp is zero, then the index of that gauge entry is returned;
> - otherwise, the the number of gauge entries in the array is returned.
> + if (Index == BufferSize - 1) {
> + NameString[Index] = 0;
> + }
> + //
> + // Module Name is got.
> + //
> + goto Done;
> + }
> + }
>
> + //
> + // Method 2: Get the name string from ComponentName2 protocol
> + //
> + Status = gBS->HandleProtocol (
> + Handle,
> + &gEfiComponentName2ProtocolGuid,
> + (VOID **) &ComponentName2
> + );
> + if (!EFI_ERROR (Status)) {
> + //
> + // Get the current platform language setting
> + //
> + if (mPlatformLanguage == NULL) {
> + GetEfiGlobalVariable2 (L"PlatformLang", (VOID **) &mPlatformLanguage, NULL);
> + }
> + if (mPlatformLanguage != NULL) {
> + Status = ComponentName2->GetDriverName (
> + ComponentName2,
> + mPlatformLanguage != NULL ? mPlatformLanguage : "en-US",
> + &StringPtr
> + );
> + if (!EFI_ERROR (Status)) {
> + for (Index = 0; Index < BufferSize - 1 && StringPtr[Index] != 0; Index++) {
> + NameString[Index] = (CHAR8) StringPtr[Index];
> + }
> + NameString[Index] = 0;
> + //
> + // Module Name is got.
> + //
> + goto Done;
> + }
> + }
> + }
> +
> + if (ModuleGuidIsGet) {
> + //
> + // Method 3 Try to get the image's FFS UI section by image GUID
> + //
> + StringPtr = NULL;
> + StringSize = 0;
> + Status = GetSectionFromAnyFv (
> + TempGuid,
> + EFI_SECTION_USER_INTERFACE,
> + 0,
> + (VOID **) &StringPtr,
> + &StringSize
> + );
> +
> + if (!EFI_ERROR (Status)) {
> + //
> + // Method 3. Get the name string from FFS UI section
> + //
> + for (Index = 0; Index < BufferSize - 1 && StringPtr[Index] != 0; Index++) {
> + NameString[Index] = (CHAR8) StringPtr[Index];
> + }
> + NameString[Index] = 0;
> + FreePool (StringPtr);
> + }
> + }
> +
> +Done:
> + //
> + // Copy Module Guid
> + //
> + if (ModuleGuid != NULL) {
> + CopyGuid (ModuleGuid, TempGuid);
> + if (IsZeroGuid(TempGuid) && (Handle != NULL) && !ModuleGuidIsGet) {
> + // Handle is GUID
> + CopyGuid (ModuleGuid, (EFI_GUID *) Handle);
> + }
> + }
> +
> + //
> + // Cache the Handle and Guid pairs.
> + //
> + if (mCachePairCount < CACHE_HANDLE_GUID_COUNT) {
> + mCacheHandleGuidTable[mCachePairCount].Handle = Handle;
> + CopyGuid (&mCacheHandleGuidTable[mCachePairCount].ModuleGuid, ModuleGuid);
> + AsciiStrCpyS (mCacheHandleGuidTable[mCachePairCount].NameString, EDKII_STRING_EVENT_RECORD_NAME_LENGTH, NameString);
> + mCachePairCount ++;
> + }
> +
> + return Status;
> +}
> +
> +/**
> + Get the FPDT record info.
> +
> + @param IsStart TRUE if the performance log is start log.
> @param Handle Pointer to environment specific context used
> to identify the component being measured.
> @param Token Pointer to a Null-terminated ASCII string
> that identifies the component being measured.
> @param Module Pointer to a Null-terminated ASCII string
> that identifies the module being measured.
> - @param Identifier 32-bit identifier.
> + @param RecordInfo On return, pointer to the info of the record.
> + @param UseModuleName Only useful for DYNAMIC_STRING_EVENT_TYPE, indicate that whether need use
> + Module name to fill the string field in the DYNAMIC_STRING_EVENT_RECORD.
>
> - @retval The index of gauge entry in the array.
> + @retval EFI_SUCCESS Get record info successfully.
> + @retval EFI_UNSUPPORTED No matched FPDT record.
>
> **/
> -UINT32
> -InternalSearchForGaugeEntry (
> - IN CONST VOID *Handle, OPTIONAL
> - IN CONST CHAR8 *Token, OPTIONAL
> - IN CONST CHAR8 *Module, OPTIONAL
> - IN UINT32 Identifier
> +EFI_STATUS
> +GetFpdtRecordInfo (
> + IN BOOLEAN IsStart,
> + IN CONST VOID *Handle,
> + IN CONST CHAR8 *Token,
> + IN CONST CHAR8 *Module,
> + OUT BASIC_RECORD_INFO *RecordInfo,
> + IN OUT BOOLEAN *UseModuleName
> )
> {
> - UINT32 Index;
> - UINT32 Index2;
> - UINT32 NumberOfEntries;
> - GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;
> + UINT16 RecordType;
> + UINTN StringSize;
>
> - if (Token == NULL) {
> - Token = "";
> - }
> - if (Module == NULL) {
> - Module = "";
> + RecordType = DYNAMIC_STRING_EVENT_TYPE;
> +
> + //
> + // Token to Type and Id.
> + //
> + if (Token != NULL) {
> + if (AsciiStrCmp (Token, START_IMAGE_TOK) == 0) { // "StartImage:"
> + *UseModuleName = TRUE;
> + RecordType = GUID_EVENT_TYPE;
> + if (IsStart) {
> + RecordInfo->ProgressID = MODULE_START_ID;
> + } else {
> + RecordInfo->ProgressID = MODULE_END_ID;
> + }
> + } else if (AsciiStrCmp (Token, LOAD_IMAGE_TOK) == 0) { // "LoadImage:"
> + *UseModuleName = TRUE;
> + RecordType = GUID_QWORD_EVENT_TYPE;
> + if (IsStart) {
> + RecordInfo->ProgressID = MODULE_LOADIMAGE_START_ID;
> + } else {
> + RecordInfo->ProgressID = MODULE_LOADIMAGE_END_ID;
> + }
> + } else if (AsciiStrCmp (Token, DRIVERBINDING_START_TOK) == 0) { // "DB:Start:"
> + *UseModuleName = TRUE;
> + if (IsStart) {
> + RecordInfo->ProgressID = MODULE_DB_START_ID;
> + RecordType = GUID_QWORD_EVENT_TYPE;
> + } else {
> + RecordInfo->ProgressID = MODULE_DB_END_ID;
> + RecordType = GUID_QWORD_STRING_EVENT_TYPE;
> + }
> + } else if (AsciiStrCmp (Token, DRIVERBINDING_SUPPORT_TOK) == 0) { // "DB:Support:"
> + *UseModuleName = TRUE;
> + if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
> + return RETURN_UNSUPPORTED;
> + }
> + RecordType = GUID_QWORD_EVENT_TYPE;
> + if (IsStart) {
> + RecordInfo->ProgressID = MODULE_DB_SUPPORT_START_ID;
> + } else {
> + RecordInfo->ProgressID = MODULE_DB_SUPPORT_END_ID;
> + }
> + } else if (AsciiStrCmp (Token, DRIVERBINDING_STOP_TOK) == 0) { // "DB:Stop:"
> + *UseModuleName = TRUE;
> + if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
> + return RETURN_UNSUPPORTED;
> + }
> + RecordType = GUID_QWORD_EVENT_TYPE;
> + if (IsStart) {
> + RecordInfo->ProgressID = MODULE_DB_STOP_START_ID;
> + } else {
> + RecordInfo->ProgressID = MODULE_DB_STOP_END_ID;
> + }
> + } else if (AsciiStrCmp (Token, PEI_TOK) == 0 || // "PEI"
> + AsciiStrCmp (Token, DXE_TOK) == 0 || // "DXE"
> + AsciiStrCmp (Token, BDS_TOK) == 0) { // "BDS"
> + if (IsStart) {
> + RecordInfo->ProgressID = PERF_CROSSMODULE_START_ID;
> + } else {
> + RecordInfo->ProgressID = PERF_CROSSMODULE_END_ID;
> + }
> + } else { // Pref used in Modules.
> + if (IsStart) {
> + RecordInfo->ProgressID = PERF_INMODULE_START_ID;
> + } else {
> + RecordInfo->ProgressID = PERF_INMODULE_END_ID;
> + }
> + }
> + } else if (Handle!= NULL || Module != NULL) { // Pref used in Modules.
> + if (IsStart) {
> + RecordInfo->ProgressID = PERF_INMODULE_START_ID;
> + } else {
> + RecordInfo->ProgressID = PERF_INMODULE_END_ID;
> + }
> + } else {
> + return EFI_UNSUPPORTED;
> }
>
> - NumberOfEntries = mGaugeData->NumberOfEntries;
> - GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);
> + //
> + // Get Record size baesed on the record type.
> + // When PcdEdkiiFpdtStringRecordEnableOnly is TRUE, all records are with type of DYNAMIC_STRING_EVENT_TYPE.
> + //
> + if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
> + RecordType = DYNAMIC_STRING_EVENT_TYPE;
> + RecordInfo->RecordSize = sizeof (DYNAMIC_STRING_EVENT_RECORD) + STRING_SIZE;
> + } else {
> + switch (RecordType) {
> + case GUID_EVENT_TYPE:
> + RecordInfo->RecordSize = sizeof (GUID_EVENT_RECORD);
> + break;
>
> - Index2 = 0;
> + case DYNAMIC_STRING_EVENT_TYPE:
> + if (*UseModuleName) {
> + StringSize = STRING_SIZE;
> + } else if (Token != NULL) {
> + StringSize = AsciiStrSize (Token);
> + } else if (Module != NULL) {
> + StringSize = AsciiStrSize (Module);
> + } else {
> + StringSize = STRING_SIZE;
> + }
> + if (StringSize > STRING_SIZE) {
> + StringSize = STRING_SIZE;
> + }
> + RecordInfo->RecordSize = (UINT8)(sizeof (DYNAMIC_STRING_EVENT_RECORD) + StringSize);
> + break;
>
> - for (Index = 0; Index < NumberOfEntries; Index++) {
> - Index2 = NumberOfEntries - 1 - Index;
> - if (GaugeEntryExArray[Index2].EndTimeStamp == 0 &&
> - (GaugeEntryExArray[Index2].Handle == (EFI_PHYSICAL_ADDRESS) (UINTN) Handle) &&
> - AsciiStrnCmp (GaugeEntryExArray[Index2].Token, Token, DXE_PERFORMANCE_STRING_LENGTH) == 0 &&
> - AsciiStrnCmp (GaugeEntryExArray[Index2].Module, Module, DXE_PERFORMANCE_STRING_LENGTH) == 0) {
> - Index = Index2;
> + case GUID_QWORD_EVENT_TYPE:
> + RecordInfo->RecordSize = (UINT8)sizeof (GUID_QWORD_EVENT_RECORD);
> break;
> +
> + case GUID_QWORD_STRING_EVENT_TYPE:
> + RecordInfo->RecordSize = (UINT8)sizeof (GUID_QWORD_STRING_EVENT_RECORD);
> + break;
> +
> + default:
> + //
> + // Record is unsupported yet, return EFI_UNSUPPORTED
> + //
> + return EFI_UNSUPPORTED;
> }
> }
>
> - return Index;
> + RecordInfo->Type = RecordType;
> + return EFI_SUCCESS;
> }
>
> /**
> - Adds a record at the end of the performance measurement log
> - that records the start time of a performance measurement.
> -
> - Adds a record to the end of the performance measurement log
> - that contains the Handle, Token, Module and Identifier.
> - The end time of the new record must be set to zero.
> - If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
> - If TimeStamp is zero, the start time in the record is filled in with the value
> - read from the current time stamp.
> + Add performance log to FPDT boot record table.
>
> + @param IsStart TRUE if the performance log is start log.
> @param Handle Pointer to environment specific context used
> to identify the component being measured.
> @param Token Pointer to a Null-terminated ASCII string
> that identifies the component being measured.
> @param Module Pointer to a Null-terminated ASCII string
> that identifies the module being measured.
> - @param TimeStamp 64-bit time stamp.
> + @param Ticker 64-bit time stamp.
> @param Identifier 32-bit identifier. If the value is 0, the created record
> is same as the one created by StartGauge of PERFORMANCE_PROTOCOL.
>
> - @retval EFI_SUCCESS The data was read correctly from the device.
> + @retval EFI_SUCCESS Add FPDT boot record.
> @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement.
> + @retval EFI_UNSUPPORTED No matched FPDT record.
>
> **/
> EFI_STATUS
> -EFIAPI
> -StartGaugeEx (
> +InsertFpdtMeasurement (
> + IN BOOLEAN IsStart,
> IN CONST VOID *Handle, OPTIONAL
> IN CONST CHAR8 *Token, OPTIONAL
> IN CONST CHAR8 *Module, OPTIONAL
> - IN UINT64 TimeStamp,
> + IN UINT64 Ticker,
> IN UINT32 Identifier
> )
> {
> - GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;
> - UINTN GaugeDataSize;
> - GAUGE_DATA_HEADER *NewGaugeData;
> - UINTN OldGaugeDataSize;
> - GAUGE_DATA_HEADER *OldGaugeData;
> - UINT32 Index;
> - EFI_STATUS Status;
> + EFI_GUID ModuleGuid;
> + CHAR8 ModuleName[EDKII_STRING_EVENT_RECORD_NAME_LENGTH];
> + UINT8 FpdtRecord[MAX_RECORD_SIZE];
> + EFI_STATUS Status;
> + FPDT_RECORD_PTR FpdtRecordPtr;
> + BASIC_RECORD_INFO RecordInfo;
> + UINT64 TimeStamp;
> + UINTN DestMax;
> + UINTN StrLength;
> + CONST CHAR8 *StringPtr;
> + BOOLEAN UseModuleName;
> +
> + StringPtr = NULL;
> + UseModuleName = FALSE;
> + ZeroMem (ModuleName, sizeof (ModuleName));
> + ZeroMem (FpdtRecord, sizeof (FpdtRecord));
>
> - Status = EfiAcquireLockOrFail (&mPerfRecordLock);
> + //
> + // Get record info (type, size, ProgressID and Module Guid).
> + //
> + Status = GetFpdtRecordInfo (IsStart, Handle, Token, Module, &RecordInfo, &UseModuleName);
> if (EFI_ERROR (Status)) {
> return Status;
> }
>
> - Index = mGaugeData->NumberOfEntries;
> - if (Index >= mMaxGaugeRecords) {
> + //
> + // If PERF_START()/PERF_END() have specified the ProgressID,it has high priority.
> + // !!! Note: If the Pref is not the known Token used in the core but have same
> + // ID with the core Token, this case will not be supported.
> + // And in currtnt usage mode, for the unkown ID, there is a general rule:
> + // If it is start pref: the lower 4 bits of the ID should be 0.
> + // If it is end pref: the lower 4 bits of the ID should not be 0.
> + // If input ID doesn't follow the rule, we will adjust it.
> + //
> + if ((Identifier != 0) && (IsKnownID (Identifier)) && (!IsKnownTokens (Token))) {
> + return EFI_UNSUPPORTED;
> + } else if ((Identifier != 0) && (!IsKnownID (Identifier)) && (!IsKnownTokens (Token))) {
> + if (IsStart && ((Identifier & 0x000F) != 0)) {
> + Identifier &= 0xFFF0;
> + } else if ((!IsStart) && ((Identifier & 0x000F) == 0)) {
> + Identifier += 1;
> + }
> + RecordInfo.ProgressID = (UINT16)Identifier;
> + }
> +
> + if (mFpdtBufferIsReported) {
> + FpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)FpdtRecord;
> + } else {
> + //
> + // Check if pre-allocated buffer is full
> //
> - // Try to enlarge the scale of gauge array.
> + if (mPerformanceLength + RecordInfo.RecordSize > mMaxPerformanceLength) {
> + mPerformancePointer = ReallocatePool (
> + mPerformanceLength,
> + mPerformanceLength + RecordInfo.RecordSize + FIRMWARE_RECORD_BUFFER,
> + mPerformancePointer
> + );
> +
> + if (mPerformancePointer == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> + mMaxPerformanceLength = mPerformanceLength + RecordInfo.RecordSize + FIRMWARE_RECORD_BUFFER;
> + }
> //
> - OldGaugeData = mGaugeData;
> - OldGaugeDataSize = sizeof (GAUGE_DATA_HEADER) + sizeof (GAUGE_DATA_ENTRY_EX) * mMaxGaugeRecords;
> + // Covert buffer to FPDT Ptr Union type.
> + //
> + FpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(mPerformancePointer + mPerformanceLength);
> + }
> + FpdtRecordPtr.RecordHeader->Length = 0;
>
> - GaugeDataSize = sizeof (GAUGE_DATA_HEADER) + sizeof (GAUGE_DATA_ENTRY_EX) * mMaxGaugeRecords * 2;
> + //
> + // Get the TimeStamp.
> + //
> + if (Ticker == 0) {
> + Ticker = GetPerformanceCounter ();
> + TimeStamp = GetTimeInNanoSecond (Ticker);
> + } else if (Ticker == 1) {
> + TimeStamp = 0;
> + } else {
> + TimeStamp = GetTimeInNanoSecond (Ticker);
> + }
>
> - NewGaugeData = AllocateZeroPool (GaugeDataSize);
> - if (NewGaugeData == NULL) {
> - EfiReleaseLock (&mPerfRecordLock);
> - return EFI_OUT_OF_RESOURCES;
> + //
> + // Get the ModuleName and ModuleGuid form the handle.
> + //
> + GetModuleInfoFromHandle ((EFI_HANDLE *)Handle, ModuleName, sizeof (ModuleName), &ModuleGuid);
> +
> + //
> + // Fill in the record information.
> + //
> + switch (RecordInfo.Type) {
> + case GUID_EVENT_TYPE:
> + FpdtRecordPtr.GuidEvent->Header.Type = GUID_EVENT_TYPE;
> + FpdtRecordPtr.GuidEvent->Header.Length = RecordInfo.RecordSize;
> + FpdtRecordPtr.GuidEvent->Header.Revision = RECORD_REVISION_1;
> + FpdtRecordPtr.GuidEvent->ProgressID = RecordInfo.ProgressID;
> + FpdtRecordPtr.GuidEvent->Timestamp = TimeStamp;
> + CopyMem (&FpdtRecordPtr.GuidEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidEvent->Guid));
> + break;
> +
> + case DYNAMIC_STRING_EVENT_TYPE:
> + FpdtRecordPtr.DynamicStringEvent->Header.Type = DYNAMIC_STRING_EVENT_TYPE;
> + FpdtRecordPtr.DynamicStringEvent->Header.Length = RecordInfo.RecordSize;
> + FpdtRecordPtr.DynamicStringEvent->Header.Revision = RECORD_REVISION_1;
> + FpdtRecordPtr.DynamicStringEvent->ProgressID = RecordInfo.ProgressID;
> + FpdtRecordPtr.DynamicStringEvent->Timestamp = TimeStamp;
> + CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));
> +
> + if (UseModuleName) {
> + StringPtr = ModuleName;
> + } else if (Token != NULL) {
> + StringPtr = Token;
> + } else if (Module != NULL) {
> + StringPtr = Module;
> + } else if (ModuleName != NULL) {
> + StringPtr = ModuleName;
> + }
> + if (StringPtr != NULL && AsciiStrLen (StringPtr) != 0) {
> + StrLength = AsciiStrLen (StringPtr);
> + DestMax = (RecordInfo.RecordSize - sizeof (DYNAMIC_STRING_EVENT_RECORD)) / sizeof (CHAR8);
> + if (StrLength >= DestMax) {
> + StrLength = DestMax -1;
> + }
> + AsciiStrnCpyS (FpdtRecordPtr.DynamicStringEvent->String, DestMax, StringPtr, StrLength);
> }
> + break;
> +
> + case GUID_QWORD_EVENT_TYPE:
> + FpdtRecordPtr.GuidQwordEvent->Header.Type = GUID_QWORD_EVENT_TYPE;
> + FpdtRecordPtr.GuidQwordEvent->Header.Length = RecordInfo.RecordSize;
> + FpdtRecordPtr.GuidQwordEvent->Header.Revision = RECORD_REVISION_1;
> + FpdtRecordPtr.GuidQwordEvent->ProgressID = RecordInfo.ProgressID;
> + FpdtRecordPtr.GuidQwordEvent->Timestamp = TimeStamp;
> + CopyMem (&FpdtRecordPtr.GuidQwordEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidQwordEvent->Guid));
> + if ((MODULE_LOADIMAGE_START_ID == RecordInfo.ProgressID) && AsciiStrCmp (Token, LOAD_IMAGE_TOK) == 0) {
> + mLoadImageCount++;
> + FpdtRecordPtr.GuidQwordEvent->Qword = mLoadImageCount;
> + }
> + break;
> +
> + case GUID_QWORD_STRING_EVENT_TYPE:
> + FpdtRecordPtr.GuidQwordStringEvent->Header.Type = GUID_QWORD_STRING_EVENT_TYPE;
> + FpdtRecordPtr.GuidQwordStringEvent->Header.Length = RecordInfo.RecordSize;
> + FpdtRecordPtr.GuidQwordStringEvent->Header.Revision = RECORD_REVISION_1;
> + FpdtRecordPtr.GuidQwordStringEvent->ProgressID = RecordInfo.ProgressID;
> + FpdtRecordPtr.GuidQwordStringEvent->Timestamp = TimeStamp;
> + CopyMem (&FpdtRecordPtr.GuidQwordStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidQwordStringEvent->Guid));
> + break;
> +
> + default:
> + //
> + // Record is not supported in current DXE phase, return EFI_ABORTED
> + //
> + return EFI_UNSUPPORTED;
> + }
> +
> + //
> + // Report record one by one after records have been reported together.
> + //
> + if (mFpdtBufferIsReported) {
> + //
> + // Append Boot records to the boot performance table.
> + //
> + if (mBootRecordSize + FpdtRecordPtr.RecordHeader->Length > mBootRecordMaxSize) {
> + if (!mLackSpaceIsReported) {
> + DEBUG ((DEBUG_INFO, "DxeCorePerformanceLib: No enough space to save boot records\n"));
> + mLackSpaceIsReported = TRUE;
> + }
> + return EFI_OUT_OF_RESOURCES;
> + } else {
> + //
> + // Save boot record into BootPerformance table
> + //
> + CopyMem (mBootRecordBuffer + mBootRecordSize, FpdtRecordPtr.RecordHeader, FpdtRecordPtr.RecordHeader->Length);
> + mBootRecordSize += FpdtRecordPtr.RecordHeader->Length;
> + mAcpiBootPerformanceTable->Header.Length += FpdtRecordPtr.RecordHeader->Length;
> + }
> + } else {
> + //
> + // Update the cached FPDT record buffer.
> + //
> + mPerformanceLength += FpdtRecordPtr.RecordHeader->Length;
> + }
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Dumps all the PEI performance.
> +
> + @param HobStart A pointer to a Guid.
>
> - mGaugeData = NewGaugeData;
> - mMaxGaugeRecords *= 2;
> + This internal function dumps all the PEI performance log to the DXE performance gauge array.
> + It retrieves the optional GUID HOB for PEI performance and then saves the performance data
> + to DXE performance data structures.
>
> +**/
> +VOID
> +InternalGetPeiPerformance (
> + VOID *HobStart
> + )
> +{
> + UINT8 *FirmwarePerformanceHob;
> + PEI_EXT_FIRMWARE_PERF_HEADER *PeiPerformanceLogHeader;
> + UINT8 *EventRec;
> + EFI_HOB_GUID_TYPE *GuidHob;
> +
> + GuidHob = GetNextGuidHob (&gEdkiiExtendedFirmwarePerformanceGuid, HobStart);
> + while (GuidHob != NULL) {
> + FirmwarePerformanceHob = GET_GUID_HOB_DATA (GuidHob);
> + PeiPerformanceLogHeader = (PEI_EXT_FIRMWARE_PERF_HEADER *)FirmwarePerformanceHob;
> +
> + if (mPerformanceLength + PeiPerformanceLogHeader->SizeOfAllEntries > mMaxPerformanceLength) {
> + mPerformancePointer = ReallocatePool (
> + mPerformanceLength,
> + mPerformanceLength +
> + (UINTN)PeiPerformanceLogHeader->SizeOfAllEntries +
> + FIRMWARE_RECORD_BUFFER,
> + mPerformancePointer
> + );
> + ASSERT (mPerformancePointer != NULL);
> + mMaxPerformanceLength = mPerformanceLength +
> + (UINTN)(PeiPerformanceLogHeader->SizeOfAllEntries) +
> + FIRMWARE_RECORD_BUFFER;
> + }
> +
> + EventRec = mPerformancePointer + mPerformanceLength;
> + CopyMem (EventRec, FirmwarePerformanceHob + sizeof (PEI_EXT_FIRMWARE_PERF_HEADER), (UINTN)(PeiPerformanceLogHeader->SizeOfAllEntries));
> //
> - // Initialize new data array and migrate old data one.
> + // Update the used buffer size.
> //
> - mGaugeData = CopyMem (mGaugeData, OldGaugeData, OldGaugeDataSize);
> + mPerformanceLength += (UINTN)(PeiPerformanceLogHeader->SizeOfAllEntries);
> + mLoadImageCount += PeiPerformanceLogHeader->LoadImageCount;
>
> - FreePool (OldGaugeData);
> + //
> + // Get next performance guid hob
> + //
> + GuidHob = GetNextGuidHob (&gEdkiiExtendedFirmwarePerformanceGuid, GET_NEXT_HOB (GuidHob));
> }
> +}
>
> - GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);
> - GaugeEntryExArray[Index].Handle = (EFI_PHYSICAL_ADDRESS) (UINTN) Handle;
> +/**
> + Report Boot Perforamnce table address as report status code.
>
> - if (Token != NULL) {
> - AsciiStrnCpyS (GaugeEntryExArray[Index].Token, DXE_PERFORMANCE_STRING_SIZE, Token, DXE_PERFORMANCE_STRING_LENGTH);
> - }
> - if (Module != NULL) {
> - AsciiStrnCpyS (GaugeEntryExArray[Index].Module, DXE_PERFORMANCE_STRING_SIZE, Module, DXE_PERFORMANCE_STRING_LENGTH);
> + @param Event The event of notify protocol.
> + @param Context Notify event context.
> +
> +**/
> +VOID
> +EFIAPI
> +ReportFpdtRecordBuffer (
> + IN EFI_EVENT Event,
> + IN VOID *Context
> + )
> +{
> + EFI_STATUS Status;
> + UINT64 BPDTAddr;
> +
> + if (!mFpdtBufferIsReported) {
> + Status = AllocateBootPerformanceTable ();
> + if (!EFI_ERROR(Status)) {
> + BPDTAddr = (UINT64)(UINTN)mAcpiBootPerformanceTable;
> + REPORT_STATUS_CODE_EX (
> + EFI_PROGRESS_CODE,
> + EFI_SOFTWARE_DXE_BS_DRIVER,
> + 0,
> + NULL,
> + &gEfiFirmwarePerformanceGuid,
> + &BPDTAddr,
> + sizeof (UINT64)
> + );
> + }
> + //
> + // Free Cached FPDT record Buffer
> + //
> + if (mPerformancePointer != NULL) {
> + FreePool (mPerformancePointer);
> + mPerformancePointer = NULL;
> + }
> + mPerformanceLength = 0;
> + mMaxPerformanceLength = 0;
> + //
> + // Set FPDT report state to TRUE.
> + //
> + mFpdtBufferIsReported = TRUE;
> }
> +}
>
> - GaugeEntryExArray[Index].EndTimeStamp = 0;
> - GaugeEntryExArray[Index].Identifier = Identifier;
> +/**
> + Adds a record at the end of the performance measurement log
> + that records the start time of a performance measurement.
>
> - if (TimeStamp == 0) {
> - TimeStamp = GetPerformanceCounter ();
> - }
> - GaugeEntryExArray[Index].StartTimeStamp = TimeStamp;
> + Adds a record to the end of the performance measurement log
> + that contains the Handle, Token, Module and Identifier.
> + The end time of the new record must be set to zero.
> + If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
> + If TimeStamp is zero, the start time in the record is filled in with the value
> + read from the current time stamp.
>
> - mGaugeData->NumberOfEntries++;
> + @param Handle Pointer to environment specific context used
> + to identify the component being measured.
> + @param Token Pointer to a Null-terminated ASCII string
> + that identifies the component being measured.
> + @param Module Pointer to a Null-terminated ASCII string
> + that identifies the module being measured.
> + @param TimeStamp 64-bit time stamp.
> + @param Identifier 32-bit identifier. If the value is 0, the created record
> + is same as the one created by StartGauge of PERFORMANCE_PROTOCOL.
>
> - EfiReleaseLock (&mPerfRecordLock);
> + @retval EFI_SUCCESS The data was read correctly from the device.
> + @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement.
>
> - return EFI_SUCCESS;
> +**/
> +EFI_STATUS
> +EFIAPI
> +StartGaugeEx (
> + IN CONST VOID *Handle, OPTIONAL
> + IN CONST CHAR8 *Token, OPTIONAL
> + IN CONST CHAR8 *Module, OPTIONAL
> + IN UINT64 TimeStamp,
> + IN UINT32 Identifier
> + )
> +{
> + return InsertFpdtMeasurement (TRUE, Handle, Token, Module, TimeStamp, Identifier);
> }
>
> /**
> Searches the performance measurement log from the beginning of the log
> for the first matching record that contains a zero end time and fills in a valid end time.
>
> Searches the performance measurement log from the beginning of the log
> - for the first record that matches Handle, Token and Module and has an end time value of zero.
> + for the first record that matches Handle, Token, Module and Identifier and has an end time value of zero.
> If the record can not be found then return EFI_NOT_FOUND.
> If the record is found and TimeStamp is not zero,
> then the end time in the record is filled in with the value specified by TimeStamp.
> If the record is found and TimeStamp is zero, then the end time in the matching record
> is filled in with the current time stamp value.
> @@ -260,89 +1188,19 @@ EndGaugeEx (
> IN CONST CHAR8 *Module, OPTIONAL
> IN UINT64 TimeStamp,
> IN UINT32 Identifier
> )
> {
> - GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;
> - UINT32 Index;
> - EFI_STATUS Status;
> -
> - Status = EfiAcquireLockOrFail (&mPerfRecordLock);
> - if (EFI_ERROR (Status)) {
> - return Status;
> - }
> -
> - if (TimeStamp == 0) {
> - TimeStamp = GetPerformanceCounter ();
> - }
> -
> - Index = InternalSearchForGaugeEntry (Handle, Token, Module, Identifier);
> - if (Index >= mGaugeData->NumberOfEntries) {
> - EfiReleaseLock (&mPerfRecordLock);
> - return EFI_NOT_FOUND;
> - }
> - GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);
> - GaugeEntryExArray[Index].EndTimeStamp = TimeStamp;
> -
> - EfiReleaseLock (&mPerfRecordLock);
> - return EFI_SUCCESS;
> + return InsertFpdtMeasurement (FALSE, Handle, Token, Module, TimeStamp, Identifier);
> }
>
> /**
> Retrieves a previously logged performance measurement.
> It can also retrieve the log created by StartGauge and EndGauge of PERFORMANCE_PROTOCOL,
> and then assign the Identifier with 0.
>
> - Retrieves the performance log entry from the performance log specified by LogEntryKey.
> - If it stands for a valid entry, then EFI_SUCCESS is returned and
> - GaugeDataEntryEx stores the pointer to that entry.
> -
> - This internal function is added to avoid releasing lock before each return statement.
> -
> - @param LogEntryKey The key for the previous performance measurement log entry.
> - If 0, then the first performance measurement log entry is retrieved.
> - @param GaugeDataEntryEx The indirect pointer to the extended gauge data entry specified by LogEntryKey
> - if the retrieval is successful.
> -
> - @retval EFI_SUCCESS The GuageDataEntryEx is successfully found based on LogEntryKey.
> - @retval EFI_NOT_FOUND The LogEntryKey is the last entry (equals to the total entry number).
> - @retval EFI_INVALIDE_PARAMETER The LogEntryKey is not a valid entry (greater than the total entry number).
> - @retval EFI_INVALIDE_PARAMETER GaugeDataEntryEx is NULL.
> -
> -**/
> -EFI_STATUS
> -EFIAPI
> -InternalGetGaugeEx (
> - IN UINTN LogEntryKey,
> - OUT GAUGE_DATA_ENTRY_EX **GaugeDataEntryEx
> - )
> -{
> - UINTN NumberOfEntries;
> - GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;
> -
> - NumberOfEntries = (UINTN) (mGaugeData->NumberOfEntries);
> - if (LogEntryKey > NumberOfEntries) {
> - return EFI_INVALID_PARAMETER;
> - }
> - if (LogEntryKey == NumberOfEntries) {
> - return EFI_NOT_FOUND;
> - }
> -
> - GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);
> -
> - if (GaugeDataEntryEx == NULL) {
> - return EFI_INVALID_PARAMETER;
> - }
> - *GaugeDataEntryEx = &GaugeEntryExArray[LogEntryKey];
> -
> - return EFI_SUCCESS;
> -}
> -
> -/**
> - Retrieves a previously logged performance measurement.
> - It can also retrieve the log created by StartGauge and EndGauge of PERFORMANCE_PROTOCOL,
> - and then assign the Identifier with 0.
> + !!! Not support!!!
>
> Retrieves the performance log entry from the performance log specified by LogEntryKey.
> If it stands for a valid entry, then EFI_SUCCESS is returned and
> GaugeDataEntryEx stores the pointer to that entry.
>
> @@ -362,22 +1220,11 @@ EFIAPI
> GetGaugeEx (
> IN UINTN LogEntryKey,
> OUT GAUGE_DATA_ENTRY_EX **GaugeDataEntryEx
> )
> {
> - EFI_STATUS Status;
> -
> - Status = EfiAcquireLockOrFail (&mPerfRecordLock);
> - if (EFI_ERROR (Status)) {
> - return Status;
> - }
> -
> - Status = InternalGetGaugeEx (LogEntryKey, GaugeDataEntryEx);
> -
> - EfiReleaseLock (&mPerfRecordLock);
> -
> - return Status;
> + return EFI_UNSUPPORTED;
> }
>
> /**
> Adds a record at the end of the performance measurement log
> that records the start time of a performance measurement.
> @@ -452,10 +1299,12 @@ EndGauge (
> /**
> Retrieves a previously logged performance measurement.
> It can also retrieve the log created by StartGaugeEx and EndGaugeEx of PERFORMANCE_EX_PROTOCOL,
> and then eliminate the Identifier.
>
> + !!! Not support!!!
> +
> Retrieves the performance log entry from the performance log specified by LogEntryKey.
> If it stands for a valid entry, then EFI_SUCCESS is returned and
> GaugeDataEntry stores the pointer to that entry.
>
> @param LogEntryKey The key for the previous performance measurement log entry.
> @@ -474,81 +1323,13 @@ EFIAPI
> GetGauge (
> IN UINTN LogEntryKey,
> OUT GAUGE_DATA_ENTRY **GaugeDataEntry
> )
> {
> - EFI_STATUS Status;
> - GAUGE_DATA_ENTRY_EX *GaugeEntryEx;
> -
> - GaugeEntryEx = NULL;
> -
> - Status = GetGaugeEx (LogEntryKey, &GaugeEntryEx);
> - if (EFI_ERROR (Status)) {
> - return Status;
> - }
> -
> - if (GaugeDataEntry == NULL) {
> - return EFI_INVALID_PARAMETER;
> - }
> -
> - *GaugeDataEntry = (GAUGE_DATA_ENTRY *) GaugeEntryEx;
> -
> - return EFI_SUCCESS;
> + return EFI_UNSUPPORTED;
> }
>
> -/**
> - Dumps all the PEI performance log to DXE performance gauge array.
> -
> - This internal function dumps all the PEI performance log to the DXE performance gauge array.
> - It retrieves the optional GUID HOB for PEI performance and then saves the performance data
> - to DXE performance data structures.
> -
> -**/
> -VOID
> -InternalGetPeiPerformance (
> - VOID
> - )
> -{
> - EFI_HOB_GUID_TYPE *GuidHob;
> - PEI_PERFORMANCE_LOG_HEADER *LogHob;
> - PEI_PERFORMANCE_LOG_ENTRY *LogEntryArray;
> - UINT32 *LogIdArray;
> - GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;
> - UINT32 Index;
> - UINT32 NumberOfEntries;
> -
> - NumberOfEntries = 0;
> - GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);
> -
> - //
> - // Dump PEI Log Entries to DXE Guage Data structure.
> - //
> - GuidHob = GetFirstGuidHob (&gPerformanceProtocolGuid);
> - if (GuidHob != NULL) {
> - LogHob = GET_GUID_HOB_DATA (GuidHob);
> - LogEntryArray = (PEI_PERFORMANCE_LOG_ENTRY *) (LogHob + 1);
> -
> - NumberOfEntries = LogHob->NumberOfEntries;
> - for (Index = 0; Index < NumberOfEntries; Index++) {
> - GaugeEntryExArray[Index].Handle = LogEntryArray[Index].Handle;
> - AsciiStrCpyS (GaugeEntryExArray[Index].Token, DXE_PERFORMANCE_STRING_SIZE, LogEntryArray[Index].Token);
> - AsciiStrCpyS (GaugeEntryExArray[Index].Module, DXE_PERFORMANCE_STRING_SIZE, LogEntryArray[Index].Module);
> - GaugeEntryExArray[Index].StartTimeStamp = LogEntryArray[Index].StartTimeStamp;
> - GaugeEntryExArray[Index].EndTimeStamp = LogEntryArray[Index].EndTimeStamp;
> - GaugeEntryExArray[Index].Identifier = 0;
> - }
> -
> - GuidHob = GetFirstGuidHob (&gPerformanceExProtocolGuid);
> - if (GuidHob != NULL) {
> - LogIdArray = GET_GUID_HOB_DATA (GuidHob);
> - for (Index = 0; Index < NumberOfEntries; Index++) {
> - GaugeEntryExArray[Index].Identifier = LogIdArray[Index];
> - }
> - }
> - }
> - mGaugeData->NumberOfEntries = NumberOfEntries;
> -}
>
> /**
> The constructor function initializes Performance infrastructure for DXE phase.
>
> The constructor function publishes Performance and PerformanceEx protocol, allocates memory to log DXE performance
> @@ -567,40 +1348,53 @@ DxeCorePerformanceLibConstructor (
> IN EFI_HANDLE ImageHandle,
> IN EFI_SYSTEM_TABLE *SystemTable
> )
> {
> EFI_STATUS Status;
> + EFI_HANDLE Handle;
> + EFI_EVENT ReadyToBootEvent;
> PERFORMANCE_PROPERTY *PerformanceProperty;
>
> -
> if (!PerformanceMeasurementEnabled ()) {
> //
> // Do not initialize performance infrastructure if not required.
> //
> return EFI_SUCCESS;
> }
> +
> + //
> + // Dump normal PEI performance records
> + //
> + InternalGetPeiPerformance (GetHobList());
> +
> //
> - // Install the protocol interfaces.
> + // Install the protocol interfaces for DXE performance library instance.
> //
> + Handle = NULL;
> Status = gBS->InstallMultipleProtocolInterfaces (
> - &mHandle,
> + &Handle,
> &gPerformanceProtocolGuid,
> &mPerformanceInterface,
> &gPerformanceExProtocolGuid,
> &mPerformanceExInterface,
> NULL
> );
> ASSERT_EFI_ERROR (Status);
>
> - mMaxGaugeRecords = INIT_DXE_GAUGE_DATA_ENTRIES + (UINT16) (PcdGet16 (PcdMaxPeiPerformanceLogEntries16) != 0 ?
> - PcdGet16 (PcdMaxPeiPerformanceLogEntries16) :
> - PcdGet8 (PcdMaxPeiPerformanceLogEntries));
> -
> - mGaugeData = AllocateZeroPool (sizeof (GAUGE_DATA_HEADER) + (sizeof (GAUGE_DATA_ENTRY_EX) * mMaxGaugeRecords));
> - ASSERT (mGaugeData != NULL);
> + //
> + // Register ReadyToBoot event to report StatusCode data
> + //
> + Status = gBS->CreateEventEx (
> + EVT_NOTIFY_SIGNAL,
> + TPL_CALLBACK,
> + ReportFpdtRecordBuffer,
> + NULL,
> + &gEfiEventReadyToBootGuid,
> + &ReadyToBootEvent
> + );
>
> - InternalGetPeiPerformance ();
> + ASSERT_EFI_ERROR (Status);
>
> Status = EfiGetSystemConfigurationTable (&gPerformanceProtocolGuid, (VOID **) &PerformanceProperty);
> if (EFI_ERROR (Status)) {
> //
> // Install configuration table for performance property.
> @@ -651,19 +1445,19 @@ StartPerformanceMeasurementEx (
> IN CONST CHAR8 *Module, OPTIONAL
> IN UINT64 TimeStamp,
> IN UINT32 Identifier
> )
> {
> - return (RETURN_STATUS) StartGaugeEx (Handle, Token, Module, TimeStamp, Identifier);
> + return InsertFpdtMeasurement (TRUE, Handle, Token, Module, TimeStamp, Identifier);
> }
>
> /**
> Searches the performance measurement log from the beginning of the log
> for the first matching record that contains a zero end time and fills in a valid end time.
>
> Searches the performance measurement log from the beginning of the log
> - for the first record that matches Handle, Token and Module and has an end time value of zero.
> + for the first record that matches Handle, Token, Module and Identifier and has an end time value of zero.
> If the record can not be found then return RETURN_NOT_FOUND.
> If the record is found and TimeStamp is not zero,
> then the end time in the record is filled in with the value specified by TimeStamp.
> If the record is found and TimeStamp is zero, then the end time in the matching record
> is filled in with the current time stamp value.
> @@ -690,18 +1484,20 @@ EndPerformanceMeasurementEx (
> IN CONST CHAR8 *Module, OPTIONAL
> IN UINT64 TimeStamp,
> IN UINT32 Identifier
> )
> {
> - return (RETURN_STATUS) EndGaugeEx (Handle, Token, Module, TimeStamp, Identifier);
> + return InsertFpdtMeasurement (FALSE, Handle, Token, Module, TimeStamp, Identifier);
> }
>
> /**
> Attempts to retrieve a performance measurement log entry from the performance measurement log.
> It can also retrieve the log created by StartPerformanceMeasurement and EndPerformanceMeasurement,
> and then assign the Identifier with 0.
>
> + !!! Not support!!!
> +
> Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is
> zero on entry, then an attempt is made to retrieve the first entry from the performance log,
> and the key for the second entry in the log is returned. If the performance log is empty,
> then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance
> log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
> @@ -729,63 +1525,29 @@ EndPerformanceMeasurementEx (
> being measured.
> @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
> was started.
> @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
> was ended.
> - @param Identifier Pointer to the 32-bit identifier that was recorded.
> + @param Identifier Pointer to the 32-bit identifier that was recorded when the measurement
> + was ended.
>
> @return The key for the next performance log entry (in general case).
>
> **/
> UINTN
> EFIAPI
> GetPerformanceMeasurementEx (
> - IN UINTN LogEntryKey,
> + IN UINTN LogEntryKey,
> OUT CONST VOID **Handle,
> OUT CONST CHAR8 **Token,
> OUT CONST CHAR8 **Module,
> OUT UINT64 *StartTimeStamp,
> OUT UINT64 *EndTimeStamp,
> OUT UINT32 *Identifier
> )
> {
> - EFI_STATUS Status;
> - GAUGE_DATA_ENTRY_EX *GaugeData;
> -
> - GaugeData = NULL;
> -
> - ASSERT (Handle != NULL);
> - ASSERT (Token != NULL);
> - ASSERT (Module != NULL);
> - ASSERT (StartTimeStamp != NULL);
> - ASSERT (EndTimeStamp != NULL);
> - ASSERT (Identifier != NULL);
> -
> - Status = GetGaugeEx (LogEntryKey++, &GaugeData);
> -
> - //
> - // Make sure that LogEntryKey is a valid log entry key,
> - //
> - ASSERT (Status != EFI_INVALID_PARAMETER);
> -
> - if (EFI_ERROR (Status)) {
> - //
> - // The LogEntryKey is the last entry (equals to the total entry number).
> - //
> - return 0;
> - }
> -
> - ASSERT (GaugeData != NULL);
> -
> - *Handle = (VOID *) (UINTN) GaugeData->Handle;
> - *Token = GaugeData->Token;
> - *Module = GaugeData->Module;
> - *StartTimeStamp = GaugeData->StartTimeStamp;
> - *EndTimeStamp = GaugeData->EndTimeStamp;
> - *Identifier = GaugeData->Identifier;
> -
> - return LogEntryKey;
> + return 0;
> }
>
> /**
> Adds a record at the end of the performance measurement log
> that records the start time of a performance measurement.
> @@ -816,11 +1578,11 @@ StartPerformanceMeasurement (
> IN CONST CHAR8 *Token, OPTIONAL
> IN CONST CHAR8 *Module, OPTIONAL
> IN UINT64 TimeStamp
> )
> {
> - return StartPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);
> + return InsertFpdtMeasurement (TRUE, Handle, Token, Module, TimeStamp, 0);
> }
>
> /**
> Searches the performance measurement log from the beginning of the log
> for the first matching record that contains a zero end time and fills in a valid end time.
> @@ -852,18 +1614,20 @@ EndPerformanceMeasurement (
> IN CONST CHAR8 *Token, OPTIONAL
> IN CONST CHAR8 *Module, OPTIONAL
> IN UINT64 TimeStamp
> )
> {
> - return EndPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);
> + return InsertFpdtMeasurement (FALSE, Handle, Token, Module, TimeStamp, 0);
> }
>
> /**
> Attempts to retrieve a performance measurement log entry from the performance measurement log.
> It can also retrieve the log created by StartPerformanceMeasurementEx and EndPerformanceMeasurementEx,
> and then eliminate the Identifier.
>
> + !!! Not support!!!
> +
> Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is
> zero on entry, then an attempt is made to retrieve the first entry from the performance log,
> and the key for the second entry in the log is returned. If the performance log is empty,
> then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance
> log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
> @@ -905,12 +1669,11 @@ GetPerformanceMeasurement (
> OUT CONST CHAR8 **Module,
> OUT UINT64 *StartTimeStamp,
> OUT UINT64 *EndTimeStamp
> )
> {
> - UINT32 Identifier;
> - return GetPerformanceMeasurementEx (LogEntryKey, Handle, Token, Module, StartTimeStamp, EndTimeStamp, &Identifier);
> + return 0;
> }
>
> /**
> Returns TRUE if the performance measurement macros are enabled.
>
> diff --git a/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf b/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf
> index 5b89ce2..71c181f 100644
> --- a/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf
> +++ b/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf
> @@ -7,11 +7,11 @@
> # It initializes DXE phase performance logging by publishing the Performance and PerformanceEx Protocol,
> # which is consumed by DxePerformanceLib to logging performance data in DXE phase.
> # This library is mainly used by DxeCore to start performance logging to ensure that
> # Performance and PerformanceEx Protocol are installed at the very beginning of DXE phase.
> #
> -# Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
> +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
> # (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
> # This program and the accompanying materials
> # are licensed and made available under the terms and conditions of the BSD License
> # which accompanies this distribution. The full text of the license may be found at
> # http://opensource.org/licenses/bsd-license.php
> @@ -48,27 +48,39 @@
>
>
> [LibraryClasses]
> MemoryAllocationLib
> UefiBootServicesTableLib
> + UefiRuntimeServicesTableLib
> PcdLib
> TimerLib
> BaseMemoryLib
> BaseLib
> HobLib
> DebugLib
> UefiLib
> + ReportStatusCodeLib
> + DxeServicesLib
> + PeCoffGetEntryPointLib
> +
> +[Protocols]
> + gEfiSmmCommunicationProtocolGuid ## SOMETIMES_CONSUMES
>
>
> [Guids]
> ## SOMETIMES_CONSUMES ## HOB
> ## PRODUCES ## UNDEFINED # Install protocol
> ## PRODUCES ## SystemTable
> gPerformanceProtocolGuid
> ## SOMETIMES_CONSUMES ## HOB
> ## PRODUCES ## UNDEFINED # Install protocol
> gPerformanceExProtocolGuid
> + gZeroGuid ## SOMETIMES_CONSUMES ## GUID
> + gEfiFirmwarePerformanceGuid ## SOMETIMES_PRODUCES ## UNDEFINED # StatusCode Data
> + gEdkiiExtendedFirmwarePerformanceGuid ## SOMETIMES_CONSUMES ## HOB # StatusCode Data
> + gEfiEventReadyToBootGuid ## CONSUMES ## Event
> + gEdkiiPiSmmCommunicationRegionTableGuid ## SOMETIMES_CONSUMES ## SystemTable
>
> [Pcd]
> - gEfiMdeModulePkgTokenSpaceGuid.PcdMaxPeiPerformanceLogEntries ## CONSUMES
> - gEfiMdeModulePkgTokenSpaceGuid.PcdMaxPeiPerformanceLogEntries16 ## CONSUMES
> - gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask ## CONSUMES
> + gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask ## CONSUMES
> + gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiFpdtStringRecordEnableOnly ## CONSUMES
> + gEfiMdeModulePkgTokenSpaceGuid.PcdExtFpdtBootRecordPadSize ## CONSUMES
> diff --git a/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLibInternal.h b/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLibInternal.h
> index f1540d8..7e79675 100644
> --- a/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLibInternal.h
> +++ b/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLibInternal.h
> @@ -2,11 +2,11 @@
> Master header files for DxeCorePerformanceLib instance.
>
> This header file holds the prototypes of the Performance and PerformanceEx Protocol published by this
> library instance at its constructor.
>
> -Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
> This program and the accompanying materials
> are licensed and made available under the terms and conditions of the BSD License
> which accompanies this distribution. The full text of the license may be found at
> http://opensource.org/licenses/bsd-license.php
>
> @@ -20,21 +20,36 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
>
>
> #include <PiDxe.h>
>
> #include <Guid/Performance.h>
> +#include <Guid/ExtendedFirmwarePerformance.h>
> +#include <Guid/ZeroGuid.h>
> +#include <Guid/EventGroup.h>
> +#include <Guid/FirmwarePerformance.h>
> +#include <Guid/PiSmmCommunicationRegionTable.h>
> +
> +#include <Protocol/DriverBinding.h>
> +#include <Protocol/LoadedImage.h>
> +#include <Protocol/ComponentName2.h>
> +#include <Protocol/DevicePathToText.h>
> +#include <Protocol/SmmCommunication.h>
>
> #include <Library/PerformanceLib.h>
> #include <Library/DebugLib.h>
> #include <Library/HobLib.h>
> #include <Library/BaseLib.h>
> #include <Library/BaseMemoryLib.h>
> #include <Library/TimerLib.h>
> #include <Library/PcdLib.h>
> #include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> #include <Library/MemoryAllocationLib.h>
> #include <Library/UefiLib.h>
> +#include <Library/ReportStatusCodeLib.h>
> +#include <Library/DxeServicesLib.h>
> +#include <Library/PeCoffGetEntryPointLib.h>
>
> //
> // Interface declarations for PerformanceEx Protocol.
> //
> /**
> --
> 1.9.5.msysgit.1
>
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel
next prev parent reply other threads:[~2018-05-01 16:26 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-01-30 13:53 [PATCH v2 0/8] Update EDKII Performance infrastructure based on ACPI FPDT table Dandan Bi
2018-01-30 13:53 ` [PATCH v2 1/8] MdeModulePkg:Add definitions for new Performance infrastructure Dandan Bi
2018-01-31 2:07 ` Zeng, Star
2018-01-30 13:53 ` [PATCH v2 2/8] MdeModulePkg/PeiPerformance:Updated to track FPDT record in PEI phase Dandan Bi
2018-01-30 13:53 ` [PATCH v2 3/8] MdeModulePkg/DxeCorePerformanceLib:Track FPDT record in DXE phase Dandan Bi
2018-05-01 16:26 ` Ard Biesheuvel [this message]
2018-05-22 0:33 ` Bi, Dandan
2018-05-22 8:51 ` Ard Biesheuvel
2018-05-22 8:58 ` Zeng, Star
2018-05-22 9:02 ` Ard Biesheuvel
2018-05-22 9:38 ` Zeng, Star
2018-05-22 10:00 ` Laszlo Ersek
2018-05-22 10:38 ` Zeng, Star
2018-05-22 10:43 ` Ard Biesheuvel
2018-05-22 10:00 ` Ard Biesheuvel
2018-01-30 13:53 ` [PATCH v2 4/8] MdeModulePkg/SmmCorePerformanceLib:Track FPDT record in SMM phase Dandan Bi
2018-01-30 13:53 ` [PATCH v2 5/8] MdeModulePkg/FirmwarePerformancePei:Add FPDT records for S3 phase Dandan Bi
2018-01-30 13:53 ` [PATCH v2 6/8] MdeModulePkg/FirmwarePerfDxe:Enhance for new pref infrastructure Dandan Bi
2018-01-30 13:53 ` [PATCH v2 7/8] MdeModulePkg/FirmwarePerfSmm:Enhance " Dandan Bi
2018-01-30 13:53 ` [PATCH v2 8/8] ShellPkg/Dp: Updated to dump perf log based on FPDT table Dandan Bi
2020-04-28 7:45 ` [edk2-devel] [PATCH v2 0/8] Update EDKII Performance infrastructure based on ACPI " boonewang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='CAKv+Gu8eUd7S4or41HAiUfb49ROVzJ+xaZG3nq8C_EKktNc=gA@mail.gmail.com' \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox