]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c
MdeModulePkg: Update PerformanceLib instances not to check Identifier.
[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
7a9395cd 19Copyright (c) 2011 - 2016, 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
7a9395cd 121 AsciiStrnCmp (GaugeEntryExArray[Index2].Module, Module, SMM_PERFORMANCE_STRING_LENGTH) == 0) {\r
b504f519 122 Index = Index2;\r
d042c6e8 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
f0da4d7d 135 that contains the Handle, Token, Module and Identifier.\r
d042c6e8 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
f0da4d7d
SZ
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
d042c6e8 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
f0da4d7d 157StartGaugeEx (\r
d042c6e8 158 IN CONST VOID *Handle, OPTIONAL\r
159 IN CONST CHAR8 *Token, OPTIONAL\r
160 IN CONST CHAR8 *Module, OPTIONAL\r
f0da4d7d
SZ
161 IN UINT64 TimeStamp,\r
162 IN UINT32 Identifier\r
d042c6e8 163 )\r
164{\r
f0da4d7d 165 GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;\r
d042c6e8 166 UINTN GaugeDataSize;\r
f0da4d7d 167 GAUGE_DATA_HEADER *NewGaugeData;\r
d042c6e8 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
f0da4d7d 180 OldGaugeDataSize = sizeof (GAUGE_DATA_HEADER) + sizeof (GAUGE_DATA_ENTRY_EX) * mMaxGaugeRecords;\r
d042c6e8 181\r
f0da4d7d 182 GaugeDataSize = sizeof (GAUGE_DATA_HEADER) + sizeof (GAUGE_DATA_ENTRY_EX) * mMaxGaugeRecords * 2;\r
d042c6e8 183\r
f0da4d7d
SZ
184 NewGaugeData = AllocateZeroPool (GaugeDataSize);\r
185 if (NewGaugeData == NULL) {\r
186 ReleaseSpinLock (&mSmmPerfLock);\r
d042c6e8 187 return EFI_OUT_OF_RESOURCES;\r
188 }\r
f0da4d7d
SZ
189\r
190 mGaugeData = NewGaugeData;\r
191 mMaxGaugeRecords *= 2;\r
192\r
d042c6e8 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
f0da4d7d
SZ
201 GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);\r
202 GaugeEntryExArray[Index].Handle = (EFI_PHYSICAL_ADDRESS) (UINTN) Handle;\r
d042c6e8 203\r
204 if (Token != NULL) {\r
8feb7452 205 AsciiStrnCpyS (GaugeEntryExArray[Index].Token, SMM_PERFORMANCE_STRING_SIZE, Token, SMM_PERFORMANCE_STRING_LENGTH);\r
d042c6e8 206 }\r
207 if (Module != NULL) {\r
8feb7452 208 AsciiStrnCpyS (GaugeEntryExArray[Index].Module, SMM_PERFORMANCE_STRING_SIZE, Module, SMM_PERFORMANCE_STRING_LENGTH);\r
d042c6e8 209 }\r
210\r
f0da4d7d
SZ
211 GaugeEntryExArray[Index].EndTimeStamp = 0;\r
212 GaugeEntryExArray[Index].Identifier = Identifier;\r
213\r
d042c6e8 214 if (TimeStamp == 0) {\r
215 TimeStamp = GetPerformanceCounter ();\r
216 }\r
f0da4d7d 217 GaugeEntryExArray[Index].StartTimeStamp = TimeStamp;\r
d042c6e8 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
7a9395cd 231 for the first record that matches Handle, Token and Module and has an end time value of zero.\r
d042c6e8 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
f0da4d7d
SZ
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
d042c6e8 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
f0da4d7d 254EndGaugeEx (\r
d042c6e8 255 IN CONST VOID *Handle, OPTIONAL\r
256 IN CONST CHAR8 *Token, OPTIONAL\r
257 IN CONST CHAR8 *Module, OPTIONAL\r
f0da4d7d
SZ
258 IN UINT64 TimeStamp,\r
259 IN UINT32 Identifier\r
d042c6e8 260 )\r
261{\r
f0da4d7d
SZ
262 GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;\r
263 UINT32 Index;\r
264\r
265 AcquireSpinLock (&mSmmPerfLock);\r
d042c6e8 266\r
267 if (TimeStamp == 0) {\r
268 TimeStamp = GetPerformanceCounter ();\r
269 }\r
270\r
f0da4d7d 271 Index = SmmSearchForGaugeEntry (Handle, Token, Module, Identifier);\r
d042c6e8 272 if (Index >= mGaugeData->NumberOfEntries) {\r
f0da4d7d 273 ReleaseSpinLock (&mSmmPerfLock);\r
d042c6e8 274 return EFI_NOT_FOUND;\r
275 }\r
f0da4d7d
SZ
276 GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);\r
277 GaugeEntryExArray[Index].EndTimeStamp = TimeStamp;\r
278\r
279 ReleaseSpinLock (&mSmmPerfLock);\r
d042c6e8 280\r
281 return EFI_SUCCESS;\r
282}\r
283\r
284/**\r
285 Retrieves a previously logged performance measurement.\r
f0da4d7d
SZ
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
d042c6e8 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
f0da4d7d 291 GaugeDataEntryEx stores the pointer to that entry.\r
d042c6e8 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
f0da4d7d 295 @param GaugeDataEntryEx The indirect pointer to the extended gauge data entry specified by LogEntryKey\r
d042c6e8 296 if the retrieval is successful.\r
297\r
f0da4d7d 298 @retval EFI_SUCCESS The GuageDataEntryEx is successfully found based on LogEntryKey.\r
d042c6e8 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
f0da4d7d 301 @retval EFI_INVALIDE_PARAMETER GaugeDataEntryEx is NULL.\r
d042c6e8 302\r
303**/\r
304EFI_STATUS\r
305EFIAPI\r
f0da4d7d
SZ
306GetGaugeEx (\r
307 IN UINTN LogEntryKey,\r
308 OUT GAUGE_DATA_ENTRY_EX **GaugeDataEntryEx\r
d042c6e8 309 )\r
310{\r
311 UINTN NumberOfEntries;\r
f0da4d7d 312 GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;\r
d042c6e8 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
f0da4d7d 322 GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);\r
d042c6e8 323\r
f0da4d7d 324 if (GaugeDataEntryEx == NULL) {\r
d042c6e8 325 return EFI_INVALID_PARAMETER;\r
326 }\r
f0da4d7d 327 *GaugeDataEntryEx = &GaugeEntryExArray[LogEntryKey];\r
d042c6e8 328\r
329 return EFI_SUCCESS;\r
330}\r
331\r
f0da4d7d
SZ
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
1658440e
SZ
433 GaugeEntryEx = NULL;\r
434\r
f0da4d7d
SZ
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
d042c6e8 448\r
d042c6e8 449/**\r
450 Communication service SMI Handler entry.\r
451\r
f0da4d7d 452 This SMI handler provides services for the performance wrapper driver.\r
ccd2f6b0 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
f0da4d7d
SZ
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
579b5ef2
RN
484 UINT64 DataSize;\r
485 UINTN Index;\r
5e5bb2a9
SZ
486 GAUGE_DATA_ENTRY_EX *GaugeDataEx;\r
487 UINTN NumberOfEntries;\r
488 UINTN LogEntryKey;\r
164a9b67 489 UINTN TempCommBufferSize;\r
f0da4d7d
SZ
490\r
491 GaugeEntryExArray = NULL;\r
492\r
ccd2f6b0 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
164a9b67
SZ
500 TempCommBufferSize = *CommBufferSize;\r
501\r
502 if(TempCommBufferSize < sizeof (SMM_PERF_COMMUNICATE_EX)) {\r
ccd2f6b0 503 return EFI_SUCCESS;\r
504 }\r
f0da4d7d 505\r
842b1242 506 if (!SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) {\r
5e5bb2a9 507 DEBUG ((EFI_D_ERROR, "SmmPerformanceHandlerEx: SMM communcation data buffer in SMRAM or overflow!\n"));\r
ccd2f6b0 508 return EFI_SUCCESS;\r
509 }\r
510 \r
f0da4d7d
SZ
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
5e5bb2a9
SZ
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
579b5ef2 524 NumberOfEntries > mGaugeData->NumberOfEntries || LogEntryKey > (mGaugeData->NumberOfEntries - NumberOfEntries)) {\r
f0da4d7d
SZ
525 Status = EFI_INVALID_PARAMETER;\r
526 break;\r
527 }\r
528\r
529 //\r
530 // Sanity check\r
531 //\r
579b5ef2
RN
532 DataSize = MultU64x32 (NumberOfEntries, sizeof(GAUGE_DATA_ENTRY_EX));\r
533 if (!SmmIsBufferOutsideSmmValid ((UINTN) GaugeDataEx, DataSize)) {\r
5e5bb2a9 534 DEBUG ((EFI_D_ERROR, "SmmPerformanceHandlerEx: SMM Performance Data buffer in SMRAM or overflow!\n"));\r
f0da4d7d 535 Status = EFI_ACCESS_DENIED;\r
ccd2f6b0 536 break;\r
f0da4d7d
SZ
537 }\r
538\r
539 GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);\r
579b5ef2
RN
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
f0da4d7d
SZ
548 Status = EFI_SUCCESS;\r
549 break;\r
550\r
551 default:\r
f0da4d7d
SZ
552 Status = EFI_UNSUPPORTED;\r
553 }\r
554\r
ccd2f6b0 555\r
f0da4d7d 556 SmmPerfCommData->ReturnStatus = Status;\r
ccd2f6b0 557 \r
f0da4d7d
SZ
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
d042c6e8 565\r
ccd2f6b0 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
d042c6e8 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
f0da4d7d
SZ
589 IN OUT VOID *CommBuffer,\r
590 IN OUT UINTN *CommBufferSize\r
d042c6e8 591 )\r
592{\r
593 EFI_STATUS Status;\r
594 SMM_PERF_COMMUNICATE *SmmPerfCommData;\r
f0da4d7d 595 GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;\r
579b5ef2 596 UINT64 DataSize;\r
f0da4d7d 597 UINTN Index;\r
5e5bb2a9
SZ
598 GAUGE_DATA_ENTRY *GaugeData;\r
599 UINTN NumberOfEntries;\r
f0da4d7d 600 UINTN LogEntryKey;\r
164a9b67
SZ
601 UINTN TempCommBufferSize;\r
602\r
f0da4d7d 603 GaugeEntryExArray = NULL;\r
d042c6e8 604\r
ccd2f6b0 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
164a9b67
SZ
612 TempCommBufferSize = *CommBufferSize;\r
613\r
614 if(TempCommBufferSize < sizeof (SMM_PERF_COMMUNICATE)) {\r
ccd2f6b0 615 return EFI_SUCCESS;\r
616 }\r
617\r
842b1242 618 if (!SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) {\r
5e5bb2a9 619 DEBUG ((EFI_D_ERROR, "SmmPerformanceHandler: SMM communcation data buffer in SMRAM or overflow!\n"));\r
ccd2f6b0 620 return EFI_SUCCESS;\r
621 }\r
d042c6e8 622\r
f0da4d7d 623 SmmPerfCommData = (SMM_PERF_COMMUNICATE *)CommBuffer;\r
d042c6e8 624\r
625 switch (SmmPerfCommData->Function) {\r
626 case SMM_PERF_FUNCTION_GET_GAUGE_ENTRY_NUMBER :\r
627 SmmPerfCommData->NumberOfEntries = mGaugeData->NumberOfEntries;\r
f0da4d7d 628 Status = EFI_SUCCESS;\r
d042c6e8 629 break;\r
630\r
631 case SMM_PERF_FUNCTION_GET_GAUGE_DATA :\r
5e5bb2a9
SZ
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
579b5ef2 636 NumberOfEntries > mGaugeData->NumberOfEntries || LogEntryKey > (mGaugeData->NumberOfEntries - NumberOfEntries)) {\r
d042c6e8 637 Status = EFI_INVALID_PARAMETER;\r
638 break;\r
d042c6e8 639 }\r
f0da4d7d 640\r
d042c6e8 641 //\r
642 // Sanity check\r
643 //\r
579b5ef2
RN
644 DataSize = MultU64x32 (NumberOfEntries, sizeof(GAUGE_DATA_ENTRY));\r
645 if (!SmmIsBufferOutsideSmmValid ((UINTN) GaugeData, DataSize)) {\r
5e5bb2a9 646 DEBUG ((EFI_D_ERROR, "SmmPerformanceHandler: SMM Performance Data buffer in SMRAM or overflow!\n"));\r
d042c6e8 647 Status = EFI_ACCESS_DENIED;\r
ccd2f6b0 648 break;\r
d042c6e8 649 }\r
650\r
f0da4d7d
SZ
651 GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);\r
652\r
5e5bb2a9 653 for (Index = 0; Index < NumberOfEntries; Index++) {\r
579b5ef2 654 CopyMem (\r
5e5bb2a9 655 (UINT8 *) &GaugeData[Index],\r
f0da4d7d
SZ
656 (UINT8 *) &GaugeEntryExArray[LogEntryKey++],\r
657 sizeof (GAUGE_DATA_ENTRY)\r
658 );\r
659 }\r
660 Status = EFI_SUCCESS;\r
d042c6e8 661 break;\r
662\r
663 default:\r
d042c6e8 664 Status = EFI_UNSUPPORTED;\r
f0da4d7d 665 }\r
d042c6e8 666\r
ccd2f6b0 667\r
d042c6e8 668 SmmPerfCommData->ReturnStatus = Status;\r
ccd2f6b0 669 \r
d042c6e8 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
f0da4d7d 675 this function is callbacked to initialize the Smm Performance Lib \r
d042c6e8 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
d042c6e8 690\r
691 //\r
692 // Initialize spin lock\r
693 //\r
694 InitializeSpinLock (&mSmmPerfLock);\r
695\r
f0da4d7d 696 mMaxGaugeRecords = INIT_SMM_GAUGE_DATA_ENTRIES;\r
d042c6e8 697\r
f0da4d7d 698 mGaugeData = AllocateZeroPool (sizeof (GAUGE_DATA_HEADER) + (sizeof (GAUGE_DATA_ENTRY_EX) * mMaxGaugeRecords));\r
d042c6e8 699 ASSERT (mGaugeData != NULL);\r
700 \r
d042c6e8 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
f0da4d7d
SZ
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
d042c6e8 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
f0da4d7d
SZ
726 Status = gSmst->SmiHandlerRegister (SmmPerformanceHandlerEx, &gSmmPerformanceExProtocolGuid, &Handle);\r
727 ASSERT_EFI_ERROR (Status);\r
d042c6e8 728}\r
729\r
730/**\r
f0da4d7d
SZ
731 The constructor function initializes the Performance Measurement Enable flag and \r
732 registers SmmBase2 protocol notify callback.\r
d042c6e8 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
f0da4d7d 791 that contains the Handle, Token, Module and Identifier.\r
d042c6e8 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
f0da4d7d
SZ
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
d042c6e8 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
f0da4d7d 813StartPerformanceMeasurementEx (\r
d042c6e8 814 IN CONST VOID *Handle, OPTIONAL\r
815 IN CONST CHAR8 *Token, OPTIONAL\r
816 IN CONST CHAR8 *Module, OPTIONAL\r
f0da4d7d
SZ
817 IN UINT64 TimeStamp,\r
818 IN UINT32 Identifier\r
d042c6e8 819 )\r
820{\r
f0da4d7d 821 return (RETURN_STATUS) StartGaugeEx (Handle, Token, Module, TimeStamp, Identifier);\r
d042c6e8 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
7a9395cd 829 for the first record that matches Handle, Token and Module and has an end time value of zero.\r
d042c6e8 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
f0da4d7d
SZ
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
d042c6e8 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
f0da4d7d 852EndPerformanceMeasurementEx (\r
d042c6e8 853 IN CONST VOID *Handle, OPTIONAL\r
854 IN CONST CHAR8 *Token, OPTIONAL\r
855 IN CONST CHAR8 *Module, OPTIONAL\r
f0da4d7d
SZ
856 IN UINT64 TimeStamp,\r
857 IN UINT32 Identifier\r
d042c6e8 858 )\r
859{\r
f0da4d7d 860 return (RETURN_STATUS) EndGaugeEx (Handle, Token, Module, TimeStamp, Identifier);\r
d042c6e8 861}\r
862\r
863/**\r
864 Attempts to retrieve a performance measurement log entry from the performance measurement log.\r
f0da4d7d
SZ
865 It can also retrieve the log created by StartPerformanceMeasurement and EndPerformanceMeasurement,\r
866 and then assign the Identifier with 0.\r
d042c6e8 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
f0da4d7d 877 the log entry is returned in Handle, Token, Module, StartTimeStamp, EndTimeStamp and Identifier.\r
d042c6e8 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
f0da4d7d 884 If Identifier is NULL, then ASSERT().\r
d042c6e8 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
f0da4d7d 899 @param Identifier Pointer to the 32-bit identifier that was recorded.\r
d042c6e8 900\r
901 @return The key for the next performance log entry (in general case).\r
902\r
903**/\r
904UINTN\r
905EFIAPI\r
f0da4d7d
SZ
906GetPerformanceMeasurementEx (\r
907 IN UINTN LogEntryKey, \r
d042c6e8 908 OUT CONST VOID **Handle,\r
909 OUT CONST CHAR8 **Token,\r
910 OUT CONST CHAR8 **Module,\r
911 OUT UINT64 *StartTimeStamp,\r
f0da4d7d
SZ
912 OUT UINT64 *EndTimeStamp,\r
913 OUT UINT32 *Identifier\r
d042c6e8 914 )\r
915{\r
f0da4d7d
SZ
916 EFI_STATUS Status;\r
917 GAUGE_DATA_ENTRY_EX *GaugeData;\r
d042c6e8 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
f0da4d7d 926 ASSERT (Identifier != NULL);\r
d042c6e8 927\r
f0da4d7d 928 Status = GetGaugeEx (LogEntryKey++, &GaugeData);\r
d042c6e8 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
f0da4d7d 949 *Identifier = GaugeData->Identifier;\r
d042c6e8 950\r
951 return LogEntryKey;\r
952}\r
953\r
f0da4d7d
SZ
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
d042c6e8 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