]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c
Add performance library instances for SMM performance measurement.
[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
6 It initializes SMM phase performance logging by publishing the Performance Protocol,\r
7 which is consumed by SmmPerformanceLib to logging performance data in SMM phase.\r
8\r
9 This library is mainly used by SMM Core to start performance logging to ensure that\r
10 SMM Performance Protocol is installed at the very beginning of SMM phase.\r
11\r
12Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>\r
13This program and the accompanying materials\r
14are licensed and made available under the terms and conditions of the BSD License\r
15which accompanies this distribution. The full text of the license may be found at\r
16http://opensource.org/licenses/bsd-license.php\r
17\r
18THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
19WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
20\r
21**/\r
22\r
23\r
24#include "SmmCorePerformanceLibInternal.h"\r
25\r
26//\r
27// The data structure to hold global performance data.\r
28//\r
29GAUGE_DATA_HEADER *mGaugeData;\r
30\r
31//\r
32// The current maximum number of logging entries. If current number of \r
33// entries exceeds this value, it will re-allocate a larger array and\r
34// migration the old data to the larger array.\r
35//\r
36UINT32 mMaxGaugeRecords;\r
37\r
38//\r
39// The handle to install Performance Protocol instance.\r
40//\r
41EFI_HANDLE mHandle = NULL;\r
42\r
43BOOLEAN mPerformanceMeasurementEnabled;\r
44\r
45SPIN_LOCK mSmmPerfLock;\r
46\r
47EFI_SMRAM_DESCRIPTOR *mSmramRanges;\r
48UINTN mSmramRangeCount;\r
49\r
50//\r
51// Interfaces for performance protocol.\r
52//\r
53PERFORMANCE_PROTOCOL mPerformanceInterface = {\r
54 StartGauge,\r
55 EndGauge,\r
56 GetGauge\r
57};\r
58\r
59/**\r
60 Searches in the gauge array with keyword Handle, Token and Module.\r
61\r
62 This internal function searches for the gauge entry in the gauge array.\r
63 If there is an entry that exactly matches the given key word triple\r
64 and its end time stamp is zero, then the index of that gauge entry is returned;\r
65 otherwise, the the number of gauge entries in the array is returned.\r
66\r
67 @param Handle Pointer to environment specific context used\r
68 to identify the component being measured.\r
69 @param Token Pointer to a Null-terminated ASCII string\r
70 that identifies the component being measured.\r
71 @param Module Pointer to a Null-terminated ASCII string\r
72 that identifies the module being measured.\r
73\r
74 @retval The index of gauge entry in the array.\r
75\r
76**/\r
77UINT32\r
78SmmSearchForGaugeEntry (\r
79 IN CONST VOID *Handle, OPTIONAL\r
80 IN CONST CHAR8 *Token, OPTIONAL\r
81 IN CONST CHAR8 *Module OPTIONAL\r
82 )\r
83{\r
84 UINT32 Index;\r
85 UINT32 NumberOfEntries;\r
86 GAUGE_DATA_ENTRY *GaugeEntryArray;\r
87\r
88 if (Token == NULL) {\r
89 Token = "";\r
90 }\r
91 if (Module == NULL) {\r
92 Module = "";\r
93 }\r
94\r
95 NumberOfEntries = mGaugeData->NumberOfEntries;\r
96 GaugeEntryArray = (GAUGE_DATA_ENTRY *) (mGaugeData + 1);\r
97\r
98 for (Index = 0; Index < NumberOfEntries; Index++) {\r
99 if ((GaugeEntryArray[Index].Handle == (EFI_PHYSICAL_ADDRESS) (UINTN) Handle) &&\r
100 AsciiStrnCmp (GaugeEntryArray[Index].Token, Token, SMM_PERFORMANCE_STRING_LENGTH) == 0 &&\r
101 AsciiStrnCmp (GaugeEntryArray[Index].Module, Module, SMM_PERFORMANCE_STRING_LENGTH) == 0 &&\r
102 GaugeEntryArray[Index].EndTimeStamp == 0) {\r
103 break;\r
104 }\r
105 }\r
106\r
107 return Index;\r
108}\r
109\r
110/**\r
111 Adds a record at the end of the performance measurement log\r
112 that records the start time of a performance measurement.\r
113\r
114 Adds a record to the end of the performance measurement log\r
115 that contains the Handle, Token, and Module.\r
116 The end time of the new record must be set to zero.\r
117 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.\r
118 If TimeStamp is zero, the start time in the record is filled in with the value\r
119 read from the current time stamp.\r
120\r
121 @param Handle Pointer to environment specific context used\r
122 to identify the component being measured.\r
123 @param Token Pointer to a Null-terminated ASCII string\r
124 that identifies the component being measured.\r
125 @param Module Pointer to a Null-terminated ASCII string\r
126 that identifies the module being measured.\r
127 @param TimeStamp 64-bit time stamp.\r
128\r
129 @retval EFI_SUCCESS The data was read correctly from the device.\r
130 @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement.\r
131\r
132**/\r
133EFI_STATUS\r
134EFIAPI\r
135StartGauge (\r
136 IN CONST VOID *Handle, OPTIONAL\r
137 IN CONST CHAR8 *Token, OPTIONAL\r
138 IN CONST CHAR8 *Module, OPTIONAL\r
139 IN UINT64 TimeStamp\r
140 )\r
141{\r
142 GAUGE_DATA_ENTRY *GaugeEntryArray;\r
143 UINTN GaugeDataSize;\r
144 UINTN OldGaugeDataSize;\r
145 GAUGE_DATA_HEADER *OldGaugeData;\r
146 UINT32 Index;\r
147\r
148 AcquireSpinLock (&mSmmPerfLock);\r
149\r
150 Index = mGaugeData->NumberOfEntries;\r
151 if (Index >= mMaxGaugeRecords) {\r
152 //\r
153 // Try to enlarge the scale of gauge array.\r
154 //\r
155 OldGaugeData = mGaugeData;\r
156 OldGaugeDataSize = sizeof (GAUGE_DATA_HEADER) + sizeof (GAUGE_DATA_ENTRY) * mMaxGaugeRecords;\r
157\r
158 mMaxGaugeRecords *= 2;\r
159 GaugeDataSize = sizeof (GAUGE_DATA_HEADER) + sizeof (GAUGE_DATA_ENTRY) * mMaxGaugeRecords;\r
160\r
161 mGaugeData = AllocateZeroPool (GaugeDataSize);\r
162 if (mGaugeData == NULL) {\r
163 return EFI_OUT_OF_RESOURCES;\r
164 }\r
165 //\r
166 // Initialize new data array and migrate old data one.\r
167 //\r
168 mGaugeData = CopyMem (mGaugeData, OldGaugeData, OldGaugeDataSize);\r
169\r
170 FreePool (OldGaugeData);\r
171 }\r
172\r
173 GaugeEntryArray = (GAUGE_DATA_ENTRY *) (mGaugeData + 1);\r
174 GaugeEntryArray[Index].Handle = (EFI_PHYSICAL_ADDRESS) (UINTN) Handle;\r
175\r
176 if (Token != NULL) {\r
177 AsciiStrnCpy (GaugeEntryArray[Index].Token, Token, SMM_PERFORMANCE_STRING_LENGTH);\r
178 }\r
179 if (Module != NULL) {\r
180 AsciiStrnCpy (GaugeEntryArray[Index].Module, Module, SMM_PERFORMANCE_STRING_LENGTH);\r
181 }\r
182\r
183 if (TimeStamp == 0) {\r
184 TimeStamp = GetPerformanceCounter ();\r
185 }\r
186 GaugeEntryArray[Index].StartTimeStamp = TimeStamp;\r
187\r
188 mGaugeData->NumberOfEntries++;\r
189\r
190 ReleaseSpinLock (&mSmmPerfLock);\r
191\r
192 return EFI_SUCCESS;\r
193}\r
194\r
195/**\r
196 Searches the performance measurement log from the beginning of the log\r
197 for the first matching record that contains a zero end time and fills in a valid end time.\r
198\r
199 Searches the performance measurement log from the beginning of the log\r
200 for the first record that matches Handle, Token, and Module and has an end time value of zero.\r
201 If the record can not be found then return EFI_NOT_FOUND.\r
202 If the record is found and TimeStamp is not zero,\r
203 then the end time in the record is filled in with the value specified by TimeStamp.\r
204 If the record is found and TimeStamp is zero, then the end time in the matching record\r
205 is filled in with the current time stamp value.\r
206\r
207 @param Handle Pointer to environment specific context used\r
208 to identify the component being measured.\r
209 @param Token Pointer to a Null-terminated ASCII string\r
210 that identifies the component being measured.\r
211 @param Module Pointer to a Null-terminated ASCII string\r
212 that identifies the module being measured.\r
213 @param TimeStamp 64-bit time stamp.\r
214\r
215 @retval EFI_SUCCESS The end of the measurement was recorded.\r
216 @retval EFI_NOT_FOUND The specified measurement record could not be found.\r
217\r
218**/\r
219EFI_STATUS\r
220EFIAPI\r
221EndGauge (\r
222 IN CONST VOID *Handle, OPTIONAL\r
223 IN CONST CHAR8 *Token, OPTIONAL\r
224 IN CONST CHAR8 *Module, OPTIONAL\r
225 IN UINT64 TimeStamp\r
226 )\r
227{\r
228 GAUGE_DATA_ENTRY *GaugeEntryArray;\r
229 UINT32 Index;\r
230\r
231 if (TimeStamp == 0) {\r
232 TimeStamp = GetPerformanceCounter ();\r
233 }\r
234\r
235 Index = SmmSearchForGaugeEntry (Handle, Token, Module);\r
236 if (Index >= mGaugeData->NumberOfEntries) {\r
237 return EFI_NOT_FOUND;\r
238 }\r
239 GaugeEntryArray = (GAUGE_DATA_ENTRY *) (mGaugeData + 1);\r
240 GaugeEntryArray[Index].EndTimeStamp = TimeStamp;\r
241\r
242 return EFI_SUCCESS;\r
243}\r
244\r
245/**\r
246 Retrieves a previously logged performance measurement.\r
247\r
248 Retrieves the performance log entry from the performance log specified by LogEntryKey.\r
249 If it stands for a valid entry, then EFI_SUCCESS is returned and\r
250 GaugeDataEntry stores the pointer to that entry.\r
251\r
252 @param LogEntryKey The key for the previous performance measurement log entry.\r
253 If 0, then the first performance measurement log entry is retrieved.\r
254 @param GaugeDataEntry The indirect pointer to the gauge data entry specified by LogEntryKey\r
255 if the retrieval is successful.\r
256\r
257 @retval EFI_SUCCESS The GuageDataEntry is successfully found based on LogEntryKey.\r
258 @retval EFI_NOT_FOUND The LogEntryKey is the last entry (equals to the total entry number).\r
259 @retval EFI_INVALIDE_PARAMETER The LogEntryKey is not a valid entry (greater than the total entry number).\r
260 @retval EFI_INVALIDE_PARAMETER GaugeDataEntry is NULL.\r
261\r
262**/\r
263EFI_STATUS\r
264EFIAPI\r
265GetGauge (\r
266 IN UINTN LogEntryKey,\r
267 OUT GAUGE_DATA_ENTRY **GaugeDataEntry\r
268 )\r
269{\r
270 UINTN NumberOfEntries;\r
271 GAUGE_DATA_ENTRY *LogEntryArray;\r
272\r
273 NumberOfEntries = (UINTN) (mGaugeData->NumberOfEntries);\r
274 if (LogEntryKey > NumberOfEntries) {\r
275 return EFI_INVALID_PARAMETER;\r
276 }\r
277 if (LogEntryKey == NumberOfEntries) {\r
278 return EFI_NOT_FOUND;\r
279 }\r
280\r
281 LogEntryArray = (GAUGE_DATA_ENTRY *) (mGaugeData + 1);\r
282\r
283 if (GaugeDataEntry == NULL) {\r
284 return EFI_INVALID_PARAMETER;\r
285 }\r
286 *GaugeDataEntry = &LogEntryArray[LogEntryKey];\r
287\r
288 return EFI_SUCCESS;\r
289}\r
290\r
291\r
292/**\r
293 This function check if the address is in SMRAM.\r
294\r
295 @param Buffer the buffer address to be checked.\r
296 @param Length the buffer length to be checked.\r
297\r
298 @retval TRUE this address is in SMRAM.\r
299 @retval FALSE this address is NOT in SMRAM.\r
300**/\r
301BOOLEAN\r
302IsAddressInSmram (\r
303 IN EFI_PHYSICAL_ADDRESS Buffer,\r
304 IN UINT64 Length\r
305 )\r
306{\r
307 UINTN Index;\r
308\r
309 for (Index = 0; Index < mSmramRangeCount; Index ++) {\r
310 if (((Buffer >= mSmramRanges[Index].CpuStart) && (Buffer < mSmramRanges[Index].CpuStart + mSmramRanges[Index].PhysicalSize)) ||\r
311 ((mSmramRanges[Index].CpuStart >= Buffer) && (mSmramRanges[Index].CpuStart < Buffer + Length))) {\r
312 return TRUE;\r
313 }\r
314 }\r
315\r
316 return FALSE;\r
317}\r
318\r
319/**\r
320 Communication service SMI Handler entry.\r
321\r
322 This SMI handler provides services for the variable wrapper driver.\r
323\r
324 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
325 @param[in] RegisterContext Points to an optional handler context which was specified when the\r
326 handler was registered.\r
327 @param[in, out] CommBuffer A pointer to a collection of data in memory that will\r
328 be conveyed from a non-SMM environment into an SMM environment.\r
329 @param[in, out] CommBufferSize The size of the CommBuffer.\r
330\r
331 @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers \r
332 should still be called.\r
333 @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should \r
334 still be called.\r
335 @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still \r
336 be called.\r
337 @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.\r
338**/\r
339EFI_STATUS\r
340EFIAPI\r
341SmmPerformanceHandler (\r
342 IN EFI_HANDLE DispatchHandle,\r
343 IN CONST VOID *RegisterContext,\r
344 IN OUT VOID *CommBuffer,\r
345 IN OUT UINTN *CommBufferSize\r
346 )\r
347{\r
348 EFI_STATUS Status;\r
349 SMM_PERF_COMMUNICATE *SmmPerfCommData;\r
350 GAUGE_DATA_ENTRY *GaugeData; \r
351 UINTN DataSize;\r
352\r
353 GaugeData = NULL;\r
354 \r
355 ASSERT (CommBuffer != NULL);\r
356\r
357 SmmPerfCommData = (SMM_PERF_COMMUNICATE*)CommBuffer;\r
358\r
359 switch (SmmPerfCommData->Function) {\r
360 case SMM_PERF_FUNCTION_GET_GAUGE_ENTRY_NUMBER :\r
361 SmmPerfCommData->NumberOfEntries = mGaugeData->NumberOfEntries;\r
362 return Status = EFI_SUCCESS;\r
363 break;\r
364\r
365 case SMM_PERF_FUNCTION_GET_GAUGE_DATA :\r
366 if ( SmmPerfCommData->GaugeData == NULL || SmmPerfCommData->NumberOfEntries <= 0 ||\r
367 (SmmPerfCommData->LogEntryKey + SmmPerfCommData->NumberOfEntries) > mGaugeData->NumberOfEntries) {\r
368 Status = EFI_INVALID_PARAMETER;\r
369 break;\r
370 } \r
371\r
372 Status = GetGauge(SmmPerfCommData->LogEntryKey, &GaugeData);\r
373 if (EFI_ERROR(Status)) {\r
374 break;\r
375 }\r
376 \r
377 //\r
378 // Sanity check\r
379 //\r
380 DataSize = SmmPerfCommData->NumberOfEntries * sizeof(GAUGE_DATA_ENTRY);\r
381 if (IsAddressInSmram ((EFI_PHYSICAL_ADDRESS)(UINTN)SmmPerfCommData->GaugeData, DataSize)) {\r
382 DEBUG ((EFI_D_ERROR, "Smm Performance Data buffer is in SMRAM!\n"));\r
383 Status = EFI_ACCESS_DENIED;\r
384 break ;\r
385 }\r
386\r
387 CopyMem(\r
388 (UINT8*)SmmPerfCommData->GaugeData, \r
389 (UINT8*)GaugeData, \r
390 DataSize\r
391 );\r
392 break;\r
393\r
394 default:\r
395 ASSERT (FALSE);\r
396 Status = EFI_UNSUPPORTED;\r
397 } \r
398\r
399 SmmPerfCommData->ReturnStatus = Status;\r
400 return EFI_SUCCESS;\r
401}\r
402\r
403/**\r
404 SmmBase2 protocol notify callback function, when SMST and SMM memory service get initialized \r
405 this function is callbacked to to initialize the Smm Performance Lib \r
406\r
407 @param Event The event of notify protocol.\r
408 @param Context Notify event context.\r
409\r
410**/\r
411VOID\r
412EFIAPI\r
413InitializeSmmCorePerformanceLib (\r
414 IN EFI_EVENT Event,\r
415 IN VOID *Context\r
416 )\r
417{\r
418 EFI_STATUS Status;\r
419 EFI_HANDLE Handle;\r
420 EFI_SMM_ACCESS2_PROTOCOL *SmmAccess;\r
421 UINTN Size;\r
422\r
423\r
424 //\r
425 // Initialize spin lock\r
426 //\r
427 InitializeSpinLock (&mSmmPerfLock);\r
428\r
429 mMaxGaugeRecords = INIT_SMM_GAUGE_DATA_ENTRIES + PcdGet8 (PcdMaxPeiPerformanceLogEntries);\r
430\r
431 mGaugeData = AllocateZeroPool (sizeof (GAUGE_DATA_HEADER) + (sizeof (GAUGE_DATA_ENTRY) * mMaxGaugeRecords));\r
432 ASSERT (mGaugeData != NULL);\r
433 \r
434 //\r
435 // Get SMRAM information\r
436 //\r
437 Status = gBS->LocateProtocol (&gEfiSmmAccess2ProtocolGuid, NULL, (VOID **)&SmmAccess);\r
438 ASSERT_EFI_ERROR (Status);\r
439\r
440 Size = 0;\r
441 Status = SmmAccess->GetCapabilities (SmmAccess, &Size, NULL);\r
442 ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
443\r
444 Status = gSmst->SmmAllocatePool (\r
445 EfiRuntimeServicesData,\r
446 Size,\r
447 (VOID **)&mSmramRanges\r
448 );\r
449 ASSERT_EFI_ERROR (Status);\r
450\r
451 Status = SmmAccess->GetCapabilities (SmmAccess, &Size, mSmramRanges);\r
452 ASSERT_EFI_ERROR (Status);\r
453\r
454 mSmramRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR);\r
455\r
456 //\r
457 // Install the protocol interfaces.\r
458 //\r
459 Status = gSmst->SmmInstallProtocolInterface (\r
460 &mHandle,\r
461 &gSmmPerformanceProtocolGuid,\r
462 EFI_NATIVE_INTERFACE,\r
463 &mPerformanceInterface\r
464 );\r
465 ASSERT_EFI_ERROR (Status);\r
466\r
467 ///\r
468 /// Register SMM Performance SMI handler\r
469 ///\r
470 Handle = NULL;\r
471 Status = gSmst->SmiHandlerRegister (SmmPerformanceHandler, &gSmmPerformanceProtocolGuid, &Handle);\r
472 ASSERT_EFI_ERROR (Status);\r
473}\r
474\r
475/**\r
476 The constructor function initializes Performance infrastructure for DXE phase.\r
477\r
478 The constructor function publishes Performance protocol, allocates memory to log DXE performance\r
479 and merges PEI performance data to DXE performance log.\r
480 It will ASSERT() if one of these operations fails and it will always return EFI_SUCCESS.\r
481\r
482 @param ImageHandle The firmware allocated handle for the EFI image.\r
483 @param SystemTable A pointer to the EFI System Table.\r
484\r
485 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.\r
486\r
487**/\r
488EFI_STATUS\r
489EFIAPI\r
490SmmCorePerformanceLibConstructor (\r
491 IN EFI_HANDLE ImageHandle,\r
492 IN EFI_SYSTEM_TABLE *SystemTable\r
493 )\r
494{\r
495 EFI_STATUS Status;\r
496 EFI_EVENT Event;\r
497 VOID *Registration;\r
498\r
499 mPerformanceMeasurementEnabled = (BOOLEAN) ((PcdGet8(PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0);\r
500 if (!mPerformanceMeasurementEnabled) {\r
501 //\r
502 // Do not initialize performance infrastructure if not required.\r
503 //\r
504 return EFI_SUCCESS;\r
505 }\r
506\r
507 //\r
508 // Create the events to do the library init.\r
509 //\r
510 Status = gBS->CreateEvent (\r
511 EVT_NOTIFY_SIGNAL,\r
512 TPL_CALLBACK,\r
513 InitializeSmmCorePerformanceLib,\r
514 NULL,\r
515 &Event\r
516 );\r
517 ASSERT_EFI_ERROR (Status);\r
518\r
519 //\r
520 // Register for protocol notifications on this event\r
521 //\r
522 Status = gBS->RegisterProtocolNotify (\r
523 &gEfiSmmBase2ProtocolGuid,\r
524 Event,\r
525 &Registration\r
526 );\r
527\r
528 ASSERT_EFI_ERROR (Status);\r
529\r
530 return EFI_SUCCESS;\r
531}\r
532\r
533/**\r
534 Adds a record at the end of the performance measurement log\r
535 that records the start time of a performance measurement.\r
536\r
537 Adds a record to the end of the performance measurement log\r
538 that contains the Handle, Token, and Module.\r
539 The end time of the new record must be set to zero.\r
540 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.\r
541 If TimeStamp is zero, the start time in the record is filled in with the value\r
542 read from the current time stamp.\r
543\r
544 @param Handle Pointer to environment specific context used\r
545 to identify the component being measured.\r
546 @param Token Pointer to a Null-terminated ASCII string\r
547 that identifies the component being measured.\r
548 @param Module Pointer to a Null-terminated ASCII string\r
549 that identifies the module being measured.\r
550 @param TimeStamp 64-bit time stamp.\r
551\r
552 @retval RETURN_SUCCESS The start of the measurement was recorded.\r
553 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.\r
554\r
555**/\r
556RETURN_STATUS\r
557EFIAPI\r
558StartPerformanceMeasurement (\r
559 IN CONST VOID *Handle, OPTIONAL\r
560 IN CONST CHAR8 *Token, OPTIONAL\r
561 IN CONST CHAR8 *Module, OPTIONAL\r
562 IN UINT64 TimeStamp\r
563 )\r
564{\r
565 EFI_STATUS Status;\r
566\r
567 Status = StartGauge (Handle, Token, Module, TimeStamp);\r
568 return (RETURN_STATUS) Status;\r
569}\r
570\r
571/**\r
572 Searches the performance measurement log from the beginning of the log\r
573 for the first matching record that contains a zero end time and fills in a valid end time.\r
574\r
575 Searches the performance measurement log from the beginning of the log\r
576 for the first record that matches Handle, Token, and Module and has an end time value of zero.\r
577 If the record can not be found then return RETURN_NOT_FOUND.\r
578 If the record is found and TimeStamp is not zero,\r
579 then the end time in the record is filled in with the value specified by TimeStamp.\r
580 If the record is found and TimeStamp is zero, then the end time in the matching record\r
581 is filled in with the current time stamp value.\r
582\r
583 @param Handle Pointer to environment specific context used\r
584 to identify the component being measured.\r
585 @param Token Pointer to a Null-terminated ASCII string\r
586 that identifies the component being measured.\r
587 @param Module Pointer to a Null-terminated ASCII string\r
588 that identifies the module being measured.\r
589 @param TimeStamp 64-bit time stamp.\r
590\r
591 @retval RETURN_SUCCESS The end of the measurement was recorded.\r
592 @retval RETURN_NOT_FOUND The specified measurement record could not be found.\r
593\r
594**/\r
595RETURN_STATUS\r
596EFIAPI\r
597EndPerformanceMeasurement (\r
598 IN CONST VOID *Handle, OPTIONAL\r
599 IN CONST CHAR8 *Token, OPTIONAL\r
600 IN CONST CHAR8 *Module, OPTIONAL\r
601 IN UINT64 TimeStamp\r
602 )\r
603{\r
604 EFI_STATUS Status;\r
605\r
606 Status = EndGauge (Handle, Token, Module, TimeStamp);\r
607 return (RETURN_STATUS) Status;\r
608}\r
609\r
610/**\r
611 Attempts to retrieve a performance measurement log entry from the performance measurement log.\r
612\r
613 Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is\r
614 zero on entry, then an attempt is made to retrieve the first entry from the performance log,\r
615 and the key for the second entry in the log is returned. If the performance log is empty,\r
616 then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance\r
617 log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is\r
618 returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is\r
619 retrieved and an implementation specific non-zero key value that specifies the end of the performance\r
620 log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry\r
621 is retrieved and zero is returned. In the cases where a performance log entry can be returned,\r
622 the log entry is returned in Handle, Token, Module, StartTimeStamp, and EndTimeStamp.\r
623 If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().\r
624 If Handle is NULL, then ASSERT().\r
625 If Token is NULL, then ASSERT().\r
626 If Module is NULL, then ASSERT().\r
627 If StartTimeStamp is NULL, then ASSERT().\r
628 If EndTimeStamp is NULL, then ASSERT().\r
629\r
630 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.\r
631 0, then the first performance measurement log entry is retrieved.\r
632 On exit, the key of the next performance log entry.\r
633 @param Handle Pointer to environment specific context used to identify the component\r
634 being measured.\r
635 @param Token Pointer to a Null-terminated ASCII string that identifies the component\r
636 being measured.\r
637 @param Module Pointer to a Null-terminated ASCII string that identifies the module\r
638 being measured.\r
639 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement\r
640 was started.\r
641 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement\r
642 was ended.\r
643\r
644 @return The key for the next performance log entry (in general case).\r
645\r
646**/\r
647UINTN\r
648EFIAPI\r
649GetPerformanceMeasurement (\r
650 IN UINTN LogEntryKey,\r
651 OUT CONST VOID **Handle,\r
652 OUT CONST CHAR8 **Token,\r
653 OUT CONST CHAR8 **Module,\r
654 OUT UINT64 *StartTimeStamp,\r
655 OUT UINT64 *EndTimeStamp\r
656 )\r
657{\r
658 EFI_STATUS Status;\r
659 GAUGE_DATA_ENTRY *GaugeData;\r
660\r
661 GaugeData = NULL;\r
662 \r
663 ASSERT (Handle != NULL);\r
664 ASSERT (Token != NULL);\r
665 ASSERT (Module != NULL);\r
666 ASSERT (StartTimeStamp != NULL);\r
667 ASSERT (EndTimeStamp != NULL);\r
668\r
669 Status = GetGauge (LogEntryKey++, &GaugeData);\r
670\r
671 //\r
672 // Make sure that LogEntryKey is a valid log entry key,\r
673 //\r
674 ASSERT (Status != EFI_INVALID_PARAMETER);\r
675\r
676 if (EFI_ERROR (Status)) {\r
677 //\r
678 // The LogEntryKey is the last entry (equals to the total entry number).\r
679 //\r
680 return 0;\r
681 }\r
682\r
683 ASSERT (GaugeData != NULL);\r
684\r
685 *Handle = (VOID *) (UINTN) GaugeData->Handle;\r
686 *Token = GaugeData->Token;\r
687 *Module = GaugeData->Module;\r
688 *StartTimeStamp = GaugeData->StartTimeStamp;\r
689 *EndTimeStamp = GaugeData->EndTimeStamp;\r
690\r
691 return LogEntryKey;\r
692}\r
693\r
694/**\r
695 Returns TRUE if the performance measurement macros are enabled.\r
696\r
697 This function returns TRUE if the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of\r
698 PcdPerformanceLibraryPropertyMask is set. Otherwise FALSE is returned.\r
699\r
700 @retval TRUE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of\r
701 PcdPerformanceLibraryPropertyMask is set.\r
702 @retval FALSE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of\r
703 PcdPerformanceLibraryPropertyMask is clear.\r
704\r
705**/\r
706BOOLEAN\r
707EFIAPI\r
708PerformanceMeasurementEnabled (\r
709 VOID\r
710 )\r
711{\r
712 return mPerformanceMeasurementEnabled;\r
713}\r
714\r
715\r