Home | History | Annotate | Download | only in DxeSmmPerformanceLib
      1 /** @file
      2   Performance library instance used in DXE phase to dump both PEI/DXE and SMM performance data.
      3 
      4   This library instance allows a DXE driver or UEFI application to dump both PEI/DXE and SMM performance data.
      5   StartPerformanceMeasurement(), EndPerformanceMeasurement(), StartPerformanceMeasurementEx()
      6   and EndPerformanceMeasurementEx() are not implemented.
      7 
      8   Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
      9 This program and the accompanying materials
     10 are licensed and made available under the terms and conditions of the BSD License
     11 which accompanies this distribution.  The full text of the license may be found at
     12 http://opensource.org/licenses/bsd-license.php
     13 
     14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     15 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     16 
     17 **/
     18 
     19 
     20 #include <PiDxe.h>
     21 
     22 #include <Guid/Performance.h>
     23 
     24 #include <Library/PerformanceLib.h>
     25 #include <Library/DebugLib.h>
     26 #include <Library/UefiBootServicesTableLib.h>
     27 #include <Library/UefiRuntimeServicesTableLib.h>
     28 #include <Library/PcdLib.h>
     29 #include <Library/BaseMemoryLib.h>
     30 #include <Library/BaseLib.h>
     31 #include <Library/MemoryAllocationLib.h>
     32 
     33 #include <Protocol/SmmCommunication.h>
     34 
     35 #define SMM_PERFORMANCE_COMMUNICATION_BUFFER_SIZE (OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)  + sizeof (SMM_PERF_COMMUNICATE))
     36 
     37 EFI_SMM_COMMUNICATION_PROTOCOL  *mSmmCommunication = NULL;
     38 UINT8                           mSmmPerformanceBuffer[SMM_PERFORMANCE_COMMUNICATION_BUFFER_SIZE];
     39 GAUGE_DATA_ENTRY                *mGaugeData = NULL;
     40 UINTN                           mGaugeNumberOfEntries = 0;
     41 GAUGE_DATA_ENTRY_EX             *mGaugeDataEx = NULL;
     42 UINTN                           mGaugeNumberOfEntriesEx = 0;
     43 
     44 BOOLEAN                         mNoSmmPerfHandler = FALSE;
     45 BOOLEAN                         mNoSmmPerfExHandler = FALSE;
     46 
     47 //
     48 // The cached Performance Protocol and PerformanceEx Protocol interface.
     49 //
     50 PERFORMANCE_PROTOCOL            *mPerformance = NULL;
     51 PERFORMANCE_EX_PROTOCOL         *mPerformanceEx = NULL;
     52 
     53 /**
     54   The function caches the pointer to SMM Communication protocol.
     55 
     56   The function locates SMM Communication protocol from protocol database.
     57 
     58   @retval EFI_SUCCESS     SMM Communication protocol is successfully located.
     59   @retval Other           SMM Communication protocol is not located to log performance.
     60 
     61 **/
     62 EFI_STATUS
     63 GetCommunicationProtocol (
     64   VOID
     65   )
     66 {
     67   EFI_STATUS                      Status;
     68   EFI_SMM_COMMUNICATION_PROTOCOL  *Communication;
     69 
     70   if (mSmmCommunication != NULL) {
     71     return EFI_SUCCESS;
     72   }
     73 
     74   Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &Communication);
     75   if (!EFI_ERROR (Status)) {
     76     ASSERT (Communication != NULL);
     77     //
     78     // Cache SMM Communication protocol.
     79     //
     80     mSmmCommunication = Communication;
     81   }
     82 
     83   return Status;
     84 }
     85 
     86 /**
     87   The function caches the pointers to PerformanceEx protocol and Performance Protocol.
     88 
     89   The function locates PerformanceEx protocol and Performance Protocol from protocol database.
     90 
     91   @retval EFI_SUCCESS     PerformanceEx protocol or Performance Protocol is successfully located.
     92   @retval EFI_NOT_FOUND   Both PerformanceEx protocol and Performance Protocol are not located to log performance.
     93 
     94 **/
     95 EFI_STATUS
     96 GetPerformanceProtocol (
     97   VOID
     98   )
     99 {
    100   EFI_STATUS                Status;
    101   PERFORMANCE_PROTOCOL      *Performance;
    102   PERFORMANCE_EX_PROTOCOL   *PerformanceEx;
    103 
    104   if (mPerformanceEx != NULL || mPerformance != NULL) {
    105     return EFI_SUCCESS;
    106   }
    107 
    108   Status = gBS->LocateProtocol (&gPerformanceExProtocolGuid, NULL, (VOID **) &PerformanceEx);
    109   if (!EFI_ERROR (Status)) {
    110     ASSERT (PerformanceEx != NULL);
    111     //
    112     // Cache PerformanceEx Protocol.
    113     //
    114     mPerformanceEx = PerformanceEx;
    115     return EFI_SUCCESS;
    116   }
    117 
    118   Status = gBS->LocateProtocol (&gPerformanceProtocolGuid, NULL, (VOID **) &Performance);
    119   if (!EFI_ERROR (Status)) {
    120     ASSERT (Performance != NULL);
    121     //
    122     // Cache performance protocol.
    123     //
    124     mPerformance = Performance;
    125     return EFI_SUCCESS;
    126   }
    127 
    128   return EFI_NOT_FOUND;
    129 }
    130 
    131 /**
    132   Creates a record for the beginning of a performance measurement.
    133 
    134   Creates a record that contains the Handle, Token, Module and Identifier.
    135   If TimeStamp is not zero, then TimeStamp is added to the record as the start time.
    136   If TimeStamp is zero, then this function reads the current time stamp
    137   and adds that time stamp value to the record as the start time.
    138 
    139   @param  Handle                  Pointer to environment specific context used
    140                                   to identify the component being measured.
    141   @param  Token                   Pointer to a Null-terminated ASCII string
    142                                   that identifies the component being measured.
    143   @param  Module                  Pointer to a Null-terminated ASCII string
    144                                   that identifies the module being measured.
    145   @param  TimeStamp               64-bit time stamp.
    146   @param  Identifier              32-bit identifier. If the value is 0, the created record
    147                                   is same as the one created by StartPerformanceMeasurement.
    148 
    149   @retval RETURN_SUCCESS          The start of the measurement was recorded.
    150   @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.
    151 
    152 **/
    153 RETURN_STATUS
    154 EFIAPI
    155 StartPerformanceMeasurementEx (
    156   IN CONST VOID   *Handle,  OPTIONAL
    157   IN CONST CHAR8  *Token,   OPTIONAL
    158   IN CONST CHAR8  *Module,  OPTIONAL
    159   IN UINT64       TimeStamp,
    160   IN UINT32       Identifier
    161   )
    162 {
    163   return RETURN_SUCCESS;
    164 }
    165 
    166 /**
    167   Fills in the end time of a performance measurement.
    168 
    169   Looks up the record that matches Handle, Token, Module and Identifier.
    170   If the record can not be found then return RETURN_NOT_FOUND.
    171   If the record is found and TimeStamp is not zero,
    172   then TimeStamp is added to the record as the end time.
    173   If the record is found and TimeStamp is zero, then this function reads
    174   the current time stamp and adds that time stamp value to the record as the end time.
    175 
    176   @param  Handle                  Pointer to environment specific context used
    177                                   to identify the component being measured.
    178   @param  Token                   Pointer to a Null-terminated ASCII string
    179                                   that identifies the component being measured.
    180   @param  Module                  Pointer to a Null-terminated ASCII string
    181                                   that identifies the module being measured.
    182   @param  TimeStamp               64-bit time stamp.
    183   @param  Identifier              32-bit identifier. If the value is 0, the found record
    184                                   is same as the one found by EndPerformanceMeasurement.
    185 
    186   @retval RETURN_SUCCESS          The end of  the measurement was recorded.
    187   @retval RETURN_NOT_FOUND        The specified measurement record could not be found.
    188 
    189 **/
    190 RETURN_STATUS
    191 EFIAPI
    192 EndPerformanceMeasurementEx (
    193   IN CONST VOID   *Handle,  OPTIONAL
    194   IN CONST CHAR8  *Token,   OPTIONAL
    195   IN CONST CHAR8  *Module,  OPTIONAL
    196   IN UINT64       TimeStamp,
    197   IN UINT32       Identifier
    198   )
    199 {
    200   return RETURN_SUCCESS;
    201 }
    202 
    203 /**
    204   Creates a record for the beginning of a performance measurement.
    205 
    206   Creates a record that contains the Handle, Token, and Module.
    207   If TimeStamp is not zero, then TimeStamp is added to the record as the start time.
    208   If TimeStamp is zero, then this function reads the current time stamp
    209   and adds that time stamp value to the record as the start time.
    210 
    211   @param  Handle                  Pointer to environment specific context used
    212                                   to identify the component being measured.
    213   @param  Token                   Pointer to a Null-terminated ASCII string
    214                                   that identifies the component being measured.
    215   @param  Module                  Pointer to a Null-terminated ASCII string
    216                                   that identifies the module being measured.
    217   @param  TimeStamp               64-bit time stamp.
    218 
    219   @retval RETURN_SUCCESS          The start of the measurement was recorded.
    220   @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.
    221 
    222 **/
    223 RETURN_STATUS
    224 EFIAPI
    225 StartPerformanceMeasurement (
    226   IN CONST VOID   *Handle,  OPTIONAL
    227   IN CONST CHAR8  *Token,   OPTIONAL
    228   IN CONST CHAR8  *Module,  OPTIONAL
    229   IN UINT64       TimeStamp
    230   )
    231 {
    232   return RETURN_SUCCESS;
    233 }
    234 
    235 /**
    236   Fills in the end time of a performance measurement.
    237 
    238   Looks up the record that matches Handle, Token, and Module.
    239   If the record can not be found then return RETURN_NOT_FOUND.
    240   If the record is found and TimeStamp is not zero,
    241   then TimeStamp is added to the record as the end time.
    242   If the record is found and TimeStamp is zero, then this function reads
    243   the current time stamp and adds that time stamp value to the record as the end time.
    244 
    245   @param  Handle                  Pointer to environment specific context used
    246                                   to identify the component being measured.
    247   @param  Token                   Pointer to a Null-terminated ASCII string
    248                                   that identifies the component being measured.
    249   @param  Module                  Pointer to a Null-terminated ASCII string
    250                                   that identifies the module being measured.
    251   @param  TimeStamp               64-bit time stamp.
    252 
    253   @retval RETURN_SUCCESS          The end of  the measurement was recorded.
    254   @retval RETURN_NOT_FOUND        The specified measurement record could not be found.
    255 
    256 **/
    257 RETURN_STATUS
    258 EFIAPI
    259 EndPerformanceMeasurement (
    260   IN CONST VOID   *Handle,  OPTIONAL
    261   IN CONST CHAR8  *Token,   OPTIONAL
    262   IN CONST CHAR8  *Module,  OPTIONAL
    263   IN UINT64       TimeStamp
    264   )
    265 {
    266   return RETURN_SUCCESS;
    267 }
    268 
    269 /**
    270   Attempts to retrieve a performance measurement log entry from the performance measurement log.
    271   It can also retrieve the log created by StartPerformanceMeasurement and EndPerformanceMeasurement,
    272   and then assign the Identifier with 0.
    273 
    274   Attempts to retrieve the performance log entry specified by LogEntryKey.  If LogEntryKey is
    275   zero on entry, then an attempt is made to retrieve the first entry from the performance log,
    276   and the key for the second entry in the log is returned.  If the performance log is empty,
    277   then no entry is retrieved and zero is returned.  If LogEntryKey is not zero, then the performance
    278   log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
    279   returned.  If LogEntryKey is the key for the last entry in the log, then the last log entry is
    280   retrieved and an implementation specific non-zero key value that specifies the end of the performance
    281   log is returned.  If LogEntryKey is equal this implementation specific non-zero key value, then no entry
    282   is retrieved and zero is returned.  In the cases where a performance log entry can be returned,
    283   the log entry is returned in Handle, Token, Module, StartTimeStamp, EndTimeStamp and Identifier.
    284   If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().
    285   If Handle is NULL, then ASSERT().
    286   If Token is NULL, then ASSERT().
    287   If Module is NULL, then ASSERT().
    288   If StartTimeStamp is NULL, then ASSERT().
    289   If EndTimeStamp is NULL, then ASSERT().
    290   If Identifier is NULL, then ASSERT().
    291 
    292   @param  LogEntryKey             On entry, the key of the performance measurement log entry to retrieve.
    293                                   0, then the first performance measurement log entry is retrieved.
    294                                   On exit, the key of the next performance log entry.
    295   @param  Handle                  Pointer to environment specific context used to identify the component
    296                                   being measured.
    297   @param  Token                   Pointer to a Null-terminated ASCII string that identifies the component
    298                                   being measured.
    299   @param  Module                  Pointer to a Null-terminated ASCII string that identifies the module
    300                                   being measured.
    301   @param  StartTimeStamp          Pointer to the 64-bit time stamp that was recorded when the measurement
    302                                   was started.
    303   @param  EndTimeStamp            Pointer to the 64-bit time stamp that was recorded when the measurement
    304                                   was ended.
    305   @param  Identifier              Pointer to the 32-bit identifier that was recorded.
    306 
    307   @return The key for the next performance log entry (in general case).
    308 
    309 **/
    310 UINTN
    311 EFIAPI
    312 GetByPerformanceProtocol (
    313   IN  UINTN       LogEntryKey,
    314   OUT CONST VOID  **Handle,
    315   OUT CONST CHAR8 **Token,
    316   OUT CONST CHAR8 **Module,
    317   OUT UINT64      *StartTimeStamp,
    318   OUT UINT64      *EndTimeStamp,
    319   OUT UINT32      *Identifier
    320   )
    321 {
    322   EFI_STATUS            Status;
    323   GAUGE_DATA_ENTRY_EX   *GaugeData;
    324 
    325   Status = GetPerformanceProtocol ();
    326   if (EFI_ERROR (Status)) {
    327     return 0;
    328   }
    329 
    330   if (mPerformanceEx != NULL) {
    331     Status = mPerformanceEx->GetGaugeEx (LogEntryKey++, &GaugeData);
    332   } else if (mPerformance != NULL) {
    333     Status = mPerformance->GetGauge (LogEntryKey++, (GAUGE_DATA_ENTRY **) &GaugeData);
    334   } else {
    335     ASSERT (FALSE);
    336     return 0;
    337   }
    338 
    339   //
    340   // Make sure that LogEntryKey is a valid log entry key,
    341   //
    342   ASSERT (Status != EFI_INVALID_PARAMETER);
    343 
    344   if (EFI_ERROR (Status)) {
    345     //
    346     // The LogEntryKey is the last entry (equals to the total entry number).
    347     //
    348     return 0;
    349   }
    350 
    351   ASSERT (GaugeData != NULL);
    352 
    353   *Handle         = (VOID *) (UINTN) GaugeData->Handle;
    354   *Token          = GaugeData->Token;
    355   *Module         = GaugeData->Module;
    356   *StartTimeStamp = GaugeData->StartTimeStamp;
    357   *EndTimeStamp   = GaugeData->EndTimeStamp;
    358   if (mPerformanceEx != NULL) {
    359     *Identifier   = GaugeData->Identifier;
    360   } else {
    361     *Identifier   = 0;
    362   }
    363 
    364   return LogEntryKey;
    365 }
    366 
    367 
    368 /**
    369   Retrieves all previous logged performance measurement.
    370   Function will use SMM communicate protocol to get all previous SMM performance measurement data.
    371   If success, data buffer will be returned. If fail function will return NULL.
    372 
    373   @param  LogEntryKey             On entry, the key of the performance measurement log entry to retrieve.
    374                                   0, then the first performance measurement log entry is retrieved.
    375                                   On exit, the key of the next performance log entry.
    376 
    377   @retval !NULL           Get all gauge data success.
    378   @retval NULL            Get all gauge data failed.
    379 **/
    380 GAUGE_DATA_ENTRY *
    381 EFIAPI
    382 GetAllSmmGaugeData (
    383   IN UINTN      LogEntryKey
    384   )
    385 {
    386   EFI_STATUS                  Status;
    387   EFI_SMM_COMMUNICATE_HEADER  *SmmCommBufferHeader;
    388   SMM_PERF_COMMUNICATE        *SmmPerfCommData;
    389   UINTN                       CommSize;
    390   UINTN                       DataSize;
    391 
    392   if (mNoSmmPerfHandler) {
    393     //
    394     // Not try to get the SMM gauge data again
    395     // if no SMM Performance handler found.
    396     //
    397     return NULL;
    398   }
    399 
    400   if (LogEntryKey != 0) {
    401     if (mGaugeData != NULL) {
    402       return mGaugeData;
    403     }
    404   } else {
    405     //
    406     // Reget the SMM gauge data at the first entry get.
    407     //
    408     if (mGaugeData != NULL) {
    409       FreePool (mGaugeData);
    410       mGaugeData = NULL;
    411       mGaugeNumberOfEntries = 0;
    412     }
    413   }
    414 
    415   Status = GetCommunicationProtocol ();
    416   if (EFI_ERROR (Status)) {
    417     return NULL;
    418   }
    419 
    420   //
    421   // Initialize communicate buffer
    422   //
    423   SmmCommBufferHeader = (EFI_SMM_COMMUNICATE_HEADER *)mSmmPerformanceBuffer;
    424   SmmPerfCommData = (SMM_PERF_COMMUNICATE *)SmmCommBufferHeader->Data;
    425   ZeroMem((UINT8*)SmmPerfCommData, sizeof(SMM_PERF_COMMUNICATE));
    426 
    427   CopyGuid (&SmmCommBufferHeader->HeaderGuid, &gSmmPerformanceProtocolGuid);
    428   SmmCommBufferHeader->MessageLength = sizeof(SMM_PERF_COMMUNICATE);
    429   CommSize = SMM_PERFORMANCE_COMMUNICATION_BUFFER_SIZE;
    430 
    431   //
    432   // Get total number of SMM gauge entries
    433   //
    434   SmmPerfCommData->Function = SMM_PERF_FUNCTION_GET_GAUGE_ENTRY_NUMBER;
    435   Status = mSmmCommunication->Communicate (mSmmCommunication, mSmmPerformanceBuffer, &CommSize);
    436   if (Status == EFI_NOT_FOUND) {
    437     mNoSmmPerfHandler = TRUE;
    438   }
    439   if (EFI_ERROR (Status) || EFI_ERROR (SmmPerfCommData->ReturnStatus) || SmmPerfCommData->NumberOfEntries == 0) {
    440     return NULL;
    441   }
    442 
    443   mGaugeNumberOfEntries = SmmPerfCommData->NumberOfEntries;
    444 
    445   DataSize = mGaugeNumberOfEntries * sizeof(GAUGE_DATA_ENTRY);
    446   mGaugeData = AllocateZeroPool(DataSize);
    447   ASSERT (mGaugeData != NULL);
    448 
    449   //
    450   // Get all SMM gauge data
    451   //
    452   SmmPerfCommData->Function = SMM_PERF_FUNCTION_GET_GAUGE_DATA;
    453   SmmPerfCommData->LogEntryKey = 0;
    454   SmmPerfCommData->NumberOfEntries = mGaugeNumberOfEntries;
    455   SmmPerfCommData->GaugeData = mGaugeData;
    456   Status = mSmmCommunication->Communicate (mSmmCommunication, mSmmPerformanceBuffer, &CommSize);
    457   if (EFI_ERROR (Status) || EFI_ERROR (SmmPerfCommData->ReturnStatus)) {
    458     FreePool (mGaugeData);
    459     mGaugeData = NULL;
    460     mGaugeNumberOfEntries = 0;
    461   }
    462 
    463   return mGaugeData;
    464 }
    465 
    466 /**
    467   Retrieves all previous logged performance measurement.
    468   Function will use SMM communicate protocol to get all previous SMM performance measurement data.
    469   If success, data buffer will be returned. If fail function will return NULL.
    470 
    471   @param  LogEntryKey             On entry, the key of the performance measurement log entry to retrieve.
    472                                   0, then the first performance measurement log entry is retrieved.
    473                                   On exit, the key of the next performance log entry.
    474 
    475   @retval !NULL           Get all gauge data success.
    476   @retval NULL            Get all gauge data failed.
    477 **/
    478 GAUGE_DATA_ENTRY_EX *
    479 EFIAPI
    480 GetAllSmmGaugeDataEx (
    481   IN UINTN      LogEntryKey
    482   )
    483 {
    484   EFI_STATUS                  Status;
    485   EFI_SMM_COMMUNICATE_HEADER  *SmmCommBufferHeader;
    486   SMM_PERF_COMMUNICATE_EX     *SmmPerfCommData;
    487   UINTN                       CommSize;
    488   UINTN                       DataSize;
    489 
    490   if (mNoSmmPerfExHandler) {
    491     //
    492     // Not try to get the SMM gauge data again
    493     // if no SMM PerformanceEx handler found.
    494     //
    495     return NULL;
    496   }
    497 
    498   if (LogEntryKey != 0) {
    499     if (mGaugeDataEx != NULL) {
    500       return mGaugeDataEx;
    501     }
    502   } else {
    503     //
    504     // Reget the SMM gauge data at the first entry get.
    505     //
    506     if (mGaugeDataEx != NULL) {
    507       FreePool (mGaugeDataEx);
    508       mGaugeDataEx = NULL;
    509       mGaugeNumberOfEntriesEx = 0;
    510     }
    511   }
    512 
    513   Status = GetCommunicationProtocol ();
    514   if (EFI_ERROR (Status)) {
    515     return NULL;
    516   }
    517 
    518   //
    519   // Initialize communicate buffer
    520   //
    521   SmmCommBufferHeader = (EFI_SMM_COMMUNICATE_HEADER *)mSmmPerformanceBuffer;
    522   SmmPerfCommData = (SMM_PERF_COMMUNICATE_EX *)SmmCommBufferHeader->Data;
    523   ZeroMem((UINT8*)SmmPerfCommData, sizeof(SMM_PERF_COMMUNICATE_EX));
    524 
    525   CopyGuid (&SmmCommBufferHeader->HeaderGuid, &gSmmPerformanceExProtocolGuid);
    526   SmmCommBufferHeader->MessageLength = sizeof(SMM_PERF_COMMUNICATE_EX);
    527   CommSize = SMM_PERFORMANCE_COMMUNICATION_BUFFER_SIZE;
    528 
    529   //
    530   // Get total number of SMM gauge entries
    531   //
    532   SmmPerfCommData->Function = SMM_PERF_FUNCTION_GET_GAUGE_ENTRY_NUMBER;
    533   Status = mSmmCommunication->Communicate (mSmmCommunication, mSmmPerformanceBuffer, &CommSize);
    534   if (Status == EFI_NOT_FOUND) {
    535     mNoSmmPerfExHandler = TRUE;
    536   }
    537   if (EFI_ERROR (Status) || EFI_ERROR (SmmPerfCommData->ReturnStatus) || SmmPerfCommData->NumberOfEntries == 0) {
    538     return NULL;
    539   }
    540 
    541   mGaugeNumberOfEntriesEx = SmmPerfCommData->NumberOfEntries;
    542 
    543   DataSize = mGaugeNumberOfEntriesEx * sizeof(GAUGE_DATA_ENTRY_EX);
    544   mGaugeDataEx = AllocateZeroPool(DataSize);
    545   ASSERT (mGaugeDataEx != NULL);
    546 
    547   //
    548   // Get all SMM gauge data
    549   //
    550   SmmPerfCommData->Function = SMM_PERF_FUNCTION_GET_GAUGE_DATA;
    551   SmmPerfCommData->LogEntryKey = 0;
    552   SmmPerfCommData->NumberOfEntries = mGaugeNumberOfEntriesEx;
    553   SmmPerfCommData->GaugeDataEx = mGaugeDataEx;
    554   Status = mSmmCommunication->Communicate (mSmmCommunication, mSmmPerformanceBuffer, &CommSize);
    555   if (EFI_ERROR (Status) || EFI_ERROR (SmmPerfCommData->ReturnStatus)) {
    556     FreePool (mGaugeDataEx);
    557     mGaugeDataEx = NULL;
    558     mGaugeNumberOfEntriesEx = 0;
    559   }
    560 
    561   return mGaugeDataEx;
    562 }
    563 
    564 /**
    565   Attempts to retrieve a performance measurement log entry from the performance measurement log.
    566   It can also retrieve the log created by StartPerformanceMeasurement and EndPerformanceMeasurement,
    567   and then assign the Identifier with 0.
    568 
    569   Attempts to retrieve the performance log entry specified by LogEntryKey.  If LogEntryKey is
    570   zero on entry, then an attempt is made to retrieve the first entry from the performance log,
    571   and the key for the second entry in the log is returned.  If the performance log is empty,
    572   then no entry is retrieved and zero is returned.  If LogEntryKey is not zero, then the performance
    573   log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
    574   returned.  If LogEntryKey is the key for the last entry in the log, then the last log entry is
    575   retrieved and an implementation specific non-zero key value that specifies the end of the performance
    576   log is returned.  If LogEntryKey is equal this implementation specific non-zero key value, then no entry
    577   is retrieved and zero is returned.  In the cases where a performance log entry can be returned,
    578   the log entry is returned in Handle, Token, Module, StartTimeStamp, EndTimeStamp and Identifier.
    579   If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().
    580   If Handle is NULL, then ASSERT().
    581   If Token is NULL, then ASSERT().
    582   If Module is NULL, then ASSERT().
    583   If StartTimeStamp is NULL, then ASSERT().
    584   If EndTimeStamp is NULL, then ASSERT().
    585   If Identifier is NULL, then ASSERT().
    586 
    587   @param  LogEntryKey             On entry, the key of the performance measurement log entry to retrieve.
    588                                   0, then the first performance measurement log entry is retrieved.
    589                                   On exit, the key of the next performance log entry.
    590   @param  Handle                  Pointer to environment specific context used to identify the component
    591                                   being measured.
    592   @param  Token                   Pointer to a Null-terminated ASCII string that identifies the component
    593                                   being measured.
    594   @param  Module                  Pointer to a Null-terminated ASCII string that identifies the module
    595                                   being measured.
    596   @param  StartTimeStamp          Pointer to the 64-bit time stamp that was recorded when the measurement
    597                                   was started.
    598   @param  EndTimeStamp            Pointer to the 64-bit time stamp that was recorded when the measurement
    599                                   was ended.
    600   @param  Identifier              Pointer to the 32-bit identifier that was recorded.
    601 
    602   @return The key for the next performance log entry (in general case).
    603 
    604 **/
    605 UINTN
    606 EFIAPI
    607 GetPerformanceMeasurementEx (
    608   IN  UINTN       LogEntryKey,
    609   OUT CONST VOID  **Handle,
    610   OUT CONST CHAR8 **Token,
    611   OUT CONST CHAR8 **Module,
    612   OUT UINT64      *StartTimeStamp,
    613   OUT UINT64      *EndTimeStamp,
    614   OUT UINT32      *Identifier
    615   )
    616 {
    617   GAUGE_DATA_ENTRY_EX   *GaugeData;
    618 
    619   GaugeData = NULL;
    620 
    621   ASSERT (Handle != NULL);
    622   ASSERT (Token != NULL);
    623   ASSERT (Module != NULL);
    624   ASSERT (StartTimeStamp != NULL);
    625   ASSERT (EndTimeStamp != NULL);
    626   ASSERT (Identifier != NULL);
    627 
    628   mGaugeDataEx = GetAllSmmGaugeDataEx (LogEntryKey);
    629   if (mGaugeDataEx != NULL) {
    630     if (LogEntryKey >= mGaugeNumberOfEntriesEx) {
    631       //
    632       // Try to get the data by Performance Protocol.
    633       //
    634       LogEntryKey = LogEntryKey - mGaugeNumberOfEntriesEx;
    635       LogEntryKey = GetByPerformanceProtocol (
    636                       LogEntryKey,
    637                       Handle,
    638                       Token,
    639                       Module,
    640                       StartTimeStamp,
    641                       EndTimeStamp,
    642                       Identifier
    643                       );
    644       if (LogEntryKey == 0) {
    645         //
    646         // Last entry.
    647         //
    648         return LogEntryKey;
    649       } else {
    650         return (LogEntryKey + mGaugeNumberOfEntriesEx);
    651       }
    652     }
    653 
    654     GaugeData = &mGaugeDataEx[LogEntryKey++];
    655     *Identifier = GaugeData->Identifier;
    656   } else {
    657     mGaugeData = GetAllSmmGaugeData (LogEntryKey);
    658     if (mGaugeData != NULL) {
    659       if (LogEntryKey >= mGaugeNumberOfEntries) {
    660         //
    661         // Try to get the data by Performance Protocol.
    662         //
    663         LogEntryKey = LogEntryKey - mGaugeNumberOfEntries;
    664         LogEntryKey = GetByPerformanceProtocol (
    665                         LogEntryKey,
    666                         Handle,
    667                         Token,
    668                         Module,
    669                         StartTimeStamp,
    670                         EndTimeStamp,
    671                         Identifier
    672                         );
    673         if (LogEntryKey == 0) {
    674           //
    675           // Last entry.
    676           //
    677           return LogEntryKey;
    678         } else {
    679           return (LogEntryKey + mGaugeNumberOfEntries);
    680         }
    681       }
    682 
    683       GaugeData = (GAUGE_DATA_ENTRY_EX *) &mGaugeData[LogEntryKey++];
    684       *Identifier = 0;
    685     } else {
    686       return GetByPerformanceProtocol (
    687                LogEntryKey,
    688                Handle,
    689                Token,
    690                Module,
    691                StartTimeStamp,
    692                EndTimeStamp,
    693                Identifier
    694                );
    695     }
    696   }
    697 
    698   *Handle         = (VOID *) (UINTN) GaugeData->Handle;
    699   *Token          = GaugeData->Token;
    700   *Module         = GaugeData->Module;
    701   *StartTimeStamp = GaugeData->StartTimeStamp;
    702   *EndTimeStamp   = GaugeData->EndTimeStamp;
    703 
    704   return LogEntryKey;
    705 }
    706 
    707 /**
    708   Attempts to retrieve a performance measurement log entry from the performance measurement log.
    709   It can also retrieve the log created by StartPerformanceMeasurementEx and EndPerformanceMeasurementEx,
    710   and then eliminate the Identifier.
    711 
    712   Attempts to retrieve the performance log entry specified by LogEntryKey.  If LogEntryKey is
    713   zero on entry, then an attempt is made to retrieve the first entry from the performance log,
    714   and the key for the second entry in the log is returned.  If the performance log is empty,
    715   then no entry is retrieved and zero is returned.  If LogEntryKey is not zero, then the performance
    716   log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
    717   returned.  If LogEntryKey is the key for the last entry in the log, then the last log entry is
    718   retrieved and an implementation specific non-zero key value that specifies the end of the performance
    719   log is returned.  If LogEntryKey is equal this implementation specific non-zero key value, then no entry
    720   is retrieved and zero is returned.  In the cases where a performance log entry can be returned,
    721   the log entry is returned in Handle, Token, Module, StartTimeStamp, and EndTimeStamp.
    722   If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().
    723   If Handle is NULL, then ASSERT().
    724   If Token is NULL, then ASSERT().
    725   If Module is NULL, then ASSERT().
    726   If StartTimeStamp is NULL, then ASSERT().
    727   If EndTimeStamp is NULL, then ASSERT().
    728 
    729   @param  LogEntryKey             On entry, the key of the performance measurement log entry to retrieve.
    730                                   0, then the first performance measurement log entry is retrieved.
    731                                   On exit, the key of the next performance log entry.
    732   @param  Handle                  Pointer to environment specific context used to identify the component
    733                                   being measured.
    734   @param  Token                   Pointer to a Null-terminated ASCII string that identifies the component
    735                                   being measured.
    736   @param  Module                  Pointer to a Null-terminated ASCII string that identifies the module
    737                                   being measured.
    738   @param  StartTimeStamp          Pointer to the 64-bit time stamp that was recorded when the measurement
    739                                   was started.
    740   @param  EndTimeStamp            Pointer to the 64-bit time stamp that was recorded when the measurement
    741                                   was ended.
    742 
    743   @return The key for the next performance log entry (in general case).
    744 
    745 **/
    746 UINTN
    747 EFIAPI
    748 GetPerformanceMeasurement (
    749   IN  UINTN       LogEntryKey,
    750   OUT CONST VOID  **Handle,
    751   OUT CONST CHAR8 **Token,
    752   OUT CONST CHAR8 **Module,
    753   OUT UINT64      *StartTimeStamp,
    754   OUT UINT64      *EndTimeStamp
    755   )
    756 {
    757   UINT32 Identifier;
    758   return GetPerformanceMeasurementEx (LogEntryKey, Handle, Token, Module, StartTimeStamp, EndTimeStamp, &Identifier);
    759 }
    760 
    761 /**
    762   Returns TRUE if the performance measurement macros are enabled.
    763 
    764   This function returns TRUE if the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
    765   PcdPerformanceLibraryPropertyMask is set.  Otherwise FALSE is returned.
    766 
    767   @retval TRUE                    The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
    768                                   PcdPerformanceLibraryPropertyMask is set.
    769   @retval FALSE                   The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
    770                                   PcdPerformanceLibraryPropertyMask is clear.
    771 
    772 **/
    773 BOOLEAN
    774 EFIAPI
    775 PerformanceMeasurementEnabled (
    776   VOID
    777   )
    778 {
    779   return (BOOLEAN) ((PcdGet8(PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0);
    780 }
    781