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