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