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