]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c
MdeModulePkg/SmmCorePerformanceLib:Track FPDT record in SMM phase
[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
2001f84e 19Copyright (c) 2011 - 2018, 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
2001f84e
DB
33#define STRING_SIZE (FPDT_STRING_EVENT_RECORD_NAME_LENGTH * sizeof (CHAR8))\r
34#define FIRMWARE_RECORD_BUFFER 0x1000\r
35#define CACHE_HANDLE_GUID_COUNT 0x100\r
d042c6e8 36\r
2001f84e 37SMM_BOOT_PERFORMANCE_TABLE *mSmmBootPerformanceTable = NULL;\r
d042c6e8 38\r
2001f84e
DB
39typedef struct {\r
40 EFI_HANDLE Handle;\r
41 CHAR8 NameString[FPDT_STRING_EVENT_RECORD_NAME_LENGTH];\r
42 EFI_GUID ModuleGuid;\r
43} HANDLE_GUID_MAP;\r
d042c6e8 44\r
2001f84e
DB
45HANDLE_GUID_MAP mCacheHandleGuidTable[CACHE_HANDLE_GUID_COUNT];\r
46UINTN mCachePairCount = 0;\r
d042c6e8 47\r
2001f84e
DB
48UINT32 mPerformanceLength = 0;\r
49UINT32 mMaxPerformanceLength = 0;\r
50BOOLEAN mFpdtDataIsReported = FALSE;\r
51BOOLEAN mLackSpaceIsReport = FALSE;\r
52CHAR8 *mPlatformLanguage = NULL;\r
53SPIN_LOCK mSmmFpdtLock;\r
54PERFORMANCE_PROPERTY mPerformanceProperty;\r
d042c6e8 55\r
d042c6e8 56//\r
f0da4d7d 57// Interfaces for SMM Performance Protocol.\r
d042c6e8 58//\r
59PERFORMANCE_PROTOCOL mPerformanceInterface = {\r
60 StartGauge,\r
61 EndGauge,\r
62 GetGauge\r
63};\r
64\r
f0da4d7d
SZ
65//\r
66// Interfaces for SMM PerformanceEx Protocol.\r
67//\r
68PERFORMANCE_EX_PROTOCOL mPerformanceExInterface = {\r
69 StartGaugeEx,\r
70 EndGaugeEx,\r
71 GetGaugeEx\r
72};\r
73\r
2001f84e
DB
74/**\r
75Check whether the Token is a known one which is uesed by core.\r
76\r
77@param Token Pointer to a Null-terminated ASCII string\r
78\r
79@retval TRUE Is a known one used by core.\r
80@retval FALSE Not a known one.\r
81\r
82**/\r
83BOOLEAN\r
84IsKnownTokens (\r
85 IN CONST CHAR8 *Token\r
86 )\r
87{\r
88 if (AsciiStrCmp (Token, SEC_TOK) == 0 ||\r
89 AsciiStrCmp (Token, PEI_TOK) == 0 ||\r
90 AsciiStrCmp (Token, DXE_TOK) == 0 ||\r
91 AsciiStrCmp (Token, BDS_TOK) == 0 ||\r
92 AsciiStrCmp (Token, DRIVERBINDING_START_TOK) == 0 ||\r
93 AsciiStrCmp (Token, DRIVERBINDING_SUPPORT_TOK) == 0 ||\r
94 AsciiStrCmp (Token, DRIVERBINDING_STOP_TOK) == 0 ||\r
95 AsciiStrCmp (Token, LOAD_IMAGE_TOK) == 0 ||\r
96 AsciiStrCmp (Token, START_IMAGE_TOK) == 0 ||\r
97 AsciiStrCmp (Token, PEIM_TOK) == 0) {\r
98 return TRUE;\r
99 } else {\r
100 return FALSE;\r
101 }\r
102}\r
cfb0aba7 103\r
d042c6e8 104/**\r
2001f84e 105Check whether the ID is a known one which map to the known Token.\r
d042c6e8 106\r
2001f84e 107@param Identifier 32-bit identifier.\r
d042c6e8 108\r
2001f84e
DB
109@retval TRUE Is a known one used by core.\r
110@retval FALSE Not a known one.\r
111\r
112**/\r
113BOOLEAN\r
114IsKnownID (\r
115 IN UINT32 Identifier\r
116 )\r
117{\r
118 if (Identifier == MODULE_START_ID ||\r
119 Identifier == MODULE_END_ID ||\r
120 Identifier == MODULE_LOADIMAGE_START_ID ||\r
121 Identifier == MODULE_LOADIMAGE_END_ID ||\r
122 Identifier == MODULE_DB_START_ID ||\r
123 Identifier == MODULE_DB_END_ID ||\r
124 Identifier == MODULE_DB_SUPPORT_START_ID ||\r
125 Identifier == MODULE_DB_SUPPORT_END_ID ||\r
126 Identifier == MODULE_DB_STOP_START_ID ||\r
127 Identifier == MODULE_DB_STOP_END_ID) {\r
128 return TRUE;\r
129 } else {\r
130 return FALSE;\r
131 }\r
132}\r
133\r
134/**\r
135 Get the FPDT record info.\r
136\r
137 @param IsStart TRUE if the performance log is start log.\r
d042c6e8 138 @param Handle Pointer to environment specific context used\r
139 to identify the component being measured.\r
140 @param Token Pointer to a Null-terminated ASCII string\r
141 that identifies the component being measured.\r
142 @param Module Pointer to a Null-terminated ASCII string\r
143 that identifies the module being measured.\r
2001f84e
DB
144 @param RecordInfo On return, pointer to the info of the record.\r
145 @param UseModuleName Only useful for FPDT_DYNAMIC_STRING_EVENT_TYPE, indicate that whether need use\r
146 Module name to fill the string field in the FPDT_DYNAMIC_STRING_EVENT_RECORD.\r
d042c6e8 147\r
2001f84e
DB
148 @retval EFI_SUCCESS Get record info successfully.\r
149 @retval EFI_UNSUPPORTED No matched FPDT record.\r
d042c6e8 150\r
151**/\r
2001f84e
DB
152EFI_STATUS\r
153GetFpdtRecordInfo (\r
154 IN BOOLEAN IsStart,\r
155 IN CONST VOID *Handle,\r
156 IN CONST CHAR8 *Token,\r
157 IN CONST CHAR8 *Module,\r
158 OUT FPDT_BASIC_RECORD_INFO *RecordInfo,\r
159 IN OUT BOOLEAN *UseModuleName\r
d042c6e8 160 )\r
161{\r
2001f84e
DB
162 UINT16 RecordType;\r
163 UINTN StringSize;\r
d042c6e8 164\r
2001f84e
DB
165 RecordType = FPDT_DYNAMIC_STRING_EVENT_TYPE;\r
166\r
167 //\r
168 // Token to Type and Id.\r
169 //\r
170 if (Token != NULL) {\r
171 if (AsciiStrCmp (Token, START_IMAGE_TOK) == 0) { // "StartImage:"\r
172 *UseModuleName = TRUE;\r
173 RecordType = FPDT_GUID_EVENT_TYPE;\r
174 if (IsStart) {\r
175 RecordInfo->ProgressID = MODULE_START_ID;\r
176 } else {\r
177 RecordInfo->ProgressID = MODULE_END_ID;\r
178 }\r
179 } else if (AsciiStrCmp (Token, LOAD_IMAGE_TOK) == 0) { // "LoadImage:"\r
180 *UseModuleName = TRUE;\r
181 RecordType = FPDT_GUID_QWORD_EVENT_TYPE;\r
182 if (IsStart) {\r
183 RecordInfo->ProgressID = MODULE_LOADIMAGE_START_ID;\r
184 } else {\r
185 RecordInfo->ProgressID = MODULE_LOADIMAGE_END_ID;\r
186 }\r
187 } else { // Pref used in Modules\r
188 if (IsStart) {\r
189 RecordInfo->ProgressID = PERF_INMODULE_START_ID;\r
190 } else {\r
191 RecordInfo->ProgressID = PERF_INMODULE_END_ID;\r
192 }\r
193 }\r
194 } else if (Handle != NULL || Module != NULL) { // Pref used in Modules\r
195 if (IsStart) {\r
196 RecordInfo->ProgressID = PERF_INMODULE_START_ID;\r
197 } else {\r
198 RecordInfo->ProgressID = PERF_INMODULE_END_ID;\r
199 }\r
200 } else {\r
201 return EFI_UNSUPPORTED;\r
d042c6e8 202 }\r
203\r
2001f84e
DB
204 if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {\r
205 RecordType = FPDT_DYNAMIC_STRING_EVENT_TYPE;\r
206 RecordInfo->RecordSize = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD) + STRING_SIZE;\r
207 } else {\r
208 switch (RecordType) {\r
209 case FPDT_GUID_EVENT_TYPE:\r
210 RecordInfo->RecordSize = sizeof (FPDT_GUID_EVENT_RECORD);\r
211 break;\r
d042c6e8 212\r
2001f84e
DB
213 case FPDT_DYNAMIC_STRING_EVENT_TYPE:\r
214 if (*UseModuleName) {\r
215 StringSize = STRING_SIZE;\r
216 } else if (Token != NULL) {\r
217 StringSize = AsciiStrSize (Token);\r
218 } else if (Module != NULL) {\r
219 StringSize = AsciiStrSize (Module);\r
220 } else {\r
221 StringSize = STRING_SIZE;\r
222 }\r
223 if (StringSize > STRING_SIZE) {\r
224 StringSize = STRING_SIZE;\r
225 }\r
226 RecordInfo->RecordSize = (UINT8)(sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD) + StringSize);\r
227 break;\r
b504f519 228\r
2001f84e
DB
229 case FPDT_GUID_QWORD_EVENT_TYPE:\r
230 RecordInfo->RecordSize = (UINT8)sizeof (FPDT_GUID_QWORD_EVENT_RECORD);\r
d042c6e8 231 break;\r
2001f84e
DB
232\r
233 default:\r
234 //\r
235 // Record type is unsupported in SMM phase.\r
236 //\r
237 return EFI_UNSUPPORTED;\r
d042c6e8 238 }\r
239 }\r
240\r
2001f84e
DB
241 RecordInfo->Type = RecordType;\r
242 return EFI_SUCCESS;\r
d042c6e8 243}\r
244\r
245/**\r
2001f84e
DB
246 Get a human readable module name and module guid for the given image handle.\r
247 If module name can't be found, "" string will return.\r
248 If module guid can't be found, Zero Guid will return.\r
249\r
250 @param Handle Image handle or Controller handle.\r
251 @param NameString The ascii string will be filled into it. If not found, null string will return.\r
252 @param BufferSize Size of the input NameString buffer.\r
253 @param ModuleGuid Point to the guid buffer to store the got module guid value.\r
254\r
255 @retval EFI_SUCCESS Successfully get module name and guid.\r
256 @retval EFI_INVALID_PARAMETER The input parameter NameString is NULL.\r
257 @retval other value Module Name can't be got.\r
258**/\r
259EFI_STATUS\r
260EFIAPI\r
261GetModuleInfoFromHandle (\r
262 IN EFI_HANDLE Handle,\r
263 OUT CHAR8 *NameString,\r
264 IN UINTN BufferSize,\r
265 OUT EFI_GUID *ModuleGuid OPTIONAL\r
266 )\r
267{\r
268 EFI_STATUS Status;\r
269 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
270 EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;\r
271 CHAR8 *PdbFileName;\r
272 EFI_GUID *TempGuid;\r
273 UINTN StartIndex;\r
274 UINTN Index;\r
275 INTN Count;\r
276 BOOLEAN ModuleGuidIsGet;\r
277 UINTN StringSize;\r
278 CHAR16 *StringPtr;\r
279 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFilePath;\r
280\r
281 if (NameString == NULL || BufferSize == 0) {\r
282 return EFI_INVALID_PARAMETER;\r
283 }\r
d042c6e8 284\r
2001f84e
DB
285 //\r
286 // Try to get the ModuleGuid and name string form the caached array.\r
287 //\r
288 if (mCachePairCount > 0) {\r
289 for (Count = mCachePairCount - 1; Count >= 0; Count--) {\r
290 if (Handle == mCacheHandleGuidTable[Count].Handle) {\r
291 CopyGuid (ModuleGuid, &mCacheHandleGuidTable[Count].ModuleGuid);\r
292 AsciiStrCpyS (NameString, FPDT_STRING_EVENT_RECORD_NAME_LENGTH, mCacheHandleGuidTable[Count].NameString);\r
293 return EFI_SUCCESS;\r
294 }\r
295 }\r
296 }\r
297\r
298 Status = EFI_INVALID_PARAMETER;\r
299 LoadedImage = NULL;\r
300 ModuleGuidIsGet = FALSE;\r
d042c6e8 301\r
2001f84e
DB
302 //\r
303 // Initialize GUID as zero value.\r
304 //\r
305 TempGuid = &gZeroGuid;\r
306 //\r
307 // Initialize it as "" string.\r
308 //\r
309 NameString[0] = 0;\r
310\r
311 if (Handle != NULL) {\r
312 //\r
313 // Try Handle as ImageHandle.\r
314 //\r
315 Status = gBS->HandleProtocol (\r
316 Handle,\r
317 &gEfiLoadedImageProtocolGuid,\r
318 (VOID**) &LoadedImage\r
319 );\r
320\r
321 if (EFI_ERROR (Status)) {\r
322 //\r
323 // Try Handle as Controller Handle\r
324 //\r
325 Status = gBS->OpenProtocol (\r
326 Handle,\r
327 &gEfiDriverBindingProtocolGuid,\r
328 (VOID **) &DriverBinding,\r
329 NULL,\r
330 NULL,\r
331 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
332 );\r
333 if (!EFI_ERROR (Status)) {\r
334 //\r
335 // Get Image protocol from ImageHandle\r
336 //\r
337 Status = gBS->HandleProtocol (\r
338 DriverBinding->ImageHandle,\r
339 &gEfiLoadedImageProtocolGuid,\r
340 (VOID**) &LoadedImage\r
341 );\r
342 }\r
343 }\r
344 }\r
345\r
346 if (!EFI_ERROR (Status) && LoadedImage != NULL) {\r
347 //\r
348 // Get Module Guid from DevicePath.\r
349 //\r
350 if (LoadedImage->FilePath != NULL &&\r
351 LoadedImage->FilePath->Type == MEDIA_DEVICE_PATH &&\r
352 LoadedImage->FilePath->SubType == MEDIA_PIWG_FW_FILE_DP\r
353 ) {\r
354 //\r
355 // Determine GUID associated with module logging performance\r
356 //\r
357 ModuleGuidIsGet = TRUE;\r
358 FvFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LoadedImage->FilePath;\r
359 TempGuid = &FvFilePath->FvFileName;\r
360 }\r
361\r
362 //\r
363 // Method 1 Get Module Name from PDB string.\r
364 //\r
365 PdbFileName = PeCoffLoaderGetPdbPointer (LoadedImage->ImageBase);\r
366 if (PdbFileName != NULL && BufferSize > 0) {\r
367 StartIndex = 0;\r
368 for (Index = 0; PdbFileName[Index] != 0; Index++) {\r
369 if ((PdbFileName[Index] == '\\') || (PdbFileName[Index] == '/')) {\r
370 StartIndex = Index + 1;\r
371 }\r
372 }\r
373 //\r
374 // Copy the PDB file name to our temporary string.\r
375 // If the length is bigger than BufferSize, trim the redudant characters to avoid overflow in array boundary.\r
376 //\r
377 for (Index = 0; Index < BufferSize - 1; Index++) {\r
378 NameString[Index] = PdbFileName[Index + StartIndex];\r
379 if (NameString[Index] == 0 || NameString[Index] == '.') {\r
380 NameString[Index] = 0;\r
381 break;\r
382 }\r
383 }\r
384\r
385 if (Index == BufferSize - 1) {\r
386 NameString[Index] = 0;\r
387 }\r
388 //\r
389 // Module Name is got.\r
390 //\r
391 goto Done;\r
392 }\r
393 }\r
394\r
395 if (ModuleGuidIsGet) {\r
396 //\r
397 // Method 2 Try to get the image's FFS UI section by image GUID\r
398 //\r
399 StringPtr = NULL;\r
400 StringSize = 0;\r
401 Status = GetSectionFromAnyFv (\r
402 TempGuid,\r
403 EFI_SECTION_USER_INTERFACE,\r
404 0,\r
405 (VOID **) &StringPtr,\r
406 &StringSize\r
407 );\r
408\r
409 if (!EFI_ERROR (Status)) {\r
410 //\r
411 // Method 3. Get the name string from FFS UI section\r
412 //\r
413 for (Index = 0; Index < BufferSize - 1 && StringPtr[Index] != 0; Index++) {\r
414 NameString[Index] = (CHAR8) StringPtr[Index];\r
415 }\r
416 NameString[Index] = 0;\r
417 FreePool (StringPtr);\r
418 }\r
419 }\r
420\r
421Done:\r
422 //\r
423 // Copy Module Guid\r
424 //\r
425 if (ModuleGuid != NULL) {\r
426 CopyGuid (ModuleGuid, TempGuid);\r
427 if (IsZeroGuid(TempGuid) && (Handle != NULL) && !ModuleGuidIsGet) {\r
428 // Handle is GUID\r
429 CopyGuid (ModuleGuid, (EFI_GUID *) Handle);\r
430 }\r
431 }\r
432\r
433 //\r
434 // Cache the Handle and Guid pairs.\r
435 //\r
436 if (mCachePairCount < CACHE_HANDLE_GUID_COUNT) {\r
437 mCacheHandleGuidTable[mCachePairCount].Handle = Handle;\r
438 CopyGuid (&mCacheHandleGuidTable[mCachePairCount].ModuleGuid, ModuleGuid);\r
439 AsciiStrCpyS (mCacheHandleGuidTable[mCachePairCount].NameString, FPDT_STRING_EVENT_RECORD_NAME_LENGTH, NameString);\r
440 mCachePairCount ++;\r
441 }\r
442\r
443 return Status;\r
444}\r
445\r
446/**\r
447 Add performance log to FPDT boot record table.\r
448\r
449 @param IsStart TRUE if the performance log is start log.\r
d042c6e8 450 @param Handle Pointer to environment specific context used\r
451 to identify the component being measured.\r
452 @param Token Pointer to a Null-terminated ASCII string\r
453 that identifies the component being measured.\r
454 @param Module Pointer to a Null-terminated ASCII string\r
455 that identifies the module being measured.\r
2001f84e 456 @param Ticker 64-bit time stamp.\r
f0da4d7d
SZ
457 @param Identifier 32-bit identifier. If the value is 0, the created record\r
458 is same as the one created by StartGauge of PERFORMANCE_PROTOCOL.\r
d042c6e8 459\r
2001f84e 460 @retval EFI_SUCCESS Add FPDT boot record.\r
d042c6e8 461 @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement.\r
2001f84e 462 @retval EFI_UNSUPPORTED No matched FPDT record.\r
d042c6e8 463\r
464**/\r
465EFI_STATUS\r
2001f84e
DB
466InsertFpdtMeasurement (\r
467 IN BOOLEAN IsStart,\r
d042c6e8 468 IN CONST VOID *Handle, OPTIONAL\r
469 IN CONST CHAR8 *Token, OPTIONAL\r
470 IN CONST CHAR8 *Module, OPTIONAL\r
2001f84e 471 IN UINT64 Ticker,\r
f0da4d7d 472 IN UINT32 Identifier\r
d042c6e8 473 )\r
474{\r
2001f84e
DB
475 EFI_GUID ModuleGuid;\r
476 CHAR8 ModuleName[FPDT_STRING_EVENT_RECORD_NAME_LENGTH];\r
477 EFI_STATUS Status;\r
478 FPDT_RECORD_PTR FpdtRecordPtr;\r
479 UINT64 TimeStamp;\r
480 FPDT_BASIC_RECORD_INFO RecordInfo;\r
481 UINTN DestMax;\r
482 UINTN StrLength;\r
483 CONST CHAR8 *StringPtr;\r
484 BOOLEAN UseModuleName;\r
485\r
486 StringPtr = NULL;\r
487 UseModuleName = FALSE;\r
488 ZeroMem (ModuleName, sizeof (ModuleName));\r
d042c6e8 489\r
2001f84e
DB
490 //\r
491 // Get record info includes type, size, ProgressID.\r
492 //\r
493 Status = GetFpdtRecordInfo (IsStart, Handle, Token, Module, &RecordInfo, &UseModuleName);\r
494 if (EFI_ERROR (Status)) {\r
495 return Status;\r
496 }\r
d042c6e8 497\r
2001f84e
DB
498 //\r
499 // If PERF_START()/PERF_END() have specified the ProgressID,it has high priority.\r
500 // !!! Note: If the Pref is not the known Token used in the core but have same\r
501 // ID with the core Token, this case will not be supported.\r
502 // And in currtnt usage mode, for the unkown ID, there is a general rule:\r
503 // If it is start pref: the lower 4 bits of the ID should be 0.\r
504 // If it is end pref: the lower 4 bits of the ID should not be 0.\r
505 // If input ID doesn't follow the rule, we will adjust it.\r
506 //\r
507 if ((Identifier != 0) && (IsKnownID (Identifier)) && (!IsKnownTokens (Token))) {\r
508 return EFI_UNSUPPORTED;\r
509 } else if ((Identifier != 0) && (!IsKnownID (Identifier)) && (!IsKnownTokens (Token))) {\r
510 if (IsStart && ((Identifier & 0x000F) != 0)) {\r
511 Identifier &= 0xFFF0;\r
512 } else if ((!IsStart) && ((Identifier & 0x000F) == 0)) {\r
513 Identifier += 1;\r
514 }\r
515 RecordInfo.ProgressID = (UINT16)Identifier;\r
516 }\r
517\r
518 if (mFpdtDataIsReported) {\r
d042c6e8 519 //\r
2001f84e 520 // Append Boot records after Smm boot performance records have been reported.\r
d042c6e8 521 //\r
2001f84e
DB
522 if (mPerformanceLength + RecordInfo.RecordSize > mMaxPerformanceLength) {\r
523 if (!mLackSpaceIsReport) {\r
524 DEBUG ((DEBUG_INFO, "SmmCorePerformanceLib: No enough space to save boot records\n"));\r
525 mLackSpaceIsReport = TRUE;\r
526 }\r
d042c6e8 527 return EFI_OUT_OF_RESOURCES;\r
2001f84e
DB
528 } else {\r
529 //\r
530 // Covert buffer to FPDT Ptr Union type.\r
531 //\r
532 FpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)((UINT8*)mSmmBootPerformanceTable + mSmmBootPerformanceTable->Header.Length);\r
533 }\r
534 } else {\r
535 //\r
536 // Check if pre-allocated buffer is full\r
537 //\r
538 if (mPerformanceLength + RecordInfo.RecordSize > mMaxPerformanceLength) {\r
539 mSmmBootPerformanceTable = ReallocatePool (\r
540 mPerformanceLength,\r
541 mPerformanceLength + sizeof (SMM_BOOT_PERFORMANCE_TABLE) + RecordInfo.RecordSize + FIRMWARE_RECORD_BUFFER,\r
542 mSmmBootPerformanceTable\r
543 );\r
544\r
545 if (mSmmBootPerformanceTable == NULL) {\r
546 return EFI_OUT_OF_RESOURCES;\r
547 }\r
548 mSmmBootPerformanceTable->Header.Length = sizeof (SMM_BOOT_PERFORMANCE_TABLE) + mPerformanceLength;\r
549 mMaxPerformanceLength = mPerformanceLength + sizeof (SMM_BOOT_PERFORMANCE_TABLE) + RecordInfo.RecordSize + FIRMWARE_RECORD_BUFFER;\r
d042c6e8 550 }\r
551 //\r
2001f84e 552 // Covert buffer to FPDT Ptr Union type.\r
d042c6e8 553 //\r
2001f84e
DB
554 FpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)((UINT8*)mSmmBootPerformanceTable + mSmmBootPerformanceTable->Header.Length);\r
555 }\r
556 FpdtRecordPtr.RecordHeader->Length = 0;\r
d042c6e8 557\r
2001f84e
DB
558 //\r
559 // Get the TimeStamp.\r
560 //\r
561 if (Ticker == 0) {\r
562 Ticker = GetPerformanceCounter ();\r
563 TimeStamp = GetTimeInNanoSecond (Ticker);\r
564 } else if (Ticker == 1) {\r
565 TimeStamp = 0;\r
566 } else {\r
567 TimeStamp = GetTimeInNanoSecond (Ticker);\r
d042c6e8 568 }\r
569\r
2001f84e
DB
570 //\r
571 // Get the ModuleName and ModuleGuid form the handle.\r
572 //\r
573 GetModuleInfoFromHandle ((EFI_HANDLE *)Handle, ModuleName, sizeof (ModuleName), &ModuleGuid);\r
d042c6e8 574\r
2001f84e
DB
575 //\r
576 // Fill in the record information.\r
577 //\r
578 switch (RecordInfo.Type) {\r
579 case FPDT_GUID_EVENT_TYPE:\r
580 FpdtRecordPtr.GuidEvent->Header.Type = FPDT_GUID_EVENT_TYPE;\r
581 FpdtRecordPtr.GuidEvent->Header.Length = RecordInfo.RecordSize;\r
582 FpdtRecordPtr.GuidEvent->Header.Revision = FPDT_RECORD_REVISION_1;\r
583 FpdtRecordPtr.GuidEvent->ProgressID = RecordInfo.ProgressID;\r
584 FpdtRecordPtr.GuidEvent->Timestamp = TimeStamp;\r
585 CopyMem (&FpdtRecordPtr.GuidEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidEvent->Guid));\r
586 break;\r
587\r
588 case FPDT_DYNAMIC_STRING_EVENT_TYPE:\r
589 FpdtRecordPtr.DynamicStringEvent->Header.Type = FPDT_DYNAMIC_STRING_EVENT_TYPE;\r
590 FpdtRecordPtr.DynamicStringEvent->Header.Length = RecordInfo.RecordSize;\r
591 FpdtRecordPtr.DynamicStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;\r
592 FpdtRecordPtr.DynamicStringEvent->ProgressID = RecordInfo.ProgressID;\r
593 FpdtRecordPtr.DynamicStringEvent->Timestamp = TimeStamp;\r
594 CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));\r
595\r
596 if (UseModuleName) {\r
597 StringPtr = ModuleName;\r
598 } else if (Token != NULL) {\r
599 StringPtr = Token;\r
600 } else if (Module != NULL) {\r
601 StringPtr = Module;\r
602 } else if (ModuleName != NULL) {\r
603 StringPtr = ModuleName;\r
604 }\r
605 if (StringPtr != NULL && AsciiStrLen (StringPtr) != 0) {\r
606 StrLength = AsciiStrLen (StringPtr);\r
607 DestMax = (RecordInfo.RecordSize - sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD)) / sizeof (CHAR8);\r
608 if (StrLength >= DestMax) {\r
609 StrLength = DestMax -1;\r
610 }\r
611 AsciiStrnCpyS (FpdtRecordPtr.DynamicStringEvent->String, DestMax, StringPtr, StrLength);\r
612 } else {\r
613 AsciiStrCpyS (FpdtRecordPtr.DynamicStringEvent->String, FPDT_STRING_EVENT_RECORD_NAME_LENGTH, "unknown name");\r
614 }\r
615 break;\r
616\r
617 case FPDT_GUID_QWORD_EVENT_TYPE:\r
618 FpdtRecordPtr.GuidQwordEvent->Header.Type = FPDT_GUID_QWORD_EVENT_TYPE;\r
619 FpdtRecordPtr.GuidQwordEvent->Header.Length = RecordInfo.RecordSize;\r
620 FpdtRecordPtr.GuidQwordEvent->Header.Revision = FPDT_RECORD_REVISION_1;\r
621 FpdtRecordPtr.GuidQwordEvent->ProgressID = RecordInfo.ProgressID;\r
622 FpdtRecordPtr.GuidQwordEvent->Timestamp = TimeStamp;\r
623 CopyMem (&FpdtRecordPtr.GuidQwordEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidQwordEvent->Guid));\r
624 break;\r
625\r
626 default:\r
627 //\r
628 // Record is not supported in current SMM phase, return EFI_UNSUPPORTED\r
629 //\r
630 return EFI_UNSUPPORTED;\r
d042c6e8 631 }\r
632\r
2001f84e
DB
633 //\r
634 // Update the cached FPDT record buffer.\r
635 //\r
636 mPerformanceLength += FpdtRecordPtr.RecordHeader->Length;\r
637 mSmmBootPerformanceTable->Header.Length += FpdtRecordPtr.RecordHeader->Length;\r
f0da4d7d 638\r
2001f84e
DB
639 return EFI_SUCCESS;\r
640}\r
d042c6e8 641\r
2001f84e
DB
642/**\r
643 Adds a record at the end of the performance measurement log\r
644 that records the start time of a performance measurement.\r
d042c6e8 645\r
2001f84e
DB
646 Adds a record to the end of the performance measurement log\r
647 that contains the Handle, Token, Module and Identifier.\r
648 The end time of the new record must be set to zero.\r
649 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.\r
650 If TimeStamp is zero, the start time in the record is filled in with the value\r
651 read from the current time stamp.\r
d042c6e8 652\r
2001f84e
DB
653 @param Handle Pointer to environment specific context used\r
654 to identify the component being measured.\r
655 @param Token Pointer to a Null-terminated ASCII string\r
656 that identifies the component being measured.\r
657 @param Module Pointer to a Null-terminated ASCII string\r
658 that identifies the module being measured.\r
659 @param TimeStamp 64-bit time stamp.\r
660 @param Identifier 32-bit identifier. If the value is 0, the created record\r
661 is same as the one created by StartGauge of PERFORMANCE_PROTOCOL.\r
662\r
663 @retval EFI_SUCCESS The data was read correctly from the device.\r
664 @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement.\r
665\r
666**/\r
667EFI_STATUS\r
668EFIAPI\r
669StartGaugeEx (\r
670 IN CONST VOID *Handle, OPTIONAL\r
671 IN CONST CHAR8 *Token, OPTIONAL\r
672 IN CONST CHAR8 *Module, OPTIONAL\r
673 IN UINT64 TimeStamp,\r
674 IN UINT32 Identifier\r
675 )\r
676{\r
677 EFI_STATUS Status;\r
678\r
679 AcquireSpinLock (&mSmmFpdtLock);\r
680\r
681 Status = InsertFpdtMeasurement (TRUE, Handle, Token, Module, TimeStamp, Identifier);\r
682\r
683 ReleaseSpinLock (&mSmmFpdtLock);\r
684\r
685 return Status;\r
d042c6e8 686}\r
687\r
688/**\r
689 Searches the performance measurement log from the beginning of the log\r
690 for the first matching record that contains a zero end time and fills in a valid end time.\r
691\r
692 Searches the performance measurement log from the beginning of the log\r
2001f84e 693 for the first record that matches Handle, Token, Module and Identifier and has an end time value of zero.\r
d042c6e8 694 If the record can not be found then return EFI_NOT_FOUND.\r
695 If the record is found and TimeStamp is not zero,\r
696 then the end time in the record is filled in with the value specified by TimeStamp.\r
697 If the record is found and TimeStamp is zero, then the end time in the matching record\r
698 is filled in with the current time stamp value.\r
699\r
700 @param Handle Pointer to environment specific context used\r
701 to identify the component being measured.\r
702 @param Token Pointer to a Null-terminated ASCII string\r
703 that identifies the component being measured.\r
704 @param Module Pointer to a Null-terminated ASCII string\r
705 that identifies the module being measured.\r
706 @param TimeStamp 64-bit time stamp.\r
f0da4d7d
SZ
707 @param Identifier 32-bit identifier. If the value is 0, the found record\r
708 is same as the one found by EndGauge of PERFORMANCE_PROTOCOL.\r
d042c6e8 709\r
710 @retval EFI_SUCCESS The end of the measurement was recorded.\r
711 @retval EFI_NOT_FOUND The specified measurement record could not be found.\r
712\r
713**/\r
714EFI_STATUS\r
715EFIAPI\r
f0da4d7d 716EndGaugeEx (\r
d042c6e8 717 IN CONST VOID *Handle, OPTIONAL\r
718 IN CONST CHAR8 *Token, OPTIONAL\r
719 IN CONST CHAR8 *Module, OPTIONAL\r
f0da4d7d
SZ
720 IN UINT64 TimeStamp,\r
721 IN UINT32 Identifier\r
d042c6e8 722 )\r
723{\r
2001f84e 724 EFI_STATUS Status;\r
f0da4d7d 725\r
2001f84e 726 AcquireSpinLock (&mSmmFpdtLock);\r
d042c6e8 727\r
2001f84e 728 Status = InsertFpdtMeasurement (FALSE, Handle, Token, Module, TimeStamp, Identifier);\r
d042c6e8 729\r
2001f84e 730 ReleaseSpinLock (&mSmmFpdtLock);\r
d042c6e8 731\r
2001f84e 732 return Status;\r
d042c6e8 733}\r
734\r
735/**\r
736 Retrieves a previously logged performance measurement.\r
f0da4d7d
SZ
737 It can also retrieve the log created by StartGauge and EndGauge of PERFORMANCE_PROTOCOL,\r
738 and then assign the Identifier with 0.\r
d042c6e8 739\r
2001f84e
DB
740 !!! Not Support!!!\r
741\r
d042c6e8 742 Retrieves the performance log entry from the performance log specified by LogEntryKey.\r
743 If it stands for a valid entry, then EFI_SUCCESS is returned and\r
f0da4d7d 744 GaugeDataEntryEx stores the pointer to that entry.\r
d042c6e8 745\r
746 @param LogEntryKey The key for the previous performance measurement log entry.\r
747 If 0, then the first performance measurement log entry is retrieved.\r
f0da4d7d 748 @param GaugeDataEntryEx The indirect pointer to the extended gauge data entry specified by LogEntryKey\r
d042c6e8 749 if the retrieval is successful.\r
750\r
f0da4d7d 751 @retval EFI_SUCCESS The GuageDataEntryEx is successfully found based on LogEntryKey.\r
d042c6e8 752 @retval EFI_NOT_FOUND The LogEntryKey is the last entry (equals to the total entry number).\r
753 @retval EFI_INVALIDE_PARAMETER The LogEntryKey is not a valid entry (greater than the total entry number).\r
f0da4d7d 754 @retval EFI_INVALIDE_PARAMETER GaugeDataEntryEx is NULL.\r
d042c6e8 755\r
756**/\r
757EFI_STATUS\r
758EFIAPI\r
f0da4d7d
SZ
759GetGaugeEx (\r
760 IN UINTN LogEntryKey,\r
761 OUT GAUGE_DATA_ENTRY_EX **GaugeDataEntryEx\r
d042c6e8 762 )\r
763{\r
2001f84e 764 return EFI_UNSUPPORTED;\r
d042c6e8 765}\r
766\r
f0da4d7d
SZ
767/**\r
768 Adds a record at the end of the performance measurement log\r
769 that records the start time of a performance measurement.\r
770\r
771 Adds a record to the end of the performance measurement log\r
772 that contains the Handle, Token, and Module.\r
773 The end time of the new record must be set to zero.\r
774 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.\r
775 If TimeStamp is zero, the start time in the record is filled in with the value\r
776 read from the current time stamp.\r
777\r
778 @param Handle Pointer to environment specific context used\r
779 to identify the component being measured.\r
780 @param Token Pointer to a Null-terminated ASCII string\r
781 that identifies the component being measured.\r
782 @param Module Pointer to a Null-terminated ASCII string\r
783 that identifies the module being measured.\r
784 @param TimeStamp 64-bit time stamp.\r
785\r
786 @retval EFI_SUCCESS The data was read correctly from the device.\r
787 @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement.\r
788\r
789**/\r
790EFI_STATUS\r
791EFIAPI\r
792StartGauge (\r
793 IN CONST VOID *Handle, OPTIONAL\r
794 IN CONST CHAR8 *Token, OPTIONAL\r
795 IN CONST CHAR8 *Module, OPTIONAL\r
796 IN UINT64 TimeStamp\r
797 )\r
798{\r
799 return StartGaugeEx (Handle, Token, Module, TimeStamp, 0);\r
800}\r
801\r
802/**\r
803 Searches the performance measurement log from the beginning of the log\r
804 for the first matching record that contains a zero end time and fills in a valid end time.\r
805\r
806 Searches the performance measurement log from the beginning of the log\r
807 for the first record that matches Handle, Token, and Module and has an end time value of zero.\r
808 If the record can not be found then return EFI_NOT_FOUND.\r
809 If the record is found and TimeStamp is not zero,\r
810 then the end time in the record is filled in with the value specified by TimeStamp.\r
811 If the record is found and TimeStamp is zero, then the end time in the matching record\r
812 is filled in with the current time stamp value.\r
813\r
814 @param Handle Pointer to environment specific context used\r
815 to identify the component being measured.\r
816 @param Token Pointer to a Null-terminated ASCII string\r
817 that identifies the component being measured.\r
818 @param Module Pointer to a Null-terminated ASCII string\r
819 that identifies the module being measured.\r
820 @param TimeStamp 64-bit time stamp.\r
821\r
822 @retval EFI_SUCCESS The end of the measurement was recorded.\r
823 @retval EFI_NOT_FOUND The specified measurement record could not be found.\r
824\r
825**/\r
826EFI_STATUS\r
827EFIAPI\r
828EndGauge (\r
829 IN CONST VOID *Handle, OPTIONAL\r
830 IN CONST CHAR8 *Token, OPTIONAL\r
831 IN CONST CHAR8 *Module, OPTIONAL\r
832 IN UINT64 TimeStamp\r
833 )\r
834{\r
835 return EndGaugeEx (Handle, Token, Module, TimeStamp, 0);\r
836}\r
837\r
838/**\r
839 Retrieves a previously logged performance measurement.\r
840 It can also retrieve the log created by StartGaugeEx and EndGaugeEx of PERFORMANCE_EX_PROTOCOL,\r
841 and then eliminate the Identifier.\r
842\r
2001f84e
DB
843 !!! Not Support!!!\r
844\r
f0da4d7d
SZ
845 Retrieves the performance log entry from the performance log specified by LogEntryKey.\r
846 If it stands for a valid entry, then EFI_SUCCESS is returned and\r
847 GaugeDataEntry stores the pointer to that entry.\r
848\r
849 @param LogEntryKey The key for the previous performance measurement log entry.\r
850 If 0, then the first performance measurement log entry is retrieved.\r
851 @param GaugeDataEntry The indirect pointer to the gauge data entry specified by LogEntryKey\r
852 if the retrieval is successful.\r
853\r
854 @retval EFI_SUCCESS The GuageDataEntry is successfully found based on LogEntryKey.\r
855 @retval EFI_NOT_FOUND The LogEntryKey is the last entry (equals to the total entry number).\r
856 @retval EFI_INVALIDE_PARAMETER The LogEntryKey is not a valid entry (greater than the total entry number).\r
857 @retval EFI_INVALIDE_PARAMETER GaugeDataEntry is NULL.\r
858\r
859**/\r
860EFI_STATUS\r
861EFIAPI\r
862GetGauge (\r
863 IN UINTN LogEntryKey,\r
864 OUT GAUGE_DATA_ENTRY **GaugeDataEntry\r
865 )\r
866{\r
2001f84e 867 return EFI_UNSUPPORTED;\r
f0da4d7d 868}\r
d042c6e8 869\r
ccd2f6b0 870\r
2001f84e
DB
871/**\r
872 SmmReadyToBoot protocol notification event handler.\r
f0da4d7d 873\r
2001f84e
DB
874 @param Protocol Points to the protocol's unique identifier\r
875 @param Interface Points to the interface instance\r
876 @param Handle The handle on which the interface was installed\r
ccd2f6b0 877\r
2001f84e 878 @retval EFI_SUCCESS SmmReadyToBootCallback runs successfully\r
f0da4d7d 879\r
d042c6e8 880**/\r
881EFI_STATUS\r
882EFIAPI\r
2001f84e
DB
883SmmReportFpdtRecordData (\r
884 IN CONST EFI_GUID *Protocol,\r
885 IN VOID *Interface,\r
886 IN EFI_HANDLE Handle\r
d042c6e8 887 )\r
888{\r
2001f84e
DB
889 UINT64 SmmBPDTddr;\r
890\r
891 if (!mFpdtDataIsReported && mSmmBootPerformanceTable != NULL) {\r
892 SmmBPDTddr = (UINT64)(UINTN)mSmmBootPerformanceTable;\r
893 REPORT_STATUS_CODE_EX (\r
894 EFI_PROGRESS_CODE,\r
895 EFI_SOFTWARE_SMM_DRIVER,\r
896 0,\r
897 NULL,\r
898 &gEdkiiFpdtExtendedFirmwarePerformanceGuid,\r
899 &SmmBPDTddr,\r
900 sizeof (UINT64)\r
901 );\r
902 //\r
903 // Set FPDT report state to TRUE.\r
904 //\r
905 mFpdtDataIsReported = TRUE;\r
f0da4d7d 906 }\r
d042c6e8 907 return EFI_SUCCESS;\r
908}\r
909\r
910/**\r
2001f84e
DB
911 SmmBase2 protocol notify callback function, when SMST and SMM memory service get initialized\r
912 this function is callbacked to initialize the Smm Performance Lib\r
d042c6e8 913\r
914 @param Event The event of notify protocol.\r
915 @param Context Notify event context.\r
916\r
917**/\r
918VOID\r
919EFIAPI\r
920InitializeSmmCorePerformanceLib (\r
921 IN EFI_EVENT Event,\r
922 IN VOID *Context\r
923 )\r
924{\r
d042c6e8 925 EFI_HANDLE Handle;\r
2001f84e
DB
926 EFI_STATUS Status;\r
927 VOID *SmmReadyToBootRegistration;\r
cfb0aba7 928 PERFORMANCE_PROPERTY *PerformanceProperty;\r
d042c6e8 929\r
930 //\r
931 // Initialize spin lock\r
932 //\r
2001f84e 933 InitializeSpinLock (&mSmmFpdtLock);\r
d042c6e8 934\r
d042c6e8 935 //\r
2001f84e 936 // Install the protocol interfaces for SMM performance library instance.\r
d042c6e8 937 //\r
2001f84e 938 Handle = NULL;\r
d042c6e8 939 Status = gSmst->SmmInstallProtocolInterface (\r
2001f84e 940 &Handle,\r
d042c6e8 941 &gSmmPerformanceProtocolGuid,\r
942 EFI_NATIVE_INTERFACE,\r
943 &mPerformanceInterface\r
944 );\r
945 ASSERT_EFI_ERROR (Status);\r
f0da4d7d 946 Status = gSmst->SmmInstallProtocolInterface (\r
2001f84e 947 &Handle,\r
f0da4d7d
SZ
948 &gSmmPerformanceExProtocolGuid,\r
949 EFI_NATIVE_INTERFACE,\r
950 &mPerformanceExInterface\r
951 );\r
952 ASSERT_EFI_ERROR (Status);\r
953\r
2001f84e
DB
954 Status = gSmst->SmmRegisterProtocolNotify (\r
955 &gEdkiiSmmReadyToBootProtocolGuid,\r
956 SmmReportFpdtRecordData,\r
957 &SmmReadyToBootRegistration\r
958 );\r
9802d6d5 959 Status = EfiGetSystemConfigurationTable (&gPerformanceProtocolGuid, (VOID **) &PerformanceProperty);\r
cfb0aba7
SZ
960 if (EFI_ERROR (Status)) {\r
961 //\r
962 // Install configuration table for performance property.\r
963 //\r
964 mPerformanceProperty.Revision = PERFORMANCE_PROPERTY_REVISION;\r
965 mPerformanceProperty.Reserved = 0;\r
966 mPerformanceProperty.Frequency = GetPerformanceCounterProperties (\r
967 &mPerformanceProperty.TimerStartValue,\r
968 &mPerformanceProperty.TimerEndValue\r
969 );\r
970 Status = gBS->InstallConfigurationTable (&gPerformanceProtocolGuid, &mPerformanceProperty);\r
971 ASSERT_EFI_ERROR (Status);\r
972 }\r
d042c6e8 973}\r
974\r
975/**\r
2001f84e 976 The constructor function initializes the Performance Measurement Enable flag and\r
f0da4d7d 977 registers SmmBase2 protocol notify callback.\r
d042c6e8 978 It will ASSERT() if one of these operations fails and it will always return EFI_SUCCESS.\r
979\r
980 @param ImageHandle The firmware allocated handle for the EFI image.\r
981 @param SystemTable A pointer to the EFI System Table.\r
982\r
983 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.\r
984\r
985**/\r
986EFI_STATUS\r
987EFIAPI\r
988SmmCorePerformanceLibConstructor (\r
989 IN EFI_HANDLE ImageHandle,\r
990 IN EFI_SYSTEM_TABLE *SystemTable\r
991 )\r
992{\r
993 EFI_STATUS Status;\r
994 EFI_EVENT Event;\r
995 VOID *Registration;\r
996\r
2001f84e 997 if (!PerformanceMeasurementEnabled ()) {\r
d042c6e8 998 //\r
999 // Do not initialize performance infrastructure if not required.\r
1000 //\r
1001 return EFI_SUCCESS;\r
1002 }\r
1003\r
1004 //\r
1005 // Create the events to do the library init.\r
1006 //\r
1007 Status = gBS->CreateEvent (\r
1008 EVT_NOTIFY_SIGNAL,\r
1009 TPL_CALLBACK,\r
1010 InitializeSmmCorePerformanceLib,\r
1011 NULL,\r
1012 &Event\r
1013 );\r
1014 ASSERT_EFI_ERROR (Status);\r
1015\r
1016 //\r
1017 // Register for protocol notifications on this event\r
1018 //\r
1019 Status = gBS->RegisterProtocolNotify (\r
1020 &gEfiSmmBase2ProtocolGuid,\r
1021 Event,\r
1022 &Registration\r
1023 );\r
1024\r
1025 ASSERT_EFI_ERROR (Status);\r
1026\r
1027 return EFI_SUCCESS;\r
1028}\r
1029\r
1030/**\r
1031 Adds a record at the end of the performance measurement log\r
1032 that records the start time of a performance measurement.\r
1033\r
1034 Adds a record to the end of the performance measurement log\r
f0da4d7d 1035 that contains the Handle, Token, Module and Identifier.\r
d042c6e8 1036 The end time of the new record must be set to zero.\r
1037 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.\r
1038 If TimeStamp is zero, the start time in the record is filled in with the value\r
1039 read from the current time stamp.\r
1040\r
1041 @param Handle Pointer to environment specific context used\r
1042 to identify the component being measured.\r
1043 @param Token Pointer to a Null-terminated ASCII string\r
1044 that identifies the component being measured.\r
1045 @param Module Pointer to a Null-terminated ASCII string\r
1046 that identifies the module being measured.\r
1047 @param TimeStamp 64-bit time stamp.\r
f0da4d7d
SZ
1048 @param Identifier 32-bit identifier. If the value is 0, the created record\r
1049 is same as the one created by StartPerformanceMeasurement.\r
d042c6e8 1050\r
1051 @retval RETURN_SUCCESS The start of the measurement was recorded.\r
1052 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.\r
1053\r
1054**/\r
1055RETURN_STATUS\r
1056EFIAPI\r
f0da4d7d 1057StartPerformanceMeasurementEx (\r
d042c6e8 1058 IN CONST VOID *Handle, OPTIONAL\r
1059 IN CONST CHAR8 *Token, OPTIONAL\r
1060 IN CONST CHAR8 *Module, OPTIONAL\r
f0da4d7d
SZ
1061 IN UINT64 TimeStamp,\r
1062 IN UINT32 Identifier\r
d042c6e8 1063 )\r
1064{\r
f0da4d7d 1065 return (RETURN_STATUS) StartGaugeEx (Handle, Token, Module, TimeStamp, Identifier);\r
d042c6e8 1066}\r
1067\r
1068/**\r
1069 Searches the performance measurement log from the beginning of the log\r
1070 for the first matching record that contains a zero end time and fills in a valid end time.\r
1071\r
1072 Searches the performance measurement log from the beginning of the log\r
2001f84e 1073 for the first record that matches Handle, Token, Module and Identifier and has an end time value of zero.\r
d042c6e8 1074 If the record can not be found then return RETURN_NOT_FOUND.\r
1075 If the record is found and TimeStamp is not zero,\r
1076 then the end time in the record is filled in with the value specified by TimeStamp.\r
1077 If the record is found and TimeStamp is zero, then the end time in the matching record\r
1078 is filled in with the current time stamp value.\r
1079\r
1080 @param Handle Pointer to environment specific context used\r
1081 to identify the component being measured.\r
1082 @param Token Pointer to a Null-terminated ASCII string\r
1083 that identifies the component being measured.\r
1084 @param Module Pointer to a Null-terminated ASCII string\r
1085 that identifies the module being measured.\r
1086 @param TimeStamp 64-bit time stamp.\r
f0da4d7d
SZ
1087 @param Identifier 32-bit identifier. If the value is 0, the found record\r
1088 is same as the one found by EndPerformanceMeasurement.\r
d042c6e8 1089\r
1090 @retval RETURN_SUCCESS The end of the measurement was recorded.\r
1091 @retval RETURN_NOT_FOUND The specified measurement record could not be found.\r
1092\r
1093**/\r
1094RETURN_STATUS\r
1095EFIAPI\r
f0da4d7d 1096EndPerformanceMeasurementEx (\r
d042c6e8 1097 IN CONST VOID *Handle, OPTIONAL\r
1098 IN CONST CHAR8 *Token, OPTIONAL\r
1099 IN CONST CHAR8 *Module, OPTIONAL\r
f0da4d7d
SZ
1100 IN UINT64 TimeStamp,\r
1101 IN UINT32 Identifier\r
d042c6e8 1102 )\r
1103{\r
f0da4d7d 1104 return (RETURN_STATUS) EndGaugeEx (Handle, Token, Module, TimeStamp, Identifier);\r
d042c6e8 1105}\r
1106\r
1107/**\r
1108 Attempts to retrieve a performance measurement log entry from the performance measurement log.\r
f0da4d7d
SZ
1109 It can also retrieve the log created by StartPerformanceMeasurement and EndPerformanceMeasurement,\r
1110 and then assign the Identifier with 0.\r
d042c6e8 1111\r
2001f84e
DB
1112 !!! Not Support!!!\r
1113\r
d042c6e8 1114 Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is\r
1115 zero on entry, then an attempt is made to retrieve the first entry from the performance log,\r
1116 and the key for the second entry in the log is returned. If the performance log is empty,\r
1117 then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance\r
1118 log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is\r
1119 returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is\r
1120 retrieved and an implementation specific non-zero key value that specifies the end of the performance\r
1121 log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry\r
1122 is retrieved and zero is returned. In the cases where a performance log entry can be returned,\r
f0da4d7d 1123 the log entry is returned in Handle, Token, Module, StartTimeStamp, EndTimeStamp and Identifier.\r
d042c6e8 1124 If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().\r
1125 If Handle is NULL, then ASSERT().\r
1126 If Token is NULL, then ASSERT().\r
1127 If Module is NULL, then ASSERT().\r
1128 If StartTimeStamp is NULL, then ASSERT().\r
1129 If EndTimeStamp is NULL, then ASSERT().\r
f0da4d7d 1130 If Identifier is NULL, then ASSERT().\r
d042c6e8 1131\r
1132 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.\r
1133 0, then the first performance measurement log entry is retrieved.\r
1134 On exit, the key of the next performance log entry.\r
1135 @param Handle Pointer to environment specific context used to identify the component\r
1136 being measured.\r
1137 @param Token Pointer to a Null-terminated ASCII string that identifies the component\r
1138 being measured.\r
1139 @param Module Pointer to a Null-terminated ASCII string that identifies the module\r
1140 being measured.\r
1141 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement\r
1142 was started.\r
1143 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement\r
1144 was ended.\r
f0da4d7d 1145 @param Identifier Pointer to the 32-bit identifier that was recorded.\r
d042c6e8 1146\r
1147 @return The key for the next performance log entry (in general case).\r
1148\r
1149**/\r
1150UINTN\r
1151EFIAPI\r
f0da4d7d 1152GetPerformanceMeasurementEx (\r
2001f84e 1153 IN UINTN LogEntryKey,\r
d042c6e8 1154 OUT CONST VOID **Handle,\r
1155 OUT CONST CHAR8 **Token,\r
1156 OUT CONST CHAR8 **Module,\r
1157 OUT UINT64 *StartTimeStamp,\r
f0da4d7d
SZ
1158 OUT UINT64 *EndTimeStamp,\r
1159 OUT UINT32 *Identifier\r
d042c6e8 1160 )\r
1161{\r
2001f84e 1162 return 0;\r
d042c6e8 1163}\r
1164\r
f0da4d7d
SZ
1165/**\r
1166 Adds a record at the end of the performance measurement log\r
1167 that records the start time of a performance measurement.\r
1168\r
1169 Adds a record to the end of the performance measurement log\r
1170 that contains the Handle, Token, and Module.\r
1171 The end time of the new record must be set to zero.\r
1172 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.\r
1173 If TimeStamp is zero, the start time in the record is filled in with the value\r
1174 read from the current time stamp.\r
1175\r
1176 @param Handle Pointer to environment specific context used\r
1177 to identify the component being measured.\r
1178 @param Token Pointer to a Null-terminated ASCII string\r
1179 that identifies the component being measured.\r
1180 @param Module Pointer to a Null-terminated ASCII string\r
1181 that identifies the module being measured.\r
1182 @param TimeStamp 64-bit time stamp.\r
1183\r
1184 @retval RETURN_SUCCESS The start of the measurement was recorded.\r
1185 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.\r
1186\r
1187**/\r
1188RETURN_STATUS\r
1189EFIAPI\r
1190StartPerformanceMeasurement (\r
1191 IN CONST VOID *Handle, OPTIONAL\r
1192 IN CONST CHAR8 *Token, OPTIONAL\r
1193 IN CONST CHAR8 *Module, OPTIONAL\r
1194 IN UINT64 TimeStamp\r
1195 )\r
1196{\r
2001f84e 1197 return StartGaugeEx (Handle, Token, Module, TimeStamp, 0);\r
f0da4d7d
SZ
1198}\r
1199\r
1200/**\r
1201 Searches the performance measurement log from the beginning of the log\r
1202 for the first matching record that contains a zero end time and fills in a valid end time.\r
1203\r
1204 Searches the performance measurement log from the beginning of the log\r
1205 for the first record that matches Handle, Token, and Module and has an end time value of zero.\r
1206 If the record can not be found then return RETURN_NOT_FOUND.\r
1207 If the record is found and TimeStamp is not zero,\r
1208 then the end time in the record is filled in with the value specified by TimeStamp.\r
1209 If the record is found and TimeStamp is zero, then the end time in the matching record\r
1210 is filled in with the current time stamp value.\r
1211\r
1212 @param Handle Pointer to environment specific context used\r
1213 to identify the component being measured.\r
1214 @param Token Pointer to a Null-terminated ASCII string\r
1215 that identifies the component being measured.\r
1216 @param Module Pointer to a Null-terminated ASCII string\r
1217 that identifies the module being measured.\r
1218 @param TimeStamp 64-bit time stamp.\r
1219\r
1220 @retval RETURN_SUCCESS The end of the measurement was recorded.\r
1221 @retval RETURN_NOT_FOUND The specified measurement record could not be found.\r
1222\r
1223**/\r
1224RETURN_STATUS\r
1225EFIAPI\r
1226EndPerformanceMeasurement (\r
1227 IN CONST VOID *Handle, OPTIONAL\r
1228 IN CONST CHAR8 *Token, OPTIONAL\r
1229 IN CONST CHAR8 *Module, OPTIONAL\r
1230 IN UINT64 TimeStamp\r
1231 )\r
1232{\r
2001f84e 1233 return EndGaugeEx (Handle, Token, Module, TimeStamp, 0);\r
f0da4d7d
SZ
1234}\r
1235\r
1236/**\r
1237 Attempts to retrieve a performance measurement log entry from the performance measurement log.\r
1238 It can also retrieve the log created by StartPerformanceMeasurementEx and EndPerformanceMeasurementEx,\r
1239 and then eliminate the Identifier.\r
1240\r
2001f84e
DB
1241 !!! Not Support!!!\r
1242\r
f0da4d7d
SZ
1243 Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is\r
1244 zero on entry, then an attempt is made to retrieve the first entry from the performance log,\r
1245 and the key for the second entry in the log is returned. If the performance log is empty,\r
1246 then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance\r
1247 log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is\r
1248 returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is\r
1249 retrieved and an implementation specific non-zero key value that specifies the end of the performance\r
1250 log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry\r
1251 is retrieved and zero is returned. In the cases where a performance log entry can be returned,\r
1252 the log entry is returned in Handle, Token, Module, StartTimeStamp, and EndTimeStamp.\r
1253 If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().\r
1254 If Handle is NULL, then ASSERT().\r
1255 If Token is NULL, then ASSERT().\r
1256 If Module is NULL, then ASSERT().\r
1257 If StartTimeStamp is NULL, then ASSERT().\r
1258 If EndTimeStamp is NULL, then ASSERT().\r
1259\r
1260 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.\r
1261 0, then the first performance measurement log entry is retrieved.\r
1262 On exit, the key of the next performance log entry.\r
1263 @param Handle Pointer to environment specific context used to identify the component\r
1264 being measured.\r
1265 @param Token Pointer to a Null-terminated ASCII string that identifies the component\r
1266 being measured.\r
1267 @param Module Pointer to a Null-terminated ASCII string that identifies the module\r
1268 being measured.\r
1269 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement\r
1270 was started.\r
1271 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement\r
1272 was ended.\r
1273\r
1274 @return The key for the next performance log entry (in general case).\r
1275\r
1276**/\r
1277UINTN\r
1278EFIAPI\r
1279GetPerformanceMeasurement (\r
1280 IN UINTN LogEntryKey,\r
1281 OUT CONST VOID **Handle,\r
1282 OUT CONST CHAR8 **Token,\r
1283 OUT CONST CHAR8 **Module,\r
1284 OUT UINT64 *StartTimeStamp,\r
1285 OUT UINT64 *EndTimeStamp\r
1286 )\r
1287{\r
2001f84e 1288 return 0;\r
f0da4d7d
SZ
1289}\r
1290\r
d042c6e8 1291/**\r
1292 Returns TRUE if the performance measurement macros are enabled.\r
1293\r
1294 This function returns TRUE if the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of\r
1295 PcdPerformanceLibraryPropertyMask is set. Otherwise FALSE is returned.\r
1296\r
1297 @retval TRUE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of\r
1298 PcdPerformanceLibraryPropertyMask is set.\r
1299 @retval FALSE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of\r
1300 PcdPerformanceLibraryPropertyMask is clear.\r
1301\r
1302**/\r
1303BOOLEAN\r
1304EFIAPI\r
1305PerformanceMeasurementEnabled (\r
1306 VOID\r
1307 )\r
1308{\r
2001f84e 1309 return (BOOLEAN) ((PcdGet8(PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0);\r
d042c6e8 1310}\r