MdeModulePkg: Fix potential integer overflow issue
[mirror_edk2.git] / MdeModulePkg / Library / SmmCorePerformanceLib / SmmCorePerformanceLib.c
CommitLineData
d042c6e8 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
f0da4d7d 6 It initializes SMM phase performance logging by publishing the SMM Performance and PerformanceEx Protocol,\r
d042c6e8 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
f0da4d7d 10 SMM Performance and PerformanceEx Protocol are installed at the very beginning of SMM phase.\r
d042c6e8 11\r
ccd2f6b0 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
842b1242 19Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>\r
d042c6e8 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
d042c6e8 54//\r
f0da4d7d 55// Interfaces for SMM Performance Protocol.\r
d042c6e8 56//\r
57PERFORMANCE_PROTOCOL mPerformanceInterface = {\r
58 StartGauge,\r
59 EndGauge,\r
60 GetGauge\r
61};\r
62\r
f0da4d7d
SZ
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
d042c6e8 72/**\r
f0da4d7d 73 Searches in the gauge array with keyword Handle, Token, Module and Identfier.\r
d042c6e8 74\r
75 This internal function searches for the gauge entry in the gauge array.\r
f0da4d7d 76 If there is an entry that exactly matches the given keywords\r
d042c6e8 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
f0da4d7d 86 @param Identifier 32-bit identifier.\r
d042c6e8 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
f0da4d7d
SZ
95 IN CONST CHAR8 *Module, OPTIONAL\r
96 IN CONST UINT32 Identifier\r
d042c6e8 97 )\r
98{\r
99 UINT32 Index;\r
b504f519 100 UINT32 Index2;\r
d042c6e8 101 UINT32 NumberOfEntries;\r
f0da4d7d 102 GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;\r
d042c6e8 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
f0da4d7d 112 GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);\r
d042c6e8 113\r
b504f519
SZ
114 Index2 = 0;\r
115\r
d042c6e8 116 for (Index = 0; Index < NumberOfEntries; Index++) {\r
b504f519
SZ
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
d042c6e8 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
f0da4d7d 136 that contains the Handle, Token, Module and Identifier.\r
d042c6e8 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
f0da4d7d
SZ
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
d042c6e8 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
f0da4d7d 158StartGaugeEx (\r
d042c6e8 159 IN CONST VOID *Handle, OPTIONAL\r
160 IN CONST CHAR8 *Token, OPTIONAL\r
161 IN CONST CHAR8 *Module, OPTIONAL\r
f0da4d7d
SZ
162 IN UINT64 TimeStamp,\r
163 IN UINT32 Identifier\r
d042c6e8 164 )\r
165{\r
f0da4d7d 166 GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;\r
d042c6e8 167 UINTN GaugeDataSize;\r
f0da4d7d 168 GAUGE_DATA_HEADER *NewGaugeData;\r
d042c6e8 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
f0da4d7d 181 OldGaugeDataSize = sizeof (GAUGE_DATA_HEADER) + sizeof (GAUGE_DATA_ENTRY_EX) * mMaxGaugeRecords;\r
d042c6e8 182\r
f0da4d7d 183 GaugeDataSize = sizeof (GAUGE_DATA_HEADER) + sizeof (GAUGE_DATA_ENTRY_EX) * mMaxGaugeRecords * 2;\r
d042c6e8 184\r
f0da4d7d
SZ
185 NewGaugeData = AllocateZeroPool (GaugeDataSize);\r
186 if (NewGaugeData == NULL) {\r
187 ReleaseSpinLock (&mSmmPerfLock);\r
d042c6e8 188 return EFI_OUT_OF_RESOURCES;\r
189 }\r
f0da4d7d
SZ
190\r
191 mGaugeData = NewGaugeData;\r
192 mMaxGaugeRecords *= 2;\r
193\r
d042c6e8 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
f0da4d7d
SZ
202 GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);\r
203 GaugeEntryExArray[Index].Handle = (EFI_PHYSICAL_ADDRESS) (UINTN) Handle;\r
d042c6e8 204\r
205 if (Token != NULL) {\r
8feb7452 206 AsciiStrnCpyS (GaugeEntryExArray[Index].Token, SMM_PERFORMANCE_STRING_SIZE, Token, SMM_PERFORMANCE_STRING_LENGTH);\r
d042c6e8 207 }\r
208 if (Module != NULL) {\r
8feb7452 209 AsciiStrnCpyS (GaugeEntryExArray[Index].Module, SMM_PERFORMANCE_STRING_SIZE, Module, SMM_PERFORMANCE_STRING_LENGTH);\r
d042c6e8 210 }\r
211\r
f0da4d7d
SZ
212 GaugeEntryExArray[Index].EndTimeStamp = 0;\r
213 GaugeEntryExArray[Index].Identifier = Identifier;\r
214\r
d042c6e8 215 if (TimeStamp == 0) {\r
216 TimeStamp = GetPerformanceCounter ();\r
217 }\r
f0da4d7d 218 GaugeEntryExArray[Index].StartTimeStamp = TimeStamp;\r
d042c6e8 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
f0da4d7d 232 for the first record that matches Handle, Token, Module and Identifier and has an end time value of zero.\r
d042c6e8 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
f0da4d7d
SZ
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
d042c6e8 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
f0da4d7d 255EndGaugeEx (\r
d042c6e8 256 IN CONST VOID *Handle, OPTIONAL\r
257 IN CONST CHAR8 *Token, OPTIONAL\r
258 IN CONST CHAR8 *Module, OPTIONAL\r
f0da4d7d
SZ
259 IN UINT64 TimeStamp,\r
260 IN UINT32 Identifier\r
d042c6e8 261 )\r
262{\r
f0da4d7d
SZ
263 GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;\r
264 UINT32 Index;\r
265\r
266 AcquireSpinLock (&mSmmPerfLock);\r
d042c6e8 267\r
268 if (TimeStamp == 0) {\r
269 TimeStamp = GetPerformanceCounter ();\r
270 }\r
271\r
f0da4d7d 272 Index = SmmSearchForGaugeEntry (Handle, Token, Module, Identifier);\r
d042c6e8 273 if (Index >= mGaugeData->NumberOfEntries) {\r
f0da4d7d 274 ReleaseSpinLock (&mSmmPerfLock);\r
d042c6e8 275 return EFI_NOT_FOUND;\r
276 }\r
f0da4d7d
SZ
277 GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);\r
278 GaugeEntryExArray[Index].EndTimeStamp = TimeStamp;\r
279\r
280 ReleaseSpinLock (&mSmmPerfLock);\r
d042c6e8 281\r
282 return EFI_SUCCESS;\r
283}\r
284\r
285/**\r
286 Retrieves a previously logged performance measurement.\r
f0da4d7d
SZ
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
d042c6e8 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
f0da4d7d 292 GaugeDataEntryEx stores the pointer to that entry.\r
d042c6e8 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
f0da4d7d 296 @param GaugeDataEntryEx The indirect pointer to the extended gauge data entry specified by LogEntryKey\r
d042c6e8 297 if the retrieval is successful.\r
298\r
f0da4d7d 299 @retval EFI_SUCCESS The GuageDataEntryEx is successfully found based on LogEntryKey.\r
d042c6e8 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
f0da4d7d 302 @retval EFI_INVALIDE_PARAMETER GaugeDataEntryEx is NULL.\r
d042c6e8 303\r
304**/\r
305EFI_STATUS\r
306EFIAPI\r
f0da4d7d
SZ
307GetGaugeEx (\r
308 IN UINTN LogEntryKey,\r
309 OUT GAUGE_DATA_ENTRY_EX **GaugeDataEntryEx\r
d042c6e8 310 )\r
311{\r
312 UINTN NumberOfEntries;\r
f0da4d7d 313 GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;\r
d042c6e8 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
f0da4d7d 323 GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);\r
d042c6e8 324\r
f0da4d7d 325 if (GaugeDataEntryEx == NULL) {\r
d042c6e8 326 return EFI_INVALID_PARAMETER;\r
327 }\r
f0da4d7d 328 *GaugeDataEntryEx = &GaugeEntryExArray[LogEntryKey];\r
d042c6e8 329\r
330 return EFI_SUCCESS;\r
331}\r
332\r
f0da4d7d
SZ
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
1658440e
SZ
434 GaugeEntryEx = NULL;\r
435\r
f0da4d7d
SZ
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
d042c6e8 449\r
d042c6e8 450/**\r
451 Communication service SMI Handler entry.\r
452\r
f0da4d7d 453 This SMI handler provides services for the performance wrapper driver.\r
ccd2f6b0 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
f0da4d7d
SZ
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
579b5ef2
RN
485 UINT64 DataSize;\r
486 UINTN Index;\r
5e5bb2a9
SZ
487 GAUGE_DATA_ENTRY_EX *GaugeDataEx;\r
488 UINTN NumberOfEntries;\r
489 UINTN LogEntryKey;\r
164a9b67 490 UINTN TempCommBufferSize;\r
f0da4d7d
SZ
491\r
492 GaugeEntryExArray = NULL;\r
493\r
ccd2f6b0 494 //\r
495 // If input is invalid, stop processing this SMI\r
496 //\r
497 if (CommBuffer == NULL || CommBufferSize == NULL) {\r
498 return EFI_SUCCESS;\r
499 }\r
500\r
164a9b67
SZ
501 TempCommBufferSize = *CommBufferSize;\r
502\r
503 if(TempCommBufferSize < sizeof (SMM_PERF_COMMUNICATE_EX)) {\r
ccd2f6b0 504 return EFI_SUCCESS;\r
505 }\r
f0da4d7d 506\r
842b1242 507 if (!SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) {\r
5e5bb2a9 508 DEBUG ((EFI_D_ERROR, "SmmPerformanceHandlerEx: SMM communcation data buffer in SMRAM or overflow!\n"));\r
ccd2f6b0 509 return EFI_SUCCESS;\r
510 }\r
511 \r
f0da4d7d
SZ
512 SmmPerfCommData = (SMM_PERF_COMMUNICATE_EX *)CommBuffer;\r
513\r
514 switch (SmmPerfCommData->Function) {\r
515 case SMM_PERF_FUNCTION_GET_GAUGE_ENTRY_NUMBER :\r
516 SmmPerfCommData->NumberOfEntries = mGaugeData->NumberOfEntries;\r
517 Status = EFI_SUCCESS;\r
518 break;\r
519\r
520 case SMM_PERF_FUNCTION_GET_GAUGE_DATA :\r
5e5bb2a9
SZ
521 GaugeDataEx = SmmPerfCommData->GaugeDataEx;\r
522 NumberOfEntries = SmmPerfCommData->NumberOfEntries;\r
523 LogEntryKey = SmmPerfCommData->LogEntryKey;\r
524 if (GaugeDataEx == NULL || NumberOfEntries == 0 || LogEntryKey > mGaugeData->NumberOfEntries ||\r
579b5ef2 525 NumberOfEntries > mGaugeData->NumberOfEntries || LogEntryKey > (mGaugeData->NumberOfEntries - NumberOfEntries)) {\r
f0da4d7d
SZ
526 Status = EFI_INVALID_PARAMETER;\r
527 break;\r
528 }\r
529\r
530 //\r
531 // Sanity check\r
532 //\r
579b5ef2
RN
533 DataSize = MultU64x32 (NumberOfEntries, sizeof(GAUGE_DATA_ENTRY_EX));\r
534 if (!SmmIsBufferOutsideSmmValid ((UINTN) GaugeDataEx, DataSize)) {\r
5e5bb2a9 535 DEBUG ((EFI_D_ERROR, "SmmPerformanceHandlerEx: SMM Performance Data buffer in SMRAM or overflow!\n"));\r
f0da4d7d 536 Status = EFI_ACCESS_DENIED;\r
ccd2f6b0 537 break;\r
f0da4d7d
SZ
538 }\r
539\r
540 GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);\r
579b5ef2
RN
541\r
542 for (Index = 0; Index < NumberOfEntries; Index++) {\r
543 CopyMem (\r
544 (UINT8 *) &GaugeDataEx[Index],\r
545 (UINT8 *) &GaugeEntryExArray[LogEntryKey++],\r
546 sizeof (GAUGE_DATA_ENTRY_EX)\r
547 );\r
548 }\r
f0da4d7d
SZ
549 Status = EFI_SUCCESS;\r
550 break;\r
551\r
552 default:\r
f0da4d7d
SZ
553 Status = EFI_UNSUPPORTED;\r
554 }\r
555\r
ccd2f6b0 556\r
f0da4d7d 557 SmmPerfCommData->ReturnStatus = Status;\r
ccd2f6b0 558 \r
f0da4d7d
SZ
559 return EFI_SUCCESS;\r
560}\r
561\r
562/**\r
563 Communication service SMI Handler entry.\r
564\r
565 This SMI handler provides services for the performance wrapper driver.\r
d042c6e8 566\r
ccd2f6b0 567 Caution: This function may receive untrusted input.\r
568 Communicate buffer and buffer size are external input, so this function will do basic validation.\r
569\r
d042c6e8 570 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
571 @param[in] RegisterContext Points to an optional handler context which was specified when the\r
572 handler was registered.\r
573 @param[in, out] CommBuffer A pointer to a collection of data in memory that will\r
574 be conveyed from a non-SMM environment into an SMM environment.\r
575 @param[in, out] CommBufferSize The size of the CommBuffer.\r
576\r
577 @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers \r
578 should still be called.\r
579 @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should \r
580 still be called.\r
581 @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still \r
582 be called.\r
583 @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.\r
584**/\r
585EFI_STATUS\r
586EFIAPI\r
587SmmPerformanceHandler (\r
588 IN EFI_HANDLE DispatchHandle,\r
589 IN CONST VOID *RegisterContext,\r
f0da4d7d
SZ
590 IN OUT VOID *CommBuffer,\r
591 IN OUT UINTN *CommBufferSize\r
d042c6e8 592 )\r
593{\r
594 EFI_STATUS Status;\r
595 SMM_PERF_COMMUNICATE *SmmPerfCommData;\r
f0da4d7d 596 GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;\r
579b5ef2 597 UINT64 DataSize;\r
f0da4d7d 598 UINTN Index;\r
5e5bb2a9
SZ
599 GAUGE_DATA_ENTRY *GaugeData;\r
600 UINTN NumberOfEntries;\r
f0da4d7d 601 UINTN LogEntryKey;\r
164a9b67
SZ
602 UINTN TempCommBufferSize;\r
603\r
f0da4d7d 604 GaugeEntryExArray = NULL;\r
d042c6e8 605\r
ccd2f6b0 606 //\r
607 // If input is invalid, stop processing this SMI\r
608 //\r
609 if (CommBuffer == NULL || CommBufferSize == NULL) {\r
610 return EFI_SUCCESS;\r
611 }\r
612\r
164a9b67
SZ
613 TempCommBufferSize = *CommBufferSize;\r
614\r
615 if(TempCommBufferSize < sizeof (SMM_PERF_COMMUNICATE)) {\r
ccd2f6b0 616 return EFI_SUCCESS;\r
617 }\r
618\r
842b1242 619 if (!SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) {\r
5e5bb2a9 620 DEBUG ((EFI_D_ERROR, "SmmPerformanceHandler: SMM communcation data buffer in SMRAM or overflow!\n"));\r
ccd2f6b0 621 return EFI_SUCCESS;\r
622 }\r
d042c6e8 623\r
f0da4d7d 624 SmmPerfCommData = (SMM_PERF_COMMUNICATE *)CommBuffer;\r
d042c6e8 625\r
626 switch (SmmPerfCommData->Function) {\r
627 case SMM_PERF_FUNCTION_GET_GAUGE_ENTRY_NUMBER :\r
628 SmmPerfCommData->NumberOfEntries = mGaugeData->NumberOfEntries;\r
f0da4d7d 629 Status = EFI_SUCCESS;\r
d042c6e8 630 break;\r
631\r
632 case SMM_PERF_FUNCTION_GET_GAUGE_DATA :\r
5e5bb2a9
SZ
633 GaugeData = SmmPerfCommData->GaugeData;\r
634 NumberOfEntries = SmmPerfCommData->NumberOfEntries;\r
635 LogEntryKey = SmmPerfCommData->LogEntryKey;\r
636 if (GaugeData == NULL || NumberOfEntries == 0 || LogEntryKey > mGaugeData->NumberOfEntries ||\r
579b5ef2 637 NumberOfEntries > mGaugeData->NumberOfEntries || LogEntryKey > (mGaugeData->NumberOfEntries - NumberOfEntries)) {\r
d042c6e8 638 Status = EFI_INVALID_PARAMETER;\r
639 break;\r
d042c6e8 640 }\r
f0da4d7d 641\r
d042c6e8 642 //\r
643 // Sanity check\r
644 //\r
579b5ef2
RN
645 DataSize = MultU64x32 (NumberOfEntries, sizeof(GAUGE_DATA_ENTRY));\r
646 if (!SmmIsBufferOutsideSmmValid ((UINTN) GaugeData, DataSize)) {\r
5e5bb2a9 647 DEBUG ((EFI_D_ERROR, "SmmPerformanceHandler: SMM Performance Data buffer in SMRAM or overflow!\n"));\r
d042c6e8 648 Status = EFI_ACCESS_DENIED;\r
ccd2f6b0 649 break;\r
d042c6e8 650 }\r
651\r
f0da4d7d
SZ
652 GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);\r
653\r
5e5bb2a9 654 for (Index = 0; Index < NumberOfEntries; Index++) {\r
579b5ef2 655 CopyMem (\r
5e5bb2a9 656 (UINT8 *) &GaugeData[Index],\r
f0da4d7d
SZ
657 (UINT8 *) &GaugeEntryExArray[LogEntryKey++],\r
658 sizeof (GAUGE_DATA_ENTRY)\r
659 );\r
660 }\r
661 Status = EFI_SUCCESS;\r
d042c6e8 662 break;\r
663\r
664 default:\r
d042c6e8 665 Status = EFI_UNSUPPORTED;\r
f0da4d7d 666 }\r
d042c6e8 667\r
ccd2f6b0 668\r
d042c6e8 669 SmmPerfCommData->ReturnStatus = Status;\r
ccd2f6b0 670 \r
d042c6e8 671 return EFI_SUCCESS;\r
672}\r
673\r
674/**\r
675 SmmBase2 protocol notify callback function, when SMST and SMM memory service get initialized \r
f0da4d7d 676 this function is callbacked to initialize the Smm Performance Lib \r
d042c6e8 677\r
678 @param Event The event of notify protocol.\r
679 @param Context Notify event context.\r
680\r
681**/\r
682VOID\r
683EFIAPI\r
684InitializeSmmCorePerformanceLib (\r
685 IN EFI_EVENT Event,\r
686 IN VOID *Context\r
687 )\r
688{\r
689 EFI_STATUS Status;\r
690 EFI_HANDLE Handle;\r
d042c6e8 691\r
692 //\r
693 // Initialize spin lock\r
694 //\r
695 InitializeSpinLock (&mSmmPerfLock);\r
696\r
f0da4d7d 697 mMaxGaugeRecords = INIT_SMM_GAUGE_DATA_ENTRIES;\r
d042c6e8 698\r
f0da4d7d 699 mGaugeData = AllocateZeroPool (sizeof (GAUGE_DATA_HEADER) + (sizeof (GAUGE_DATA_ENTRY_EX) * mMaxGaugeRecords));\r
d042c6e8 700 ASSERT (mGaugeData != NULL);\r
701 \r
d042c6e8 702 //\r
703 // Install the protocol interfaces.\r
704 //\r
705 Status = gSmst->SmmInstallProtocolInterface (\r
706 &mHandle,\r
707 &gSmmPerformanceProtocolGuid,\r
708 EFI_NATIVE_INTERFACE,\r
709 &mPerformanceInterface\r
710 );\r
711 ASSERT_EFI_ERROR (Status);\r
712\r
f0da4d7d
SZ
713 Status = gSmst->SmmInstallProtocolInterface (\r
714 &mHandle,\r
715 &gSmmPerformanceExProtocolGuid,\r
716 EFI_NATIVE_INTERFACE,\r
717 &mPerformanceExInterface\r
718 );\r
719 ASSERT_EFI_ERROR (Status);\r
720\r
d042c6e8 721 ///\r
722 /// Register SMM Performance SMI handler\r
723 ///\r
724 Handle = NULL;\r
725 Status = gSmst->SmiHandlerRegister (SmmPerformanceHandler, &gSmmPerformanceProtocolGuid, &Handle);\r
726 ASSERT_EFI_ERROR (Status);\r
f0da4d7d
SZ
727 Status = gSmst->SmiHandlerRegister (SmmPerformanceHandlerEx, &gSmmPerformanceExProtocolGuid, &Handle);\r
728 ASSERT_EFI_ERROR (Status);\r
d042c6e8 729}\r
730\r
731/**\r
f0da4d7d
SZ
732 The constructor function initializes the Performance Measurement Enable flag and \r
733 registers SmmBase2 protocol notify callback.\r
d042c6e8 734 It will ASSERT() if one of these operations fails and it will always return EFI_SUCCESS.\r
735\r
736 @param ImageHandle The firmware allocated handle for the EFI image.\r
737 @param SystemTable A pointer to the EFI System Table.\r
738\r
739 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.\r
740\r
741**/\r
742EFI_STATUS\r
743EFIAPI\r
744SmmCorePerformanceLibConstructor (\r
745 IN EFI_HANDLE ImageHandle,\r
746 IN EFI_SYSTEM_TABLE *SystemTable\r
747 )\r
748{\r
749 EFI_STATUS Status;\r
750 EFI_EVENT Event;\r
751 VOID *Registration;\r
752\r
753 mPerformanceMeasurementEnabled = (BOOLEAN) ((PcdGet8(PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0);\r
754 if (!mPerformanceMeasurementEnabled) {\r
755 //\r
756 // Do not initialize performance infrastructure if not required.\r
757 //\r
758 return EFI_SUCCESS;\r
759 }\r
760\r
761 //\r
762 // Create the events to do the library init.\r
763 //\r
764 Status = gBS->CreateEvent (\r
765 EVT_NOTIFY_SIGNAL,\r
766 TPL_CALLBACK,\r
767 InitializeSmmCorePerformanceLib,\r
768 NULL,\r
769 &Event\r
770 );\r
771 ASSERT_EFI_ERROR (Status);\r
772\r
773 //\r
774 // Register for protocol notifications on this event\r
775 //\r
776 Status = gBS->RegisterProtocolNotify (\r
777 &gEfiSmmBase2ProtocolGuid,\r
778 Event,\r
779 &Registration\r
780 );\r
781\r
782 ASSERT_EFI_ERROR (Status);\r
783\r
784 return EFI_SUCCESS;\r
785}\r
786\r
787/**\r
788 Adds a record at the end of the performance measurement log\r
789 that records the start time of a performance measurement.\r
790\r
791 Adds a record to the end of the performance measurement log\r
f0da4d7d 792 that contains the Handle, Token, Module and Identifier.\r
d042c6e8 793 The end time of the new record must be set to zero.\r
794 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.\r
795 If TimeStamp is zero, the start time in the record is filled in with the value\r
796 read from the current time stamp.\r
797\r
798 @param Handle Pointer to environment specific context used\r
799 to identify the component being measured.\r
800 @param Token Pointer to a Null-terminated ASCII string\r
801 that identifies the component being measured.\r
802 @param Module Pointer to a Null-terminated ASCII string\r
803 that identifies the module being measured.\r
804 @param TimeStamp 64-bit time stamp.\r
f0da4d7d
SZ
805 @param Identifier 32-bit identifier. If the value is 0, the created record\r
806 is same as the one created by StartPerformanceMeasurement.\r
d042c6e8 807\r
808 @retval RETURN_SUCCESS The start of the measurement was recorded.\r
809 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.\r
810\r
811**/\r
812RETURN_STATUS\r
813EFIAPI\r
f0da4d7d 814StartPerformanceMeasurementEx (\r
d042c6e8 815 IN CONST VOID *Handle, OPTIONAL\r
816 IN CONST CHAR8 *Token, OPTIONAL\r
817 IN CONST CHAR8 *Module, OPTIONAL\r
f0da4d7d
SZ
818 IN UINT64 TimeStamp,\r
819 IN UINT32 Identifier\r
d042c6e8 820 )\r
821{\r
f0da4d7d 822 return (RETURN_STATUS) StartGaugeEx (Handle, Token, Module, TimeStamp, Identifier);\r
d042c6e8 823}\r
824\r
825/**\r
826 Searches the performance measurement log from the beginning of the log\r
827 for the first matching record that contains a zero end time and fills in a valid end time.\r
828\r
829 Searches the performance measurement log from the beginning of the log\r
f0da4d7d 830 for the first record that matches Handle, Token, Module and Identifier and has an end time value of zero.\r
d042c6e8 831 If the record can not be found then return RETURN_NOT_FOUND.\r
832 If the record is found and TimeStamp is not zero,\r
833 then the end time in the record is filled in with the value specified by TimeStamp.\r
834 If the record is found and TimeStamp is zero, then the end time in the matching record\r
835 is filled in with the current time stamp value.\r
836\r
837 @param Handle Pointer to environment specific context used\r
838 to identify the component being measured.\r
839 @param Token Pointer to a Null-terminated ASCII string\r
840 that identifies the component being measured.\r
841 @param Module Pointer to a Null-terminated ASCII string\r
842 that identifies the module being measured.\r
843 @param TimeStamp 64-bit time stamp.\r
f0da4d7d
SZ
844 @param Identifier 32-bit identifier. If the value is 0, the found record\r
845 is same as the one found by EndPerformanceMeasurement.\r
d042c6e8 846\r
847 @retval RETURN_SUCCESS The end of the measurement was recorded.\r
848 @retval RETURN_NOT_FOUND The specified measurement record could not be found.\r
849\r
850**/\r
851RETURN_STATUS\r
852EFIAPI\r
f0da4d7d 853EndPerformanceMeasurementEx (\r
d042c6e8 854 IN CONST VOID *Handle, OPTIONAL\r
855 IN CONST CHAR8 *Token, OPTIONAL\r
856 IN CONST CHAR8 *Module, OPTIONAL\r
f0da4d7d
SZ
857 IN UINT64 TimeStamp,\r
858 IN UINT32 Identifier\r
d042c6e8 859 )\r
860{\r
f0da4d7d 861 return (RETURN_STATUS) EndGaugeEx (Handle, Token, Module, TimeStamp, Identifier);\r
d042c6e8 862}\r
863\r
864/**\r
865 Attempts to retrieve a performance measurement log entry from the performance measurement log.\r
f0da4d7d
SZ
866 It can also retrieve the log created by StartPerformanceMeasurement and EndPerformanceMeasurement,\r
867 and then assign the Identifier with 0.\r
d042c6e8 868\r
869 Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is\r
870 zero on entry, then an attempt is made to retrieve the first entry from the performance log,\r
871 and the key for the second entry in the log is returned. If the performance log is empty,\r
872 then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance\r
873 log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is\r
874 returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is\r
875 retrieved and an implementation specific non-zero key value that specifies the end of the performance\r
876 log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry\r
877 is retrieved and zero is returned. In the cases where a performance log entry can be returned,\r
f0da4d7d 878 the log entry is returned in Handle, Token, Module, StartTimeStamp, EndTimeStamp and Identifier.\r
d042c6e8 879 If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().\r
880 If Handle is NULL, then ASSERT().\r
881 If Token is NULL, then ASSERT().\r
882 If Module is NULL, then ASSERT().\r
883 If StartTimeStamp is NULL, then ASSERT().\r
884 If EndTimeStamp is NULL, then ASSERT().\r
f0da4d7d 885 If Identifier is NULL, then ASSERT().\r
d042c6e8 886\r
887 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.\r
888 0, then the first performance measurement log entry is retrieved.\r
889 On exit, the key of the next performance log entry.\r
890 @param Handle Pointer to environment specific context used to identify the component\r
891 being measured.\r
892 @param Token Pointer to a Null-terminated ASCII string that identifies the component\r
893 being measured.\r
894 @param Module Pointer to a Null-terminated ASCII string that identifies the module\r
895 being measured.\r
896 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement\r
897 was started.\r
898 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement\r
899 was ended.\r
f0da4d7d 900 @param Identifier Pointer to the 32-bit identifier that was recorded.\r
d042c6e8 901\r
902 @return The key for the next performance log entry (in general case).\r
903\r
904**/\r
905UINTN\r
906EFIAPI\r
f0da4d7d
SZ
907GetPerformanceMeasurementEx (\r
908 IN UINTN LogEntryKey, \r
d042c6e8 909 OUT CONST VOID **Handle,\r
910 OUT CONST CHAR8 **Token,\r
911 OUT CONST CHAR8 **Module,\r
912 OUT UINT64 *StartTimeStamp,\r
f0da4d7d
SZ
913 OUT UINT64 *EndTimeStamp,\r
914 OUT UINT32 *Identifier\r
d042c6e8 915 )\r
916{\r
f0da4d7d
SZ
917 EFI_STATUS Status;\r
918 GAUGE_DATA_ENTRY_EX *GaugeData;\r
d042c6e8 919\r
920 GaugeData = NULL;\r
921 \r
922 ASSERT (Handle != NULL);\r
923 ASSERT (Token != NULL);\r
924 ASSERT (Module != NULL);\r
925 ASSERT (StartTimeStamp != NULL);\r
926 ASSERT (EndTimeStamp != NULL);\r
f0da4d7d 927 ASSERT (Identifier != NULL);\r
d042c6e8 928\r
f0da4d7d 929 Status = GetGaugeEx (LogEntryKey++, &GaugeData);\r
d042c6e8 930\r
931 //\r
932 // Make sure that LogEntryKey is a valid log entry key,\r
933 //\r
934 ASSERT (Status != EFI_INVALID_PARAMETER);\r
935\r
936 if (EFI_ERROR (Status)) {\r
937 //\r
938 // The LogEntryKey is the last entry (equals to the total entry number).\r
939 //\r
940 return 0;\r
941 }\r
942\r
943 ASSERT (GaugeData != NULL);\r
944\r
945 *Handle = (VOID *) (UINTN) GaugeData->Handle;\r
946 *Token = GaugeData->Token;\r
947 *Module = GaugeData->Module;\r
948 *StartTimeStamp = GaugeData->StartTimeStamp;\r
949 *EndTimeStamp = GaugeData->EndTimeStamp;\r
f0da4d7d 950 *Identifier = GaugeData->Identifier;\r
d042c6e8 951\r
952 return LogEntryKey;\r
953}\r
954\r
f0da4d7d
SZ
955/**\r
956 Adds a record at the end of the performance measurement log\r
957 that records the start time of a performance measurement.\r
958\r
959 Adds a record to the end of the performance measurement log\r
960 that contains the Handle, Token, and Module.\r
961 The end time of the new record must be set to zero.\r
962 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.\r
963 If TimeStamp is zero, the start time in the record is filled in with the value\r
964 read from the current time stamp.\r
965\r
966 @param Handle Pointer to environment specific context used\r
967 to identify the component being measured.\r
968 @param Token Pointer to a Null-terminated ASCII string\r
969 that identifies the component being measured.\r
970 @param Module Pointer to a Null-terminated ASCII string\r
971 that identifies the module being measured.\r
972 @param TimeStamp 64-bit time stamp.\r
973\r
974 @retval RETURN_SUCCESS The start of the measurement was recorded.\r
975 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.\r
976\r
977**/\r
978RETURN_STATUS\r
979EFIAPI\r
980StartPerformanceMeasurement (\r
981 IN CONST VOID *Handle, OPTIONAL\r
982 IN CONST CHAR8 *Token, OPTIONAL\r
983 IN CONST CHAR8 *Module, OPTIONAL\r
984 IN UINT64 TimeStamp\r
985 )\r
986{\r
987 return StartPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);\r
988}\r
989\r
990/**\r
991 Searches the performance measurement log from the beginning of the log\r
992 for the first matching record that contains a zero end time and fills in a valid end time.\r
993\r
994 Searches the performance measurement log from the beginning of the log\r
995 for the first record that matches Handle, Token, and Module and has an end time value of zero.\r
996 If the record can not be found then return RETURN_NOT_FOUND.\r
997 If the record is found and TimeStamp is not zero,\r
998 then the end time in the record is filled in with the value specified by TimeStamp.\r
999 If the record is found and TimeStamp is zero, then the end time in the matching record\r
1000 is filled in with the current time stamp value.\r
1001\r
1002 @param Handle Pointer to environment specific context used\r
1003 to identify the component being measured.\r
1004 @param Token Pointer to a Null-terminated ASCII string\r
1005 that identifies the component being measured.\r
1006 @param Module Pointer to a Null-terminated ASCII string\r
1007 that identifies the module being measured.\r
1008 @param TimeStamp 64-bit time stamp.\r
1009\r
1010 @retval RETURN_SUCCESS The end of the measurement was recorded.\r
1011 @retval RETURN_NOT_FOUND The specified measurement record could not be found.\r
1012\r
1013**/\r
1014RETURN_STATUS\r
1015EFIAPI\r
1016EndPerformanceMeasurement (\r
1017 IN CONST VOID *Handle, OPTIONAL\r
1018 IN CONST CHAR8 *Token, OPTIONAL\r
1019 IN CONST CHAR8 *Module, OPTIONAL\r
1020 IN UINT64 TimeStamp\r
1021 )\r
1022{\r
1023 return EndPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);\r
1024}\r
1025\r
1026/**\r
1027 Attempts to retrieve a performance measurement log entry from the performance measurement log.\r
1028 It can also retrieve the log created by StartPerformanceMeasurementEx and EndPerformanceMeasurementEx,\r
1029 and then eliminate the Identifier.\r
1030\r
1031 Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is\r
1032 zero on entry, then an attempt is made to retrieve the first entry from the performance log,\r
1033 and the key for the second entry in the log is returned. If the performance log is empty,\r
1034 then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance\r
1035 log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is\r
1036 returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is\r
1037 retrieved and an implementation specific non-zero key value that specifies the end of the performance\r
1038 log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry\r
1039 is retrieved and zero is returned. In the cases where a performance log entry can be returned,\r
1040 the log entry is returned in Handle, Token, Module, StartTimeStamp, and EndTimeStamp.\r
1041 If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().\r
1042 If Handle is NULL, then ASSERT().\r
1043 If Token is NULL, then ASSERT().\r
1044 If Module is NULL, then ASSERT().\r
1045 If StartTimeStamp is NULL, then ASSERT().\r
1046 If EndTimeStamp is NULL, then ASSERT().\r
1047\r
1048 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.\r
1049 0, then the first performance measurement log entry is retrieved.\r
1050 On exit, the key of the next performance log entry.\r
1051 @param Handle Pointer to environment specific context used to identify the component\r
1052 being measured.\r
1053 @param Token Pointer to a Null-terminated ASCII string that identifies the component\r
1054 being measured.\r
1055 @param Module Pointer to a Null-terminated ASCII string that identifies the module\r
1056 being measured.\r
1057 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement\r
1058 was started.\r
1059 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement\r
1060 was ended.\r
1061\r
1062 @return The key for the next performance log entry (in general case).\r
1063\r
1064**/\r
1065UINTN\r
1066EFIAPI\r
1067GetPerformanceMeasurement (\r
1068 IN UINTN LogEntryKey,\r
1069 OUT CONST VOID **Handle,\r
1070 OUT CONST CHAR8 **Token,\r
1071 OUT CONST CHAR8 **Module,\r
1072 OUT UINT64 *StartTimeStamp,\r
1073 OUT UINT64 *EndTimeStamp\r
1074 )\r
1075{\r
1076 UINT32 Identifier;\r
1077 return GetPerformanceMeasurementEx (LogEntryKey, Handle, Token, Module, StartTimeStamp, EndTimeStamp, &Identifier);\r
1078}\r
1079\r
d042c6e8 1080/**\r
1081 Returns TRUE if the performance measurement macros are enabled.\r
1082\r
1083 This function returns TRUE if the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of\r
1084 PcdPerformanceLibraryPropertyMask is set. Otherwise FALSE is returned.\r
1085\r
1086 @retval TRUE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of\r
1087 PcdPerformanceLibraryPropertyMask is set.\r
1088 @retval FALSE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of\r
1089 PcdPerformanceLibraryPropertyMask is clear.\r
1090\r
1091**/\r
1092BOOLEAN\r
1093EFIAPI\r
1094PerformanceMeasurementEnabled (\r
1095 VOID\r
1096 )\r
1097{\r
1098 return mPerformanceMeasurementEnabled;\r
1099}\r