]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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
d1102dba 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
466ebdd2 13Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>\r
7c50b343 14(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
9d510e61 15SPDX-License-Identifier: BSD-2-Clause-Patent\r
a0afd019 16\r
8dbae30d 17**/\r
a0afd019 18\r
aa79b0b3 19#include "DxeCorePerformanceLibInternal.h"\r
ed7748fe 20\r
a0afd019 21//\r
9609d24b 22// Data for FPDT performance records.\r
a0afd019 23//\r
1436aea4
MK
24#define SMM_BOOT_RECORD_COMM_SIZE (OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data) + sizeof(SMM_BOOT_RECORD_COMMUNICATE))\r
25#define STRING_SIZE (FPDT_STRING_EVENT_RECORD_NAME_LENGTH * sizeof (CHAR8))\r
26#define FIRMWARE_RECORD_BUFFER 0x10000\r
27#define CACHE_HANDLE_GUID_COUNT 0x800\r
9609d24b 28\r
1436aea4
MK
29BOOT_PERFORMANCE_TABLE *mAcpiBootPerformanceTable = NULL;\r
30BOOT_PERFORMANCE_TABLE mBootPerformanceTableTemplate = {\r
9609d24b
DB
31 {\r
32 EFI_ACPI_5_0_FPDT_BOOT_PERFORMANCE_TABLE_SIGNATURE,\r
33 sizeof (BOOT_PERFORMANCE_TABLE)\r
34 },\r
35 {\r
36 {\r
37 EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_TYPE_FIRMWARE_BASIC_BOOT, // Type\r
38 sizeof (EFI_ACPI_5_0_FPDT_FIRMWARE_BASIC_BOOT_RECORD), // Length\r
39 EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_REVISION_FIRMWARE_BASIC_BOOT // Revision\r
40 },\r
41 0, // Reserved\r
42 //\r
43 // These values will be updated at runtime.\r
44 //\r
45 0, // ResetEnd\r
46 0, // OsLoaderLoadImageStart\r
47 0, // OsLoaderStartImageStart\r
48 0, // ExitBootServicesEntry\r
49 0 // ExitBootServicesExit\r
50 }\r
51};\r
857dfc45 52\r
9609d24b
DB
53typedef struct {\r
54 EFI_HANDLE Handle;\r
55 CHAR8 NameString[FPDT_STRING_EVENT_RECORD_NAME_LENGTH];\r
56 EFI_GUID ModuleGuid;\r
57} HANDLE_GUID_MAP;\r
a0afd019 58\r
1436aea4
MK
59HANDLE_GUID_MAP mCacheHandleGuidTable[CACHE_HANDLE_GUID_COUNT];\r
60UINTN mCachePairCount = 0;\r
9609d24b
DB
61\r
62UINT32 mLoadImageCount = 0;\r
63UINT32 mPerformanceLength = 0;\r
64UINT32 mMaxPerformanceLength = 0;\r
65UINT32 mBootRecordSize = 0;\r
466ebdd2 66UINTN mBootRecordMaxSize = 0;\r
6b4d58a1 67UINT32 mCachedLength = 0;\r
9609d24b 68\r
1436aea4
MK
69BOOLEAN mFpdtBufferIsReported = FALSE;\r
70BOOLEAN mLackSpaceIsReported = FALSE;\r
71CHAR8 *mPlatformLanguage = NULL;\r
72UINT8 *mPerformancePointer = NULL;\r
73UINT8 *mBootRecordBuffer = NULL;\r
74BOOLEAN mLockInsertRecord = FALSE;\r
75CHAR8 *mDevicePathString = NULL;\r
9609d24b
DB
76\r
77EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *mDevicePathToText = NULL;\r
857dfc45 78\r
79//\r
137fb13d 80// Interfaces for PerformanceMeasurement Protocol.\r
857dfc45 81//\r
1436aea4 82EDKII_PERFORMANCE_MEASUREMENT_PROTOCOL mPerformanceMeasurementInterface = {\r
137fb13d 83 CreatePerformanceMeasurement,\r
1436aea4 84};\r
f0da4d7d 85\r
cfb0aba7
SZ
86PERFORMANCE_PROPERTY mPerformanceProperty;\r
87\r
6b4d58a1
BD
88/**\r
89 Return the pointer to the FPDT record in the allocated memory.\r
90\r
91 @param RecordSize The size of FPDT record.\r
92 @param FpdtRecordPtr Pointer the FPDT record in the allocated memory.\r
93\r
94 @retval EFI_SUCCESS Successfully get the pointer to the FPDT record.\r
95 @retval EFI_OUT_OF_RESOURCES Ran out of space to store the records.\r
96**/\r
97EFI_STATUS\r
98GetFpdtRecordPtr (\r
1436aea4
MK
99 IN UINT8 RecordSize,\r
100 IN OUT FPDT_RECORD_PTR *FpdtRecordPtr\r
101 )\r
6b4d58a1
BD
102{\r
103 if (mFpdtBufferIsReported) {\r
104 //\r
105 // Append Boot records to the boot performance table.\r
106 //\r
107 if (mBootRecordSize + RecordSize > mBootRecordMaxSize) {\r
108 if (!mLackSpaceIsReported) {\r
109 DEBUG ((DEBUG_INFO, "DxeCorePerformanceLib: No enough space to save boot records\n"));\r
110 mLackSpaceIsReported = TRUE;\r
111 }\r
1436aea4 112\r
6b4d58a1
BD
113 return EFI_OUT_OF_RESOURCES;\r
114 } else {\r
115 //\r
116 // Save boot record into BootPerformance table\r
117 //\r
118 FpdtRecordPtr->RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(mBootRecordBuffer + mBootRecordSize);\r
119 }\r
120 } else {\r
121 //\r
122 // Check if pre-allocated buffer is full\r
123 //\r
124 if (mPerformanceLength + RecordSize > mMaxPerformanceLength) {\r
125 mPerformancePointer = ReallocatePool (\r
126 mPerformanceLength,\r
127 mPerformanceLength + RecordSize + FIRMWARE_RECORD_BUFFER,\r
128 mPerformancePointer\r
129 );\r
130 if (mPerformancePointer == NULL) {\r
1436aea4
MK
131 return EFI_OUT_OF_RESOURCES;\r
132 }\r
133\r
6b4d58a1
BD
134 mMaxPerformanceLength = mPerformanceLength + RecordSize + FIRMWARE_RECORD_BUFFER;\r
135 }\r
1436aea4 136\r
6b4d58a1
BD
137 //\r
138 // Covert buffer to FPDT Ptr Union type.\r
139 //\r
140 FpdtRecordPtr->RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(mPerformancePointer + mPerformanceLength);\r
141 }\r
1436aea4 142\r
6b4d58a1
BD
143 return EFI_SUCCESS;\r
144}\r
145\r
9609d24b
DB
146/**\r
147Check whether the Token is a known one which is uesed by core.\r
148\r
149@param Token Pointer to a Null-terminated ASCII string\r
150\r
151@retval TRUE Is a known one used by core.\r
152@retval FALSE Not a known one.\r
153\r
154**/\r
155BOOLEAN\r
156IsKnownTokens (\r
157 IN CONST CHAR8 *Token\r
158 )\r
159{\r
c9faac27
DB
160 if (Token == NULL) {\r
161 return FALSE;\r
162 }\r
163\r
1436aea4
MK
164 if ((AsciiStrCmp (Token, SEC_TOK) == 0) ||\r
165 (AsciiStrCmp (Token, PEI_TOK) == 0) ||\r
166 (AsciiStrCmp (Token, DXE_TOK) == 0) ||\r
167 (AsciiStrCmp (Token, BDS_TOK) == 0) ||\r
168 (AsciiStrCmp (Token, DRIVERBINDING_START_TOK) == 0) ||\r
169 (AsciiStrCmp (Token, DRIVERBINDING_SUPPORT_TOK) == 0) ||\r
170 (AsciiStrCmp (Token, DRIVERBINDING_STOP_TOK) == 0) ||\r
171 (AsciiStrCmp (Token, LOAD_IMAGE_TOK) == 0) ||\r
172 (AsciiStrCmp (Token, START_IMAGE_TOK) == 0) ||\r
173 (AsciiStrCmp (Token, PEIM_TOK) == 0))\r
174 {\r
9609d24b
DB
175 return TRUE;\r
176 } else {\r
177 return FALSE;\r
178 }\r
179}\r
f1f7190b 180\r
a0afd019 181/**\r
9609d24b
DB
182Check whether the ID is a known one which map to the known Token.\r
183\r
184@param Identifier 32-bit identifier.\r
185\r
186@retval TRUE Is a known one used by core.\r
187@retval FALSE Not a known one.\r
188\r
189**/\r
190BOOLEAN\r
191IsKnownID (\r
1436aea4 192 IN UINT32 Identifier\r
9609d24b
DB
193 )\r
194{\r
1436aea4
MK
195 if ((Identifier == MODULE_START_ID) ||\r
196 (Identifier == MODULE_END_ID) ||\r
197 (Identifier == MODULE_LOADIMAGE_START_ID) ||\r
198 (Identifier == MODULE_LOADIMAGE_END_ID) ||\r
199 (Identifier == MODULE_DB_START_ID) ||\r
200 (Identifier == MODULE_DB_END_ID) ||\r
201 (Identifier == MODULE_DB_SUPPORT_START_ID) ||\r
202 (Identifier == MODULE_DB_SUPPORT_END_ID) ||\r
203 (Identifier == MODULE_DB_STOP_START_ID) ||\r
204 (Identifier == MODULE_DB_STOP_END_ID))\r
205 {\r
9609d24b
DB
206 return TRUE;\r
207 } else {\r
208 return FALSE;\r
209 }\r
210}\r
211\r
9609d24b 212/**\r
466ebdd2 213 This internal function dumps all the SMM performance data and size.\r
9609d24b 214\r
466ebdd2
DB
215 @param SmmPerfData Smm Performance data. The buffer contain the SMM perf data is allocated by this function and caller needs to free it.\r
216 @param SmmPerfDataSize Smm Performance data size.\r
217 @param SkipGetPerfData Skip to get performance data, just get the size.\r
9609d24b
DB
218\r
219**/\r
466ebdd2
DB
220VOID\r
221InternalGetSmmPerfData (\r
1436aea4
MK
222 OUT VOID **SmmPerfData,\r
223 OUT UINTN *SmmPerfDataSize,\r
224 IN BOOLEAN SkipGetPerfData\r
9609d24b
DB
225 )\r
226{\r
1436aea4
MK
227 EFI_STATUS Status;\r
228 UINT8 *SmmBootRecordCommBuffer;\r
229 EFI_SMM_COMMUNICATE_HEADER *SmmCommBufferHeader;\r
230 SMM_BOOT_RECORD_COMMUNICATE *SmmCommData;\r
231 UINTN CommSize;\r
232 EFI_SMM_COMMUNICATION_PROTOCOL *Communication;\r
233 EDKII_PI_SMM_COMMUNICATION_REGION_TABLE *SmmCommRegionTable;\r
234 EFI_MEMORY_DESCRIPTOR *SmmCommMemRegion;\r
235 UINTN Index;\r
236 VOID *SmmBootRecordData;\r
237 UINTN SmmBootRecordDataSize;\r
238 UINTN ReservedMemSize;\r
a0afd019 239\r
9609d24b
DB
240 //\r
241 // Collect boot records from SMM drivers.\r
242 //\r
243 SmmBootRecordCommBuffer = NULL;\r
244 SmmCommData = NULL;\r
245 SmmBootRecordData = NULL;\r
9609d24b 246 ReservedMemSize = 0;\r
1436aea4 247 Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **)&Communication);\r
9609d24b
DB
248 if (!EFI_ERROR (Status)) {\r
249 //\r
250 // Initialize communicate buffer\r
251 // Get the prepared Reserved Memory Range\r
252 //\r
253 Status = EfiGetSystemConfigurationTable (\r
1436aea4
MK
254 &gEdkiiPiSmmCommunicationRegionTableGuid,\r
255 (VOID **)&SmmCommRegionTable\r
256 );\r
9609d24b
DB
257 if (!EFI_ERROR (Status)) {\r
258 ASSERT (SmmCommRegionTable != NULL);\r
1436aea4
MK
259 SmmCommMemRegion = (EFI_MEMORY_DESCRIPTOR *)(SmmCommRegionTable + 1);\r
260 for (Index = 0; Index < SmmCommRegionTable->NumberOfEntries; Index++) {\r
9609d24b
DB
261 if (SmmCommMemRegion->Type == EfiConventionalMemory) {\r
262 break;\r
263 }\r
1436aea4
MK
264\r
265 SmmCommMemRegion = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)SmmCommMemRegion + SmmCommRegionTable->DescriptorSize);\r
9609d24b 266 }\r
1436aea4 267\r
9609d24b
DB
268 ASSERT (Index < SmmCommRegionTable->NumberOfEntries);\r
269 ASSERT (SmmCommMemRegion->PhysicalStart > 0);\r
270 ASSERT (SmmCommMemRegion->NumberOfPages > 0);\r
1436aea4 271 ReservedMemSize = (UINTN)SmmCommMemRegion->NumberOfPages * EFI_PAGE_SIZE;\r
9609d24b
DB
272\r
273 //\r
274 // Check enough reserved memory space\r
275 //\r
276 if (ReservedMemSize > SMM_BOOT_RECORD_COMM_SIZE) {\r
1436aea4
MK
277 SmmBootRecordCommBuffer = (VOID *)(UINTN)SmmCommMemRegion->PhysicalStart;\r
278 SmmCommBufferHeader = (EFI_SMM_COMMUNICATE_HEADER *)SmmBootRecordCommBuffer;\r
279 SmmCommData = (SMM_BOOT_RECORD_COMMUNICATE *)SmmCommBufferHeader->Data;\r
280 ZeroMem ((UINT8 *)SmmCommData, sizeof (SMM_BOOT_RECORD_COMMUNICATE));\r
9609d24b
DB
281\r
282 CopyGuid (&SmmCommBufferHeader->HeaderGuid, &gEfiFirmwarePerformanceGuid);\r
1436aea4
MK
283 SmmCommBufferHeader->MessageLength = sizeof (SMM_BOOT_RECORD_COMMUNICATE);\r
284 CommSize = SMM_BOOT_RECORD_COMM_SIZE;\r
9609d24b
DB
285\r
286 //\r
287 // Get the size of boot records.\r
288 //\r
289 SmmCommData->Function = SMM_FPDT_FUNCTION_GET_BOOT_RECORD_SIZE;\r
290 SmmCommData->BootRecordData = NULL;\r
1436aea4 291 Status = Communication->Communicate (Communication, SmmBootRecordCommBuffer, &CommSize);\r
9609d24b 292\r
1436aea4 293 if (!EFI_ERROR (Status) && !EFI_ERROR (SmmCommData->ReturnStatus) && (SmmCommData->BootRecordSize != 0)) {\r
466ebdd2
DB
294 if (SkipGetPerfData) {\r
295 *SmmPerfDataSize = SmmCommData->BootRecordSize;\r
296 return;\r
297 }\r
1436aea4 298\r
9609d24b
DB
299 //\r
300 // Get all boot records\r
301 //\r
1436aea4
MK
302 SmmCommData->Function = SMM_FPDT_FUNCTION_GET_BOOT_RECORD_DATA_BY_OFFSET;\r
303 SmmBootRecordDataSize = SmmCommData->BootRecordSize;\r
304 SmmBootRecordData = AllocateZeroPool (SmmBootRecordDataSize);\r
9609d24b
DB
305 ASSERT (SmmBootRecordData != NULL);\r
306 SmmCommData->BootRecordOffset = 0;\r
1436aea4 307 SmmCommData->BootRecordData = (VOID *)((UINTN)SmmCommMemRegion->PhysicalStart + SMM_BOOT_RECORD_COMM_SIZE);\r
9609d24b
DB
308 SmmCommData->BootRecordSize = ReservedMemSize - SMM_BOOT_RECORD_COMM_SIZE;\r
309 while (SmmCommData->BootRecordOffset < SmmBootRecordDataSize) {\r
310 Status = Communication->Communicate (Communication, SmmBootRecordCommBuffer, &CommSize);\r
311 ASSERT_EFI_ERROR (Status);\r
1436aea4 312 ASSERT_EFI_ERROR (SmmCommData->ReturnStatus);\r
9609d24b 313 if (SmmCommData->BootRecordOffset + SmmCommData->BootRecordSize > SmmBootRecordDataSize) {\r
1436aea4 314 CopyMem ((UINT8 *)SmmBootRecordData + SmmCommData->BootRecordOffset, SmmCommData->BootRecordData, SmmBootRecordDataSize - SmmCommData->BootRecordOffset);\r
9609d24b 315 } else {\r
1436aea4 316 CopyMem ((UINT8 *)SmmBootRecordData + SmmCommData->BootRecordOffset, SmmCommData->BootRecordData, SmmCommData->BootRecordSize);\r
9609d24b 317 }\r
1436aea4 318\r
9609d24b
DB
319 SmmCommData->BootRecordOffset = SmmCommData->BootRecordOffset + SmmCommData->BootRecordSize;\r
320 }\r
1436aea4 321\r
466ebdd2
DB
322 *SmmPerfData = SmmBootRecordData;\r
323 *SmmPerfDataSize = SmmBootRecordDataSize;\r
9609d24b
DB
324 }\r
325 }\r
326 }\r
327 }\r
466ebdd2
DB
328}\r
329\r
330/**\r
331 Allocate buffer for Boot Performance table.\r
332\r
333 @return Status code.\r
334\r
335**/\r
336EFI_STATUS\r
337AllocateBootPerformanceTable (\r
338 VOID\r
339 )\r
340{\r
1436aea4
MK
341 EFI_STATUS Status;\r
342 UINTN Size;\r
343 UINTN BootPerformanceDataSize;\r
344 UINT8 *BootPerformanceData;\r
345 FIRMWARE_PERFORMANCE_VARIABLE PerformanceVariable;\r
346 UINTN SmmBootRecordDataSize;\r
466ebdd2
DB
347\r
348 SmmBootRecordDataSize = 0;\r
349\r
350 //\r
351 // Get SMM performance data size at the point of EndOfDxe in order to allocate the boot performance table.\r
352 // Will Get all the data at ReadyToBoot.\r
353 //\r
354 InternalGetSmmPerfData (NULL, &SmmBootRecordDataSize, TRUE);\r
a0afd019 355\r
9609d24b
DB
356 //\r
357 // Prepare memory for Boot Performance table.\r
358 // Boot Performance table includes BasicBoot record, and one or more appended Boot Records.\r
359 //\r
466ebdd2 360 BootPerformanceDataSize = sizeof (BOOT_PERFORMANCE_TABLE) + mPerformanceLength + SmmBootRecordDataSize + PcdGet32 (PcdExtFpdtBootRecordPadSize);\r
9609d24b
DB
361\r
362 //\r
363 // Try to allocate the same runtime buffer as last time boot.\r
364 //\r
365 ZeroMem (&PerformanceVariable, sizeof (PerformanceVariable));\r
1436aea4 366 Size = sizeof (PerformanceVariable);\r
9609d24b
DB
367 Status = gRT->GetVariable (\r
368 EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME,\r
369 &gEfiFirmwarePerformanceGuid,\r
370 NULL,\r
371 &Size,\r
372 &PerformanceVariable\r
373 );\r
374 if (!EFI_ERROR (Status)) {\r
375 Status = gBS->AllocatePages (\r
376 AllocateAddress,\r
377 EfiReservedMemoryType,\r
378 EFI_SIZE_TO_PAGES (BootPerformanceDataSize),\r
379 &PerformanceVariable.BootPerformanceTablePointer\r
380 );\r
381 if (!EFI_ERROR (Status)) {\r
1436aea4 382 mAcpiBootPerformanceTable = (BOOT_PERFORMANCE_TABLE *)(UINTN)PerformanceVariable.BootPerformanceTablePointer;\r
9609d24b
DB
383 }\r
384 }\r
385\r
386 if (mAcpiBootPerformanceTable == NULL) {\r
387 //\r
388 // Fail to allocate at specified address, continue to allocate at any address.\r
389 //\r
1436aea4
MK
390 mAcpiBootPerformanceTable = (BOOT_PERFORMANCE_TABLE *)AllocatePeiAccessiblePages (\r
391 EfiReservedMemoryType,\r
392 EFI_SIZE_TO_PAGES (BootPerformanceDataSize)\r
393 );\r
d79d7b58
AB
394 if (mAcpiBootPerformanceTable != NULL) {\r
395 ZeroMem (mAcpiBootPerformanceTable, BootPerformanceDataSize);\r
396 }\r
9609d24b 397 }\r
1436aea4 398\r
9609d24b
DB
399 DEBUG ((DEBUG_INFO, "DxeCorePerformanceLib: ACPI Boot Performance Table address = 0x%x\n", mAcpiBootPerformanceTable));\r
400\r
401 if (mAcpiBootPerformanceTable == NULL) {\r
9609d24b
DB
402 return EFI_OUT_OF_RESOURCES;\r
403 }\r
404\r
405 //\r
406 // Prepare Boot Performance Table.\r
407 //\r
1436aea4 408 BootPerformanceData = (UINT8 *)mAcpiBootPerformanceTable;\r
9609d24b
DB
409 //\r
410 // Fill Basic Boot record to Boot Performance Table.\r
411 //\r
412 CopyMem (mAcpiBootPerformanceTable, &mBootPerformanceTableTemplate, sizeof (mBootPerformanceTableTemplate));\r
413 BootPerformanceData = BootPerformanceData + mAcpiBootPerformanceTable->Header.Length;\r
414 //\r
415 // Fill Boot records from boot drivers.\r
416 //\r
417 if (mPerformancePointer != NULL) {\r
418 CopyMem (BootPerformanceData, mPerformancePointer, mPerformanceLength);\r
419 mAcpiBootPerformanceTable->Header.Length += mPerformanceLength;\r
1436aea4 420 BootPerformanceData = BootPerformanceData + mPerformanceLength;\r
9609d24b
DB
421 FreePool (mPerformancePointer);\r
422 mPerformancePointer = NULL;\r
423 mPerformanceLength = 0;\r
424 mMaxPerformanceLength = 0;\r
425 }\r
9609d24b 426\r
1436aea4 427 mBootRecordBuffer = (UINT8 *)mAcpiBootPerformanceTable;\r
9609d24b 428 mBootRecordSize = mAcpiBootPerformanceTable->Header.Length;\r
466ebdd2 429 mBootRecordMaxSize = BootPerformanceDataSize;\r
9609d24b
DB
430\r
431 return EFI_SUCCESS;\r
432}\r
433\r
434/**\r
435 Get a human readable module name and module guid for the given image handle.\r
436 If module name can't be found, "" string will return.\r
437 If module guid can't be found, Zero Guid will return.\r
438\r
439 @param Handle Image handle or Controller handle.\r
440 @param NameString The ascii string will be filled into it. If not found, null string will return.\r
441 @param BufferSize Size of the input NameString buffer.\r
442 @param ModuleGuid Point to the guid buffer to store the got module guid value.\r
443\r
444 @retval EFI_SUCCESS Successfully get module name and guid.\r
445 @retval EFI_INVALID_PARAMETER The input parameter NameString is NULL.\r
446 @retval other value Module Name can't be got.\r
447**/\r
448EFI_STATUS\r
449GetModuleInfoFromHandle (\r
450 IN EFI_HANDLE Handle,\r
1436aea4
MK
451 OUT CHAR8 *NameString,\r
452 IN UINTN BufferSize,\r
453 OUT EFI_GUID *ModuleGuid OPTIONAL\r
9609d24b
DB
454 )\r
455{\r
1436aea4
MK
456 EFI_STATUS Status;\r
457 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
458 EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;\r
459 CHAR8 *PdbFileName;\r
460 EFI_GUID *TempGuid;\r
461 UINTN StartIndex;\r
462 UINTN Index;\r
463 INTN Count;\r
464 BOOLEAN ModuleGuidIsGet;\r
465 UINTN StringSize;\r
466 CHAR16 *StringPtr;\r
467 EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2;\r
468 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFilePath;\r
469\r
470 if ((NameString == NULL) || (BufferSize == 0)) {\r
9609d24b
DB
471 return EFI_INVALID_PARAMETER;\r
472 }\r
1436aea4 473\r
9609d24b
DB
474 //\r
475 // Try to get the ModuleGuid and name string form the caached array.\r
476 //\r
477 if (mCachePairCount > 0) {\r
478 for (Count = mCachePairCount -1; Count >= 0; Count--) {\r
479 if (Handle == mCacheHandleGuidTable[Count].Handle) {\r
480 CopyGuid (ModuleGuid, &mCacheHandleGuidTable[Count].ModuleGuid);\r
481 AsciiStrCpyS (NameString, FPDT_STRING_EVENT_RECORD_NAME_LENGTH, mCacheHandleGuidTable[Count].NameString);\r
482 return EFI_SUCCESS;\r
483 }\r
484 }\r
485 }\r
486\r
1436aea4 487 Status = EFI_INVALID_PARAMETER;\r
9609d24b
DB
488 LoadedImage = NULL;\r
489 ModuleGuidIsGet = FALSE;\r
490\r
491 //\r
492 // Initialize GUID as zero value.\r
493 //\r
1436aea4 494 TempGuid = &gZeroGuid;\r
9609d24b
DB
495 //\r
496 // Initialize it as "" string.\r
497 //\r
498 NameString[0] = 0;\r
499\r
500 if (Handle != NULL) {\r
501 //\r
502 // Try Handle as ImageHandle.\r
503 //\r
504 Status = gBS->HandleProtocol (\r
1436aea4
MK
505 Handle,\r
506 &gEfiLoadedImageProtocolGuid,\r
507 (VOID **)&LoadedImage\r
508 );\r
9609d24b
DB
509\r
510 if (EFI_ERROR (Status)) {\r
511 //\r
512 // Try Handle as Controller Handle\r
513 //\r
514 Status = gBS->OpenProtocol (\r
1436aea4
MK
515 Handle,\r
516 &gEfiDriverBindingProtocolGuid,\r
517 (VOID **)&DriverBinding,\r
518 NULL,\r
519 NULL,\r
520 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
521 );\r
9609d24b
DB
522 if (!EFI_ERROR (Status)) {\r
523 //\r
524 // Get Image protocol from ImageHandle\r
525 //\r
526 Status = gBS->HandleProtocol (\r
1436aea4
MK
527 DriverBinding->ImageHandle,\r
528 &gEfiLoadedImageProtocolGuid,\r
529 (VOID **)&LoadedImage\r
530 );\r
9609d24b
DB
531 }\r
532 }\r
533 }\r
534\r
1436aea4 535 if (!EFI_ERROR (Status) && (LoadedImage != NULL)) {\r
9609d24b
DB
536 //\r
537 // Get Module Guid from DevicePath.\r
538 //\r
1436aea4
MK
539 if ((LoadedImage->FilePath != NULL) &&\r
540 (LoadedImage->FilePath->Type == MEDIA_DEVICE_PATH) &&\r
541 (LoadedImage->FilePath->SubType == MEDIA_PIWG_FW_FILE_DP)\r
542 )\r
543 {\r
9609d24b
DB
544 //\r
545 // Determine GUID associated with module logging performance\r
546 //\r
547 ModuleGuidIsGet = TRUE;\r
1436aea4 548 FvFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)LoadedImage->FilePath;\r
9609d24b
DB
549 TempGuid = &FvFilePath->FvFileName;\r
550 }\r
551\r
552 //\r
553 // Method 1 Get Module Name from PDB string.\r
554 //\r
555 PdbFileName = PeCoffLoaderGetPdbPointer (LoadedImage->ImageBase);\r
1436aea4 556 if ((PdbFileName != NULL) && (BufferSize > 0)) {\r
9609d24b
DB
557 StartIndex = 0;\r
558 for (Index = 0; PdbFileName[Index] != 0; Index++) {\r
559 if ((PdbFileName[Index] == '\\') || (PdbFileName[Index] == '/')) {\r
560 StartIndex = Index + 1;\r
561 }\r
562 }\r
1436aea4 563\r
9609d24b
DB
564 //\r
565 // Copy the PDB file name to our temporary string.\r
566 // If the length is bigger than BufferSize, trim the redudant characters to avoid overflow in array boundary.\r
567 //\r
568 for (Index = 0; Index < BufferSize - 1; Index++) {\r
569 NameString[Index] = PdbFileName[Index + StartIndex];\r
1436aea4 570 if ((NameString[Index] == 0) || (NameString[Index] == '.')) {\r
9609d24b
DB
571 NameString[Index] = 0;\r
572 break;\r
573 }\r
574 }\r
575\r
576 if (Index == BufferSize - 1) {\r
577 NameString[Index] = 0;\r
578 }\r
1436aea4 579\r
9609d24b
DB
580 //\r
581 // Module Name is got.\r
582 //\r
583 goto Done;\r
584 }\r
585 }\r
586\r
587 //\r
588 // Method 2: Get the name string from ComponentName2 protocol\r
589 //\r
590 Status = gBS->HandleProtocol (\r
591 Handle,\r
592 &gEfiComponentName2ProtocolGuid,\r
1436aea4 593 (VOID **)&ComponentName2\r
9609d24b
DB
594 );\r
595 if (!EFI_ERROR (Status)) {\r
596 //\r
597 // Get the current platform language setting\r
598 //\r
599 if (mPlatformLanguage == NULL) {\r
1436aea4 600 GetEfiGlobalVariable2 (L"PlatformLang", (VOID **)&mPlatformLanguage, NULL);\r
9609d24b 601 }\r
1436aea4 602\r
9609d24b
DB
603 if (mPlatformLanguage != NULL) {\r
604 Status = ComponentName2->GetDriverName (\r
605 ComponentName2,\r
606 mPlatformLanguage != NULL ? mPlatformLanguage : "en-US",\r
607 &StringPtr\r
608 );\r
609 if (!EFI_ERROR (Status)) {\r
610 for (Index = 0; Index < BufferSize - 1 && StringPtr[Index] != 0; Index++) {\r
1436aea4 611 NameString[Index] = (CHAR8)StringPtr[Index];\r
9609d24b 612 }\r
1436aea4 613\r
9609d24b
DB
614 NameString[Index] = 0;\r
615 //\r
616 // Module Name is got.\r
617 //\r
618 goto Done;\r
619 }\r
620 }\r
621 }\r
622\r
623 if (ModuleGuidIsGet) {\r
624 //\r
625 // Method 3 Try to get the image's FFS UI section by image GUID\r
626 //\r
627 StringPtr = NULL;\r
628 StringSize = 0;\r
1436aea4
MK
629 Status = GetSectionFromAnyFv (\r
630 TempGuid,\r
631 EFI_SECTION_USER_INTERFACE,\r
632 0,\r
633 (VOID **)&StringPtr,\r
634 &StringSize\r
635 );\r
9609d24b
DB
636\r
637 if (!EFI_ERROR (Status)) {\r
638 //\r
639 // Method 3. Get the name string from FFS UI section\r
640 //\r
641 for (Index = 0; Index < BufferSize - 1 && StringPtr[Index] != 0; Index++) {\r
1436aea4 642 NameString[Index] = (CHAR8)StringPtr[Index];\r
9609d24b 643 }\r
1436aea4 644\r
9609d24b
DB
645 NameString[Index] = 0;\r
646 FreePool (StringPtr);\r
647 }\r
648 }\r
649\r
650Done:\r
651 //\r
652 // Copy Module Guid\r
653 //\r
654 if (ModuleGuid != NULL) {\r
655 CopyGuid (ModuleGuid, TempGuid);\r
1436aea4
MK
656 if (IsZeroGuid (TempGuid) && (Handle != NULL) && !ModuleGuidIsGet) {\r
657 // Handle is GUID\r
658 CopyGuid (ModuleGuid, (EFI_GUID *)Handle);\r
9609d24b
DB
659 }\r
660 }\r
661\r
662 //\r
663 // Cache the Handle and Guid pairs.\r
664 //\r
665 if (mCachePairCount < CACHE_HANDLE_GUID_COUNT) {\r
666 mCacheHandleGuidTable[mCachePairCount].Handle = Handle;\r
667 CopyGuid (&mCacheHandleGuidTable[mCachePairCount].ModuleGuid, ModuleGuid);\r
668 AsciiStrCpyS (mCacheHandleGuidTable[mCachePairCount].NameString, FPDT_STRING_EVENT_RECORD_NAME_LENGTH, NameString);\r
1436aea4 669 mCachePairCount++;\r
9609d24b
DB
670 }\r
671\r
672 return Status;\r
673}\r
674\r
675/**\r
6b4d58a1 676 Get the FPDT record identifier.\r
9609d24b 677\r
6b4d58a1
BD
678 @param Attribute The attribute of the Record.\r
679 PerfStartEntry: Start Record.\r
680 PerfEndEntry: End Record.\r
681 @param Handle Pointer to environment specific context used to identify the component being measured.\r
682 @param String Pointer to a Null-terminated ASCII string that identifies the component being measured.\r
683 @param ProgressID On return, pointer to the ProgressID.\r
a0afd019 684\r
6b4d58a1
BD
685 @retval EFI_SUCCESS Get record info successfully.\r
686 @retval EFI_INVALID_PARAMETER No matched FPDT record.\r
a0afd019 687\r
688**/\r
9609d24b 689EFI_STATUS\r
6b4d58a1
BD
690GetFpdtRecordId (\r
691 IN PERF_MEASUREMENT_ATTRIBUTE Attribute,\r
1436aea4
MK
692 IN CONST VOID *Handle,\r
693 IN CONST CHAR8 *String,\r
694 OUT UINT16 *ProgressID\r
a0afd019 695 )\r
696{\r
9609d24b 697 //\r
6b4d58a1 698 // Token to PerfId.\r
9609d24b 699 //\r
6b4d58a1 700 if (String != NULL) {\r
1436aea4
MK
701 if (AsciiStrCmp (String, START_IMAGE_TOK) == 0) {\r
702 // "StartImage:"\r
6b4d58a1 703 if (Attribute == PerfStartEntry) {\r
1436aea4 704 *ProgressID = MODULE_START_ID;\r
9609d24b 705 } else {\r
1436aea4 706 *ProgressID = MODULE_END_ID;\r
9609d24b 707 }\r
1436aea4
MK
708 } else if (AsciiStrCmp (String, LOAD_IMAGE_TOK) == 0) {\r
709 // "LoadImage:"\r
6b4d58a1 710 if (Attribute == PerfStartEntry) {\r
1436aea4 711 *ProgressID = MODULE_LOADIMAGE_START_ID;\r
9609d24b 712 } else {\r
1436aea4 713 *ProgressID = MODULE_LOADIMAGE_END_ID;\r
9609d24b 714 }\r
1436aea4
MK
715 } else if (AsciiStrCmp (String, DRIVERBINDING_START_TOK) == 0) {\r
716 // "DB:Start:"\r
6b4d58a1 717 if (Attribute == PerfStartEntry) {\r
1436aea4 718 *ProgressID = MODULE_DB_START_ID;\r
9609d24b 719 } else {\r
1436aea4 720 *ProgressID = MODULE_DB_END_ID;\r
9609d24b 721 }\r
1436aea4
MK
722 } else if (AsciiStrCmp (String, DRIVERBINDING_SUPPORT_TOK) == 0) {\r
723 // "DB:Support:"\r
9609d24b
DB
724 if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {\r
725 return RETURN_UNSUPPORTED;\r
726 }\r
1436aea4 727\r
6b4d58a1 728 if (Attribute == PerfStartEntry) {\r
1436aea4 729 *ProgressID = MODULE_DB_SUPPORT_START_ID;\r
9609d24b 730 } else {\r
1436aea4 731 *ProgressID = MODULE_DB_SUPPORT_END_ID;\r
9609d24b 732 }\r
1436aea4
MK
733 } else if (AsciiStrCmp (String, DRIVERBINDING_STOP_TOK) == 0) {\r
734 // "DB:Stop:"\r
9609d24b 735 if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {\r
1436aea4 736 return RETURN_UNSUPPORTED;\r
9609d24b 737 }\r
1436aea4 738\r
6b4d58a1 739 if (Attribute == PerfStartEntry) {\r
1436aea4 740 *ProgressID = MODULE_DB_STOP_START_ID;\r
9609d24b 741 } else {\r
1436aea4 742 *ProgressID = MODULE_DB_STOP_END_ID;\r
9609d24b 743 }\r
1436aea4
MK
744 } else if ((AsciiStrCmp (String, PEI_TOK) == 0) || // "PEI"\r
745 (AsciiStrCmp (String, DXE_TOK) == 0) || // "DXE"\r
746 (AsciiStrCmp (String, BDS_TOK) == 0)) // "BDS"\r
747 {\r
6b4d58a1 748 if (Attribute == PerfStartEntry) {\r
1436aea4 749 *ProgressID = PERF_CROSSMODULE_START_ID;\r
9609d24b 750 } else {\r
1436aea4 751 *ProgressID = PERF_CROSSMODULE_END_ID;\r
9609d24b 752 }\r
1436aea4
MK
753 } else {\r
754 // Pref used in Modules.\r
6b4d58a1 755 if (Attribute == PerfStartEntry) {\r
1436aea4 756 *ProgressID = PERF_INMODULE_START_ID;\r
9609d24b 757 } else {\r
1436aea4 758 *ProgressID = PERF_INMODULE_END_ID;\r
9609d24b
DB
759 }\r
760 }\r
1436aea4
MK
761 } else if (Handle != NULL) {\r
762 // Pref used in Modules.\r
6b4d58a1 763 if (Attribute == PerfStartEntry) {\r
1436aea4 764 *ProgressID = PERF_INMODULE_START_ID;\r
9609d24b 765 } else {\r
1436aea4 766 *ProgressID = PERF_INMODULE_END_ID;\r
9609d24b
DB
767 }\r
768 } else {\r
6b4d58a1 769 return EFI_INVALID_PARAMETER;\r
a0afd019 770 }\r
1436aea4 771\r
6b4d58a1
BD
772 return EFI_SUCCESS;\r
773}\r
774\r
775/**\r
776 Copies the string from Source into Destination and updates Length with the\r
777 size of the string.\r
778\r
779 @param Destination - destination of the string copy\r
780 @param Source - pointer to the source string which will get copied\r
781 @param Length - pointer to a length variable to be updated\r
782\r
783**/\r
784VOID\r
785CopyStringIntoPerfRecordAndUpdateLength (\r
1436aea4 786 IN OUT CHAR8 *Destination,\r
6b4d58a1 787 IN CONST CHAR8 *Source,\r
1436aea4 788 IN OUT UINT8 *Length\r
6b4d58a1
BD
789 )\r
790{\r
791 UINTN StringLen;\r
792 UINTN DestMax;\r
793\r
794 ASSERT (Source != NULL);\r
a0afd019 795\r
9609d24b 796 if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {\r
6b4d58a1 797 DestMax = STRING_SIZE;\r
9609d24b 798 } else {\r
6b4d58a1
BD
799 DestMax = AsciiStrSize (Source);\r
800 if (DestMax > STRING_SIZE) {\r
801 DestMax = STRING_SIZE;\r
802 }\r
803 }\r
1436aea4 804\r
6b4d58a1
BD
805 StringLen = AsciiStrLen (Source);\r
806 if (StringLen >= DestMax) {\r
807 StringLen = DestMax -1;\r
808 }\r
809\r
1436aea4 810 AsciiStrnCpyS (Destination, DestMax, Source, StringLen);\r
6b4d58a1
BD
811 *Length += (UINT8)DestMax;\r
812\r
813 return;\r
814}\r
815\r
816/**\r
817 Get a string description for device for the given controller handle and update record\r
818 length. If ComponentName2 GetControllerName is supported, the value is included in the string,\r
819 followed by device path, otherwise just device path.\r
a0afd019 820\r
6b4d58a1
BD
821 @param Handle - Image handle\r
822 @param ControllerHandle - Controller handle.\r
823 @param ComponentNameString - Pointer to a location where the string will be saved\r
824 @param Length - Pointer to record length to be updated\r
b504f519 825\r
6b4d58a1
BD
826 @retval EFI_SUCCESS - Successfully got string description for device\r
827 @retval EFI_UNSUPPORTED - Neither ComponentName2 ControllerName nor DevicePath were found\r
9609d24b 828\r
6b4d58a1
BD
829**/\r
830EFI_STATUS\r
831GetDeviceInfoFromHandleAndUpdateLength (\r
1436aea4
MK
832 IN CONST VOID *Handle,\r
833 IN EFI_HANDLE ControllerHandle,\r
834 OUT CHAR8 *ComponentNameString,\r
835 IN OUT UINT8 *Length\r
6b4d58a1
BD
836 )\r
837{\r
838 EFI_DEVICE_PATH_PROTOCOL *DevicePathProtocol;\r
839 EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2;\r
840 EFI_STATUS Status;\r
841 CHAR16 *StringPtr;\r
842 CHAR8 *AsciiStringPtr;\r
843 UINTN ControllerNameStringSize;\r
844 UINTN DevicePathStringSize;\r
845\r
846 ControllerNameStringSize = 0;\r
847\r
848 Status = gBS->HandleProtocol (\r
1436aea4 849 (EFI_HANDLE)Handle,\r
6b4d58a1 850 &gEfiComponentName2ProtocolGuid,\r
1436aea4 851 (VOID **)&ComponentName2\r
6b4d58a1
BD
852 );\r
853\r
1436aea4 854 if (!EFI_ERROR (Status)) {\r
6b4d58a1
BD
855 //\r
856 // Get the current platform language setting\r
857 //\r
858 if (mPlatformLanguage == NULL) {\r
859 GetEfiGlobalVariable2 (L"PlatformLang", (VOID **)&mPlatformLanguage, NULL);\r
860 }\r
861\r
862 Status = ComponentName2->GetControllerName (\r
863 ComponentName2,\r
864 ControllerHandle,\r
865 NULL,\r
866 mPlatformLanguage != NULL ? mPlatformLanguage : "en-US",\r
867 &StringPtr\r
868 );\r
869 }\r
870\r
871 if (!EFI_ERROR (Status)) {\r
872 //\r
873 // This will produce the size of the unicode string, which is twice as large as the ASCII one\r
874 // This must be an even number, so ok to divide by 2\r
875 //\r
1436aea4 876 ControllerNameStringSize = StrSize (StringPtr) / 2;\r
6b4d58a1
BD
877\r
878 //\r
879 // The + 1 is because we want to add a space between the ControllerName and the device path\r
880 //\r
881 if ((ControllerNameStringSize + (*Length) + 1) > FPDT_MAX_PERF_RECORD_SIZE) {\r
9609d24b 882 //\r
6b4d58a1 883 // Only copy enough to fill FPDT_MAX_PERF_RECORD_SIZE worth of the record\r
9609d24b 884 //\r
6b4d58a1 885 ControllerNameStringSize = FPDT_MAX_PERF_RECORD_SIZE - (*Length) - 1;\r
a0afd019 886 }\r
6b4d58a1 887\r
1436aea4 888 UnicodeStrnToAsciiStrS (StringPtr, ControllerNameStringSize - 1, ComponentNameString, ControllerNameStringSize, &ControllerNameStringSize);\r
6b4d58a1
BD
889\r
890 //\r
891 // Add a space in the end of the ControllerName\r
892 //\r
1436aea4 893 AsciiStringPtr = ComponentNameString + ControllerNameStringSize - 1;\r
6b4d58a1
BD
894 *AsciiStringPtr = 0x20;\r
895 AsciiStringPtr++;\r
896 *AsciiStringPtr = 0;\r
897 ControllerNameStringSize++;\r
898\r
899 *Length += (UINT8)ControllerNameStringSize;\r
a0afd019 900 }\r
901\r
6b4d58a1
BD
902 //\r
903 // This function returns the device path protocol from the handle specified by Handle. If Handle is\r
904 // NULL or Handle does not contain a device path protocol, then NULL is returned.\r
905 //\r
1436aea4 906 DevicePathProtocol = DevicePathFromHandle (ControllerHandle);\r
6b4d58a1
BD
907\r
908 if (DevicePathProtocol != NULL) {\r
909 StringPtr = ConvertDevicePathToText (DevicePathProtocol, TRUE, FALSE);\r
910 if (StringPtr != NULL) {\r
911 //\r
912 // This will produce the size of the unicode string, which is twice as large as the ASCII one\r
913 // This must be an even number, so ok to divide by 2\r
914 //\r
1436aea4 915 DevicePathStringSize = StrSize (StringPtr) / 2;\r
6b4d58a1
BD
916\r
917 if ((DevicePathStringSize + (*Length)) > FPDT_MAX_PERF_RECORD_SIZE) {\r
918 //\r
919 // Only copy enough to fill FPDT_MAX_PERF_RECORD_SIZE worth of the record\r
920 //\r
921 DevicePathStringSize = FPDT_MAX_PERF_RECORD_SIZE - (*Length);\r
922 }\r
923\r
924 if (ControllerNameStringSize != 0) {\r
925 AsciiStringPtr = ComponentNameString + ControllerNameStringSize - 1;\r
926 } else {\r
927 AsciiStringPtr = ComponentNameString;\r
928 }\r
929\r
1436aea4 930 UnicodeStrnToAsciiStrS (StringPtr, DevicePathStringSize - 1, AsciiStringPtr, DevicePathStringSize, &DevicePathStringSize);\r
6b4d58a1
BD
931 *Length += (UINT8)DevicePathStringSize;\r
932 return EFI_SUCCESS;\r
933 }\r
934 }\r
935\r
936 return EFI_UNSUPPORTED;\r
a0afd019 937}\r
938\r
939/**\r
6b4d58a1 940 Create performance record with event description and a timestamp.\r
a0afd019 941\r
6b4d58a1
BD
942 @param CallerIdentifier - Image handle or pointer to caller ID GUID.\r
943 @param Guid - Pointer to a GUID.\r
944 @param String - Pointer to a string describing the measurement.\r
945 @param Ticker - 64-bit time stamp.\r
946 @param Address - Pointer to a location in memory relevant to the measurement.\r
947 @param PerfId - Performance identifier describing the type of measurement.\r
948 @param Attribute - The attribute of the measurement. According to attribute can create a start\r
949 record for PERF_START/PERF_START_EX, or a end record for PERF_END/PERF_END_EX,\r
950 or a general record for other Perf macros.\r
a0afd019 951\r
6b4d58a1
BD
952 @retval EFI_SUCCESS - Successfully created performance record.\r
953 @retval EFI_OUT_OF_RESOURCES - Ran out of space to store the records.\r
954 @retval EFI_INVALID_PARAMETER - Invalid parameter passed to function - NULL\r
955 pointer or invalid PerfId.\r
956\r
957 @retval EFI_SUCCESS - Successfully created performance record\r
958 @retval EFI_OUT_OF_RESOURCES - Ran out of space to store the records\r
959 @retval EFI_INVALID_PARAMETER - Invalid parameter passed to function - NULL\r
960 pointer or invalid PerfId\r
a0afd019 961\r
962**/\r
a0afd019 963EFI_STATUS\r
6b4d58a1 964InsertFpdtRecord (\r
e3917e22
MK
965 IN CONST VOID *CallerIdentifier OPTIONAL,\r
966 IN CONST VOID *Guid OPTIONAL,\r
967 IN CONST CHAR8 *String OPTIONAL,\r
6b4d58a1 968 IN UINT64 Ticker,\r
e3917e22 969 IN UINT64 Address OPTIONAL,\r
6b4d58a1
BD
970 IN UINT16 PerfId,\r
971 IN PERF_MEASUREMENT_ATTRIBUTE Attribute\r
a0afd019 972 )\r
973{\r
1436aea4
MK
974 EFI_GUID ModuleGuid;\r
975 CHAR8 ModuleName[FPDT_STRING_EVENT_RECORD_NAME_LENGTH];\r
976 FPDT_RECORD_PTR FpdtRecordPtr;\r
977 FPDT_RECORD_PTR CachedFpdtRecordPtr;\r
978 UINT64 TimeStamp;\r
979 CONST CHAR8 *StringPtr;\r
980 UINTN DestMax;\r
981 UINTN StringLen;\r
982 EFI_STATUS Status;\r
983 UINT16 ProgressId;\r
984\r
985 StringPtr = NULL;\r
986 ProgressId = 0;\r
9609d24b
DB
987 ZeroMem (ModuleName, sizeof (ModuleName));\r
988\r
9609d24b 989 //\r
6b4d58a1
BD
990 // 1. Get the Perf Id for records from PERF_START/PERF_END, PERF_START_EX/PERF_END_EX.\r
991 // notes: For other Perf macros (Attribute == PerfEntry), their Id is known.\r
9609d24b 992 //\r
6b4d58a1 993 if (Attribute != PerfEntry) {\r
9609d24b 994 //\r
6b4d58a1
BD
995 // If PERF_START_EX()/PERF_END_EX() have specified the ProgressID,it has high priority.\r
996 // !!! Note: If the Perf is not the known Token used in the core but have same\r
997 // ID with the core Token, this case will not be supported.\r
998 // And in currtnt usage mode, for the unkown ID, there is a general rule:\r
999 // If it is start pref: the lower 4 bits of the ID should be 0.\r
1000 // If it is end pref: the lower 4 bits of the ID should not be 0.\r
1001 // If input ID doesn't follow the rule, we will adjust it.\r
a0afd019 1002 //\r
6b4d58a1
BD
1003 if ((PerfId != 0) && (IsKnownID (PerfId)) && (!IsKnownTokens (String))) {\r
1004 return EFI_INVALID_PARAMETER;\r
1005 } else if ((PerfId != 0) && (!IsKnownID (PerfId)) && (!IsKnownTokens (String))) {\r
1006 if ((Attribute == PerfStartEntry) && ((PerfId & 0x000F) != 0)) {\r
1007 PerfId &= 0xFFF0;\r
1008 } else if ((Attribute == PerfEndEntry) && ((PerfId & 0x000F) == 0)) {\r
1009 PerfId += 1;\r
9609d24b 1010 }\r
6b4d58a1 1011 } else if (PerfId == 0) {\r
9609d24b 1012 //\r
6b4d58a1 1013 // Get ProgressID form the String Token.\r
9609d24b 1014 //\r
6b4d58a1
BD
1015 Status = GetFpdtRecordId (Attribute, CallerIdentifier, String, &ProgressId);\r
1016 if (EFI_ERROR (Status)) {\r
1017 return Status;\r
9609d24b 1018 }\r
1436aea4 1019\r
6b4d58a1 1020 PerfId = ProgressId;\r
9609d24b 1021 }\r
9609d24b 1022 }\r
a0afd019 1023\r
9609d24b 1024 //\r
6b4d58a1
BD
1025 // 2. Get the buffer to store the FPDT record.\r
1026 //\r
1027 Status = GetFpdtRecordPtr (FPDT_MAX_PERF_RECORD_SIZE, &FpdtRecordPtr);\r
1028 if (EFI_ERROR (Status)) {\r
1029 return Status;\r
1030 }\r
1031\r
1032 //\r
1436aea4 1033 // 3. Get the TimeStamp.\r
9609d24b
DB
1034 //\r
1035 if (Ticker == 0) {\r
1036 Ticker = GetPerformanceCounter ();\r
1037 TimeStamp = GetTimeInNanoSecond (Ticker);\r
1038 } else if (Ticker == 1) {\r
1039 TimeStamp = 0;\r
1040 } else {\r
1041 TimeStamp = GetTimeInNanoSecond (Ticker);\r
1042 }\r
a0afd019 1043\r
9609d24b 1044 //\r
6b4d58a1 1045 // 4. Fill in the FPDT record according to different Performance Identifier.\r
9609d24b 1046 //\r
6b4d58a1 1047 switch (PerfId) {\r
1436aea4
MK
1048 case MODULE_START_ID:\r
1049 case MODULE_END_ID:\r
1050 GetModuleInfoFromHandle ((EFI_HANDLE)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);\r
1051 StringPtr = ModuleName;\r
6b4d58a1 1052 //\r
1436aea4 1053 // Cache the offset of start image start record and use to update the start image end record if needed.\r
6b4d58a1 1054 //\r
1436aea4 1055 if ((Attribute == PerfEntry) && (PerfId == MODULE_START_ID)) {\r
6b4d58a1
BD
1056 if (mFpdtBufferIsReported) {\r
1057 mCachedLength = mBootRecordSize;\r
1058 } else {\r
1059 mCachedLength = mPerformanceLength;\r
1060 }\r
1061 }\r
1436aea4
MK
1062\r
1063 if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {\r
1064 FpdtRecordPtr.GuidEvent->Header.Type = FPDT_GUID_EVENT_TYPE;\r
1065 FpdtRecordPtr.GuidEvent->Header.Length = sizeof (FPDT_GUID_EVENT_RECORD);\r
1066 FpdtRecordPtr.GuidEvent->Header.Revision = FPDT_RECORD_REVISION_1;\r
1067 FpdtRecordPtr.GuidEvent->ProgressID = PerfId;\r
1068 FpdtRecordPtr.GuidEvent->Timestamp = TimeStamp;\r
1069 CopyMem (&FpdtRecordPtr.GuidEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidEvent->Guid));\r
1070 if ((CallerIdentifier == NULL) && (PerfId == MODULE_END_ID) && (mCachedLength != 0)) {\r
1071 if (mFpdtBufferIsReported) {\r
1072 CachedFpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(mBootRecordBuffer + mCachedLength);\r
1073 } else {\r
1074 CachedFpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(mPerformancePointer + mCachedLength);\r
1075 }\r
1076\r
1077 CopyMem (&FpdtRecordPtr.GuidEvent->Guid, &CachedFpdtRecordPtr.GuidEvent->Guid, sizeof (FpdtRecordPtr.GuidEvent->Guid));\r
1078 mCachedLength = 0;\r
6b4d58a1 1079 }\r
9609d24b 1080 }\r
1436aea4
MK
1081\r
1082 break;\r
1083\r
1084 case MODULE_LOADIMAGE_START_ID:\r
1085 case MODULE_LOADIMAGE_END_ID:\r
1086 GetModuleInfoFromHandle ((EFI_HANDLE)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);\r
1087 StringPtr = ModuleName;\r
1088 if (PerfId == MODULE_LOADIMAGE_START_ID) {\r
1089 mLoadImageCount++;\r
1090 //\r
1091 // Cache the offset of load image start record and use to be updated by the load image end record if needed.\r
1092 //\r
1093 if ((CallerIdentifier == NULL) && (Attribute == PerfEntry)) {\r
1094 if (mFpdtBufferIsReported) {\r
1095 mCachedLength = mBootRecordSize;\r
1096 } else {\r
1097 mCachedLength = mPerformanceLength;\r
1098 }\r
1099 }\r
6b4d58a1 1100 }\r
9609d24b 1101\r
1436aea4
MK
1102 if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {\r
1103 FpdtRecordPtr.GuidQwordEvent->Header.Type = FPDT_GUID_QWORD_EVENT_TYPE;\r
1104 FpdtRecordPtr.GuidQwordEvent->Header.Length = sizeof (FPDT_GUID_QWORD_EVENT_RECORD);\r
1105 FpdtRecordPtr.GuidQwordEvent->Header.Revision = FPDT_RECORD_REVISION_1;\r
1106 FpdtRecordPtr.GuidQwordEvent->ProgressID = PerfId;\r
1107 FpdtRecordPtr.GuidQwordEvent->Timestamp = TimeStamp;\r
1108 FpdtRecordPtr.GuidQwordEvent->Qword = mLoadImageCount;\r
1109 CopyMem (&FpdtRecordPtr.GuidQwordEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidQwordEvent->Guid));\r
1110 if ((PerfId == MODULE_LOADIMAGE_END_ID) && (mCachedLength != 0)) {\r
1111 if (mFpdtBufferIsReported) {\r
1112 CachedFpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(mBootRecordBuffer + mCachedLength);\r
1113 } else {\r
1114 CachedFpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(mPerformancePointer + mCachedLength);\r
1115 }\r
1116\r
1117 CopyMem (&CachedFpdtRecordPtr.GuidQwordEvent->Guid, &ModuleGuid, sizeof (CachedFpdtRecordPtr.GuidQwordEvent->Guid));\r
1118 mCachedLength = 0;\r
1119 }\r
1120 }\r
1121\r
1122 break;\r
1123\r
1124 case MODULE_DB_START_ID:\r
1125 case MODULE_DB_SUPPORT_START_ID:\r
1126 case MODULE_DB_SUPPORT_END_ID:\r
1127 case MODULE_DB_STOP_START_ID:\r
1128 case MODULE_DB_STOP_END_ID:\r
1129 GetModuleInfoFromHandle ((EFI_HANDLE)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);\r
6b4d58a1 1130 StringPtr = ModuleName;\r
1436aea4
MK
1131 if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {\r
1132 FpdtRecordPtr.GuidQwordEvent->Header.Type = FPDT_GUID_QWORD_EVENT_TYPE;\r
1133 FpdtRecordPtr.GuidQwordEvent->Header.Length = sizeof (FPDT_GUID_QWORD_EVENT_RECORD);\r
1134 FpdtRecordPtr.GuidQwordEvent->Header.Revision = FPDT_RECORD_REVISION_1;\r
1135 FpdtRecordPtr.GuidQwordEvent->ProgressID = PerfId;\r
1136 FpdtRecordPtr.GuidQwordEvent->Timestamp = TimeStamp;\r
1137 FpdtRecordPtr.GuidQwordEvent->Qword = Address;\r
1138 CopyMem (&FpdtRecordPtr.GuidQwordEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidQwordEvent->Guid));\r
1139 }\r
1140\r
1141 break;\r
1142\r
1143 case MODULE_DB_END_ID:\r
1144 GetModuleInfoFromHandle ((EFI_HANDLE)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);\r
1145 StringPtr = ModuleName;\r
1146 if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {\r
1147 FpdtRecordPtr.GuidQwordStringEvent->Header.Type = FPDT_GUID_QWORD_STRING_EVENT_TYPE;\r
1148 FpdtRecordPtr.GuidQwordStringEvent->Header.Length = sizeof (FPDT_GUID_QWORD_STRING_EVENT_RECORD);\r
1149 FpdtRecordPtr.GuidQwordStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;\r
1150 FpdtRecordPtr.GuidQwordStringEvent->ProgressID = PerfId;\r
1151 FpdtRecordPtr.GuidQwordStringEvent->Timestamp = TimeStamp;\r
1152 FpdtRecordPtr.GuidQwordStringEvent->Qword = Address;\r
1153 CopyMem (&FpdtRecordPtr.GuidQwordStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidQwordStringEvent->Guid));\r
1154 if (Address != 0) {\r
1155 GetDeviceInfoFromHandleAndUpdateLength (CallerIdentifier, (EFI_HANDLE)(UINTN)Address, FpdtRecordPtr.GuidQwordStringEvent->String, &FpdtRecordPtr.GuidQwordStringEvent->Header.Length);\r
1156 }\r
1157 }\r
1158\r
1159 break;\r
1160\r
1161 case PERF_EVENTSIGNAL_START_ID:\r
1162 case PERF_EVENTSIGNAL_END_ID:\r
1163 case PERF_CALLBACK_START_ID:\r
1164 case PERF_CALLBACK_END_ID:\r
1165 if ((String == NULL) || (Guid == NULL)) {\r
1166 return EFI_INVALID_PARAMETER;\r
1167 }\r
1168\r
1169 StringPtr = String;\r
1170 if (AsciiStrLen (String) == 0) {\r
1171 StringPtr = "unknown name";\r
1172 }\r
1173\r
1174 if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {\r
1175 FpdtRecordPtr.DualGuidStringEvent->Header.Type = FPDT_DUAL_GUID_STRING_EVENT_TYPE;\r
1176 FpdtRecordPtr.DualGuidStringEvent->Header.Length = sizeof (FPDT_DUAL_GUID_STRING_EVENT_RECORD);\r
1177 FpdtRecordPtr.DualGuidStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;\r
1178 FpdtRecordPtr.DualGuidStringEvent->ProgressID = PerfId;\r
1179 FpdtRecordPtr.DualGuidStringEvent->Timestamp = TimeStamp;\r
1180 CopyMem (&FpdtRecordPtr.DualGuidStringEvent->Guid1, CallerIdentifier, sizeof (FpdtRecordPtr.DualGuidStringEvent->Guid1));\r
1181 CopyMem (&FpdtRecordPtr.DualGuidStringEvent->Guid2, Guid, sizeof (FpdtRecordPtr.DualGuidStringEvent->Guid2));\r
1182 CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DualGuidStringEvent->String, StringPtr, &FpdtRecordPtr.DualGuidStringEvent->Header.Length);\r
1183 }\r
6b4d58a1 1184\r
1436aea4
MK
1185 break;\r
1186\r
1187 case PERF_EVENT_ID:\r
1188 case PERF_FUNCTION_START_ID:\r
1189 case PERF_FUNCTION_END_ID:\r
1190 case PERF_INMODULE_START_ID:\r
1191 case PERF_INMODULE_END_ID:\r
1192 case PERF_CROSSMODULE_START_ID:\r
1193 case PERF_CROSSMODULE_END_ID:\r
3522ea73 1194 GetModuleInfoFromHandle ((EFI_HANDLE)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);\r
6b4d58a1
BD
1195 if (String != NULL) {\r
1196 StringPtr = String;\r
1197 } else {\r
1198 StringPtr = ModuleName;\r
1199 }\r
1436aea4 1200\r
6b4d58a1
BD
1201 if (AsciiStrLen (StringPtr) == 0) {\r
1202 StringPtr = "unknown name";\r
1203 }\r
1436aea4 1204\r
6b4d58a1 1205 if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {\r
1436aea4
MK
1206 FpdtRecordPtr.DynamicStringEvent->Header.Type = FPDT_DYNAMIC_STRING_EVENT_TYPE;\r
1207 FpdtRecordPtr.DynamicStringEvent->Header.Length = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);\r
1208 FpdtRecordPtr.DynamicStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;\r
1209 FpdtRecordPtr.DynamicStringEvent->ProgressID = PerfId;\r
1210 FpdtRecordPtr.DynamicStringEvent->Timestamp = TimeStamp;\r
6b4d58a1
BD
1211 CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));\r
1212 CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DynamicStringEvent->String, StringPtr, &FpdtRecordPtr.DynamicStringEvent->Header.Length);\r
1213 }\r
1436aea4
MK
1214\r
1215 break;\r
1216\r
1217 default:\r
1218 if (Attribute != PerfEntry) {\r
1219 GetModuleInfoFromHandle ((EFI_HANDLE)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);\r
1220 if (String != NULL) {\r
1221 StringPtr = String;\r
1222 } else {\r
1223 StringPtr = ModuleName;\r
1224 }\r
1225\r
1226 if (AsciiStrLen (StringPtr) == 0) {\r
1227 StringPtr = "unknown name";\r
1228 }\r
1229\r
1230 if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {\r
1231 FpdtRecordPtr.DynamicStringEvent->Header.Type = FPDT_DYNAMIC_STRING_EVENT_TYPE;\r
1232 FpdtRecordPtr.DynamicStringEvent->Header.Length = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);\r
1233 FpdtRecordPtr.DynamicStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;\r
1234 FpdtRecordPtr.DynamicStringEvent->ProgressID = PerfId;\r
1235 FpdtRecordPtr.DynamicStringEvent->Timestamp = TimeStamp;\r
1236 CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));\r
1237 CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DynamicStringEvent->String, StringPtr, &FpdtRecordPtr.DynamicStringEvent->Header.Length);\r
1238 }\r
1239 } else {\r
1240 return EFI_INVALID_PARAMETER;\r
1241 }\r
1242\r
1243 break;\r
6b4d58a1
BD
1244 }\r
1245\r
1246 //\r
1247 // 4.2 When PcdEdkiiFpdtStringRecordEnableOnly==TRUE, create string record for all Perf entries.\r
1248 //\r
1249 if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {\r
1436aea4 1250 if ((StringPtr == NULL) || (PerfId == MODULE_DB_SUPPORT_START_ID) || (PerfId == MODULE_DB_SUPPORT_END_ID)) {\r
6b4d58a1
BD
1251 return EFI_INVALID_PARAMETER;\r
1252 }\r
1436aea4
MK
1253\r
1254 FpdtRecordPtr.DynamicStringEvent->Header.Type = FPDT_DYNAMIC_STRING_EVENT_TYPE;\r
1255 FpdtRecordPtr.DynamicStringEvent->Header.Length = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);\r
1256 FpdtRecordPtr.DynamicStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;\r
1257 FpdtRecordPtr.DynamicStringEvent->ProgressID = PerfId;\r
1258 FpdtRecordPtr.DynamicStringEvent->Timestamp = TimeStamp;\r
981b7edc
DB
1259 if (Guid != NULL) {\r
1260 //\r
1261 // Cache the event guid in string event record.\r
1262 //\r
1263 CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, Guid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));\r
1264 } else {\r
1265 CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));\r
1266 }\r
1436aea4 1267\r
6b4d58a1
BD
1268 if (AsciiStrLen (StringPtr) == 0) {\r
1269 StringPtr = "unknown name";\r
1270 }\r
1436aea4 1271\r
6b4d58a1
BD
1272 CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DynamicStringEvent->String, StringPtr, &FpdtRecordPtr.DynamicStringEvent->Header.Length);\r
1273\r
1274 if ((PerfId == MODULE_LOADIMAGE_START_ID) || (PerfId == MODULE_END_ID)) {\r
1275 FpdtRecordPtr.DynamicStringEvent->Header.Length = (UINT8)(sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD)+ STRING_SIZE);\r
1276 }\r
1436aea4
MK
1277\r
1278 if (((PerfId == MODULE_LOADIMAGE_END_ID) || (PerfId == MODULE_END_ID)) && (mCachedLength != 0)) {\r
6b4d58a1
BD
1279 if (mFpdtBufferIsReported) {\r
1280 CachedFpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(mBootRecordBuffer + mCachedLength);\r
1281 } else {\r
1282 CachedFpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(mPerformancePointer + mCachedLength);\r
1283 }\r
1436aea4 1284\r
6b4d58a1 1285 if (PerfId == MODULE_LOADIMAGE_END_ID) {\r
1436aea4 1286 DestMax = CachedFpdtRecordPtr.DynamicStringEvent->Header.Length - sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);\r
6b4d58a1
BD
1287 StringLen = AsciiStrLen (StringPtr);\r
1288 if (StringLen >= DestMax) {\r
1289 StringLen = DestMax -1;\r
1290 }\r
1436aea4 1291\r
6b4d58a1
BD
1292 CopyMem (&CachedFpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (CachedFpdtRecordPtr.DynamicStringEvent->Guid));\r
1293 AsciiStrnCpyS (CachedFpdtRecordPtr.DynamicStringEvent->String, DestMax, StringPtr, StringLen);\r
1294 } else if (PerfId == MODULE_END_ID) {\r
1436aea4 1295 DestMax = FpdtRecordPtr.DynamicStringEvent->Header.Length - sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);\r
6b4d58a1
BD
1296 StringLen = AsciiStrLen (CachedFpdtRecordPtr.DynamicStringEvent->String);\r
1297 if (StringLen >= DestMax) {\r
1298 StringLen = DestMax -1;\r
1299 }\r
1436aea4 1300\r
6b4d58a1
BD
1301 CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &CachedFpdtRecordPtr.DynamicStringEvent->Guid, sizeof (CachedFpdtRecordPtr.DynamicStringEvent->Guid));\r
1302 AsciiStrnCpyS (FpdtRecordPtr.DynamicStringEvent->String, DestMax, CachedFpdtRecordPtr.DynamicStringEvent->String, StringLen);\r
1303 }\r
1436aea4 1304\r
6b4d58a1
BD
1305 mCachedLength = 0;\r
1306 }\r
9609d24b
DB
1307 }\r
1308\r
6b4d58a1
BD
1309 //\r
1310 // 5. Update the length of the used buffer after fill in the record.\r
1311 //\r
1312 if (mFpdtBufferIsReported) {\r
1436aea4 1313 mBootRecordSize += FpdtRecordPtr.RecordHeader->Length;\r
6b4d58a1
BD
1314 mAcpiBootPerformanceTable->Header.Length += FpdtRecordPtr.RecordHeader->Length;\r
1315 } else {\r
1316 mPerformanceLength += FpdtRecordPtr.RecordHeader->Length;\r
1317 }\r
1436aea4 1318\r
9609d24b
DB
1319 return EFI_SUCCESS;\r
1320}\r
1321\r
1322/**\r
1323 Dumps all the PEI performance.\r
1324\r
1325 @param HobStart A pointer to a Guid.\r
1326\r
1327 This internal function dumps all the PEI performance log to the DXE performance gauge array.\r
1328 It retrieves the optional GUID HOB for PEI performance and then saves the performance data\r
1329 to DXE performance data structures.\r
f0da4d7d 1330\r
9609d24b
DB
1331**/\r
1332VOID\r
1333InternalGetPeiPerformance (\r
1334 VOID *HobStart\r
1335 )\r
1336{\r
1436aea4
MK
1337 UINT8 *FirmwarePerformanceHob;\r
1338 FPDT_PEI_EXT_PERF_HEADER *PeiPerformanceLogHeader;\r
1339 UINT8 *EventRec;\r
1340 EFI_HOB_GUID_TYPE *GuidHob;\r
9609d24b
DB
1341\r
1342 GuidHob = GetNextGuidHob (&gEdkiiFpdtExtendedFirmwarePerformanceGuid, HobStart);\r
1343 while (GuidHob != NULL) {\r
1344 FirmwarePerformanceHob = GET_GUID_HOB_DATA (GuidHob);\r
1345 PeiPerformanceLogHeader = (FPDT_PEI_EXT_PERF_HEADER *)FirmwarePerformanceHob;\r
1346\r
1347 if (mPerformanceLength + PeiPerformanceLogHeader->SizeOfAllEntries > mMaxPerformanceLength) {\r
1348 mPerformancePointer = ReallocatePool (\r
1349 mPerformanceLength,\r
1350 mPerformanceLength +\r
1351 (UINTN)PeiPerformanceLogHeader->SizeOfAllEntries +\r
1352 FIRMWARE_RECORD_BUFFER,\r
1353 mPerformancePointer\r
1354 );\r
1355 ASSERT (mPerformancePointer != NULL);\r
1356 mMaxPerformanceLength = mPerformanceLength +\r
1357 (UINTN)(PeiPerformanceLogHeader->SizeOfAllEntries) +\r
1358 FIRMWARE_RECORD_BUFFER;\r
1359 }\r
f0da4d7d 1360\r
9609d24b
DB
1361 EventRec = mPerformancePointer + mPerformanceLength;\r
1362 CopyMem (EventRec, FirmwarePerformanceHob + sizeof (FPDT_PEI_EXT_PERF_HEADER), (UINTN)(PeiPerformanceLogHeader->SizeOfAllEntries));\r
a0afd019 1363 //\r
9609d24b 1364 // Update the used buffer size.\r
a0afd019 1365 //\r
9609d24b
DB
1366 mPerformanceLength += (UINTN)(PeiPerformanceLogHeader->SizeOfAllEntries);\r
1367 mLoadImageCount += PeiPerformanceLogHeader->LoadImageCount;\r
a0afd019 1368\r
9609d24b
DB
1369 //\r
1370 // Get next performance guid hob\r
1371 //\r
1372 GuidHob = GetNextGuidHob (&gEdkiiFpdtExtendedFirmwarePerformanceGuid, GET_NEXT_HOB (GuidHob));\r
a0afd019 1373 }\r
9609d24b 1374}\r
a0afd019 1375\r
9609d24b
DB
1376/**\r
1377 Report Boot Perforamnce table address as report status code.\r
a0afd019 1378\r
9609d24b
DB
1379 @param Event The event of notify protocol.\r
1380 @param Context Notify event context.\r
1381\r
1382**/\r
1383VOID\r
1384EFIAPI\r
1385ReportFpdtRecordBuffer (\r
1436aea4
MK
1386 IN EFI_EVENT Event,\r
1387 IN VOID *Context\r
9609d24b
DB
1388 )\r
1389{\r
1436aea4
MK
1390 EFI_STATUS Status;\r
1391 UINT64 BPDTAddr;\r
9609d24b
DB
1392\r
1393 if (!mFpdtBufferIsReported) {\r
1394 Status = AllocateBootPerformanceTable ();\r
1436aea4 1395 if (!EFI_ERROR (Status)) {\r
9609d24b
DB
1396 BPDTAddr = (UINT64)(UINTN)mAcpiBootPerformanceTable;\r
1397 REPORT_STATUS_CODE_EX (\r
1436aea4
MK
1398 EFI_PROGRESS_CODE,\r
1399 EFI_SOFTWARE_DXE_BS_DRIVER,\r
1400 0,\r
1401 NULL,\r
1402 &gEdkiiFpdtExtendedFirmwarePerformanceGuid,\r
1403 &BPDTAddr,\r
1404 sizeof (UINT64)\r
1405 );\r
9609d24b 1406 }\r
1436aea4 1407\r
9609d24b
DB
1408 //\r
1409 // Set FPDT report state to TRUE.\r
1410 //\r
1411 mFpdtBufferIsReported = TRUE;\r
a0afd019 1412 }\r
9609d24b 1413}\r
a0afd019 1414\r
466ebdd2
DB
1415/**\r
1416 Update Boot Performance table.\r
1417\r
1418 @param Event The event of notify protocol.\r
1419 @param Context Notify event context.\r
1420\r
1421**/\r
1422VOID\r
1423EFIAPI\r
1424UpdateBootPerformanceTable (\r
1436aea4
MK
1425 IN EFI_EVENT Event,\r
1426 IN VOID *Context\r
466ebdd2
DB
1427 )\r
1428{\r
1436aea4
MK
1429 VOID *SmmBootRecordData;\r
1430 UINTN SmmBootRecordDataSize;\r
1431 UINTN AppendSize;\r
1432 UINT8 *FirmwarePerformanceTablePtr;\r
466ebdd2 1433\r
dfafa8e4 1434 SmmBootRecordDataSize = 0;\r
1435\r
466ebdd2
DB
1436 //\r
1437 // Get SMM performance data.\r
1438 //\r
1439 SmmBootRecordData = NULL;\r
1440 InternalGetSmmPerfData (&SmmBootRecordData, &SmmBootRecordDataSize, FALSE);\r
1441\r
1436aea4 1442 FirmwarePerformanceTablePtr = (UINT8 *)mAcpiBootPerformanceTable + mAcpiBootPerformanceTable->Header.Length;\r
466ebdd2
DB
1443\r
1444 if (mAcpiBootPerformanceTable->Header.Length + SmmBootRecordDataSize > mBootRecordMaxSize) {\r
1445 DEBUG ((DEBUG_INFO, "DxeCorePerformanceLib: No enough space to save all SMM boot performance data\n"));\r
1446 AppendSize = mBootRecordMaxSize - mAcpiBootPerformanceTable->Header.Length;\r
1447 } else {\r
1448 AppendSize = SmmBootRecordDataSize;\r
1449 }\r
1436aea4 1450\r
466ebdd2
DB
1451 if (SmmBootRecordData != NULL) {\r
1452 CopyMem (FirmwarePerformanceTablePtr, SmmBootRecordData, AppendSize);\r
1436aea4
MK
1453 mAcpiBootPerformanceTable->Header.Length += (UINT32)AppendSize;\r
1454 mBootRecordSize += (UINT32)AppendSize;\r
466ebdd2
DB
1455 FreePool (SmmBootRecordData);\r
1456 }\r
1457}\r
1458\r
a0afd019 1459/**\r
1460 The constructor function initializes Performance infrastructure for DXE phase.\r
1461\r
f0da4d7d 1462 The constructor function publishes Performance and PerformanceEx protocol, allocates memory to log DXE performance\r
a0afd019 1463 and merges PEI performance data to DXE performance log.\r
1464 It will ASSERT() if one of these operations fails and it will always return EFI_SUCCESS.\r
1465\r
1466 @param ImageHandle The firmware allocated handle for the EFI image.\r
1467 @param SystemTable A pointer to the EFI System Table.\r
1468\r
1469 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.\r
1470\r
1471**/\r
1472EFI_STATUS\r
1473EFIAPI\r
1474DxeCorePerformanceLibConstructor (\r
1475 IN EFI_HANDLE ImageHandle,\r
1476 IN EFI_SYSTEM_TABLE *SystemTable\r
1477 )\r
1478{\r
1436aea4
MK
1479 EFI_STATUS Status;\r
1480 EFI_HANDLE Handle;\r
1481 EFI_EVENT EndOfDxeEvent;\r
1482 EFI_EVENT ReadyToBootEvent;\r
1483 PERFORMANCE_PROPERTY *PerformanceProperty;\r
cfb0aba7 1484\r
a0afd019 1485 if (!PerformanceMeasurementEnabled ()) {\r
1486 //\r
1487 // Do not initialize performance infrastructure if not required.\r
1488 //\r
1489 return EFI_SUCCESS;\r
1490 }\r
9609d24b
DB
1491\r
1492 //\r
1493 // Dump normal PEI performance records\r
1494 //\r
1436aea4 1495 InternalGetPeiPerformance (GetHobList ());\r
9609d24b 1496\r
a0afd019 1497 //\r
9609d24b 1498 // Install the protocol interfaces for DXE performance library instance.\r
a0afd019 1499 //\r
9609d24b 1500 Handle = NULL;\r
f0da4d7d 1501 Status = gBS->InstallMultipleProtocolInterfaces (\r
9609d24b 1502 &Handle,\r
137fb13d
BD
1503 &gEdkiiPerformanceMeasurementProtocolGuid,\r
1504 &mPerformanceMeasurementInterface,\r
f0da4d7d 1505 NULL\r
a0afd019 1506 );\r
1507 ASSERT_EFI_ERROR (Status);\r
1508\r
9609d24b 1509 //\r
466ebdd2 1510 // Register EndOfDxe event to allocate the boot performance table and report the table address through status code.\r
9609d24b
DB
1511 //\r
1512 Status = gBS->CreateEventEx (\r
1513 EVT_NOTIFY_SIGNAL,\r
466ebdd2 1514 TPL_NOTIFY,\r
9609d24b
DB
1515 ReportFpdtRecordBuffer,\r
1516 NULL,\r
466ebdd2
DB
1517 &gEfiEndOfDxeEventGroupGuid,\r
1518 &EndOfDxeEvent\r
1519 );\r
1520\r
1521 //\r
1522 // Register ReadyToBoot event to update the boot performance table for SMM performance data.\r
1523 //\r
1524 Status = gBS->CreateEventEx (\r
1525 EVT_NOTIFY_SIGNAL,\r
1526 TPL_CALLBACK,\r
1527 UpdateBootPerformanceTable,\r
1528 NULL,\r
9609d24b
DB
1529 &gEfiEventReadyToBootGuid,\r
1530 &ReadyToBootEvent\r
1531 );\r
a0afd019 1532\r
9609d24b 1533 ASSERT_EFI_ERROR (Status);\r
a0afd019 1534\r
1436aea4 1535 Status = EfiGetSystemConfigurationTable (&gPerformanceProtocolGuid, (VOID **)&PerformanceProperty);\r
cfb0aba7
SZ
1536 if (EFI_ERROR (Status)) {\r
1537 //\r
1538 // Install configuration table for performance property.\r
1539 //\r
1540 mPerformanceProperty.Revision = PERFORMANCE_PROPERTY_REVISION;\r
1541 mPerformanceProperty.Reserved = 0;\r
1542 mPerformanceProperty.Frequency = GetPerformanceCounterProperties (\r
1543 &mPerformanceProperty.TimerStartValue,\r
1544 &mPerformanceProperty.TimerEndValue\r
1545 );\r
1546 Status = gBS->InstallConfigurationTable (&gPerformanceProtocolGuid, &mPerformanceProperty);\r
1547 ASSERT_EFI_ERROR (Status);\r
1548 }\r
1549\r
1550 return EFI_SUCCESS;\r
a0afd019 1551}\r
1552\r
137fb13d
BD
1553/**\r
1554 Create performance record with event description and a timestamp.\r
1555\r
1556 @param CallerIdentifier - Image handle or pointer to caller ID GUID.\r
1557 @param Guid - Pointer to a GUID.\r
1558 @param String - Pointer to a string describing the measurement.\r
1559 @param TimeStamp - 64-bit time stamp.\r
1560 @param Address - Pointer to a location in memory relevant to the measurement.\r
1561 @param Identifier - Performance identifier describing the type of measurement.\r
1562 @param Attribute - The attribute of the measurement. According to attribute can create a start\r
1563 record for PERF_START/PERF_START_EX, or a end record for PERF_END/PERF_END_EX,\r
1564 or a general record for other Perf macros.\r
1565\r
1566 @retval EFI_SUCCESS - Successfully created performance record.\r
1567 @retval EFI_OUT_OF_RESOURCES - Ran out of space to store the records.\r
1568 @retval EFI_INVALID_PARAMETER - Invalid parameter passed to function - NULL\r
1569 pointer or invalid PerfId.\r
1570**/\r
1571EFI_STATUS\r
1572EFIAPI\r
1573CreatePerformanceMeasurement (\r
1574 IN CONST VOID *CallerIdentifier,\r
e3917e22
MK
1575 IN CONST VOID *Guid OPTIONAL,\r
1576 IN CONST CHAR8 *String OPTIONAL,\r
137fb13d 1577 IN UINT64 TimeStamp,\r
e3917e22 1578 IN UINT64 Address OPTIONAL,\r
137fb13d
BD
1579 IN UINT32 Identifier,\r
1580 IN PERF_MEASUREMENT_ATTRIBUTE Attribute\r
1581 )\r
1582{\r
1436aea4 1583 EFI_STATUS Status;\r
137fb13d
BD
1584\r
1585 Status = EFI_SUCCESS;\r
1586\r
1587 if (mLockInsertRecord) {\r
1588 return EFI_INVALID_PARAMETER;\r
1589 }\r
1436aea4 1590\r
137fb13d
BD
1591 mLockInsertRecord = TRUE;\r
1592\r
6b4d58a1
BD
1593 Status = InsertFpdtRecord (CallerIdentifier, Guid, String, TimeStamp, Address, (UINT16)Identifier, Attribute);\r
1594\r
137fb13d
BD
1595 mLockInsertRecord = FALSE;\r
1596\r
1597 return Status;\r
1598}\r
1599\r
a0afd019 1600/**\r
1601 Adds a record at the end of the performance measurement log\r
1602 that records the start time of a performance measurement.\r
1603\r
1604 Adds a record to the end of the performance measurement log\r
f0da4d7d 1605 that contains the Handle, Token, Module and Identifier.\r
a0afd019 1606 The end time of the new record must be set to zero.\r
1607 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.\r
1608 If TimeStamp is zero, the start time in the record is filled in with the value\r
1609 read from the current time stamp.\r
1610\r
1611 @param Handle Pointer to environment specific context used\r
1612 to identify the component being measured.\r
1613 @param Token Pointer to a Null-terminated ASCII string\r
1614 that identifies the component being measured.\r
1615 @param Module Pointer to a Null-terminated ASCII string\r
1616 that identifies the module being measured.\r
1617 @param TimeStamp 64-bit time stamp.\r
f0da4d7d
SZ
1618 @param Identifier 32-bit identifier. If the value is 0, the created record\r
1619 is same as the one created by StartPerformanceMeasurement.\r
a0afd019 1620\r
1621 @retval RETURN_SUCCESS The start of the measurement was recorded.\r
1622 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.\r
1623\r
1624**/\r
1625RETURN_STATUS\r
1626EFIAPI\r
f0da4d7d 1627StartPerformanceMeasurementEx (\r
e3917e22
MK
1628 IN CONST VOID *Handle OPTIONAL,\r
1629 IN CONST CHAR8 *Token OPTIONAL,\r
1630 IN CONST CHAR8 *Module OPTIONAL,\r
f0da4d7d
SZ
1631 IN UINT64 TimeStamp,\r
1632 IN UINT32 Identifier\r
a0afd019 1633 )\r
1634{\r
1436aea4 1635 CONST CHAR8 *String;\r
137fb13d
BD
1636\r
1637 if (Token != NULL) {\r
1638 String = Token;\r
1639 } else if (Module != NULL) {\r
1640 String = Module;\r
1641 } else {\r
1642 String = NULL;\r
1643 }\r
1644\r
1645 return (RETURN_STATUS)CreatePerformanceMeasurement (Handle, NULL, String, TimeStamp, 0, Identifier, PerfStartEntry);\r
a0afd019 1646}\r
1647\r
1648/**\r
1649 Searches the performance measurement log from the beginning of the log\r
1650 for the first matching record that contains a zero end time and fills in a valid end time.\r
1651\r
1652 Searches the performance measurement log from the beginning of the log\r
9609d24b 1653 for the first record that matches Handle, Token, Module and Identifier and has an end time value of zero.\r
a0afd019 1654 If the record can not be found then return RETURN_NOT_FOUND.\r
1655 If the record is found and TimeStamp is not zero,\r
1656 then the end time in the record is filled in with the value specified by TimeStamp.\r
1657 If the record is found and TimeStamp is zero, then the end time in the matching record\r
1658 is filled in with the current time stamp value.\r
1659\r
1660 @param Handle Pointer to environment specific context used\r
1661 to identify the component being measured.\r
1662 @param Token Pointer to a Null-terminated ASCII string\r
1663 that identifies the component being measured.\r
1664 @param Module Pointer to a Null-terminated ASCII string\r
1665 that identifies the module being measured.\r
1666 @param TimeStamp 64-bit time stamp.\r
f0da4d7d
SZ
1667 @param Identifier 32-bit identifier. If the value is 0, the found record\r
1668 is same as the one found by EndPerformanceMeasurement.\r
a0afd019 1669\r
1670 @retval RETURN_SUCCESS The end of the measurement was recorded.\r
1671 @retval RETURN_NOT_FOUND The specified measurement record could not be found.\r
1672\r
1673**/\r
1674RETURN_STATUS\r
1675EFIAPI\r
f0da4d7d 1676EndPerformanceMeasurementEx (\r
e3917e22
MK
1677 IN CONST VOID *Handle OPTIONAL,\r
1678 IN CONST CHAR8 *Token OPTIONAL,\r
1679 IN CONST CHAR8 *Module OPTIONAL,\r
f0da4d7d
SZ
1680 IN UINT64 TimeStamp,\r
1681 IN UINT32 Identifier\r
a0afd019 1682 )\r
1683{\r
1436aea4 1684 CONST CHAR8 *String;\r
137fb13d
BD
1685\r
1686 if (Token != NULL) {\r
1687 String = Token;\r
1688 } else if (Module != NULL) {\r
1689 String = Module;\r
1690 } else {\r
1691 String = NULL;\r
1692 }\r
1693\r
1694 return (RETURN_STATUS)CreatePerformanceMeasurement (Handle, NULL, String, TimeStamp, 0, Identifier, PerfEndEntry);\r
a0afd019 1695}\r
1696\r
1697/**\r
1698 Attempts to retrieve a performance measurement log entry from the performance measurement log.\r
f0da4d7d
SZ
1699 It can also retrieve the log created by StartPerformanceMeasurement and EndPerformanceMeasurement,\r
1700 and then assign the Identifier with 0.\r
a0afd019 1701\r
9609d24b
DB
1702 !!! Not support!!!\r
1703\r
a0afd019 1704 Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is\r
1705 zero on entry, then an attempt is made to retrieve the first entry from the performance log,\r
1706 and the key for the second entry in the log is returned. If the performance log is empty,\r
1707 then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance\r
1708 log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is\r
1709 returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is\r
1710 retrieved and an implementation specific non-zero key value that specifies the end of the performance\r
1711 log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry\r
1712 is retrieved and zero is returned. In the cases where a performance log entry can be returned,\r
f0da4d7d 1713 the log entry is returned in Handle, Token, Module, StartTimeStamp, EndTimeStamp and Identifier.\r
a0afd019 1714 If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().\r
1715 If Handle is NULL, then ASSERT().\r
1716 If Token is NULL, then ASSERT().\r
1717 If Module is NULL, then ASSERT().\r
1718 If StartTimeStamp is NULL, then ASSERT().\r
1719 If EndTimeStamp is NULL, then ASSERT().\r
f0da4d7d 1720 If Identifier is NULL, then ASSERT().\r
a0afd019 1721\r
1722 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.\r
1723 0, then the first performance measurement log entry is retrieved.\r
857dfc45 1724 On exit, the key of the next performance log entry.\r
a0afd019 1725 @param Handle Pointer to environment specific context used to identify the component\r
1726 being measured.\r
1727 @param Token Pointer to a Null-terminated ASCII string that identifies the component\r
1728 being measured.\r
1729 @param Module Pointer to a Null-terminated ASCII string that identifies the module\r
1730 being measured.\r
1731 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement\r
1732 was started.\r
1733 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement\r
1734 was ended.\r
9609d24b
DB
1735 @param Identifier Pointer to the 32-bit identifier that was recorded when the measurement\r
1736 was ended.\r
a0afd019 1737\r
1738 @return The key for the next performance log entry (in general case).\r
1739\r
1740**/\r
1741UINTN\r
1742EFIAPI\r
f0da4d7d 1743GetPerformanceMeasurementEx (\r
1436aea4
MK
1744 IN UINTN LogEntryKey,\r
1745 OUT CONST VOID **Handle,\r
1746 OUT CONST CHAR8 **Token,\r
1747 OUT CONST CHAR8 **Module,\r
1748 OUT UINT64 *StartTimeStamp,\r
1749 OUT UINT64 *EndTimeStamp,\r
1750 OUT UINT32 *Identifier\r
a0afd019 1751 )\r
1752{\r
9609d24b 1753 return 0;\r
a0afd019 1754}\r
1755\r
f0da4d7d
SZ
1756/**\r
1757 Adds a record at the end of the performance measurement log\r
1758 that records the start time of a performance measurement.\r
1759\r
1760 Adds a record to the end of the performance measurement log\r
1761 that contains the Handle, Token, and Module.\r
1762 The end time of the new record must be set to zero.\r
1763 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.\r
1764 If TimeStamp is zero, the start time in the record is filled in with the value\r
1765 read from the current time stamp.\r
1766\r
1767 @param Handle Pointer to environment specific context used\r
1768 to identify the component being measured.\r
1769 @param Token Pointer to a Null-terminated ASCII string\r
1770 that identifies the component being measured.\r
1771 @param Module Pointer to a Null-terminated ASCII string\r
1772 that identifies the module being measured.\r
1773 @param TimeStamp 64-bit time stamp.\r
1774\r
1775 @retval RETURN_SUCCESS The start of the measurement was recorded.\r
1776 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.\r
1777\r
1778**/\r
1779RETURN_STATUS\r
1780EFIAPI\r
1781StartPerformanceMeasurement (\r
e3917e22
MK
1782 IN CONST VOID *Handle OPTIONAL,\r
1783 IN CONST CHAR8 *Token OPTIONAL,\r
1784 IN CONST CHAR8 *Module OPTIONAL,\r
f0da4d7d
SZ
1785 IN UINT64 TimeStamp\r
1786 )\r
1787{\r
137fb13d 1788 return StartPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);\r
f0da4d7d
SZ
1789}\r
1790\r
1791/**\r
1792 Searches the performance measurement log from the beginning of the log\r
1793 for the first matching record that contains a zero end time and fills in a valid end time.\r
1794\r
1795 Searches the performance measurement log from the beginning of the log\r
1796 for the first record that matches Handle, Token, and Module and has an end time value of zero.\r
1797 If the record can not be found then return RETURN_NOT_FOUND.\r
1798 If the record is found and TimeStamp is not zero,\r
1799 then the end time in the record is filled in with the value specified by TimeStamp.\r
1800 If the record is found and TimeStamp is zero, then the end time in the matching record\r
1801 is filled in with the current time stamp value.\r
1802\r
1803 @param Handle Pointer to environment specific context used\r
1804 to identify the component being measured.\r
1805 @param Token Pointer to a Null-terminated ASCII string\r
1806 that identifies the component being measured.\r
1807 @param Module Pointer to a Null-terminated ASCII string\r
1808 that identifies the module being measured.\r
1809 @param TimeStamp 64-bit time stamp.\r
1810\r
1811 @retval RETURN_SUCCESS The end of the measurement was recorded.\r
1812 @retval RETURN_NOT_FOUND The specified measurement record could not be found.\r
1813\r
1814**/\r
1815RETURN_STATUS\r
1816EFIAPI\r
1817EndPerformanceMeasurement (\r
e3917e22
MK
1818 IN CONST VOID *Handle OPTIONAL,\r
1819 IN CONST CHAR8 *Token OPTIONAL,\r
1820 IN CONST CHAR8 *Module OPTIONAL,\r
f0da4d7d
SZ
1821 IN UINT64 TimeStamp\r
1822 )\r
1823{\r
137fb13d 1824 return EndPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);\r
f0da4d7d
SZ
1825}\r
1826\r
1827/**\r
1828 Attempts to retrieve a performance measurement log entry from the performance measurement log.\r
1829 It can also retrieve the log created by StartPerformanceMeasurementEx and EndPerformanceMeasurementEx,\r
1830 and then eliminate the Identifier.\r
1831\r
9609d24b
DB
1832 !!! Not support!!!\r
1833\r
f0da4d7d
SZ
1834 Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is\r
1835 zero on entry, then an attempt is made to retrieve the first entry from the performance log,\r
1836 and the key for the second entry in the log is returned. If the performance log is empty,\r
1837 then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance\r
1838 log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is\r
1839 returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is\r
1840 retrieved and an implementation specific non-zero key value that specifies the end of the performance\r
1841 log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry\r
1842 is retrieved and zero is returned. In the cases where a performance log entry can be returned,\r
1843 the log entry is returned in Handle, Token, Module, StartTimeStamp, and EndTimeStamp.\r
1844 If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().\r
1845 If Handle is NULL, then ASSERT().\r
1846 If Token is NULL, then ASSERT().\r
1847 If Module is NULL, then ASSERT().\r
1848 If StartTimeStamp is NULL, then ASSERT().\r
1849 If EndTimeStamp is NULL, then ASSERT().\r
1850\r
1851 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.\r
1852 0, then the first performance measurement log entry is retrieved.\r
1853 On exit, the key of the next performance log entry.\r
1854 @param Handle Pointer to environment specific context used to identify the component\r
1855 being measured.\r
1856 @param Token Pointer to a Null-terminated ASCII string that identifies the component\r
1857 being measured.\r
1858 @param Module Pointer to a Null-terminated ASCII string that identifies the module\r
1859 being measured.\r
1860 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement\r
1861 was started.\r
1862 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement\r
1863 was ended.\r
1864\r
1865 @return The key for the next performance log entry (in general case).\r
1866\r
1867**/\r
1868UINTN\r
1869EFIAPI\r
1870GetPerformanceMeasurement (\r
1436aea4
MK
1871 IN UINTN LogEntryKey,\r
1872 OUT CONST VOID **Handle,\r
1873 OUT CONST CHAR8 **Token,\r
1874 OUT CONST CHAR8 **Module,\r
1875 OUT UINT64 *StartTimeStamp,\r
1876 OUT UINT64 *EndTimeStamp\r
f0da4d7d
SZ
1877 )\r
1878{\r
9609d24b 1879 return 0;\r
f0da4d7d
SZ
1880}\r
1881\r
a0afd019 1882/**\r
1883 Returns TRUE if the performance measurement macros are enabled.\r
1884\r
1885 This function returns TRUE if the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of\r
1886 PcdPerformanceLibraryPropertyMask is set. Otherwise FALSE is returned.\r
1887\r
1888 @retval TRUE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of\r
1889 PcdPerformanceLibraryPropertyMask is set.\r
1890 @retval FALSE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of\r
1891 PcdPerformanceLibraryPropertyMask is clear.\r
1892\r
1893**/\r
1894BOOLEAN\r
1895EFIAPI\r
1896PerformanceMeasurementEnabled (\r
1897 VOID\r
1898 )\r
1899{\r
1436aea4 1900 return (BOOLEAN)((PcdGet8 (PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0);\r
a0afd019 1901}\r
6b4d58a1
BD
1902\r
1903/**\r
1904 Create performance record with event description and a timestamp.\r
1905\r
1906 @param CallerIdentifier - Image handle or pointer to caller ID GUID\r
1907 @param Guid - Pointer to a GUID\r
1908 @param String - Pointer to a string describing the measurement\r
1909 @param Address - Pointer to a location in memory relevant to the measurement\r
1910 @param Identifier - Performance identifier describing the type of measurement\r
1911\r
1912 @retval RETURN_SUCCESS - Successfully created performance record\r
1913 @retval RETURN_OUT_OF_RESOURCES - Ran out of space to store the records\r
1914 @retval RETURN_INVALID_PARAMETER - Invalid parameter passed to function - NULL\r
1915 pointer or invalid PerfId\r
1916\r
1917**/\r
1918RETURN_STATUS\r
1919EFIAPI\r
1920LogPerformanceMeasurement (\r
1921 IN CONST VOID *CallerIdentifier,\r
e3917e22
MK
1922 IN CONST VOID *Guid OPTIONAL,\r
1923 IN CONST CHAR8 *String OPTIONAL,\r
1924 IN UINT64 Address OPTIONAL,\r
6b4d58a1
BD
1925 IN UINT32 Identifier\r
1926 )\r
1927{\r
1928 return (RETURN_STATUS)CreatePerformanceMeasurement (CallerIdentifier, Guid, String, 0, Address, Identifier, PerfEntry);\r
1929}\r
1930\r
1931/**\r
1932 Check whether the specified performance measurement can be logged.\r
1933\r
1934 This function returns TRUE when the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set\r
1935 and the Type disable bit in PcdPerformanceLibraryPropertyMask is not set.\r
1936\r
1937 @param Type - Type of the performance measurement entry.\r
1938\r
1939 @retval TRUE The performance measurement can be logged.\r
1940 @retval FALSE The performance measurement can NOT be logged.\r
1941\r
1942**/\r
1943BOOLEAN\r
1944EFIAPI\r
1945LogPerformanceMeasurementEnabled (\r
1436aea4 1946 IN CONST UINTN Type\r
6b4d58a1
BD
1947 )\r
1948{\r
1949 //\r
1950 // When Performance measurement is enabled and the type is not filtered, the performance can be logged.\r
1951 //\r
1436aea4 1952 if (PerformanceMeasurementEnabled () && ((PcdGet8 (PcdPerformanceLibraryPropertyMask) & Type) == 0)) {\r
6b4d58a1
BD
1953 return TRUE;\r
1954 }\r
1436aea4 1955\r
6b4d58a1
BD
1956 return FALSE;\r
1957}\r