From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=2607:f8b0:4001:c06::22a; helo=mail-io0-x22a.google.com; envelope-from=ard.biesheuvel@linaro.org; receiver=edk2-devel@lists.01.org Received: from mail-io0-x22a.google.com (mail-io0-x22a.google.com [IPv6:2607:f8b0:4001:c06::22a]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id C8A8021B02845 for ; Tue, 22 May 2018 01:51:43 -0700 (PDT) Received: by mail-io0-x22a.google.com with SMTP id e20-v6so17544719iof.4 for ; Tue, 22 May 2018 01:51:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=dfqbj/nisA2uu8YyYQnhjhCfD8YDIk8Z1r6UuLUyDn8=; b=KAiUF+GRvFevs6/ZID3XgbUcZkFCEs0ly93TBpxv5agShM6kX6N3MAkFyTM29DkxQo 2G/8NUSYh8uUEOeHKS+pWBYSFf5GIR2fjLz2t/ftR6YM6i8hsWCu6RbRqgVHJgWwkqc1 FYkqdI2f4m30O+0z0b/K7Bj19bKIus2TyWTKU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=dfqbj/nisA2uu8YyYQnhjhCfD8YDIk8Z1r6UuLUyDn8=; b=nFSDlnoiQA2tXvyrSIbCXJ1M/j/LG5GL75we5DFXJP/LlPAx5cZFwj87VBgpDMa/+t rmy6cIYXqqnuGazv6nUSdCubyg8VsUeHdoUfIDntKiy7XFEwN9TDRuncHKxpYwTc7pu5 HxA5aBXN+aq+lRKJ9AyqB2AipCmqhMx38p53H3rqiTA4dzqw5jLUwo8Q4ltvyELZ6bs9 XLRouaDebMSbd2y4CYI9axbM3x4mJA3Qwb2YCp9kHwv2Z68prWKNt2uBiPE78ad9Pz/V MlATGAiRVLZK9/xJDE2DnlrMCNet6b77W2motcm5nHk4adD7AKWRjmwE1QkqrSXuFISz RPhA== X-Gm-Message-State: ALKqPwe6y2nTRM4ENLK5tvv4t0xtRb9quv1QAz+slWeVmryDS9SF5Xs0 fNHZuvxFEZMJdUxT68aQHgHrwjNj9+kHalrUHYQAYQ== X-Google-Smtp-Source: AB8JxZqzcNxsqvjU8SCgqKZUuuBgmPXm+OZVJkQRPGJisZyY5u+nhlTbWeHeFRhrPPks3PP9yCYrzYOOXB1GLbwkU/c= X-Received: by 2002:a6b:268b:: with SMTP id m133-v6mr25804206iom.107.1526979102371; Tue, 22 May 2018 01:51:42 -0700 (PDT) MIME-Version: 1.0 Received: by 10.107.187.134 with HTTP; Tue, 22 May 2018 01:51:41 -0700 (PDT) In-Reply-To: <3C0D5C461C9E904E8F62152F6274C0BB3BAD755F@shsmsx102.ccr.corp.intel.com> References: <1517320437-11688-1-git-send-email-dandan.bi@intel.com> <1517320437-11688-4-git-send-email-dandan.bi@intel.com> <3C0D5C461C9E904E8F62152F6274C0BB3BAD755F@shsmsx102.ccr.corp.intel.com> From: Ard Biesheuvel Date: Tue, 22 May 2018 10:51:41 +0200 Message-ID: To: "Bi, Dandan" , Laszlo Ersek , Andrew Fish , "Kinney, Michael D" Cc: Leif Lindholm , "edk2-devel@lists.01.org" , "Zeng, Star" , "Gao, Liming" , Matt Sealey Subject: Re: [PATCH v2 3/8] MdeModulePkg/DxeCorePerformanceLib:Track FPDT record in DXE phase X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 22 May 2018 08:51:44 -0000 Content-Type: text/plain; charset="UTF-8" (+ Laszlo, Andrew, Mike) On 22 May 2018 at 02:33, Bi, Dandan wrote: > Sorry for the delayed response. > > The allocated performance table ( below 4G ) is to save the boot performance data in normal boot and S3 phase. > PEIM FirmwarePerformancePei will get the address of the performance table and update the performance date of S3 phase to the table. > The address need to be handled in PEI phase(32bit), that's the main reason why we allocate it below 4G. > The 32-bit PEI + 64-bit DXE combo is specific to X64. You have added code to a generic library that ASSERT()s if allocating memory below 4 GB fails, breaking non-PC architectures. So please, fix this. Or at least suggest a way around it so that other architectures can keep using this library. This is another consequence of our failure to model the special 32-bit PEI/64-bit DXE combination using proper PI interfaces, resulting in these kinds of breakages and open coded 4 GB allocations all throughout the code. Can we please work on getting this fixed? > -----Original Message----- > From: Ard Biesheuvel [mailto:ard.biesheuvel@linaro.org] > Sent: Wednesday, May 2, 2018 12:27 AM > To: Bi, Dandan ; Leif Lindholm > Cc: edk2-devel@lists.01.org; Zeng, Star ; Gao, Liming ; Matt Sealey > Subject: Re: [edk2] [PATCH v2 3/8] MdeModulePkg/DxeCorePerformanceLib:Track FPDT record in DXE phase > > On 30 January 2018 at 14:53, Dandan Bi 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 >> Cc: Star Zeng >> Contributed-under: TianoCore Contribution Agreement 1.1 >> Signed-off-by: Dandan Bi >> --- >> .../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.
>> +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
>> (C) Copyright 2016 Hewlett Packard Enterprise Development LP
>> 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.
>> +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
>> # (C) Copyright 2016 Hewlett Packard Enterprise Development LP
>> # 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.
>> +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
>> 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 >> >> #include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> >> #include >> #include >> #include >> #include >> #include >> #include >> #include >> #include >> +#include >> #include >> #include >> +#include >> +#include >> +#include >> >> // >> // 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