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