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