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