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