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