From nobody Fri Nov 1 14:28:36 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 1516679294631616.3165385681285; Mon, 22 Jan 2018 19:48:14 -0800 (PST) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id D835F2233379C; Mon, 22 Jan 2018 19:42:46 -0800 (PST) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 721B02233379C for ; Mon, 22 Jan 2018 19:42:44 -0800 (PST) Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 22 Jan 2018 19:48:10 -0800 Received: from shwdeopenpsi114.ccr.corp.intel.com ([10.239.157.135]) by orsmga008.jf.intel.com with ESMTP; 22 Jan 2018 19:48:09 -0800 X-Original-To: edk2-devel@lists.01.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=192.55.52.88; helo=mga01.intel.com; envelope-from=dandan.bi@intel.com; receiver=edk2-devel@lists.01.org X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.46,399,1511856000"; d="scan'208";a="12262539" From: Dandan Bi To: edk2-devel@lists.01.org Date: Tue, 23 Jan 2018 11:47:31 +0800 Message-Id: <1516679255-12328-5-git-send-email-dandan.bi@intel.com> X-Mailer: git-send-email 1.9.5.msysgit.1 In-Reply-To: <1516679255-12328-1-git-send-email-dandan.bi@intel.com> References: <1516679255-12328-1-git-send-email-dandan.bi@intel.com> Subject: [edk2] [patch 4/8] MdeModulePkg/SmmCorePerformanceLib:Track FPDT record in SMM phase X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Star Zeng , Liming Gao MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Updated to convert Pref entry to FPDT record in SMM phase and then export records to FPDT table. Cc: Liming Gao Cc: Star Zeng Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Dandan Bi --- .../SmmCorePerformanceLib/SmmCorePerformanceLib.c | 1094 ++++++++++++----= ---- .../SmmCorePerformanceLib.inf | 10 +- .../SmmCorePerformanceLibInternal.h | 11 +- 3 files changed, 681 insertions(+), 434 deletions(-) diff --git a/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceL= ib.c b/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c index cd1f1a5..cb880ef 100644 --- a/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c +++ b/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c @@ -14,11 +14,11 @@ This external input must be validated carefully to avoid security issue l= ike buffer overflow, integer overflow. =20 SmmPerformanceHandlerEx(), SmmPerformanceHandler() will receive untrusted= input and do basic validation. =20 -Copyright (c) 2011 - 2017, Intel Corporation. All rights reserved.
+Copyright (c) 2011 - 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 @@ -28,30 +28,32 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITH= ER EXPRESS OR IMPLIED. **/ =20 =20 #include "SmmCorePerformanceLibInternal.h" =20 -// -// The data structure to hold global performance data. -// -GAUGE_DATA_HEADER *mGaugeData; - -// -// The current maximum number of logging entries. If current number of=20 -// entries exceeds this value, it will re-allocate a larger array and -// migration the old data to the larger array. -// -UINT32 mMaxGaugeRecords; - -// -// The handle to install Performance Protocol instance. -// -EFI_HANDLE mHandle =3D NULL; - -BOOLEAN mPerformanceMeasurementEnabled; - -SPIN_LOCK mSmmPerfLock; +#define STRING_SIZE (EDKII_STRING_EVENT_RECORD_NAME_= LENGTH * sizeof (CHAR8)) +#define MAX_RECORD_SIZE (sizeof (FPDT_RECORD) + STRING_S= IZE) +#define FIRMWARE_RECORD_BUFFER 0x1000 +#define CACHE_HANDLE_GUID_COUNT 0x1000 + +typedef struct { + EFI_HANDLE Handle; + CHAR8 NameString[EDKII_STRING_EVENT_RECORD_NAME_LENGTH]; + EFI_GUID ModuleGuid; +} HANDLE_GUID_MAP; + +HANDLE_GUID_MAP mCacheHandleGuidTable[CACHE_HANDLE_GUID_COUNT]; +UINTN mCachePairCount =3D 0; + +UINT8 *mPerformancePointer =3D NULL; +UINTN mPerformanceLength =3D 0; +UINTN mMaxPerformanceLength =3D 0; +BOOLEAN mFpdtDataIsReported =3D FALSE; +BOOLEAN mStartFpdtDataReport =3D FALSE; +CHAR8 *mPlatformLanguage =3D NULL; +SPIN_LOCK mSmmFpdtLock; +PERFORMANCE_PROPERTY mPerformanceProperty; =20 // // Interfaces for SMM Performance Protocol. // PERFORMANCE_PROTOCOL mPerformanceInterface =3D { @@ -67,172 +69,634 @@ PERFORMANCE_EX_PROTOCOL mPerformanceExInterface =3D { StartGaugeEx, EndGaugeEx, GetGaugeEx }; =20 -PERFORMANCE_PROPERTY mPerformanceProperty; +/** +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) =3D=3D 0 || + AsciiStrCmp (Token, PEI_TOK) =3D=3D 0 || + AsciiStrCmp (Token, DXE_TOK) =3D=3D 0 || + AsciiStrCmp (Token, BDS_TOK) =3D=3D 0 || + AsciiStrCmp (Token, DRIVERBINDING_START_TOK) =3D=3D 0 || + AsciiStrCmp (Token, DRIVERBINDING_SUPPORT_TOK) =3D=3D 0 || + AsciiStrCmp (Token, DRIVERBINDING_STOP_TOK) =3D=3D 0 || + AsciiStrCmp (Token, LOAD_IMAGE_TOK) =3D=3D 0 || + AsciiStrCmp (Token, START_IMAGE_TOK) =3D=3D 0 || + AsciiStrCmp (Token, PEIM_TOK) =3D=3D 0) { + return TRUE; + } else { + return FALSE; + } +} =20 /** - Searches in the gauge array with keyword Handle, Token, Module and Ident= fier. +Check whether the ID is a known one which map to the known Token. + +@param Identifier 32-bit identifier. =20 - 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 re= turned; - otherwise, the the number of gauge entries in the array is returned. +@retval TRUE Is a known one used by core. +@retval FALSE Not a known one. =20 +**/ +BOOLEAN +IsKnownID ( + IN UINT32 Identifier + ) +{ + if (Identifier =3D=3D MODULE_START_ID || + Identifier =3D=3D MODULE_END_ID || + Identifier =3D=3D MODULE_LOADIMAGE_START_ID || + Identifier =3D=3D MODULE_LOADIMAGE_END_ID || + Identifier =3D=3D MODULE_DB_START_ID || + Identifier =3D=3D MODULE_DB_END_ID || + Identifier =3D=3D MODULE_DB_SUPPORT_START_ID || + Identifier =3D=3D MODULE_DB_SUPPORT_END_ID || + Identifier =3D=3D MODULE_DB_STOP_START_ID || + Identifier =3D=3D MODULE_DB_STOP_END_ID) { + return TRUE; + } else { + return FALSE; + } +} + +/** + 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 meas= ured. @param Module Pointer to a Null-terminated ASCII string that identifies the module being measure= d. - @param Identifier 32-bit identifier. + @param RecordInfo On return, pointer to the info of the re= cord. + @param UseModuleName Only useful for DYNAMIC_STRING_EVENT_TYP= E, indicate that whether need use + Module name to fill the string field in = the DYNAMIC_STRING_EVENT_RECORD. =20 - @retval The index of gauge entry in the array. + @retval EFI_SUCCESS Get record info successfully. + @retval EFI_UNSUPPORTED No matched FPDT record. =20 **/ -UINT32 -SmmSearchForGaugeEntry ( - IN CONST VOID *Handle, OPTIONAL - IN CONST CHAR8 *Token, OPTIONAL - IN CONST CHAR8 *Module, OPTIONAL - IN CONST 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; =20 - if (Token =3D=3D NULL) { - Token =3D ""; - } - if (Module =3D=3D NULL) { - Module =3D ""; + RecordType =3D DYNAMIC_STRING_EVENT_TYPE; + + // + // Token to Type and Id. + // + if (Token !=3D NULL) { + if (AsciiStrCmp (Token, START_IMAGE_TOK) =3D=3D 0) { // "= StartImage:" + *UseModuleName =3D TRUE; + RecordType =3D GUID_EVENT_TYPE; + if (IsStart) { + RecordInfo->ProgressID =3D MODULE_START_ID; + } else { + RecordInfo->ProgressID =3D MODULE_END_ID; + } + } else if (AsciiStrCmp (Token, LOAD_IMAGE_TOK) =3D=3D 0) { // "= LoadImage:" + *UseModuleName =3D TRUE; + RecordType =3D GUID_QWORD_EVENT_TYPE; + if (IsStart) { + RecordInfo->ProgressID =3D MODULE_LOADIMAGE_START_ID; + } else { + RecordInfo->ProgressID =3D MODULE_LOADIMAGE_END_ID; + } + } else { // Pref = used in Modules + if (IsStart) { + RecordInfo->ProgressID =3D PERF_INMODULE_START_ID; + } else { + RecordInfo->ProgressID =3D PERF_INMODULE_END_ID; + } + } + } else if (Handle !=3D NULL || Module !=3D NULL) { // Pr= ef used in Modules + if (IsStart) { + RecordInfo->ProgressID =3D PERF_INMODULE_START_ID; + } else { + RecordInfo->ProgressID =3D PERF_INMODULE_END_ID; + } + } else { + return EFI_UNSUPPORTED; } =20 - NumberOfEntries =3D mGaugeData->NumberOfEntries; - GaugeEntryExArray =3D (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1); + if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) { + RecordType =3D DYNAMIC_STRING_EVENT_TYPE; + RecordInfo->RecordSize =3D sizeof (DYNAMIC_STRING_EVENT_RECORD) + ST= RING_SIZE; + } else { + switch (RecordType) { + case GUID_EVENT_TYPE: + RecordInfo->RecordSize =3D sizeof (GUID_EVENT_RECORD); + break; =20 - Index2 =3D 0; + case DYNAMIC_STRING_EVENT_TYPE: + if (*UseModuleName) { + StringSize =3D STRING_SIZE; + } else if (Token !=3D NULL) { + StringSize =3D AsciiStrSize (Token); + } else if (Module !=3D NULL) { + StringSize =3D AsciiStrSize (Module); + } else { + StringSize =3D STRING_SIZE; + } + if (StringSize > STRING_SIZE) { + StringSize =3D STRING_SIZE; + } + RecordInfo->RecordSize =3D (UINT8)(sizeof (DYNAMIC_STRING_EVENT_REC= ORD) + StringSize); + break; =20 - for (Index =3D 0; Index < NumberOfEntries; Index++) { - Index2 =3D NumberOfEntries - 1 - Index; - if (GaugeEntryExArray[Index2].EndTimeStamp =3D=3D 0 && - (GaugeEntryExArray[Index2].Handle =3D=3D (EFI_PHYSICAL_ADDRESS) (U= INTN) Handle) && - AsciiStrnCmp (GaugeEntryExArray[Index2].Token, Token, SMM_PERFORMA= NCE_STRING_LENGTH) =3D=3D 0 && - AsciiStrnCmp (GaugeEntryExArray[Index2].Module, Module, SMM_PERFOR= MANCE_STRING_LENGTH) =3D=3D 0) { - Index =3D Index2; + case GUID_QWORD_EVENT_TYPE: + RecordInfo->RecordSize =3D (UINT8)sizeof (GUID_QWORD_EVENT_RECORD); break; + + default: + // + // Record type is unsupported in SMM phase. + // + return EFI_UNSUPPORTED; } } =20 - return Index; + RecordInfo->Type =3D RecordType; + return EFI_SUCCESS; } =20 /** - Adds a record at the end of the performance measurement log - that records the start time of a performance measurement. + Get a human readable module name and module guid for the given image han= dle. + 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 +EFIAPI +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; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFilePath; + + if (NameString =3D=3D NULL || BufferSize =3D=3D 0) { + return EFI_INVALID_PARAMETER; + } =20 - 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 ti= me 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. + // + // Try to get the ModuleGuid and name string form the caached array. + // + if (mCachePairCount > 0) { + for (Count =3D mCachePairCount - 1; Count >=3D 0; Count--) { + if (Handle =3D=3D mCacheHandleGuidTable[Count].Handle) { + CopyGuid (ModuleGuid, &mCacheHandleGuidTable[Count].ModuleGuid); + AsciiStrCpyS (NameString, EDKII_STRING_EVENT_RECORD_NAME_LENGTH, m= CacheHandleGuidTable[Count].NameString); + return EFI_SUCCESS; + } + } + } + + Status =3D EFI_INVALID_PARAMETER; + LoadedImage =3D NULL; + ModuleGuidIsGet =3D FALSE; + + // + // Initialize GUID as zero value. + // + TempGuid =3D &gZeroGuid; + // + // Initialize it as "" string. + // + NameString[0] =3D 0; =20 + if (Handle !=3D NULL) { + // + // Try Handle as ImageHandle. + // + Status =3D gBS->HandleProtocol ( + Handle, + &gEfiLoadedImageProtocolGuid, + (VOID**) &LoadedImage + ); + + if (EFI_ERROR (Status)) { + // + // Try Handle as Controller Handle + // + Status =3D gBS->OpenProtocol ( + Handle, + &gEfiDriverBindingProtocolGuid, + (VOID **) &DriverBinding, + NULL, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + // + // Get Image protocol from ImageHandle + // + Status =3D gBS->HandleProtocol ( + DriverBinding->ImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID**) &LoadedImage + ); + } + } + } + + if (!EFI_ERROR (Status) && LoadedImage !=3D NULL) { + // + // Get Module Guid from DevicePath. + // + if (LoadedImage->FilePath !=3D NULL && + LoadedImage->FilePath->Type =3D=3D MEDIA_DEVICE_PATH && + LoadedImage->FilePath->SubType =3D=3D MEDIA_PIWG_FW_FILE_DP + ) { + // + // Determine GUID associated with module logging performance + // + ModuleGuidIsGet =3D TRUE; + FvFilePath =3D (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LoadedImag= e->FilePath; + TempGuid =3D &FvFilePath->FvFileName; + } + + // + // Method 1 Get Module Name from PDB string. + // + PdbFileName =3D PeCoffLoaderGetPdbPointer (LoadedImage->ImageBase); + if (PdbFileName !=3D NULL && BufferSize > 0) { + StartIndex =3D 0; + for (Index =3D 0; PdbFileName[Index] !=3D 0; Index++) { + if ((PdbFileName[Index] =3D=3D '\\') || (PdbFileName[Index] =3D=3D= '/')) { + StartIndex =3D Index + 1; + } + } + // + // Copy the PDB file name to our temporary string. + // If the length is bigger than BufferSize, trim the redudant charac= ters to avoid overflow in array boundary. + // + for (Index =3D 0; Index < BufferSize - 1; Index++) { + NameString[Index] =3D PdbFileName[Index + StartIndex]; + if (NameString[Index] =3D=3D 0 || NameString[Index] =3D=3D '.') { + NameString[Index] =3D 0; + break; + } + } + + if (Index =3D=3D BufferSize - 1) { + NameString[Index] =3D 0; + } + // + // Module Name is got. + // + goto Done; + } + } + + if (ModuleGuidIsGet) { + // + // Method 2 Try to get the image's FFS UI section by image GUID + // + StringPtr =3D NULL; + StringSize =3D 0; + Status =3D 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 =3D 0; Index < BufferSize - 1 && StringPtr[Index] !=3D 0;= Index++) { + NameString[Index] =3D (CHAR8) StringPtr[Index]; + } + NameString[Index] =3D 0; + FreePool (StringPtr); + } + } + +Done: + // + // Copy Module Guid + // + if (ModuleGuid !=3D NULL) { + CopyGuid (ModuleGuid, TempGuid); + if (IsZeroGuid(TempGuid) && (Handle !=3D 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 =3D Handle; + CopyGuid (&mCacheHandleGuidTable[mCachePairCount].ModuleGuid, ModuleGu= id); + AsciiStrCpyS (mCacheHandleGuidTable[mCachePairCount].NameString, EDKII= _STRING_EVENT_RECORD_NAME_LENGTH, NameString); + mCachePairCount ++; + } + + return Status; +} + +/** + 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 meas= ured. @param Module Pointer to a Null-terminated ASCII string that identifies the module being measure= d. - @param TimeStamp 64-bit time stamp. + @param Ticker 64-bit time stamp. @param Identifier 32-bit identifier. If the value is 0, th= e created record is same as the one created by StartGauge= of PERFORMANCE_PROTOCOL. =20 - @retval EFI_SUCCESS The data was read correctly from the dev= ice. + @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. =20 **/ 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_GUID ModuleGuid; + CHAR8 ModuleName[EDKII_STRING_EVENT_RECORD_NAME_L= ENGTH]; + UINT8 FpdtRecord[MAX_RECORD_SIZE]; + EFI_STATUS Status; + FPDT_RECORD_PTR FpdtRecordPtr; + UINT64 TimeStamp; + BASIC_RECORD_INFO RecordInfo; + UINTN DestMax; + UINTN StrLength; + CONST CHAR8 *StringPtr; + BOOLEAN UseModuleName; + + StringPtr =3D NULL; + UseModuleName =3D FALSE; + ZeroMem (ModuleName, sizeof (ModuleName)); + ZeroMem (FpdtRecord, sizeof (FpdtRecord)); =20 - AcquireSpinLock (&mSmmPerfLock); + // + // Get record info includes type, size, ProgressID. + // + Status =3D GetFpdtRecordInfo (IsStart, Handle, Token, Module, &RecordInf= o, &UseModuleName); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // 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 hav= e 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 !=3D 0) && (IsKnownID (Identifier)) && (!IsKnownTokens (= Token))) { + return EFI_UNSUPPORTED; + } else if ((Identifier !=3D 0) && (!IsKnownID (Identifier)) && (!IsKnown= Tokens (Token))) { + if (IsStart && ((Identifier & 0x000F) !=3D 0)) { + Identifier &=3D 0xFFF0; + } else if ((!IsStart) && ((Identifier & 0x000F) =3D=3D 0)) { + Identifier +=3D 1; + } + RecordInfo.ProgressID =3D (UINT16)Identifier; + } =20 - Index =3D mGaugeData->NumberOfEntries; - if (Index >=3D mMaxGaugeRecords) { + if (mFpdtDataIsReported) { // - // Try to enlarge the scale of gauge array. + // Cached FPDT data has been reported. Now, report FPDT record one by = one. // - OldGaugeData =3D mGaugeData; - OldGaugeDataSize =3D sizeof (GAUGE_DATA_HEADER) + sizeof (GAUGE_DATA_= ENTRY_EX) * mMaxGaugeRecords; - - GaugeDataSize =3D sizeof (GAUGE_DATA_HEADER) + sizeof (GAUGE_DATA_= ENTRY_EX) * mMaxGaugeRecords * 2; - - NewGaugeData =3D AllocateZeroPool (GaugeDataSize); - if (NewGaugeData =3D=3D NULL) { - ReleaseSpinLock (&mSmmPerfLock); - return EFI_OUT_OF_RESOURCES; + FpdtRecordPtr.RecordHeader =3D (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_H= EADER *)FpdtRecord; + } else { + if (mStartFpdtDataReport) { + return EFI_UNSUPPORTED; + } + // + // Check if pre-allocated buffer is full + // + if (mPerformanceLength + RecordInfo.RecordSize > mMaxPerformanceLength= ) { + mPerformancePointer =3D ReallocatePool ( + mPerformanceLength, + mPerformanceLength + RecordInfo.RecordSize += FIRMWARE_RECORD_BUFFER, + mPerformancePointer + ); + + if (mPerformancePointer =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + mMaxPerformanceLength =3D mPerformanceLength + RecordInfo.RecordSize= + FIRMWARE_RECORD_BUFFER; } - - mGaugeData =3D NewGaugeData; - mMaxGaugeRecords *=3D 2; - // - // Initialize new data array and migrate old data one. + // Covert buffer to FPDT Ptr Union type. // - mGaugeData =3D CopyMem (mGaugeData, OldGaugeData, OldGaugeDataSize); + FpdtRecordPtr.RecordHeader =3D (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_H= EADER *)(mPerformancePointer + mPerformanceLength); + } + FpdtRecordPtr.RecordHeader->Length =3D 0; =20 - FreePool (OldGaugeData); + // + // Get the TimeStamp. + // + if (Ticker =3D=3D 0) { + Ticker =3D GetPerformanceCounter (); + TimeStamp =3D GetTimeInNanoSecond (Ticker); + } else if (Ticker =3D=3D 1) { + TimeStamp =3D 0; + } else { + TimeStamp =3D GetTimeInNanoSecond (Ticker); } =20 - GaugeEntryExArray =3D (GAUGE_DATA_ENTRY_EX *) (mGaugeData = + 1); - GaugeEntryExArray[Index].Handle =3D (EFI_PHYSICAL_ADDRESS) (UINTN) Handl= e; + // + // Get the ModuleName and ModuleGuid form the handle. + // + GetModuleInfoFromHandle ((EFI_HANDLE *)Handle, ModuleName, sizeof (Modul= eName), &ModuleGuid); =20 - if (Token !=3D NULL) { - AsciiStrnCpyS (GaugeEntryExArray[Index].Token, SMM_PERFORMANCE_STRING_= SIZE, Token, SMM_PERFORMANCE_STRING_LENGTH); + // + // Fill in the record information. + // + switch (RecordInfo.Type) { + case GUID_EVENT_TYPE: + FpdtRecordPtr.GuidEvent->Header.Type =3D GUID_EVENT_TYP= E; + FpdtRecordPtr.GuidEvent->Header.Length =3D RecordInfo.Rec= ordSize; + FpdtRecordPtr.GuidEvent->Header.Revision =3D RECORD_REVISIO= N_1; + FpdtRecordPtr.GuidEvent->ProgressID =3D RecordInfo.Pro= gressID; + FpdtRecordPtr.GuidEvent->Timestamp =3D TimeStamp; + CopyMem (&FpdtRecordPtr.GuidEvent->Guid, &ModuleGuid, sizeof (FpdtReco= rdPtr.GuidEvent->Guid)); + break; + + case DYNAMIC_STRING_EVENT_TYPE: + FpdtRecordPtr.DynamicStringEvent->Header.Type =3D DYNAMIC_STRING= _EVENT_TYPE; + FpdtRecordPtr.DynamicStringEvent->Header.Length =3D RecordInfo.Rec= ordSize; + FpdtRecordPtr.DynamicStringEvent->Header.Revision =3D RECORD_REVISIO= N_1; + FpdtRecordPtr.DynamicStringEvent->ProgressID =3D RecordInfo.Pro= gressID; + FpdtRecordPtr.DynamicStringEvent->Timestamp =3D TimeStamp; + CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof = (FpdtRecordPtr.DynamicStringEvent->Guid)); + + if (UseModuleName) { + StringPtr =3D ModuleName; + } else if (Token !=3D NULL) { + StringPtr =3D Token; + } else if (Module !=3D NULL) { + StringPtr =3D Module; + } else if (ModuleName !=3D NULL) { + StringPtr =3D ModuleName; + } + if (StringPtr !=3D NULL && AsciiStrLen (StringPtr) !=3D 0) { + StrLength =3D AsciiStrLen (StringPtr); + DestMax =3D (RecordInfo.RecordSize - sizeof (DYNAMIC_STRING_EV= ENT_RECORD)) / sizeof (CHAR8); + if (StrLength >=3D DestMax) { + StrLength =3D DestMax -1; + } + AsciiStrnCpyS (FpdtRecordPtr.DynamicStringEvent->String, DestMax, St= ringPtr, StrLength); + } + break; + + case GUID_QWORD_EVENT_TYPE: + FpdtRecordPtr.GuidQwordEvent->Header.Type =3D GUID_QWORD_EVE= NT_TYPE; + FpdtRecordPtr.GuidQwordEvent->Header.Length =3D RecordInfo.Rec= ordSize; + FpdtRecordPtr.GuidQwordEvent->Header.Revision =3D RECORD_REVISIO= N_1; + FpdtRecordPtr.GuidQwordEvent->ProgressID =3D RecordInfo.Pro= gressID; + FpdtRecordPtr.GuidQwordEvent->Timestamp =3D TimeStamp; + CopyMem (&FpdtRecordPtr.GuidQwordEvent->Guid, &ModuleGuid, sizeof (Fpd= tRecordPtr.GuidQwordEvent->Guid)); + break; + + default: + // + // Record is not supported in current SMM phase, return EFI_UNSUPPORTED + // + return EFI_UNSUPPORTED; } - if (Module !=3D NULL) { - AsciiStrnCpyS (GaugeEntryExArray[Index].Module, SMM_PERFORMANCE_STRING= _SIZE, Module, SMM_PERFORMANCE_STRING_LENGTH); + // + // Report record one by one after records have been reported together. + // + if (mFpdtDataIsReported) { + REPORT_STATUS_CODE_EX ( + EFI_PROGRESS_CODE, + EFI_SOFTWARE_SMM_DRIVER, + 0, + NULL, + &gEfiFirmwarePerformanceGuid, + FpdtRecordPtr.RecordHeader, + FpdtRecordPtr.RecordHeader->Length + ); + } else { + // + // Update the cached FPDT record buffer. + // + mPerformanceLength +=3D FpdtRecordPtr.RecordHeader->Length; } =20 - GaugeEntryExArray[Index].EndTimeStamp =3D 0; - GaugeEntryExArray[Index].Identifier =3D Identifier; + return EFI_SUCCESS; +} =20 - if (TimeStamp =3D=3D 0) { - TimeStamp =3D GetPerformanceCounter (); - } - GaugeEntryExArray[Index].StartTimeStamp =3D TimeStamp; +/** + Adds a record at the end of the performance measurement log + that records the start time of a performance measurement. =20 - mGaugeData->NumberOfEntries++; + 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 ti= me 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. =20 - ReleaseSpinLock (&mSmmPerfLock); + @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 meas= ured. + @param Module Pointer to a Null-terminated ASCII string + that identifies the module being measure= d. + @param TimeStamp 64-bit time stamp. + @param Identifier 32-bit identifier. If the value is 0, th= e created record + is same as the one created by StartGauge= of PERFORMANCE_PROTOCOL. =20 - return EFI_SUCCESS; + @retval EFI_SUCCESS The data was read correctly from the dev= ice. + @retval EFI_OUT_OF_RESOURCES There are not enough resources to record= the measurement. + +**/ +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 + ) +{ + EFI_STATUS Status; + + AcquireSpinLock (&mSmmFpdtLock); + + Status =3D InsertFpdtMeasurement (TRUE, Handle, Token, Module, TimeStamp= , Identifier); + + ReleaseSpinLock (&mSmmFpdtLock); + + return Status; } =20 /** 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. =20 Searches the performance measurement log from the beginning of the log - for the first record that matches Handle, Token and Module and has an en= d time value of zero. + for the first record that matches Handle, Token, Module and Identifier a= nd 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 m= atching record is filled in with the current time stamp value. @@ -259,37 +723,28 @@ EndGaugeEx ( IN CONST CHAR8 *Module, OPTIONAL IN UINT64 TimeStamp, IN UINT32 Identifier ) { - GAUGE_DATA_ENTRY_EX *GaugeEntryExArray; - UINT32 Index; + EFI_STATUS Status; =20 - AcquireSpinLock (&mSmmPerfLock); + AcquireSpinLock (&mSmmFpdtLock); =20 - if (TimeStamp =3D=3D 0) { - TimeStamp =3D GetPerformanceCounter (); - } - - Index =3D SmmSearchForGaugeEntry (Handle, Token, Module, Identifier); - if (Index >=3D mGaugeData->NumberOfEntries) { - ReleaseSpinLock (&mSmmPerfLock); - return EFI_NOT_FOUND; - } - GaugeEntryExArray =3D (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1); - GaugeEntryExArray[Index].EndTimeStamp =3D TimeStamp; + Status =3D InsertFpdtMeasurement (FALSE, Handle, Token, Module, TimeStam= p, Identifier); =20 - ReleaseSpinLock (&mSmmPerfLock); + ReleaseSpinLock (&mSmmFpdtLock); =20 - return EFI_SUCCESS; + return Status; } =20 /** Retrieves a previously logged performance measurement. It can also retrieve the log created by StartGauge and EndGauge of PERFO= RMANCE_PROTOCOL, and then assign the Identifier with 0. =20 + !!! Not Support!!! + Retrieves the performance log entry from the performance log specified b= y LogEntryKey. If it stands for a valid entry, then EFI_SUCCESS is returned and GaugeDataEntryEx stores the pointer to that entry. =20 @param LogEntryKey The key for the previous performance mea= surement log entry. @@ -308,29 +763,11 @@ EFIAPI GetGaugeEx ( IN UINTN LogEntryKey, OUT GAUGE_DATA_ENTRY_EX **GaugeDataEntryEx ) { - UINTN NumberOfEntries; - GAUGE_DATA_ENTRY_EX *GaugeEntryExArray; - - NumberOfEntries =3D (UINTN) (mGaugeData->NumberOfEntries); - if (LogEntryKey > NumberOfEntries) { - return EFI_INVALID_PARAMETER; - } - if (LogEntryKey =3D=3D NumberOfEntries) { - return EFI_NOT_FOUND; - } - - GaugeEntryExArray =3D (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1); - - if (GaugeDataEntryEx =3D=3D NULL) { - return EFI_INVALID_PARAMETER; - } - *GaugeDataEntryEx =3D &GaugeEntryExArray[LogEntryKey]; - - return EFI_SUCCESS; + return EFI_UNSUPPORTED; } =20 /** Adds a record at the end of the performance measurement log that records the start time of a performance measurement. @@ -405,10 +842,12 @@ EndGauge ( /** Retrieves a previously logged performance measurement. It can also retrieve the log created by StartGaugeEx and EndGaugeEx of P= ERFORMANCE_EX_PROTOCOL, and then eliminate the Identifier. =20 + !!! Not Support!!! + Retrieves the performance log entry from the performance log specified b= y LogEntryKey. If it stands for a valid entry, then EFI_SUCCESS is returned and GaugeDataEntry stores the pointer to that entry. =20 @param LogEntryKey The key for the previous performance mea= surement log entry. @@ -427,256 +866,90 @@ EFIAPI GetGauge ( IN UINTN LogEntryKey, OUT GAUGE_DATA_ENTRY **GaugeDataEntry ) { - EFI_STATUS Status; - GAUGE_DATA_ENTRY_EX *GaugeEntryEx; + return EFI_UNSUPPORTED; +} =20 - GaugeEntryEx =3D NULL; =20 - Status =3D GetGaugeEx (LogEntryKey, &GaugeEntryEx); - if (EFI_ERROR (Status)) { - return Status; - } +/** + SMM END_OF_DXE protocol notification event handler. =20 - if (GaugeDataEntry =3D=3D NULL) { - return EFI_INVALID_PARAMETER; - } + @param Protocol Points to the protocol's unique identifier + @param Interface Points to the interface instance + @param Handle The handle on which the interface was installed =20 - *GaugeDataEntry =3D (GAUGE_DATA_ENTRY *) GaugeEntryEx; + @retval EFI_SUCCESS SmmEndOfDxeCallback runs successfully =20 - return EFI_SUCCESS; -} - -/** - Communication service SMI Handler entry. - - This SMI handler provides services for the performance wrapper driver. - =20 - Caution: This function may receive untrusted input. - Communicate buffer and buffer size are external input, so this function= will do basic validation. - - @param[in] DispatchHandle The unique handle assigned to this handle= r by SmiHandlerRegister(). - @param[in] RegisterContext Points to an optional handler context whi= ch was specified when the - handler was registered. - @param[in, out] CommBuffer A pointer to a collection of data in memo= ry that will - be conveyed from a non-SMM environment in= to an SMM environment. - @param[in, out] CommBufferSize The size of the CommBuffer. - - @retval EFI_SUCCESS The interrupt was handled an= d quiesced. No other handlers=20 - should still be called. - @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quies= ced but other handlers should=20 - still be called. - @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pendi= ng and other handlers should still=20 - be called. - @retval EFI_INTERRUPT_PENDING The interrupt could not be q= uiesced. **/ EFI_STATUS EFIAPI -SmmPerformanceHandlerEx ( - IN EFI_HANDLE DispatchHandle, - IN CONST VOID *RegisterContext, - IN OUT VOID *CommBuffer, - IN OUT UINTN *CommBufferSize +SmmReportFpdtRecordData ( + IN CONST EFI_GUID *Protocol, + IN VOID *Interface, + IN EFI_HANDLE Handle ) { - EFI_STATUS Status; - SMM_PERF_COMMUNICATE_EX *SmmPerfCommData; - GAUGE_DATA_ENTRY_EX *GaugeEntryExArray; - UINT64 DataSize; - UINTN Index; - GAUGE_DATA_ENTRY_EX *GaugeDataEx; - UINTN NumberOfEntries; - UINTN LogEntryKey; - UINTN TempCommBufferSize; + UINT8 *PerfBuffer; + UINTN MaxUint16; =20 - GaugeEntryExArray =3D NULL; + PerfBuffer =3D mPerformancePointer; + MaxUint16 =3D 0xFFFF; =20 - // - // If input is invalid, stop processing this SMI - // - if (CommBuffer =3D=3D NULL || CommBufferSize =3D=3D NULL) { + if ( mPerformanceLength=3D=3D 0 || mPerformancePointer =3D=3D NULL) { return EFI_SUCCESS; } =20 - TempCommBufferSize =3D *CommBufferSize; + mStartFpdtDataReport =3D TRUE; =20 - if(TempCommBufferSize < sizeof (SMM_PERF_COMMUNICATE_EX)) { - return EFI_SUCCESS; - } - - if (!SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize))= { - DEBUG ((EFI_D_ERROR, "SmmPerformanceHandlerEx: SMM communcation data b= uffer in SMRAM or overflow!\n")); - return EFI_SUCCESS; - } - =20 - SmmPerfCommData =3D (SMM_PERF_COMMUNICATE_EX *)CommBuffer; - - switch (SmmPerfCommData->Function) { - case SMM_PERF_FUNCTION_GET_GAUGE_ENTRY_NUMBER : - SmmPerfCommData->NumberOfEntries =3D mGaugeData->NumberOfEntries; - Status =3D EFI_SUCCESS; - break; - - case SMM_PERF_FUNCTION_GET_GAUGE_DATA : - GaugeDataEx =3D SmmPerfCommData->GaugeDataEx; - NumberOfEntries =3D SmmPerfCommData->NumberOfEntries; - LogEntryKey =3D SmmPerfCommData->LogEntryKey; - if (GaugeDataEx =3D=3D NULL || NumberOfEntries =3D=3D 0 || LogEntry= Key > mGaugeData->NumberOfEntries || - NumberOfEntries > mGaugeData->NumberOfEntries || LogEntryKey > = (mGaugeData->NumberOfEntries - NumberOfEntries)) { - Status =3D EFI_INVALID_PARAMETER; - break; - } - - // - // Sanity check - // - DataSize =3D MultU64x32 (NumberOfEntries, sizeof(GAUGE_DATA_ENTRY_E= X)); - if (!SmmIsBufferOutsideSmmValid ((UINTN) GaugeDataEx, DataSize)) { - DEBUG ((EFI_D_ERROR, "SmmPerformanceHandlerEx: SMM Performance Da= ta buffer in SMRAM or overflow!\n")); - Status =3D EFI_ACCESS_DENIED; - break; - } - - GaugeEntryExArray =3D (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1); - - for (Index =3D 0; Index < NumberOfEntries; Index++) { - CopyMem ( - (UINT8 *) &GaugeDataEx[Index], - (UINT8 *) &GaugeEntryExArray[LogEntryKey++], - sizeof (GAUGE_DATA_ENTRY_EX) - ); - } - Status =3D EFI_SUCCESS; - break; - - default: - Status =3D EFI_UNSUPPORTED; + while (mPerformanceLength > MaxUint16) { + // + // Report extension data size is UINT16. So, the size of report data c= an't exceed 0xFFFF. + // + REPORT_STATUS_CODE_EX ( + EFI_PROGRESS_CODE, + EFI_SOFTWARE_SMM_DRIVER, + 0, + NULL, + &gEfiFirmwarePerformanceGuid, + PerfBuffer, + MaxUint16 + ); + mPerformanceLength =3D mPerformanceLength - MaxUint16; + PerfBuffer =3D PerfBuffer + MaxUint16; } =20 - - SmmPerfCommData->ReturnStatus =3D Status; - =20 - return EFI_SUCCESS; -} - -/** - Communication service SMI Handler entry. - - This SMI handler provides services for the performance wrapper driver. - - Caution: This function may receive untrusted input. - Communicate buffer and buffer size are external input, so this function = will do basic validation. - - @param[in] DispatchHandle The unique handle assigned to this handle= r by SmiHandlerRegister(). - @param[in] RegisterContext Points to an optional handler context whi= ch was specified when the - handler was registered. - @param[in, out] CommBuffer A pointer to a collection of data in memo= ry that will - be conveyed from a non-SMM environment in= to an SMM environment. - @param[in, out] CommBufferSize The size of the CommBuffer. - - @retval EFI_SUCCESS The interrupt was handled an= d quiesced. No other handlers=20 - should still be called. - @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quies= ced but other handlers should=20 - still be called. - @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pendi= ng and other handlers should still=20 - be called. - @retval EFI_INTERRUPT_PENDING The interrupt could not be q= uiesced. -**/ -EFI_STATUS -EFIAPI -SmmPerformanceHandler ( - IN EFI_HANDLE DispatchHandle, - IN CONST VOID *RegisterContext, - IN OUT VOID *CommBuffer, - IN OUT UINTN *CommBufferSize - ) -{ - EFI_STATUS Status; - SMM_PERF_COMMUNICATE *SmmPerfCommData; - GAUGE_DATA_ENTRY_EX *GaugeEntryExArray; - UINT64 DataSize; - UINTN Index; - GAUGE_DATA_ENTRY *GaugeData; - UINTN NumberOfEntries; - UINTN LogEntryKey; - UINTN TempCommBufferSize; - - GaugeEntryExArray =3D NULL; + REPORT_STATUS_CODE_EX ( + EFI_PROGRESS_CODE, + EFI_SOFTWARE_SMM_DRIVER, + 0, + NULL, + &gEfiFirmwarePerformanceGuid, + PerfBuffer, + mPerformanceLength + ); =20 // - // If input is invalid, stop processing this SMI + // Free Cached FPDT record Buffer // - if (CommBuffer =3D=3D NULL || CommBufferSize =3D=3D NULL) { - return EFI_SUCCESS; - } - - TempCommBufferSize =3D *CommBufferSize; - - if(TempCommBufferSize < sizeof (SMM_PERF_COMMUNICATE)) { - return EFI_SUCCESS; - } - - if (!SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize))= { - DEBUG ((EFI_D_ERROR, "SmmPerformanceHandler: SMM communcation data buf= fer in SMRAM or overflow!\n")); - return EFI_SUCCESS; - } - - SmmPerfCommData =3D (SMM_PERF_COMMUNICATE *)CommBuffer; - - switch (SmmPerfCommData->Function) { - case SMM_PERF_FUNCTION_GET_GAUGE_ENTRY_NUMBER : - SmmPerfCommData->NumberOfEntries =3D mGaugeData->NumberOfEntries; - Status =3D EFI_SUCCESS; - break; - - case SMM_PERF_FUNCTION_GET_GAUGE_DATA : - GaugeData =3D SmmPerfCommData->GaugeData; - NumberOfEntries =3D SmmPerfCommData->NumberOfEntries; - LogEntryKey =3D SmmPerfCommData->LogEntryKey; - if (GaugeData =3D=3D NULL || NumberOfEntries =3D=3D 0 || LogEntryKe= y > mGaugeData->NumberOfEntries || - NumberOfEntries > mGaugeData->NumberOfEntries || LogEntryKey > = (mGaugeData->NumberOfEntries - NumberOfEntries)) { - Status =3D EFI_INVALID_PARAMETER; - break; - } - - // - // Sanity check - // - DataSize =3D MultU64x32 (NumberOfEntries, sizeof(GAUGE_DATA_ENTRY)); - if (!SmmIsBufferOutsideSmmValid ((UINTN) GaugeData, DataSize)) { - DEBUG ((EFI_D_ERROR, "SmmPerformanceHandler: SMM Performance Data= buffer in SMRAM or overflow!\n")); - Status =3D EFI_ACCESS_DENIED; - break; - } - - GaugeEntryExArray =3D (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1); - - for (Index =3D 0; Index < NumberOfEntries; Index++) { - CopyMem ( - (UINT8 *) &GaugeData[Index], - (UINT8 *) &GaugeEntryExArray[LogEntryKey++], - sizeof (GAUGE_DATA_ENTRY) - ); - } - Status =3D EFI_SUCCESS; - break; - - default: - Status =3D EFI_UNSUPPORTED; - } - + FreePool (mPerformancePointer); + mPerformancePointer =3D NULL; + mPerformanceLength =3D 0; + mMaxPerformanceLength =3D 0; + // + // Set FPDT report state to TRUE. + // + mFpdtDataIsReported =3D TRUE; + mStartFpdtDataReport =3D FALSE; =20 - SmmPerfCommData->ReturnStatus =3D Status; - =20 return EFI_SUCCESS; } =20 /** - SmmBase2 protocol notify callback function, when SMST and SMM memory ser= vice get initialized=20 - this function is callbacked to initialize the Smm Performance Lib=20 + SmmBase2 protocol notify callback function, when SMST and SMM memory ser= vice get initialized + this function is callbacked to initialize the Smm Performance Lib =20 @param Event The event of notify protocol. @param Context Notify event context. =20 **/ @@ -685,52 +958,44 @@ EFIAPI InitializeSmmCorePerformanceLib ( IN EFI_EVENT Event, IN VOID *Context ) { - EFI_STATUS Status; EFI_HANDLE Handle; + EFI_STATUS Status; + VOID *SmmReadyToBootRegistration; PERFORMANCE_PROPERTY *PerformanceProperty; =20 // // Initialize spin lock // - InitializeSpinLock (&mSmmPerfLock); - - mMaxGaugeRecords =3D INIT_SMM_GAUGE_DATA_ENTRIES; + InitializeSpinLock (&mSmmFpdtLock); =20 - mGaugeData =3D AllocateZeroPool (sizeof (GAUGE_DATA_HEADER) + (sizeof (G= AUGE_DATA_ENTRY_EX) * mMaxGaugeRecords)); - ASSERT (mGaugeData !=3D NULL); - =20 // - // Install the protocol interfaces. + // Install the protocol interfaces for SMM performance library instance. // + Handle =3D NULL; Status =3D gSmst->SmmInstallProtocolInterface ( - &mHandle, + &Handle, &gSmmPerformanceProtocolGuid, EFI_NATIVE_INTERFACE, &mPerformanceInterface ); ASSERT_EFI_ERROR (Status); - Status =3D gSmst->SmmInstallProtocolInterface ( - &mHandle, + &Handle, &gSmmPerformanceExProtocolGuid, EFI_NATIVE_INTERFACE, &mPerformanceExInterface ); ASSERT_EFI_ERROR (Status); =20 - /// - /// Register SMM Performance SMI handler - /// - Handle =3D NULL; - Status =3D gSmst->SmiHandlerRegister (SmmPerformanceHandler, &gSmmPerfor= manceProtocolGuid, &Handle); - ASSERT_EFI_ERROR (Status); - Status =3D gSmst->SmiHandlerRegister (SmmPerformanceHandlerEx, &gSmmPerf= ormanceExProtocolGuid, &Handle); - ASSERT_EFI_ERROR (Status); - + Status =3D gSmst->SmmRegisterProtocolNotify ( + &gEdkiiSmmReadyToBootProtocolGuid, + SmmReportFpdtRecordData, + &SmmReadyToBootRegistration + ); Status =3D EfiGetSystemConfigurationTable (&gPerformanceProtocolGuid, (V= OID **) &PerformanceProperty); if (EFI_ERROR (Status)) { // // Install configuration table for performance property. // @@ -744,11 +1009,11 @@ InitializeSmmCorePerformanceLib ( ASSERT_EFI_ERROR (Status); } } =20 /** - The constructor function initializes the Performance Measurement Enable = flag and=20 + The constructor function initializes the Performance Measurement Enable = flag and registers SmmBase2 protocol notify callback. It will ASSERT() if one of these operations fails and it will always ret= urn EFI_SUCCESS. =20 @param ImageHandle The firmware allocated handle for the EFI image. @param SystemTable A pointer to the EFI System Table. @@ -765,12 +1030,11 @@ SmmCorePerformanceLibConstructor ( { EFI_STATUS Status; EFI_EVENT Event; VOID *Registration; =20 - mPerformanceMeasurementEnabled =3D (BOOLEAN) ((PcdGet8(PcdPerformanceLi= braryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) !=3D= 0); - if (!mPerformanceMeasurementEnabled) { + if (!PerformanceMeasurementEnabled ()) { // // Do not initialize performance infrastructure if not required. // return EFI_SUCCESS; } @@ -842,11 +1106,11 @@ StartPerformanceMeasurementEx ( /** 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. =20 Searches the performance measurement log from the beginning of the log - for the first record that matches Handle, Token and Module and has an en= d time value of zero. + for the first record that matches Handle, Token, Module and Identifier a= nd 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 m= atching record is filled in with the current time stamp value. @@ -881,10 +1145,12 @@ EndPerformanceMeasurementEx ( /** Attempts to retrieve a performance measurement log entry from the perfor= mance measurement log. It can also retrieve the log created by StartPerformanceMeasurement and = EndPerformanceMeasurement, and then assign the Identifier with 0. =20 + !!! 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 perform= ance 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 @@ -920,55 +1186,20 @@ EndPerformanceMeasurementEx ( =20 **/ UINTN EFIAPI GetPerformanceMeasurementEx ( - IN UINTN LogEntryKey,=20 + 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 =3D NULL; - =20 - ASSERT (Handle !=3D NULL); - ASSERT (Token !=3D NULL); - ASSERT (Module !=3D NULL); - ASSERT (StartTimeStamp !=3D NULL); - ASSERT (EndTimeStamp !=3D NULL); - ASSERT (Identifier !=3D NULL); - - Status =3D GetGaugeEx (LogEntryKey++, &GaugeData); - - // - // Make sure that LogEntryKey is a valid log entry key, - // - ASSERT (Status !=3D EFI_INVALID_PARAMETER); - - if (EFI_ERROR (Status)) { - // - // The LogEntryKey is the last entry (equals to the total entry number= ). - // - return 0; - } - - ASSERT (GaugeData !=3D NULL); - - *Handle =3D (VOID *) (UINTN) GaugeData->Handle; - *Token =3D GaugeData->Token; - *Module =3D GaugeData->Module; - *StartTimeStamp =3D GaugeData->StartTimeStamp; - *EndTimeStamp =3D GaugeData->EndTimeStamp; - *Identifier =3D GaugeData->Identifier; - - return LogEntryKey; + return 0; } =20 /** Adds a record at the end of the performance measurement log that records the start time of a performance measurement. @@ -999,11 +1230,11 @@ StartPerformanceMeasurement ( IN CONST CHAR8 *Token, OPTIONAL IN CONST CHAR8 *Module, OPTIONAL IN UINT64 TimeStamp ) { - return StartPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, = 0); + return StartGaugeEx (Handle, Token, Module, TimeStamp, 0); } =20 /** 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. @@ -1035,18 +1266,20 @@ EndPerformanceMeasurement ( IN CONST CHAR8 *Token, OPTIONAL IN CONST CHAR8 *Module, OPTIONAL IN UINT64 TimeStamp ) { - return EndPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0); + return EndGaugeEx (Handle, Token, Module, TimeStamp, 0); } =20 /** Attempts to retrieve a performance measurement log entry from the perfor= mance measurement log. It can also retrieve the log created by StartPerformanceMeasurementEx an= d EndPerformanceMeasurementEx, and then eliminate the Identifier. =20 + !!! 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 perform= ance 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 @@ -1088,12 +1321,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; } =20 /** Returns TRUE if the performance measurement macros are enabled. =20 @@ -1110,7 +1342,7 @@ BOOLEAN EFIAPI PerformanceMeasurementEnabled ( VOID ) { - return mPerformanceMeasurementEnabled; + return (BOOLEAN) ((PcdGet8(PcdPerformanceLibraryPropertyMask) & PERFORMA= NCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) !=3D 0); } diff --git a/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceL= ib.inf b/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.i= nf index 1b2fbd3..1d1841c 100644 --- a/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.inf +++ b/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.inf @@ -6,11 +6,11 @@ # It initializes SMM phase performance logging by publishing the SMM Perf= ormance and PerformanceEx Protocol, # which is consumed by SmmPerformanceLib to logging performance data in S= MM phase. # This library is mainly used by SMM Core to start performance logging to= ensure that # SMM Performance and PerformanceEx Protocol are installed at the very be= ginning of SMM phase. # =20 -# Copyright (c) 2011 - 2017, Intel Corporation. All rights reserved.
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
# This program and the accompanying materials # are licensed and made available under the terms and conditions of the B= SD License # which accompanies this distribution. The full text of the license may = be found at # http://opensource.org/licenses/bsd-license.php # =20 @@ -56,21 +56,27 @@ DebugLib SynchronizationLib SmmServicesTableLib SmmMemLib UefiLib + ReportStatusCodeLib + PeCoffGetEntryPointLib =20 [Protocols] gEfiSmmBase2ProtocolGuid ## CONSUMES + gEdkiiSmmReadyToBootProtocolGuid ## NOTIFY =20 [Guids] ## PRODUCES ## UNDEFINED # Install protocol ## CONSUMES ## UNDEFINED # SmiHandlerRegister gSmmPerformanceProtocolGuid ## PRODUCES ## UNDEFINED # Install protocol ## CONSUMES ## UNDEFINED # SmiHandlerRegister gSmmPerformanceExProtocolGuid ## PRODUCES ## SystemTable gPerformanceProtocolGuid + gEfiFirmwarePerformanceGuid ## SOMETIMES_PRODUCES ## UNDEF= INED # StatusCode Data + gZeroGuid ## SOMETIMES_CONSUMES ## GUID =20 [Pcd] - gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask ## CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask ## CON= SUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiFpdtStringRecordEnableOnly ## CON= SUMES diff --git a/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceL= ibInternal.h b/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanc= eLibInternal.h index 8eb3032..9d24d9f 100644 --- a/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLibInter= nal.h +++ b/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLibInter= nal.h @@ -2,11 +2,11 @@ Master header files for SmmCorePerformanceLib instance. =20 This header file holds the prototypes of the SMM Performance and Perform= anceEx Protocol published by this library instance at its constructor. =20 -Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.
+Copyright (c) 2011 - 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 @@ -18,10 +18,14 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITH= ER EXPRESS OR IMPLIED. #ifndef _SMM_CORE_PERFORMANCE_LIB_INTERNAL_H_ #define _SMM_CORE_PERFORMANCE_LIB_INTERNAL_H_ =20 =20 #include +#include +#include +#include +#include =20 #include #include #include #include @@ -31,12 +35,17 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITH= ER EXPRESS OR IMPLIED. #include =20 #include #include #include #include +#include +#include +#include =20 #include +#include +#include =20 // // Interface declarations for SMM PerformanceEx Protocol. // /** --=20 1.9.5.msysgit.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel