• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   Performance library instance used by SMM Core.
3 
4   This library provides the performance measurement interfaces and initializes performance
5   logging for the SMM phase.
6   It initializes SMM phase performance logging by publishing the SMM Performance and PerformanceEx Protocol,
7   which is consumed by SmmPerformanceLib to logging performance data in SMM phase.
8 
9   This library is mainly used by SMM Core to start performance logging to ensure that
10   SMM Performance and PerformanceEx Protocol are installed at the very beginning of SMM phase.
11 
12  Caution: This module requires additional review when modified.
13  This driver will have external input - performance data and communicate buffer in SMM mode.
14  This external input must be validated carefully to avoid security issue like
15  buffer overflow, integer overflow.
16 
17  SmmPerformanceHandlerEx(), SmmPerformanceHandler() will receive untrusted input and do basic validation.
18 
19 Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
20 This program and the accompanying materials
21 are licensed and made available under the terms and conditions of the BSD License
22 which accompanies this distribution.  The full text of the license may be found at
23 http://opensource.org/licenses/bsd-license.php
24 
25 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
26 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
27 
28 **/
29 
30 
31 #include "SmmCorePerformanceLibInternal.h"
32 
33 //
34 // The data structure to hold global performance data.
35 //
36 GAUGE_DATA_HEADER       *mGaugeData;
37 
38 //
39 // The current maximum number of logging entries. If current number of
40 // entries exceeds this value, it will re-allocate a larger array and
41 // migration the old data to the larger array.
42 //
43 UINT32                  mMaxGaugeRecords;
44 
45 //
46 // The handle to install Performance Protocol instance.
47 //
48 EFI_HANDLE              mHandle = NULL;
49 
50 BOOLEAN                 mPerformanceMeasurementEnabled;
51 
52 SPIN_LOCK               mSmmPerfLock;
53 
54 //
55 // Interfaces for SMM Performance Protocol.
56 //
57 PERFORMANCE_PROTOCOL mPerformanceInterface = {
58   StartGauge,
59   EndGauge,
60   GetGauge
61 };
62 
63 //
64 // Interfaces for SMM PerformanceEx Protocol.
65 //
66 PERFORMANCE_EX_PROTOCOL mPerformanceExInterface = {
67   StartGaugeEx,
68   EndGaugeEx,
69   GetGaugeEx
70 };
71 
72 /**
73   Searches in the gauge array with keyword Handle, Token, Module and Identfier.
74 
75   This internal function searches for the gauge entry in the gauge array.
76   If there is an entry that exactly matches the given keywords
77   and its end time stamp is zero, then the index of that gauge entry is returned;
78   otherwise, the the number of gauge entries in the array is returned.
79 
80   @param  Handle                  Pointer to environment specific context used
81                                   to identify the component being measured.
82   @param  Token                   Pointer to a Null-terminated ASCII string
83                                   that identifies the component being measured.
84   @param  Module                  Pointer to a Null-terminated ASCII string
85                                   that identifies the module being measured.
86   @param  Identifier              32-bit identifier.
87 
88   @retval The index of gauge entry in the array.
89 
90 **/
91 UINT32
SmmSearchForGaugeEntry(IN CONST VOID * Handle,OPTIONAL IN CONST CHAR8 * Token,OPTIONAL IN CONST CHAR8 * Module,OPTIONAL IN CONST UINT32 Identifier)92 SmmSearchForGaugeEntry (
93   IN CONST VOID                 *Handle,  OPTIONAL
94   IN CONST CHAR8                *Token,   OPTIONAL
95   IN CONST CHAR8                *Module,   OPTIONAL
96   IN CONST UINT32               Identifier
97   )
98 {
99   UINT32                    Index;
100   UINT32                    Index2;
101   UINT32                    NumberOfEntries;
102   GAUGE_DATA_ENTRY_EX       *GaugeEntryExArray;
103 
104   if (Token == NULL) {
105     Token = "";
106   }
107   if (Module == NULL) {
108     Module = "";
109   }
110 
111   NumberOfEntries = mGaugeData->NumberOfEntries;
112   GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);
113 
114   Index2 = 0;
115 
116   for (Index = 0; Index < NumberOfEntries; Index++) {
117     Index2 = NumberOfEntries - 1 - Index;
118     if (GaugeEntryExArray[Index2].EndTimeStamp == 0 &&
119         (GaugeEntryExArray[Index2].Handle == (EFI_PHYSICAL_ADDRESS) (UINTN) Handle) &&
120         AsciiStrnCmp (GaugeEntryExArray[Index2].Token, Token, SMM_PERFORMANCE_STRING_LENGTH) == 0 &&
121         AsciiStrnCmp (GaugeEntryExArray[Index2].Module, Module, SMM_PERFORMANCE_STRING_LENGTH) == 0 &&
122         (GaugeEntryExArray[Index2].Identifier == Identifier)) {
123       Index = Index2;
124       break;
125     }
126   }
127 
128   return Index;
129 }
130 
131 /**
132   Adds a record at the end of the performance measurement log
133   that records the start time of a performance measurement.
134 
135   Adds a record to the end of the performance measurement log
136   that contains the Handle, Token, Module and Identifier.
137   The end time of the new record must be set to zero.
138   If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
139   If TimeStamp is zero, the start time in the record is filled in with the value
140   read from the current time stamp.
141 
142   @param  Handle                  Pointer to environment specific context used
143                                   to identify the component being measured.
144   @param  Token                   Pointer to a Null-terminated ASCII string
145                                   that identifies the component being measured.
146   @param  Module                  Pointer to a Null-terminated ASCII string
147                                   that identifies the module being measured.
148   @param  TimeStamp               64-bit time stamp.
149   @param  Identifier              32-bit identifier. If the value is 0, the created record
150                                   is same as the one created by StartGauge of PERFORMANCE_PROTOCOL.
151 
152   @retval EFI_SUCCESS             The data was read correctly from the device.
153   @retval EFI_OUT_OF_RESOURCES    There are not enough resources to record the measurement.
154 
155 **/
156 EFI_STATUS
157 EFIAPI
StartGaugeEx(IN CONST VOID * Handle,OPTIONAL IN CONST CHAR8 * Token,OPTIONAL IN CONST CHAR8 * Module,OPTIONAL IN UINT64 TimeStamp,IN UINT32 Identifier)158 StartGaugeEx (
159   IN CONST VOID   *Handle,  OPTIONAL
160   IN CONST CHAR8  *Token,   OPTIONAL
161   IN CONST CHAR8  *Module,  OPTIONAL
162   IN UINT64       TimeStamp,
163   IN UINT32       Identifier
164   )
165 {
166   GAUGE_DATA_ENTRY_EX       *GaugeEntryExArray;
167   UINTN                     GaugeDataSize;
168   GAUGE_DATA_HEADER         *NewGaugeData;
169   UINTN                     OldGaugeDataSize;
170   GAUGE_DATA_HEADER         *OldGaugeData;
171   UINT32                    Index;
172 
173   AcquireSpinLock (&mSmmPerfLock);
174 
175   Index = mGaugeData->NumberOfEntries;
176   if (Index >= mMaxGaugeRecords) {
177     //
178     // Try to enlarge the scale of gauge array.
179     //
180     OldGaugeData      = mGaugeData;
181     OldGaugeDataSize  = sizeof (GAUGE_DATA_HEADER) + sizeof (GAUGE_DATA_ENTRY_EX) * mMaxGaugeRecords;
182 
183     GaugeDataSize     = sizeof (GAUGE_DATA_HEADER) + sizeof (GAUGE_DATA_ENTRY_EX) * mMaxGaugeRecords * 2;
184 
185     NewGaugeData = AllocateZeroPool (GaugeDataSize);
186     if (NewGaugeData == NULL) {
187       ReleaseSpinLock (&mSmmPerfLock);
188       return EFI_OUT_OF_RESOURCES;
189     }
190 
191     mGaugeData = NewGaugeData;
192     mMaxGaugeRecords *= 2;
193 
194     //
195     // Initialize new data array and migrate old data one.
196     //
197     mGaugeData = CopyMem (mGaugeData, OldGaugeData, OldGaugeDataSize);
198 
199     FreePool (OldGaugeData);
200   }
201 
202   GaugeEntryExArray               = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);
203   GaugeEntryExArray[Index].Handle = (EFI_PHYSICAL_ADDRESS) (UINTN) Handle;
204 
205   if (Token != NULL) {
206     AsciiStrnCpyS (GaugeEntryExArray[Index].Token, SMM_PERFORMANCE_STRING_SIZE, Token, SMM_PERFORMANCE_STRING_LENGTH);
207   }
208   if (Module != NULL) {
209     AsciiStrnCpyS (GaugeEntryExArray[Index].Module, SMM_PERFORMANCE_STRING_SIZE, Module, SMM_PERFORMANCE_STRING_LENGTH);
210   }
211 
212   GaugeEntryExArray[Index].EndTimeStamp = 0;
213   GaugeEntryExArray[Index].Identifier = Identifier;
214 
215   if (TimeStamp == 0) {
216     TimeStamp = GetPerformanceCounter ();
217   }
218   GaugeEntryExArray[Index].StartTimeStamp = TimeStamp;
219 
220   mGaugeData->NumberOfEntries++;
221 
222   ReleaseSpinLock (&mSmmPerfLock);
223 
224   return EFI_SUCCESS;
225 }
226 
227 /**
228   Searches the performance measurement log from the beginning of the log
229   for the first matching record that contains a zero end time and fills in a valid end time.
230 
231   Searches the performance measurement log from the beginning of the log
232   for the first record that matches Handle, Token, Module and Identifier and has an end time value of zero.
233   If the record can not be found then return EFI_NOT_FOUND.
234   If the record is found and TimeStamp is not zero,
235   then the end time in the record is filled in with the value specified by TimeStamp.
236   If the record is found and TimeStamp is zero, then the end time in the matching record
237   is filled in with the current time stamp value.
238 
239   @param  Handle                  Pointer to environment specific context used
240                                   to identify the component being measured.
241   @param  Token                   Pointer to a Null-terminated ASCII string
242                                   that identifies the component being measured.
243   @param  Module                  Pointer to a Null-terminated ASCII string
244                                   that identifies the module being measured.
245   @param  TimeStamp               64-bit time stamp.
246   @param  Identifier              32-bit identifier. If the value is 0, the found record
247                                   is same as the one found by EndGauge of PERFORMANCE_PROTOCOL.
248 
249   @retval EFI_SUCCESS             The end of  the measurement was recorded.
250   @retval EFI_NOT_FOUND           The specified measurement record could not be found.
251 
252 **/
253 EFI_STATUS
254 EFIAPI
EndGaugeEx(IN CONST VOID * Handle,OPTIONAL IN CONST CHAR8 * Token,OPTIONAL IN CONST CHAR8 * Module,OPTIONAL IN UINT64 TimeStamp,IN UINT32 Identifier)255 EndGaugeEx (
256   IN CONST VOID   *Handle,  OPTIONAL
257   IN CONST CHAR8  *Token,   OPTIONAL
258   IN CONST CHAR8  *Module,  OPTIONAL
259   IN UINT64       TimeStamp,
260   IN UINT32       Identifier
261   )
262 {
263   GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;
264   UINT32              Index;
265 
266   AcquireSpinLock (&mSmmPerfLock);
267 
268   if (TimeStamp == 0) {
269     TimeStamp = GetPerformanceCounter ();
270   }
271 
272   Index = SmmSearchForGaugeEntry (Handle, Token, Module, Identifier);
273   if (Index >= mGaugeData->NumberOfEntries) {
274     ReleaseSpinLock (&mSmmPerfLock);
275     return EFI_NOT_FOUND;
276   }
277   GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);
278   GaugeEntryExArray[Index].EndTimeStamp = TimeStamp;
279 
280   ReleaseSpinLock (&mSmmPerfLock);
281 
282   return EFI_SUCCESS;
283 }
284 
285 /**
286   Retrieves a previously logged performance measurement.
287   It can also retrieve the log created by StartGauge and EndGauge of PERFORMANCE_PROTOCOL,
288   and then assign the Identifier with 0.
289 
290   Retrieves the performance log entry from the performance log specified by LogEntryKey.
291   If it stands for a valid entry, then EFI_SUCCESS is returned and
292   GaugeDataEntryEx stores the pointer to that entry.
293 
294   @param  LogEntryKey             The key for the previous performance measurement log entry.
295                                   If 0, then the first performance measurement log entry is retrieved.
296   @param  GaugeDataEntryEx        The indirect pointer to the extended gauge data entry specified by LogEntryKey
297                                   if the retrieval is successful.
298 
299   @retval EFI_SUCCESS             The GuageDataEntryEx is successfully found based on LogEntryKey.
300   @retval EFI_NOT_FOUND           The LogEntryKey is the last entry (equals to the total entry number).
301   @retval EFI_INVALIDE_PARAMETER  The LogEntryKey is not a valid entry (greater than the total entry number).
302   @retval EFI_INVALIDE_PARAMETER  GaugeDataEntryEx is NULL.
303 
304 **/
305 EFI_STATUS
306 EFIAPI
GetGaugeEx(IN UINTN LogEntryKey,OUT GAUGE_DATA_ENTRY_EX ** GaugeDataEntryEx)307 GetGaugeEx (
308   IN  UINTN                 LogEntryKey,
309   OUT GAUGE_DATA_ENTRY_EX   **GaugeDataEntryEx
310   )
311 {
312   UINTN               NumberOfEntries;
313   GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;
314 
315   NumberOfEntries = (UINTN) (mGaugeData->NumberOfEntries);
316   if (LogEntryKey > NumberOfEntries) {
317     return EFI_INVALID_PARAMETER;
318   }
319   if (LogEntryKey == NumberOfEntries) {
320     return EFI_NOT_FOUND;
321   }
322 
323   GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);
324 
325   if (GaugeDataEntryEx == NULL) {
326     return EFI_INVALID_PARAMETER;
327   }
328   *GaugeDataEntryEx = &GaugeEntryExArray[LogEntryKey];
329 
330   return EFI_SUCCESS;
331 }
332 
333 /**
334   Adds a record at the end of the performance measurement log
335   that records the start time of a performance measurement.
336 
337   Adds a record to the end of the performance measurement log
338   that contains the Handle, Token, and Module.
339   The end time of the new record must be set to zero.
340   If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
341   If TimeStamp is zero, the start time in the record is filled in with the value
342   read from the current time stamp.
343 
344   @param  Handle                  Pointer to environment specific context used
345                                   to identify the component being measured.
346   @param  Token                   Pointer to a Null-terminated ASCII string
347                                   that identifies the component being measured.
348   @param  Module                  Pointer to a Null-terminated ASCII string
349                                   that identifies the module being measured.
350   @param  TimeStamp               64-bit time stamp.
351 
352   @retval EFI_SUCCESS             The data was read correctly from the device.
353   @retval EFI_OUT_OF_RESOURCES    There are not enough resources to record the measurement.
354 
355 **/
356 EFI_STATUS
357 EFIAPI
StartGauge(IN CONST VOID * Handle,OPTIONAL IN CONST CHAR8 * Token,OPTIONAL IN CONST CHAR8 * Module,OPTIONAL IN UINT64 TimeStamp)358 StartGauge (
359   IN CONST VOID   *Handle,  OPTIONAL
360   IN CONST CHAR8  *Token,   OPTIONAL
361   IN CONST CHAR8  *Module,  OPTIONAL
362   IN UINT64       TimeStamp
363   )
364 {
365   return StartGaugeEx (Handle, Token, Module, TimeStamp, 0);
366 }
367 
368 /**
369   Searches the performance measurement log from the beginning of the log
370   for the first matching record that contains a zero end time and fills in a valid end time.
371 
372   Searches the performance measurement log from the beginning of the log
373   for the first record that matches Handle, Token, and Module and has an end time value of zero.
374   If the record can not be found then return EFI_NOT_FOUND.
375   If the record is found and TimeStamp is not zero,
376   then the end time in the record is filled in with the value specified by TimeStamp.
377   If the record is found and TimeStamp is zero, then the end time in the matching record
378   is filled in with the current time stamp value.
379 
380   @param  Handle                  Pointer to environment specific context used
381                                   to identify the component being measured.
382   @param  Token                   Pointer to a Null-terminated ASCII string
383                                   that identifies the component being measured.
384   @param  Module                  Pointer to a Null-terminated ASCII string
385                                   that identifies the module being measured.
386   @param  TimeStamp               64-bit time stamp.
387 
388   @retval EFI_SUCCESS             The end of  the measurement was recorded.
389   @retval EFI_NOT_FOUND           The specified measurement record could not be found.
390 
391 **/
392 EFI_STATUS
393 EFIAPI
EndGauge(IN CONST VOID * Handle,OPTIONAL IN CONST CHAR8 * Token,OPTIONAL IN CONST CHAR8 * Module,OPTIONAL IN UINT64 TimeStamp)394 EndGauge (
395   IN CONST VOID   *Handle,  OPTIONAL
396   IN CONST CHAR8  *Token,   OPTIONAL
397   IN CONST CHAR8  *Module,  OPTIONAL
398   IN UINT64       TimeStamp
399   )
400 {
401   return EndGaugeEx (Handle, Token, Module, TimeStamp, 0);
402 }
403 
404 /**
405   Retrieves a previously logged performance measurement.
406   It can also retrieve the log created by StartGaugeEx and EndGaugeEx of PERFORMANCE_EX_PROTOCOL,
407   and then eliminate the Identifier.
408 
409   Retrieves the performance log entry from the performance log specified by LogEntryKey.
410   If it stands for a valid entry, then EFI_SUCCESS is returned and
411   GaugeDataEntry stores the pointer to that entry.
412 
413   @param  LogEntryKey             The key for the previous performance measurement log entry.
414                                   If 0, then the first performance measurement log entry is retrieved.
415   @param  GaugeDataEntry          The indirect pointer to the gauge data entry specified by LogEntryKey
416                                   if the retrieval is successful.
417 
418   @retval EFI_SUCCESS             The GuageDataEntry is successfully found based on LogEntryKey.
419   @retval EFI_NOT_FOUND           The LogEntryKey is the last entry (equals to the total entry number).
420   @retval EFI_INVALIDE_PARAMETER  The LogEntryKey is not a valid entry (greater than the total entry number).
421   @retval EFI_INVALIDE_PARAMETER  GaugeDataEntry is NULL.
422 
423 **/
424 EFI_STATUS
425 EFIAPI
GetGauge(IN UINTN LogEntryKey,OUT GAUGE_DATA_ENTRY ** GaugeDataEntry)426 GetGauge (
427   IN  UINTN               LogEntryKey,
428   OUT GAUGE_DATA_ENTRY    **GaugeDataEntry
429   )
430 {
431   EFI_STATUS          Status;
432   GAUGE_DATA_ENTRY_EX *GaugeEntryEx;
433 
434   GaugeEntryEx = NULL;
435 
436   Status = GetGaugeEx (LogEntryKey, &GaugeEntryEx);
437   if (EFI_ERROR (Status)) {
438     return Status;
439   }
440 
441   if (GaugeDataEntry == NULL) {
442     return EFI_INVALID_PARAMETER;
443   }
444 
445   *GaugeDataEntry = (GAUGE_DATA_ENTRY *) GaugeEntryEx;
446 
447   return EFI_SUCCESS;
448 }
449 
450 /**
451   Communication service SMI Handler entry.
452 
453   This SMI handler provides services for the performance wrapper driver.
454 
455    Caution: This function may receive untrusted input.
456    Communicate buffer and buffer size are external input, so this function will do basic validation.
457 
458   @param[in]     DispatchHandle  The unique handle assigned to this handler by SmiHandlerRegister().
459   @param[in]     RegisterContext Points to an optional handler context which was specified when the
460                                  handler was registered.
461   @param[in, out] CommBuffer     A pointer to a collection of data in memory that will
462                                  be conveyed from a non-SMM environment into an SMM environment.
463   @param[in, out] CommBufferSize The size of the CommBuffer.
464 
465   @retval EFI_SUCCESS                         The interrupt was handled and quiesced. No other handlers
466                                               should still be called.
467   @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED  The interrupt has been quiesced but other handlers should
468                                               still be called.
469   @retval EFI_WARN_INTERRUPT_SOURCE_PENDING   The interrupt is still pending and other handlers should still
470                                               be called.
471   @retval EFI_INTERRUPT_PENDING               The interrupt could not be quiesced.
472 **/
473 EFI_STATUS
474 EFIAPI
SmmPerformanceHandlerEx(IN EFI_HANDLE DispatchHandle,IN CONST VOID * RegisterContext,IN OUT VOID * CommBuffer,IN OUT UINTN * CommBufferSize)475 SmmPerformanceHandlerEx (
476   IN     EFI_HANDLE                    DispatchHandle,
477   IN     CONST VOID                   *RegisterContext,
478   IN OUT VOID                          *CommBuffer,
479   IN OUT UINTN                         *CommBufferSize
480   )
481 {
482   EFI_STATUS                Status;
483   SMM_PERF_COMMUNICATE_EX   *SmmPerfCommData;
484   GAUGE_DATA_ENTRY_EX       *GaugeEntryExArray;
485   UINT64                    DataSize;
486   UINTN                     Index;
487   GAUGE_DATA_ENTRY_EX       *GaugeDataEx;
488   UINTN                     NumberOfEntries;
489   UINTN                     LogEntryKey;
490   UINTN                     TempCommBufferSize;
491 
492   GaugeEntryExArray = NULL;
493 
494   //
495   // If input is invalid, stop processing this SMI
496   //
497   if (CommBuffer == NULL || CommBufferSize == NULL) {
498     return EFI_SUCCESS;
499   }
500 
501   TempCommBufferSize = *CommBufferSize;
502 
503   if(TempCommBufferSize < sizeof (SMM_PERF_COMMUNICATE_EX)) {
504     return EFI_SUCCESS;
505   }
506 
507   if (!SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) {
508     DEBUG ((EFI_D_ERROR, "SmmPerformanceHandlerEx: SMM communcation data buffer in SMRAM or overflow!\n"));
509     return EFI_SUCCESS;
510   }
511 
512   SmmPerfCommData = (SMM_PERF_COMMUNICATE_EX *)CommBuffer;
513 
514   switch (SmmPerfCommData->Function) {
515     case SMM_PERF_FUNCTION_GET_GAUGE_ENTRY_NUMBER :
516        SmmPerfCommData->NumberOfEntries = mGaugeData->NumberOfEntries;
517        Status = EFI_SUCCESS;
518        break;
519 
520     case SMM_PERF_FUNCTION_GET_GAUGE_DATA :
521       GaugeDataEx = SmmPerfCommData->GaugeDataEx;
522       NumberOfEntries = SmmPerfCommData->NumberOfEntries;
523       LogEntryKey = SmmPerfCommData->LogEntryKey;
524        if (GaugeDataEx == NULL || NumberOfEntries == 0 || LogEntryKey > mGaugeData->NumberOfEntries ||
525            NumberOfEntries > mGaugeData->NumberOfEntries || LogEntryKey > (mGaugeData->NumberOfEntries - NumberOfEntries)) {
526          Status = EFI_INVALID_PARAMETER;
527          break;
528        }
529 
530        //
531        // Sanity check
532        //
533        DataSize = MultU64x32 (NumberOfEntries, sizeof(GAUGE_DATA_ENTRY_EX));
534        if (!SmmIsBufferOutsideSmmValid ((UINTN) GaugeDataEx, DataSize)) {
535          DEBUG ((EFI_D_ERROR, "SmmPerformanceHandlerEx: SMM Performance Data buffer in SMRAM or overflow!\n"));
536          Status = EFI_ACCESS_DENIED;
537          break;
538        }
539 
540        GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);
541 
542        for (Index = 0; Index < NumberOfEntries; Index++) {
543          CopyMem (
544            (UINT8 *) &GaugeDataEx[Index],
545            (UINT8 *) &GaugeEntryExArray[LogEntryKey++],
546            sizeof (GAUGE_DATA_ENTRY_EX)
547            );
548        }
549        Status = EFI_SUCCESS;
550        break;
551 
552     default:
553        Status = EFI_UNSUPPORTED;
554   }
555 
556 
557   SmmPerfCommData->ReturnStatus = Status;
558 
559   return EFI_SUCCESS;
560 }
561 
562 /**
563   Communication service SMI Handler entry.
564 
565   This SMI handler provides services for the performance wrapper driver.
566 
567   Caution: This function may receive untrusted input.
568   Communicate buffer and buffer size are external input, so this function will do basic validation.
569 
570   @param[in]     DispatchHandle  The unique handle assigned to this handler by SmiHandlerRegister().
571   @param[in]     RegisterContext Points to an optional handler context which was specified when the
572                                  handler was registered.
573   @param[in, out] CommBuffer     A pointer to a collection of data in memory that will
574                                  be conveyed from a non-SMM environment into an SMM environment.
575   @param[in, out] CommBufferSize The size of the CommBuffer.
576 
577   @retval EFI_SUCCESS                         The interrupt was handled and quiesced. No other handlers
578                                               should still be called.
579   @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED  The interrupt has been quiesced but other handlers should
580                                               still be called.
581   @retval EFI_WARN_INTERRUPT_SOURCE_PENDING   The interrupt is still pending and other handlers should still
582                                               be called.
583   @retval EFI_INTERRUPT_PENDING               The interrupt could not be quiesced.
584 **/
585 EFI_STATUS
586 EFIAPI
SmmPerformanceHandler(IN EFI_HANDLE DispatchHandle,IN CONST VOID * RegisterContext,IN OUT VOID * CommBuffer,IN OUT UINTN * CommBufferSize)587 SmmPerformanceHandler (
588   IN     EFI_HANDLE                    DispatchHandle,
589   IN     CONST VOID                   *RegisterContext,
590   IN OUT VOID                          *CommBuffer,
591   IN OUT UINTN                         *CommBufferSize
592   )
593 {
594   EFI_STATUS            Status;
595   SMM_PERF_COMMUNICATE  *SmmPerfCommData;
596   GAUGE_DATA_ENTRY_EX   *GaugeEntryExArray;
597   UINT64                DataSize;
598   UINTN                 Index;
599   GAUGE_DATA_ENTRY      *GaugeData;
600   UINTN                 NumberOfEntries;
601   UINTN                 LogEntryKey;
602   UINTN                 TempCommBufferSize;
603 
604   GaugeEntryExArray = NULL;
605 
606   //
607   // If input is invalid, stop processing this SMI
608   //
609   if (CommBuffer == NULL || CommBufferSize == NULL) {
610     return EFI_SUCCESS;
611   }
612 
613   TempCommBufferSize = *CommBufferSize;
614 
615   if(TempCommBufferSize < sizeof (SMM_PERF_COMMUNICATE)) {
616     return EFI_SUCCESS;
617   }
618 
619   if (!SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) {
620     DEBUG ((EFI_D_ERROR, "SmmPerformanceHandler: SMM communcation data buffer in SMRAM or overflow!\n"));
621     return EFI_SUCCESS;
622   }
623 
624   SmmPerfCommData = (SMM_PERF_COMMUNICATE *)CommBuffer;
625 
626   switch (SmmPerfCommData->Function) {
627     case SMM_PERF_FUNCTION_GET_GAUGE_ENTRY_NUMBER :
628        SmmPerfCommData->NumberOfEntries = mGaugeData->NumberOfEntries;
629        Status = EFI_SUCCESS;
630        break;
631 
632     case SMM_PERF_FUNCTION_GET_GAUGE_DATA :
633        GaugeData = SmmPerfCommData->GaugeData;
634        NumberOfEntries = SmmPerfCommData->NumberOfEntries;
635        LogEntryKey = SmmPerfCommData->LogEntryKey;
636        if (GaugeData == NULL || NumberOfEntries == 0 || LogEntryKey > mGaugeData->NumberOfEntries ||
637            NumberOfEntries > mGaugeData->NumberOfEntries || LogEntryKey > (mGaugeData->NumberOfEntries - NumberOfEntries)) {
638          Status = EFI_INVALID_PARAMETER;
639          break;
640        }
641 
642        //
643        // Sanity check
644        //
645        DataSize = MultU64x32 (NumberOfEntries, sizeof(GAUGE_DATA_ENTRY));
646        if (!SmmIsBufferOutsideSmmValid ((UINTN) GaugeData, DataSize)) {
647          DEBUG ((EFI_D_ERROR, "SmmPerformanceHandler: SMM Performance Data buffer in SMRAM or overflow!\n"));
648          Status = EFI_ACCESS_DENIED;
649          break;
650        }
651 
652        GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);
653 
654        for (Index = 0; Index < NumberOfEntries; Index++) {
655          CopyMem (
656            (UINT8 *) &GaugeData[Index],
657            (UINT8 *) &GaugeEntryExArray[LogEntryKey++],
658            sizeof (GAUGE_DATA_ENTRY)
659            );
660        }
661        Status = EFI_SUCCESS;
662        break;
663 
664     default:
665        Status = EFI_UNSUPPORTED;
666   }
667 
668 
669   SmmPerfCommData->ReturnStatus = Status;
670 
671   return EFI_SUCCESS;
672 }
673 
674 /**
675   SmmBase2 protocol notify callback function, when SMST and SMM memory service get initialized
676   this function is callbacked to initialize the Smm Performance Lib
677 
678   @param  Event    The event of notify protocol.
679   @param  Context  Notify event context.
680 
681 **/
682 VOID
683 EFIAPI
InitializeSmmCorePerformanceLib(IN EFI_EVENT Event,IN VOID * Context)684 InitializeSmmCorePerformanceLib (
685   IN EFI_EVENT     Event,
686   IN VOID          *Context
687   )
688 {
689   EFI_STATUS                Status;
690   EFI_HANDLE                Handle;
691 
692   //
693   // Initialize spin lock
694   //
695   InitializeSpinLock (&mSmmPerfLock);
696 
697   mMaxGaugeRecords = INIT_SMM_GAUGE_DATA_ENTRIES;
698 
699   mGaugeData = AllocateZeroPool (sizeof (GAUGE_DATA_HEADER) + (sizeof (GAUGE_DATA_ENTRY_EX) * mMaxGaugeRecords));
700   ASSERT (mGaugeData != NULL);
701 
702   //
703   // Install the protocol interfaces.
704   //
705   Status = gSmst->SmmInstallProtocolInterface (
706                     &mHandle,
707                     &gSmmPerformanceProtocolGuid,
708                     EFI_NATIVE_INTERFACE,
709                     &mPerformanceInterface
710                     );
711   ASSERT_EFI_ERROR (Status);
712 
713   Status = gSmst->SmmInstallProtocolInterface (
714                     &mHandle,
715                     &gSmmPerformanceExProtocolGuid,
716                     EFI_NATIVE_INTERFACE,
717                     &mPerformanceExInterface
718                     );
719   ASSERT_EFI_ERROR (Status);
720 
721   ///
722   /// Register SMM Performance SMI handler
723   ///
724   Handle = NULL;
725   Status = gSmst->SmiHandlerRegister (SmmPerformanceHandler, &gSmmPerformanceProtocolGuid, &Handle);
726   ASSERT_EFI_ERROR (Status);
727   Status = gSmst->SmiHandlerRegister (SmmPerformanceHandlerEx, &gSmmPerformanceExProtocolGuid, &Handle);
728   ASSERT_EFI_ERROR (Status);
729 }
730 
731 /**
732   The constructor function initializes the Performance Measurement Enable flag and
733   registers SmmBase2 protocol notify callback.
734   It will ASSERT() if one of these operations fails and it will always return EFI_SUCCESS.
735 
736   @param  ImageHandle   The firmware allocated handle for the EFI image.
737   @param  SystemTable   A pointer to the EFI System Table.
738 
739   @retval EFI_SUCCESS   The constructor always returns EFI_SUCCESS.
740 
741 **/
742 EFI_STATUS
743 EFIAPI
SmmCorePerformanceLibConstructor(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)744 SmmCorePerformanceLibConstructor (
745   IN EFI_HANDLE        ImageHandle,
746   IN EFI_SYSTEM_TABLE  *SystemTable
747   )
748 {
749   EFI_STATUS  Status;
750   EFI_EVENT   Event;
751   VOID        *Registration;
752 
753   mPerformanceMeasurementEnabled =  (BOOLEAN) ((PcdGet8(PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0);
754   if (!mPerformanceMeasurementEnabled) {
755     //
756     // Do not initialize performance infrastructure if not required.
757     //
758     return EFI_SUCCESS;
759   }
760 
761   //
762   // Create the events to do the library init.
763   //
764   Status = gBS->CreateEvent (
765                   EVT_NOTIFY_SIGNAL,
766                   TPL_CALLBACK,
767                   InitializeSmmCorePerformanceLib,
768                   NULL,
769                   &Event
770                   );
771   ASSERT_EFI_ERROR (Status);
772 
773   //
774   // Register for protocol notifications on this event
775   //
776   Status = gBS->RegisterProtocolNotify (
777                   &gEfiSmmBase2ProtocolGuid,
778                   Event,
779                   &Registration
780                   );
781 
782   ASSERT_EFI_ERROR (Status);
783 
784   return EFI_SUCCESS;
785 }
786 
787 /**
788   Adds a record at the end of the performance measurement log
789   that records the start time of a performance measurement.
790 
791   Adds a record to the end of the performance measurement log
792   that contains the Handle, Token, Module and Identifier.
793   The end time of the new record must be set to zero.
794   If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
795   If TimeStamp is zero, the start time in the record is filled in with the value
796   read from the current time stamp.
797 
798   @param  Handle                  Pointer to environment specific context used
799                                   to identify the component being measured.
800   @param  Token                   Pointer to a Null-terminated ASCII string
801                                   that identifies the component being measured.
802   @param  Module                  Pointer to a Null-terminated ASCII string
803                                   that identifies the module being measured.
804   @param  TimeStamp               64-bit time stamp.
805   @param  Identifier              32-bit identifier. If the value is 0, the created record
806                                   is same as the one created by StartPerformanceMeasurement.
807 
808   @retval RETURN_SUCCESS          The start of the measurement was recorded.
809   @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.
810 
811 **/
812 RETURN_STATUS
813 EFIAPI
StartPerformanceMeasurementEx(IN CONST VOID * Handle,OPTIONAL IN CONST CHAR8 * Token,OPTIONAL IN CONST CHAR8 * Module,OPTIONAL IN UINT64 TimeStamp,IN UINT32 Identifier)814 StartPerformanceMeasurementEx (
815   IN CONST VOID   *Handle,  OPTIONAL
816   IN CONST CHAR8  *Token,   OPTIONAL
817   IN CONST CHAR8  *Module,  OPTIONAL
818   IN UINT64       TimeStamp,
819   IN UINT32       Identifier
820   )
821 {
822   return (RETURN_STATUS) StartGaugeEx (Handle, Token, Module, TimeStamp, Identifier);
823 }
824 
825 /**
826   Searches the performance measurement log from the beginning of the log
827   for the first matching record that contains a zero end time and fills in a valid end time.
828 
829   Searches the performance measurement log from the beginning of the log
830   for the first record that matches Handle, Token, Module and Identifier and has an end time value of zero.
831   If the record can not be found then return RETURN_NOT_FOUND.
832   If the record is found and TimeStamp is not zero,
833   then the end time in the record is filled in with the value specified by TimeStamp.
834   If the record is found and TimeStamp is zero, then the end time in the matching record
835   is filled in with the current time stamp value.
836 
837   @param  Handle                  Pointer to environment specific context used
838                                   to identify the component being measured.
839   @param  Token                   Pointer to a Null-terminated ASCII string
840                                   that identifies the component being measured.
841   @param  Module                  Pointer to a Null-terminated ASCII string
842                                   that identifies the module being measured.
843   @param  TimeStamp               64-bit time stamp.
844   @param  Identifier              32-bit identifier. If the value is 0, the found record
845                                   is same as the one found by EndPerformanceMeasurement.
846 
847   @retval RETURN_SUCCESS          The end of  the measurement was recorded.
848   @retval RETURN_NOT_FOUND        The specified measurement record could not be found.
849 
850 **/
851 RETURN_STATUS
852 EFIAPI
EndPerformanceMeasurementEx(IN CONST VOID * Handle,OPTIONAL IN CONST CHAR8 * Token,OPTIONAL IN CONST CHAR8 * Module,OPTIONAL IN UINT64 TimeStamp,IN UINT32 Identifier)853 EndPerformanceMeasurementEx (
854   IN CONST VOID   *Handle,  OPTIONAL
855   IN CONST CHAR8  *Token,   OPTIONAL
856   IN CONST CHAR8  *Module,  OPTIONAL
857   IN UINT64       TimeStamp,
858   IN UINT32       Identifier
859   )
860 {
861   return (RETURN_STATUS) EndGaugeEx (Handle, Token, Module, TimeStamp, Identifier);
862 }
863 
864 /**
865   Attempts to retrieve a performance measurement log entry from the performance measurement log.
866   It can also retrieve the log created by StartPerformanceMeasurement and EndPerformanceMeasurement,
867   and then assign the Identifier with 0.
868 
869   Attempts to retrieve the performance log entry specified by LogEntryKey.  If LogEntryKey is
870   zero on entry, then an attempt is made to retrieve the first entry from the performance log,
871   and the key for the second entry in the log is returned.  If the performance log is empty,
872   then no entry is retrieved and zero is returned.  If LogEntryKey is not zero, then the performance
873   log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
874   returned.  If LogEntryKey is the key for the last entry in the log, then the last log entry is
875   retrieved and an implementation specific non-zero key value that specifies the end of the performance
876   log is returned.  If LogEntryKey is equal this implementation specific non-zero key value, then no entry
877   is retrieved and zero is returned.  In the cases where a performance log entry can be returned,
878   the log entry is returned in Handle, Token, Module, StartTimeStamp, EndTimeStamp and Identifier.
879   If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().
880   If Handle is NULL, then ASSERT().
881   If Token is NULL, then ASSERT().
882   If Module is NULL, then ASSERT().
883   If StartTimeStamp is NULL, then ASSERT().
884   If EndTimeStamp is NULL, then ASSERT().
885   If Identifier is NULL, then ASSERT().
886 
887   @param  LogEntryKey             On entry, the key of the performance measurement log entry to retrieve.
888                                   0, then the first performance measurement log entry is retrieved.
889                                   On exit, the key of the next performance log entry.
890   @param  Handle                  Pointer to environment specific context used to identify the component
891                                   being measured.
892   @param  Token                   Pointer to a Null-terminated ASCII string that identifies the component
893                                   being measured.
894   @param  Module                  Pointer to a Null-terminated ASCII string that identifies the module
895                                   being measured.
896   @param  StartTimeStamp          Pointer to the 64-bit time stamp that was recorded when the measurement
897                                   was started.
898   @param  EndTimeStamp            Pointer to the 64-bit time stamp that was recorded when the measurement
899                                   was ended.
900   @param  Identifier              Pointer to the 32-bit identifier that was recorded.
901 
902   @return The key for the next performance log entry (in general case).
903 
904 **/
905 UINTN
906 EFIAPI
GetPerformanceMeasurementEx(IN UINTN LogEntryKey,OUT CONST VOID ** Handle,OUT CONST CHAR8 ** Token,OUT CONST CHAR8 ** Module,OUT UINT64 * StartTimeStamp,OUT UINT64 * EndTimeStamp,OUT UINT32 * Identifier)907 GetPerformanceMeasurementEx (
908   IN  UINTN       LogEntryKey,
909   OUT CONST VOID  **Handle,
910   OUT CONST CHAR8 **Token,
911   OUT CONST CHAR8 **Module,
912   OUT UINT64      *StartTimeStamp,
913   OUT UINT64      *EndTimeStamp,
914   OUT UINT32      *Identifier
915   )
916 {
917   EFI_STATUS           Status;
918   GAUGE_DATA_ENTRY_EX  *GaugeData;
919 
920   GaugeData = NULL;
921 
922   ASSERT (Handle != NULL);
923   ASSERT (Token != NULL);
924   ASSERT (Module != NULL);
925   ASSERT (StartTimeStamp != NULL);
926   ASSERT (EndTimeStamp != NULL);
927   ASSERT (Identifier != NULL);
928 
929   Status = GetGaugeEx (LogEntryKey++, &GaugeData);
930 
931   //
932   // Make sure that LogEntryKey is a valid log entry key,
933   //
934   ASSERT (Status != EFI_INVALID_PARAMETER);
935 
936   if (EFI_ERROR (Status)) {
937     //
938     // The LogEntryKey is the last entry (equals to the total entry number).
939     //
940     return 0;
941   }
942 
943   ASSERT (GaugeData != NULL);
944 
945   *Handle         = (VOID *) (UINTN) GaugeData->Handle;
946   *Token          = GaugeData->Token;
947   *Module         = GaugeData->Module;
948   *StartTimeStamp = GaugeData->StartTimeStamp;
949   *EndTimeStamp   = GaugeData->EndTimeStamp;
950   *Identifier     = GaugeData->Identifier;
951 
952   return LogEntryKey;
953 }
954 
955 /**
956   Adds a record at the end of the performance measurement log
957   that records the start time of a performance measurement.
958 
959   Adds a record to the end of the performance measurement log
960   that contains the Handle, Token, and Module.
961   The end time of the new record must be set to zero.
962   If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
963   If TimeStamp is zero, the start time in the record is filled in with the value
964   read from the current time stamp.
965 
966   @param  Handle                  Pointer to environment specific context used
967                                   to identify the component being measured.
968   @param  Token                   Pointer to a Null-terminated ASCII string
969                                   that identifies the component being measured.
970   @param  Module                  Pointer to a Null-terminated ASCII string
971                                   that identifies the module being measured.
972   @param  TimeStamp               64-bit time stamp.
973 
974   @retval RETURN_SUCCESS          The start of the measurement was recorded.
975   @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.
976 
977 **/
978 RETURN_STATUS
979 EFIAPI
StartPerformanceMeasurement(IN CONST VOID * Handle,OPTIONAL IN CONST CHAR8 * Token,OPTIONAL IN CONST CHAR8 * Module,OPTIONAL IN UINT64 TimeStamp)980 StartPerformanceMeasurement (
981   IN CONST VOID   *Handle,  OPTIONAL
982   IN CONST CHAR8  *Token,   OPTIONAL
983   IN CONST CHAR8  *Module,  OPTIONAL
984   IN UINT64       TimeStamp
985   )
986 {
987   return StartPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);
988 }
989 
990 /**
991   Searches the performance measurement log from the beginning of the log
992   for the first matching record that contains a zero end time and fills in a valid end time.
993 
994   Searches the performance measurement log from the beginning of the log
995   for the first record that matches Handle, Token, and Module and has an end time value of zero.
996   If the record can not be found then return RETURN_NOT_FOUND.
997   If the record is found and TimeStamp is not zero,
998   then the end time in the record is filled in with the value specified by TimeStamp.
999   If the record is found and TimeStamp is zero, then the end time in the matching record
1000   is filled in with the current time stamp value.
1001 
1002   @param  Handle                  Pointer to environment specific context used
1003                                   to identify the component being measured.
1004   @param  Token                   Pointer to a Null-terminated ASCII string
1005                                   that identifies the component being measured.
1006   @param  Module                  Pointer to a Null-terminated ASCII string
1007                                   that identifies the module being measured.
1008   @param  TimeStamp               64-bit time stamp.
1009 
1010   @retval RETURN_SUCCESS          The end of  the measurement was recorded.
1011   @retval RETURN_NOT_FOUND        The specified measurement record could not be found.
1012 
1013 **/
1014 RETURN_STATUS
1015 EFIAPI
EndPerformanceMeasurement(IN CONST VOID * Handle,OPTIONAL IN CONST CHAR8 * Token,OPTIONAL IN CONST CHAR8 * Module,OPTIONAL IN UINT64 TimeStamp)1016 EndPerformanceMeasurement (
1017   IN CONST VOID   *Handle,  OPTIONAL
1018   IN CONST CHAR8  *Token,   OPTIONAL
1019   IN CONST CHAR8  *Module,  OPTIONAL
1020   IN UINT64       TimeStamp
1021   )
1022 {
1023   return EndPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);
1024 }
1025 
1026 /**
1027   Attempts to retrieve a performance measurement log entry from the performance measurement log.
1028   It can also retrieve the log created by StartPerformanceMeasurementEx and EndPerformanceMeasurementEx,
1029   and then eliminate the Identifier.
1030 
1031   Attempts to retrieve the performance log entry specified by LogEntryKey.  If LogEntryKey is
1032   zero on entry, then an attempt is made to retrieve the first entry from the performance log,
1033   and the key for the second entry in the log is returned.  If the performance log is empty,
1034   then no entry is retrieved and zero is returned.  If LogEntryKey is not zero, then the performance
1035   log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
1036   returned.  If LogEntryKey is the key for the last entry in the log, then the last log entry is
1037   retrieved and an implementation specific non-zero key value that specifies the end of the performance
1038   log is returned.  If LogEntryKey is equal this implementation specific non-zero key value, then no entry
1039   is retrieved and zero is returned.  In the cases where a performance log entry can be returned,
1040   the log entry is returned in Handle, Token, Module, StartTimeStamp, and EndTimeStamp.
1041   If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().
1042   If Handle is NULL, then ASSERT().
1043   If Token is NULL, then ASSERT().
1044   If Module is NULL, then ASSERT().
1045   If StartTimeStamp is NULL, then ASSERT().
1046   If EndTimeStamp is NULL, then ASSERT().
1047 
1048   @param  LogEntryKey             On entry, the key of the performance measurement log entry to retrieve.
1049                                   0, then the first performance measurement log entry is retrieved.
1050                                   On exit, the key of the next performance log entry.
1051   @param  Handle                  Pointer to environment specific context used to identify the component
1052                                   being measured.
1053   @param  Token                   Pointer to a Null-terminated ASCII string that identifies the component
1054                                   being measured.
1055   @param  Module                  Pointer to a Null-terminated ASCII string that identifies the module
1056                                   being measured.
1057   @param  StartTimeStamp          Pointer to the 64-bit time stamp that was recorded when the measurement
1058                                   was started.
1059   @param  EndTimeStamp            Pointer to the 64-bit time stamp that was recorded when the measurement
1060                                   was ended.
1061 
1062   @return The key for the next performance log entry (in general case).
1063 
1064 **/
1065 UINTN
1066 EFIAPI
GetPerformanceMeasurement(IN UINTN LogEntryKey,OUT CONST VOID ** Handle,OUT CONST CHAR8 ** Token,OUT CONST CHAR8 ** Module,OUT UINT64 * StartTimeStamp,OUT UINT64 * EndTimeStamp)1067 GetPerformanceMeasurement (
1068   IN  UINTN       LogEntryKey,
1069   OUT CONST VOID  **Handle,
1070   OUT CONST CHAR8 **Token,
1071   OUT CONST CHAR8 **Module,
1072   OUT UINT64      *StartTimeStamp,
1073   OUT UINT64      *EndTimeStamp
1074   )
1075 {
1076   UINT32 Identifier;
1077   return GetPerformanceMeasurementEx (LogEntryKey, Handle, Token, Module, StartTimeStamp, EndTimeStamp, &Identifier);
1078 }
1079 
1080 /**
1081   Returns TRUE if the performance measurement macros are enabled.
1082 
1083   This function returns TRUE if the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
1084   PcdPerformanceLibraryPropertyMask is set.  Otherwise FALSE is returned.
1085 
1086   @retval TRUE                    The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
1087                                   PcdPerformanceLibraryPropertyMask is set.
1088   @retval FALSE                   The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
1089                                   PcdPerformanceLibraryPropertyMask is clear.
1090 
1091 **/
1092 BOOLEAN
1093 EFIAPI
PerformanceMeasurementEnabled(VOID)1094 PerformanceMeasurementEnabled (
1095   VOID
1096   )
1097 {
1098   return mPerformanceMeasurementEnabled;
1099 }
1100