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