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