]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c
MdeModulePkg: Increase the maximum number of PEI performance log entries
[mirror_edk2.git] / MdeModulePkg / Library / DxeCorePerformanceLib / DxeCorePerformanceLib.c
CommitLineData
8dbae30d 1/** @file\r
857dfc45 2 Performance library instance mainly used by DxeCore.\r
3\r
4 This library provides the performance measurement interfaces and initializes performance\r
5 logging for DXE phase. It first initializes its private global data structure for\r
6 performance logging and saves the performance GUIDed HOB passed from PEI phase. \r
f0da4d7d
SZ
7 It initializes DXE phase performance logging by publishing the Performance and PerformanceEx Protocol,\r
8 which are consumed by DxePerformanceLib to logging performance data in DXE phase.\r
857dfc45 9\r
10 This library is mainly used by DxeCore to start performance logging to ensure that\r
11 Performance Protocol is installed at the very beginning of DXE phase.\r
a0afd019 12\r
96f983fa 13Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>\r
7c50b343 14(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
cd5ebaa0 15This program and the accompanying materials\r
a0afd019 16are licensed and made available under the terms and conditions of the BSD License\r
17which accompanies this distribution. The full text of the license may be found at\r
18http://opensource.org/licenses/bsd-license.php\r
19\r
20THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
21WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
22\r
8dbae30d 23**/\r
a0afd019 24\r
ed7748fe 25\r
aa79b0b3 26#include "DxeCorePerformanceLibInternal.h"\r
ed7748fe 27\r
a0afd019 28\r
29//\r
857dfc45 30// The data structure to hold global performance data.\r
a0afd019 31//\r
fe1e36e5 32GAUGE_DATA_HEADER *mGaugeData;\r
857dfc45 33\r
34//\r
35// The current maximum number of logging entries. If current number of \r
36// entries exceeds this value, it will re-allocate a larger array and\r
37// migration the old data to the larger array.\r
38//\r
fe1e36e5 39UINT32 mMaxGaugeRecords;\r
a0afd019 40\r
857dfc45 41//\r
42// The handle to install Performance Protocol instance.\r
43//\r
a0afd019 44EFI_HANDLE mHandle = NULL;\r
857dfc45 45\r
46//\r
f0da4d7d 47// Interfaces for Performance Protocol.\r
857dfc45 48//\r
a0afd019 49PERFORMANCE_PROTOCOL mPerformanceInterface = {\r
50 StartGauge,\r
51 EndGauge,\r
52 GetGauge\r
53 };\r
54\r
f0da4d7d
SZ
55//\r
56// Interfaces for PerformanceEx Protocol.\r
57//\r
58PERFORMANCE_EX_PROTOCOL mPerformanceExInterface = {\r
59 StartGaugeEx,\r
60 EndGaugeEx,\r
61 GetGaugeEx\r
62 };\r
63\r
a0afd019 64/**\r
f0da4d7d 65 Searches in the gauge array with keyword Handle, Token, Module and Identifier.\r
a0afd019 66\r
67 This internal function searches for the gauge entry in the gauge array.\r
f0da4d7d 68 If there is an entry that exactly matches the given keywords\r
a0afd019 69 and its end time stamp is zero, then the index of that gauge entry is returned;\r
70 otherwise, the the number of gauge entries in the array is returned.\r
71\r
72 @param Handle Pointer to environment specific context used\r
73 to identify the component being measured.\r
74 @param Token Pointer to a Null-terminated ASCII string\r
75 that identifies the component being measured.\r
76 @param Module Pointer to a Null-terminated ASCII string\r
77 that identifies the module being measured.\r
f0da4d7d 78 @param Identifier 32-bit identifier.\r
a0afd019 79\r
80 @retval The index of gauge entry in the array.\r
81\r
82**/\r
a0afd019 83UINT32\r
84InternalSearchForGaugeEntry (\r
85 IN CONST VOID *Handle, OPTIONAL\r
86 IN CONST CHAR8 *Token, OPTIONAL\r
f0da4d7d
SZ
87 IN CONST CHAR8 *Module, OPTIONAL\r
88 IN UINT32 Identifier\r
a0afd019 89 )\r
90{\r
91 UINT32 Index;\r
b504f519 92 UINT32 Index2;\r
a0afd019 93 UINT32 NumberOfEntries;\r
f0da4d7d 94 GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;\r
a0afd019 95\r
96 if (Token == NULL) {\r
97 Token = "";\r
98 }\r
99 if (Module == NULL) {\r
100 Module = "";\r
101 }\r
102\r
103 NumberOfEntries = mGaugeData->NumberOfEntries;\r
f0da4d7d 104 GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);\r
a0afd019 105\r
b504f519
SZ
106 Index2 = 0;\r
107\r
a0afd019 108 for (Index = 0; Index < NumberOfEntries; Index++) {\r
b504f519
SZ
109 Index2 = NumberOfEntries - 1 - Index;\r
110 if (GaugeEntryExArray[Index2].EndTimeStamp == 0 &&\r
111 (GaugeEntryExArray[Index2].Handle == (EFI_PHYSICAL_ADDRESS) (UINTN) Handle) &&\r
112 AsciiStrnCmp (GaugeEntryExArray[Index2].Token, Token, DXE_PERFORMANCE_STRING_LENGTH) == 0 &&\r
113 AsciiStrnCmp (GaugeEntryExArray[Index2].Module, Module, DXE_PERFORMANCE_STRING_LENGTH) == 0 &&\r
114 (GaugeEntryExArray[Index2].Identifier == Identifier)) {\r
115 Index = Index2;\r
a0afd019 116 break;\r
117 }\r
118 }\r
119\r
120 return Index;\r
121}\r
122\r
123/**\r
124 Adds a record at the end of the performance measurement log\r
125 that records the start time of a performance measurement.\r
126\r
127 Adds a record to the end of the performance measurement log\r
f0da4d7d 128 that contains the Handle, Token, Module and Identifier.\r
a0afd019 129 The end time of the new record must be set to zero.\r
130 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.\r
131 If TimeStamp is zero, the start time in the record is filled in with the value\r
132 read from the current time stamp.\r
133\r
134 @param Handle Pointer to environment specific context used\r
135 to identify the component being measured.\r
136 @param Token Pointer to a Null-terminated ASCII string\r
137 that identifies the component being measured.\r
138 @param Module Pointer to a Null-terminated ASCII string\r
139 that identifies the module being measured.\r
140 @param TimeStamp 64-bit time stamp.\r
f0da4d7d
SZ
141 @param Identifier 32-bit identifier. If the value is 0, the created record\r
142 is same as the one created by StartGauge of PERFORMANCE_PROTOCOL.\r
a0afd019 143\r
144 @retval EFI_SUCCESS The data was read correctly from the device.\r
145 @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement.\r
146\r
147**/\r
a0afd019 148EFI_STATUS\r
149EFIAPI\r
f0da4d7d 150StartGaugeEx (\r
a0afd019 151 IN CONST VOID *Handle, OPTIONAL\r
152 IN CONST CHAR8 *Token, OPTIONAL\r
153 IN CONST CHAR8 *Module, OPTIONAL\r
f0da4d7d
SZ
154 IN UINT64 TimeStamp,\r
155 IN UINT32 Identifier\r
a0afd019 156 )\r
157{\r
f0da4d7d 158 GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;\r
a0afd019 159 UINTN GaugeDataSize;\r
f0da4d7d 160 GAUGE_DATA_HEADER *NewGaugeData;\r
a0afd019 161 UINTN OldGaugeDataSize;\r
162 GAUGE_DATA_HEADER *OldGaugeData;\r
163 UINT32 Index;\r
164\r
165 Index = mGaugeData->NumberOfEntries;\r
166 if (Index >= mMaxGaugeRecords) {\r
167 //\r
857dfc45 168 // Try to enlarge the scale of gauge array.\r
a0afd019 169 //\r
170 OldGaugeData = mGaugeData;\r
f0da4d7d 171 OldGaugeDataSize = sizeof (GAUGE_DATA_HEADER) + sizeof (GAUGE_DATA_ENTRY_EX) * mMaxGaugeRecords;\r
a0afd019 172\r
f0da4d7d 173 GaugeDataSize = sizeof (GAUGE_DATA_HEADER) + sizeof (GAUGE_DATA_ENTRY_EX) * mMaxGaugeRecords * 2;\r
a0afd019 174\r
f0da4d7d
SZ
175 NewGaugeData = AllocateZeroPool (GaugeDataSize);\r
176 if (NewGaugeData == NULL) {\r
a0afd019 177 return EFI_OUT_OF_RESOURCES;\r
178 }\r
f0da4d7d
SZ
179\r
180 mGaugeData = NewGaugeData;\r
181 mMaxGaugeRecords *= 2;\r
182\r
a0afd019 183 //\r
857dfc45 184 // Initialize new data array and migrate old data one.\r
a0afd019 185 //\r
186 mGaugeData = CopyMem (mGaugeData, OldGaugeData, OldGaugeDataSize);\r
187\r
188 FreePool (OldGaugeData);\r
189 }\r
190\r
f0da4d7d
SZ
191 GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);\r
192 GaugeEntryExArray[Index].Handle = (EFI_PHYSICAL_ADDRESS) (UINTN) Handle;\r
a0afd019 193\r
194 if (Token != NULL) {\r
0ec2bfc8 195 AsciiStrnCpyS (GaugeEntryExArray[Index].Token, DXE_PERFORMANCE_STRING_SIZE, Token, DXE_PERFORMANCE_STRING_LENGTH);\r
a0afd019 196 }\r
197 if (Module != NULL) {\r
0ec2bfc8 198 AsciiStrnCpyS (GaugeEntryExArray[Index].Module, DXE_PERFORMANCE_STRING_SIZE, Module, DXE_PERFORMANCE_STRING_LENGTH);\r
a0afd019 199 }\r
200\r
f0da4d7d
SZ
201 GaugeEntryExArray[Index].EndTimeStamp = 0;\r
202 GaugeEntryExArray[Index].Identifier = Identifier;\r
203\r
a0afd019 204 if (TimeStamp == 0) {\r
205 TimeStamp = GetPerformanceCounter ();\r
206 }\r
f0da4d7d 207 GaugeEntryExArray[Index].StartTimeStamp = TimeStamp;\r
a0afd019 208\r
209 mGaugeData->NumberOfEntries++;\r
210\r
211 return EFI_SUCCESS;\r
212}\r
213\r
214/**\r
215 Searches the performance measurement log from the beginning of the log\r
216 for the first matching record that contains a zero end time and fills in a valid end time.\r
217\r
218 Searches the performance measurement log from the beginning of the log\r
f0da4d7d 219 for the first record that matches Handle, Token, Module and Identifier and has an end time value of zero.\r
a0afd019 220 If the record can not be found then return EFI_NOT_FOUND.\r
221 If the record is found and TimeStamp is not zero,\r
222 then the end time in the record is filled in with the value specified by TimeStamp.\r
223 If the record is found and TimeStamp is zero, then the end time in the matching record\r
224 is filled in with the current time stamp value.\r
225\r
226 @param Handle Pointer to environment specific context used\r
227 to identify the component being measured.\r
228 @param Token Pointer to a Null-terminated ASCII string\r
229 that identifies the component being measured.\r
230 @param Module Pointer to a Null-terminated ASCII string\r
231 that identifies the module being measured.\r
232 @param TimeStamp 64-bit time stamp.\r
f0da4d7d
SZ
233 @param Identifier 32-bit identifier. If the value is 0, the found record\r
234 is same as the one found by EndGauge of PERFORMANCE_PROTOCOL.\r
a0afd019 235\r
236 @retval EFI_SUCCESS The end of the measurement was recorded.\r
237 @retval EFI_NOT_FOUND The specified measurement record could not be found.\r
238\r
239**/\r
a0afd019 240EFI_STATUS\r
241EFIAPI\r
f0da4d7d 242EndGaugeEx (\r
a0afd019 243 IN CONST VOID *Handle, OPTIONAL\r
244 IN CONST CHAR8 *Token, OPTIONAL\r
245 IN CONST CHAR8 *Module, OPTIONAL\r
f0da4d7d
SZ
246 IN UINT64 TimeStamp,\r
247 IN UINT32 Identifier\r
a0afd019 248 )\r
249{\r
f0da4d7d
SZ
250 GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;\r
251 UINT32 Index;\r
a0afd019 252\r
253 if (TimeStamp == 0) {\r
254 TimeStamp = GetPerformanceCounter ();\r
255 }\r
256\r
f0da4d7d 257 Index = InternalSearchForGaugeEntry (Handle, Token, Module, Identifier);\r
a0afd019 258 if (Index >= mGaugeData->NumberOfEntries) {\r
259 return EFI_NOT_FOUND;\r
260 }\r
f0da4d7d
SZ
261 GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);\r
262 GaugeEntryExArray[Index].EndTimeStamp = TimeStamp;\r
a0afd019 263\r
264 return EFI_SUCCESS;\r
265}\r
266\r
267/**\r
268 Retrieves a previously logged performance measurement.\r
f0da4d7d
SZ
269 It can also retrieve the log created by StartGauge and EndGauge of PERFORMANCE_PROTOCOL,\r
270 and then assign the Identifier with 0.\r
a0afd019 271\r
272 Retrieves the performance log entry from the performance log specified by LogEntryKey.\r
273 If it stands for a valid entry, then EFI_SUCCESS is returned and\r
f0da4d7d 274 GaugeDataEntryEx stores the pointer to that entry.\r
a0afd019 275\r
276 @param LogEntryKey The key for the previous performance measurement log entry.\r
277 If 0, then the first performance measurement log entry is retrieved.\r
f0da4d7d 278 @param GaugeDataEntryEx The indirect pointer to the extended gauge data entry specified by LogEntryKey\r
a0afd019 279 if the retrieval is successful.\r
280\r
f0da4d7d 281 @retval EFI_SUCCESS The GuageDataEntryEx is successfully found based on LogEntryKey.\r
a0afd019 282 @retval EFI_NOT_FOUND The LogEntryKey is the last entry (equals to the total entry number).\r
283 @retval EFI_INVALIDE_PARAMETER The LogEntryKey is not a valid entry (greater than the total entry number).\r
f0da4d7d 284 @retval EFI_INVALIDE_PARAMETER GaugeDataEntryEx is NULL.\r
a0afd019 285\r
286**/\r
a0afd019 287EFI_STATUS\r
288EFIAPI\r
f0da4d7d
SZ
289GetGaugeEx (\r
290 IN UINTN LogEntryKey,\r
291 OUT GAUGE_DATA_ENTRY_EX **GaugeDataEntryEx\r
a0afd019 292 )\r
293{\r
294 UINTN NumberOfEntries;\r
f0da4d7d 295 GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;\r
a0afd019 296\r
297 NumberOfEntries = (UINTN) (mGaugeData->NumberOfEntries);\r
298 if (LogEntryKey > NumberOfEntries) {\r
299 return EFI_INVALID_PARAMETER;\r
300 }\r
301 if (LogEntryKey == NumberOfEntries) {\r
302 return EFI_NOT_FOUND;\r
303 }\r
304\r
f0da4d7d
SZ
305 GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);\r
306\r
307 if (GaugeDataEntryEx == NULL) {\r
308 return EFI_INVALID_PARAMETER;\r
309 }\r
310 *GaugeDataEntryEx = &GaugeEntryExArray[LogEntryKey];\r
311\r
312 return EFI_SUCCESS;\r
313}\r
314\r
315/**\r
316 Adds a record at the end of the performance measurement log\r
317 that records the start time of a performance measurement.\r
318\r
319 Adds a record to the end of the performance measurement log\r
320 that contains the Handle, Token, and Module.\r
321 The end time of the new record must be set to zero.\r
322 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.\r
323 If TimeStamp is zero, the start time in the record is filled in with the value\r
324 read from the current time stamp.\r
325\r
326 @param Handle Pointer to environment specific context used\r
327 to identify the component being measured.\r
328 @param Token Pointer to a Null-terminated ASCII string\r
329 that identifies the component being measured.\r
330 @param Module Pointer to a Null-terminated ASCII string\r
331 that identifies the module being measured.\r
332 @param TimeStamp 64-bit time stamp.\r
333\r
334 @retval EFI_SUCCESS The data was read correctly from the device.\r
335 @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement.\r
336\r
337**/\r
338EFI_STATUS\r
339EFIAPI\r
340StartGauge (\r
341 IN CONST VOID *Handle, OPTIONAL\r
342 IN CONST CHAR8 *Token, OPTIONAL\r
343 IN CONST CHAR8 *Module, OPTIONAL\r
344 IN UINT64 TimeStamp\r
345 )\r
346{\r
347 return StartGaugeEx (Handle, Token, Module, TimeStamp, 0);\r
348}\r
349\r
350/**\r
351 Searches the performance measurement log from the beginning of the log\r
352 for the first matching record that contains a zero end time and fills in a valid end time.\r
353\r
354 Searches the performance measurement log from the beginning of the log\r
355 for the first record that matches Handle, Token, and Module and has an end time value of zero.\r
356 If the record can not be found then return EFI_NOT_FOUND.\r
357 If the record is found and TimeStamp is not zero,\r
358 then the end time in the record is filled in with the value specified by TimeStamp.\r
359 If the record is found and TimeStamp is zero, then the end time in the matching record\r
360 is filled in with the current time stamp value.\r
361\r
362 @param Handle Pointer to environment specific context used\r
363 to identify the component being measured.\r
364 @param Token Pointer to a Null-terminated ASCII string\r
365 that identifies the component being measured.\r
366 @param Module Pointer to a Null-terminated ASCII string\r
367 that identifies the module being measured.\r
368 @param TimeStamp 64-bit time stamp.\r
369\r
370 @retval EFI_SUCCESS The end of the measurement was recorded.\r
371 @retval EFI_NOT_FOUND The specified measurement record could not be found.\r
372\r
373**/\r
374EFI_STATUS\r
375EFIAPI\r
376EndGauge (\r
377 IN CONST VOID *Handle, OPTIONAL\r
378 IN CONST CHAR8 *Token, OPTIONAL\r
379 IN CONST CHAR8 *Module, OPTIONAL\r
380 IN UINT64 TimeStamp\r
381 )\r
382{\r
383 return EndGaugeEx (Handle, Token, Module, TimeStamp, 0);\r
384}\r
385\r
386/**\r
387 Retrieves a previously logged performance measurement.\r
388 It can also retrieve the log created by StartGaugeEx and EndGaugeEx of PERFORMANCE_EX_PROTOCOL,\r
389 and then eliminate the Identifier.\r
390\r
391 Retrieves the performance log entry from the performance log specified by LogEntryKey.\r
392 If it stands for a valid entry, then EFI_SUCCESS is returned and\r
393 GaugeDataEntry stores the pointer to that entry.\r
394\r
395 @param LogEntryKey The key for the previous performance measurement log entry.\r
396 If 0, then the first performance measurement log entry is retrieved.\r
397 @param GaugeDataEntry The indirect pointer to the gauge data entry specified by LogEntryKey\r
398 if the retrieval is successful.\r
399\r
400 @retval EFI_SUCCESS The GuageDataEntry is successfully found based on LogEntryKey.\r
401 @retval EFI_NOT_FOUND The LogEntryKey is the last entry (equals to the total entry number).\r
402 @retval EFI_INVALIDE_PARAMETER The LogEntryKey is not a valid entry (greater than the total entry number).\r
403 @retval EFI_INVALIDE_PARAMETER GaugeDataEntry is NULL.\r
404\r
405**/\r
406EFI_STATUS\r
407EFIAPI\r
408GetGauge (\r
409 IN UINTN LogEntryKey,\r
410 OUT GAUGE_DATA_ENTRY **GaugeDataEntry\r
411 )\r
412{\r
413 EFI_STATUS Status;\r
414 GAUGE_DATA_ENTRY_EX *GaugeEntryEx;\r
415\r
1658440e
SZ
416 GaugeEntryEx = NULL;\r
417\r
f0da4d7d
SZ
418 Status = GetGaugeEx (LogEntryKey, &GaugeEntryEx);\r
419 if (EFI_ERROR (Status)) {\r
420 return Status;\r
421 }\r
a0afd019 422\r
423 if (GaugeDataEntry == NULL) {\r
424 return EFI_INVALID_PARAMETER;\r
425 }\r
f0da4d7d
SZ
426\r
427 *GaugeDataEntry = (GAUGE_DATA_ENTRY *) GaugeEntryEx;\r
a0afd019 428\r
429 return EFI_SUCCESS;\r
430}\r
431\r
432/**\r
433 Dumps all the PEI performance log to DXE performance gauge array.\r
434\r
435 This internal function dumps all the PEI performance log to the DXE performance gauge array.\r
436 It retrieves the optional GUID HOB for PEI performance and then saves the performance data\r
437 to DXE performance data structures.\r
438\r
439**/\r
a0afd019 440VOID\r
441InternalGetPeiPerformance (\r
442 VOID\r
443 )\r
444{\r
445 EFI_HOB_GUID_TYPE *GuidHob;\r
446 PEI_PERFORMANCE_LOG_HEADER *LogHob;\r
447 PEI_PERFORMANCE_LOG_ENTRY *LogEntryArray;\r
f0da4d7d
SZ
448 UINT32 *LogIdArray;\r
449 GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;\r
a0afd019 450 UINT32 Index;\r
451 UINT32 NumberOfEntries;\r
452\r
453 NumberOfEntries = 0;\r
f0da4d7d 454 GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);\r
a0afd019 455\r
456 //\r
457 // Dump PEI Log Entries to DXE Guage Data structure.\r
458 //\r
ee0961f7 459 GuidHob = GetFirstGuidHob (&gPerformanceProtocolGuid);\r
a0afd019 460 if (GuidHob != NULL) {\r
461 LogHob = GET_GUID_HOB_DATA (GuidHob);\r
462 LogEntryArray = (PEI_PERFORMANCE_LOG_ENTRY *) (LogHob + 1);\r
a0afd019 463\r
464 NumberOfEntries = LogHob->NumberOfEntries;\r
465 for (Index = 0; Index < NumberOfEntries; Index++) {\r
f0da4d7d 466 GaugeEntryExArray[Index].Handle = LogEntryArray[Index].Handle;\r
96f983fa
QS
467 AsciiStrCpyS (GaugeEntryExArray[Index].Token, DXE_PERFORMANCE_STRING_SIZE, LogEntryArray[Index].Token);\r
468 AsciiStrCpyS (GaugeEntryExArray[Index].Module, DXE_PERFORMANCE_STRING_SIZE, LogEntryArray[Index].Module);\r
f0da4d7d
SZ
469 GaugeEntryExArray[Index].StartTimeStamp = LogEntryArray[Index].StartTimeStamp;\r
470 GaugeEntryExArray[Index].EndTimeStamp = LogEntryArray[Index].EndTimeStamp;\r
471 GaugeEntryExArray[Index].Identifier = 0;\r
472 }\r
473\r
474 GuidHob = GetFirstGuidHob (&gPerformanceExProtocolGuid);\r
475 if (GuidHob != NULL) {\r
476 LogIdArray = GET_GUID_HOB_DATA (GuidHob);\r
477 for (Index = 0; Index < NumberOfEntries; Index++) {\r
478 GaugeEntryExArray[Index].Identifier = LogIdArray[Index];\r
479 }\r
a0afd019 480 }\r
481 }\r
482 mGaugeData->NumberOfEntries = NumberOfEntries;\r
483}\r
484\r
485/**\r
486 The constructor function initializes Performance infrastructure for DXE phase.\r
487\r
f0da4d7d 488 The constructor function publishes Performance and PerformanceEx protocol, allocates memory to log DXE performance\r
a0afd019 489 and merges PEI performance data to DXE performance log.\r
490 It will ASSERT() if one of these operations fails and it will always return EFI_SUCCESS.\r
491\r
492 @param ImageHandle The firmware allocated handle for the EFI image.\r
493 @param SystemTable A pointer to the EFI System Table.\r
494\r
495 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.\r
496\r
497**/\r
498EFI_STATUS\r
499EFIAPI\r
500DxeCorePerformanceLibConstructor (\r
501 IN EFI_HANDLE ImageHandle,\r
502 IN EFI_SYSTEM_TABLE *SystemTable\r
503 )\r
504{\r
505 EFI_STATUS Status;\r
506\r
507 if (!PerformanceMeasurementEnabled ()) {\r
508 //\r
509 // Do not initialize performance infrastructure if not required.\r
510 //\r
511 return EFI_SUCCESS;\r
512 }\r
513 //\r
514 // Install the protocol interfaces.\r
515 //\r
f0da4d7d 516 Status = gBS->InstallMultipleProtocolInterfaces (\r
a0afd019 517 &mHandle,\r
518 &gPerformanceProtocolGuid,\r
f0da4d7d
SZ
519 &mPerformanceInterface,\r
520 &gPerformanceExProtocolGuid,\r
521 &mPerformanceExInterface,\r
522 NULL\r
a0afd019 523 );\r
524 ASSERT_EFI_ERROR (Status);\r
525\r
7c50b343
CS
526 mMaxGaugeRecords = INIT_DXE_GAUGE_DATA_ENTRIES + (UINT16) (PcdGet16 (PcdMaxPeiPerformanceLogEntries16) != 0 ?\r
527 PcdGet16 (PcdMaxPeiPerformanceLogEntries16) :\r
528 PcdGet8 (PcdMaxPeiPerformanceLogEntries));\r
a0afd019 529\r
f0da4d7d 530 mGaugeData = AllocateZeroPool (sizeof (GAUGE_DATA_HEADER) + (sizeof (GAUGE_DATA_ENTRY_EX) * mMaxGaugeRecords));\r
a0afd019 531 ASSERT (mGaugeData != NULL);\r
532\r
533 InternalGetPeiPerformance ();\r
534\r
535 return Status;\r
536}\r
537\r
538/**\r
539 Adds a record at the end of the performance measurement log\r
540 that records the start time of a performance measurement.\r
541\r
542 Adds a record to the end of the performance measurement log\r
f0da4d7d 543 that contains the Handle, Token, Module and Identifier.\r
a0afd019 544 The end time of the new record must be set to zero.\r
545 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.\r
546 If TimeStamp is zero, the start time in the record is filled in with the value\r
547 read from the current time stamp.\r
548\r
549 @param Handle Pointer to environment specific context used\r
550 to identify the component being measured.\r
551 @param Token Pointer to a Null-terminated ASCII string\r
552 that identifies the component being measured.\r
553 @param Module Pointer to a Null-terminated ASCII string\r
554 that identifies the module being measured.\r
555 @param TimeStamp 64-bit time stamp.\r
f0da4d7d
SZ
556 @param Identifier 32-bit identifier. If the value is 0, the created record\r
557 is same as the one created by StartPerformanceMeasurement.\r
a0afd019 558\r
559 @retval RETURN_SUCCESS The start of the measurement was recorded.\r
560 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.\r
561\r
562**/\r
563RETURN_STATUS\r
564EFIAPI\r
f0da4d7d 565StartPerformanceMeasurementEx (\r
a0afd019 566 IN CONST VOID *Handle, OPTIONAL\r
567 IN CONST CHAR8 *Token, OPTIONAL\r
568 IN CONST CHAR8 *Module, OPTIONAL\r
f0da4d7d
SZ
569 IN UINT64 TimeStamp,\r
570 IN UINT32 Identifier\r
a0afd019 571 )\r
572{\r
f0da4d7d 573 return (RETURN_STATUS) StartGaugeEx (Handle, Token, Module, TimeStamp, Identifier);\r
a0afd019 574}\r
575\r
576/**\r
577 Searches the performance measurement log from the beginning of the log\r
578 for the first matching record that contains a zero end time and fills in a valid end time.\r
579\r
580 Searches the performance measurement log from the beginning of the log\r
f0da4d7d 581 for the first record that matches Handle, Token, Module and Identifier and has an end time value of zero.\r
a0afd019 582 If the record can not be found then return RETURN_NOT_FOUND.\r
583 If the record is found and TimeStamp is not zero,\r
584 then the end time in the record is filled in with the value specified by TimeStamp.\r
585 If the record is found and TimeStamp is zero, then the end time in the matching record\r
586 is filled in with the current time stamp value.\r
587\r
588 @param Handle Pointer to environment specific context used\r
589 to identify the component being measured.\r
590 @param Token Pointer to a Null-terminated ASCII string\r
591 that identifies the component being measured.\r
592 @param Module Pointer to a Null-terminated ASCII string\r
593 that identifies the module being measured.\r
594 @param TimeStamp 64-bit time stamp.\r
f0da4d7d
SZ
595 @param Identifier 32-bit identifier. If the value is 0, the found record\r
596 is same as the one found by EndPerformanceMeasurement.\r
a0afd019 597\r
598 @retval RETURN_SUCCESS The end of the measurement was recorded.\r
599 @retval RETURN_NOT_FOUND The specified measurement record could not be found.\r
600\r
601**/\r
602RETURN_STATUS\r
603EFIAPI\r
f0da4d7d 604EndPerformanceMeasurementEx (\r
a0afd019 605 IN CONST VOID *Handle, OPTIONAL\r
606 IN CONST CHAR8 *Token, OPTIONAL\r
607 IN CONST CHAR8 *Module, OPTIONAL\r
f0da4d7d
SZ
608 IN UINT64 TimeStamp,\r
609 IN UINT32 Identifier\r
a0afd019 610 )\r
611{\r
f0da4d7d 612 return (RETURN_STATUS) EndGaugeEx (Handle, Token, Module, TimeStamp, Identifier);\r
a0afd019 613}\r
614\r
615/**\r
616 Attempts to retrieve a performance measurement log entry from the performance measurement log.\r
f0da4d7d
SZ
617 It can also retrieve the log created by StartPerformanceMeasurement and EndPerformanceMeasurement,\r
618 and then assign the Identifier with 0.\r
a0afd019 619\r
620 Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is\r
621 zero on entry, then an attempt is made to retrieve the first entry from the performance log,\r
622 and the key for the second entry in the log is returned. If the performance log is empty,\r
623 then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance\r
624 log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is\r
625 returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is\r
626 retrieved and an implementation specific non-zero key value that specifies the end of the performance\r
627 log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry\r
628 is retrieved and zero is returned. In the cases where a performance log entry can be returned,\r
f0da4d7d 629 the log entry is returned in Handle, Token, Module, StartTimeStamp, EndTimeStamp and Identifier.\r
a0afd019 630 If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().\r
631 If Handle is NULL, then ASSERT().\r
632 If Token is NULL, then ASSERT().\r
633 If Module is NULL, then ASSERT().\r
634 If StartTimeStamp is NULL, then ASSERT().\r
635 If EndTimeStamp is NULL, then ASSERT().\r
f0da4d7d 636 If Identifier is NULL, then ASSERT().\r
a0afd019 637\r
638 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.\r
639 0, then the first performance measurement log entry is retrieved.\r
857dfc45 640 On exit, the key of the next performance log entry.\r
a0afd019 641 @param Handle Pointer to environment specific context used to identify the component\r
642 being measured.\r
643 @param Token Pointer to a Null-terminated ASCII string that identifies the component\r
644 being measured.\r
645 @param Module Pointer to a Null-terminated ASCII string that identifies the module\r
646 being measured.\r
647 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement\r
648 was started.\r
649 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement\r
650 was ended.\r
f0da4d7d 651 @param Identifier Pointer to the 32-bit identifier that was recorded.\r
a0afd019 652\r
653 @return The key for the next performance log entry (in general case).\r
654\r
655**/\r
656UINTN\r
657EFIAPI\r
f0da4d7d
SZ
658GetPerformanceMeasurementEx (\r
659 IN UINTN LogEntryKey, \r
a0afd019 660 OUT CONST VOID **Handle,\r
661 OUT CONST CHAR8 **Token,\r
662 OUT CONST CHAR8 **Module,\r
663 OUT UINT64 *StartTimeStamp,\r
f0da4d7d
SZ
664 OUT UINT64 *EndTimeStamp,\r
665 OUT UINT32 *Identifier\r
a0afd019 666 )\r
667{\r
f0da4d7d
SZ
668 EFI_STATUS Status;\r
669 GAUGE_DATA_ENTRY_EX *GaugeData;\r
a0afd019 670\r
952671b3 671 GaugeData = NULL;\r
672 \r
a0afd019 673 ASSERT (Handle != NULL);\r
674 ASSERT (Token != NULL);\r
675 ASSERT (Module != NULL);\r
676 ASSERT (StartTimeStamp != NULL);\r
677 ASSERT (EndTimeStamp != NULL);\r
f0da4d7d 678 ASSERT (Identifier != NULL);\r
a0afd019 679\r
f0da4d7d 680 Status = GetGaugeEx (LogEntryKey++, &GaugeData);\r
a0afd019 681\r
682 //\r
683 // Make sure that LogEntryKey is a valid log entry key,\r
684 //\r
685 ASSERT (Status != EFI_INVALID_PARAMETER);\r
686\r
687 if (EFI_ERROR (Status)) {\r
688 //\r
689 // The LogEntryKey is the last entry (equals to the total entry number).\r
690 //\r
691 return 0;\r
692 }\r
693\r
694 ASSERT (GaugeData != NULL);\r
695\r
696 *Handle = (VOID *) (UINTN) GaugeData->Handle;\r
697 *Token = GaugeData->Token;\r
698 *Module = GaugeData->Module;\r
699 *StartTimeStamp = GaugeData->StartTimeStamp;\r
700 *EndTimeStamp = GaugeData->EndTimeStamp;\r
f0da4d7d 701 *Identifier = GaugeData->Identifier;\r
a0afd019 702\r
703 return LogEntryKey;\r
704}\r
705\r
f0da4d7d
SZ
706/**\r
707 Adds a record at the end of the performance measurement log\r
708 that records the start time of a performance measurement.\r
709\r
710 Adds a record to the end of the performance measurement log\r
711 that contains the Handle, Token, and Module.\r
712 The end time of the new record must be set to zero.\r
713 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.\r
714 If TimeStamp is zero, the start time in the record is filled in with the value\r
715 read from the current time stamp.\r
716\r
717 @param Handle Pointer to environment specific context used\r
718 to identify the component being measured.\r
719 @param Token Pointer to a Null-terminated ASCII string\r
720 that identifies the component being measured.\r
721 @param Module Pointer to a Null-terminated ASCII string\r
722 that identifies the module being measured.\r
723 @param TimeStamp 64-bit time stamp.\r
724\r
725 @retval RETURN_SUCCESS The start of the measurement was recorded.\r
726 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.\r
727\r
728**/\r
729RETURN_STATUS\r
730EFIAPI\r
731StartPerformanceMeasurement (\r
732 IN CONST VOID *Handle, OPTIONAL\r
733 IN CONST CHAR8 *Token, OPTIONAL\r
734 IN CONST CHAR8 *Module, OPTIONAL\r
735 IN UINT64 TimeStamp\r
736 )\r
737{\r
738 return StartPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);\r
739}\r
740\r
741/**\r
742 Searches the performance measurement log from the beginning of the log\r
743 for the first matching record that contains a zero end time and fills in a valid end time.\r
744\r
745 Searches the performance measurement log from the beginning of the log\r
746 for the first record that matches Handle, Token, and Module and has an end time value of zero.\r
747 If the record can not be found then return RETURN_NOT_FOUND.\r
748 If the record is found and TimeStamp is not zero,\r
749 then the end time in the record is filled in with the value specified by TimeStamp.\r
750 If the record is found and TimeStamp is zero, then the end time in the matching record\r
751 is filled in with the current time stamp value.\r
752\r
753 @param Handle Pointer to environment specific context used\r
754 to identify the component being measured.\r
755 @param Token Pointer to a Null-terminated ASCII string\r
756 that identifies the component being measured.\r
757 @param Module Pointer to a Null-terminated ASCII string\r
758 that identifies the module being measured.\r
759 @param TimeStamp 64-bit time stamp.\r
760\r
761 @retval RETURN_SUCCESS The end of the measurement was recorded.\r
762 @retval RETURN_NOT_FOUND The specified measurement record could not be found.\r
763\r
764**/\r
765RETURN_STATUS\r
766EFIAPI\r
767EndPerformanceMeasurement (\r
768 IN CONST VOID *Handle, OPTIONAL\r
769 IN CONST CHAR8 *Token, OPTIONAL\r
770 IN CONST CHAR8 *Module, OPTIONAL\r
771 IN UINT64 TimeStamp\r
772 )\r
773{\r
774 return EndPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);\r
775}\r
776\r
777/**\r
778 Attempts to retrieve a performance measurement log entry from the performance measurement log.\r
779 It can also retrieve the log created by StartPerformanceMeasurementEx and EndPerformanceMeasurementEx,\r
780 and then eliminate the Identifier.\r
781\r
782 Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is\r
783 zero on entry, then an attempt is made to retrieve the first entry from the performance log,\r
784 and the key for the second entry in the log is returned. If the performance log is empty,\r
785 then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance\r
786 log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is\r
787 returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is\r
788 retrieved and an implementation specific non-zero key value that specifies the end of the performance\r
789 log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry\r
790 is retrieved and zero is returned. In the cases where a performance log entry can be returned,\r
791 the log entry is returned in Handle, Token, Module, StartTimeStamp, and EndTimeStamp.\r
792 If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().\r
793 If Handle is NULL, then ASSERT().\r
794 If Token is NULL, then ASSERT().\r
795 If Module is NULL, then ASSERT().\r
796 If StartTimeStamp is NULL, then ASSERT().\r
797 If EndTimeStamp is NULL, then ASSERT().\r
798\r
799 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.\r
800 0, then the first performance measurement log entry is retrieved.\r
801 On exit, the key of the next performance log entry.\r
802 @param Handle Pointer to environment specific context used to identify the component\r
803 being measured.\r
804 @param Token Pointer to a Null-terminated ASCII string that identifies the component\r
805 being measured.\r
806 @param Module Pointer to a Null-terminated ASCII string that identifies the module\r
807 being measured.\r
808 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement\r
809 was started.\r
810 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement\r
811 was ended.\r
812\r
813 @return The key for the next performance log entry (in general case).\r
814\r
815**/\r
816UINTN\r
817EFIAPI\r
818GetPerformanceMeasurement (\r
819 IN UINTN LogEntryKey,\r
820 OUT CONST VOID **Handle,\r
821 OUT CONST CHAR8 **Token,\r
822 OUT CONST CHAR8 **Module,\r
823 OUT UINT64 *StartTimeStamp,\r
824 OUT UINT64 *EndTimeStamp\r
825 )\r
826{\r
827 UINT32 Identifier;\r
828 return GetPerformanceMeasurementEx (LogEntryKey, Handle, Token, Module, StartTimeStamp, EndTimeStamp, &Identifier);\r
829}\r
830\r
a0afd019 831/**\r
832 Returns TRUE if the performance measurement macros are enabled.\r
833\r
834 This function returns TRUE if the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of\r
835 PcdPerformanceLibraryPropertyMask is set. Otherwise FALSE is returned.\r
836\r
837 @retval TRUE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of\r
838 PcdPerformanceLibraryPropertyMask is set.\r
839 @retval FALSE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of\r
840 PcdPerformanceLibraryPropertyMask is clear.\r
841\r
842**/\r
843BOOLEAN\r
844EFIAPI\r
845PerformanceMeasurementEnabled (\r
846 VOID\r
847 )\r
848{\r
849 return (BOOLEAN) ((PcdGet8(PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0);\r
850}\r