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