2 Performance library instance mainly used by DxeCore.
4 This library provides the performance measurement interfaces and initializes performance
5 logging for DXE phase. It first initializes its private global data structure for
6 performance logging and saves the performance GUIDed HOB passed from PEI phase.
7 It initializes DXE phase performance logging by publishing the Performance and PerformanceEx Protocol,
8 which are consumed by DxePerformanceLib to logging performance data in DXE phase.
10 This library is mainly used by DxeCore to start performance logging to ensure that
11 Performance Protocol is installed at the very beginning of DXE phase.
13 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
14 (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
15 This program and the accompanying materials
16 are licensed and made available under the terms and conditions of the BSD License
17 which accompanies this distribution. The full text of the license may be found at
18 http://opensource.org/licenses/bsd-license.php
20 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
21 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
26 #include "DxeCorePerformanceLibInternal.h"
29 // Data for FPDT performance records.
31 #define SMM_BOOT_RECORD_COMM_SIZE (OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data) + sizeof(SMM_BOOT_RECORD_COMMUNICATE))
32 #define STRING_SIZE (FPDT_STRING_EVENT_RECORD_NAME_LENGTH * sizeof (CHAR8))
33 #define FIRMWARE_RECORD_BUFFER 0x10000
34 #define CACHE_HANDLE_GUID_COUNT 0x800
36 BOOT_PERFORMANCE_TABLE
*mAcpiBootPerformanceTable
= NULL
;
37 BOOT_PERFORMANCE_TABLE mBootPerformanceTableTemplate
= {
39 EFI_ACPI_5_0_FPDT_BOOT_PERFORMANCE_TABLE_SIGNATURE
,
40 sizeof (BOOT_PERFORMANCE_TABLE
)
44 EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_TYPE_FIRMWARE_BASIC_BOOT
, // Type
45 sizeof (EFI_ACPI_5_0_FPDT_FIRMWARE_BASIC_BOOT_RECORD
), // Length
46 EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_REVISION_FIRMWARE_BASIC_BOOT
// Revision
50 // These values will be updated at runtime.
53 0, // OsLoaderLoadImageStart
54 0, // OsLoaderStartImageStart
55 0, // ExitBootServicesEntry
56 0 // ExitBootServicesExit
62 CHAR8 NameString
[FPDT_STRING_EVENT_RECORD_NAME_LENGTH
];
66 HANDLE_GUID_MAP mCacheHandleGuidTable
[CACHE_HANDLE_GUID_COUNT
];
67 UINTN mCachePairCount
= 0;
69 UINT32 mLoadImageCount
= 0;
70 UINT32 mPerformanceLength
= 0;
71 UINT32 mMaxPerformanceLength
= 0;
72 UINT32 mBootRecordSize
= 0;
73 UINT32 mBootRecordMaxSize
= 0;
75 BOOLEAN mFpdtBufferIsReported
= FALSE
;
76 BOOLEAN mLackSpaceIsReported
= FALSE
;
77 CHAR8
*mPlatformLanguage
= NULL
;
78 UINT8
*mPerformancePointer
= NULL
;
79 UINT8
*mBootRecordBuffer
= NULL
;
80 BOOLEAN mLockInsertRecord
= FALSE
;
82 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL
*mDevicePathToText
= NULL
;
85 // Interfaces for Performance Protocol.
87 PERFORMANCE_PROTOCOL mPerformanceInterface
= {
94 // Interfaces for PerformanceEx Protocol.
96 PERFORMANCE_EX_PROTOCOL mPerformanceExInterface
= {
102 PERFORMANCE_PROPERTY mPerformanceProperty
;
105 Check whether the Token is a known one which is uesed by core.
107 @param Token Pointer to a Null-terminated ASCII string
109 @retval TRUE Is a known one used by core.
110 @retval FALSE Not a known one.
115 IN CONST CHAR8
*Token
118 if (AsciiStrCmp (Token
, SEC_TOK
) == 0 ||
119 AsciiStrCmp (Token
, PEI_TOK
) == 0 ||
120 AsciiStrCmp (Token
, DXE_TOK
) == 0 ||
121 AsciiStrCmp (Token
, BDS_TOK
) == 0 ||
122 AsciiStrCmp (Token
, DRIVERBINDING_START_TOK
) == 0 ||
123 AsciiStrCmp (Token
, DRIVERBINDING_SUPPORT_TOK
) == 0 ||
124 AsciiStrCmp (Token
, DRIVERBINDING_STOP_TOK
) == 0 ||
125 AsciiStrCmp (Token
, LOAD_IMAGE_TOK
) == 0 ||
126 AsciiStrCmp (Token
, START_IMAGE_TOK
) == 0 ||
127 AsciiStrCmp (Token
, PEIM_TOK
) == 0) {
135 Check whether the ID is a known one which map to the known Token.
137 @param Identifier 32-bit identifier.
139 @retval TRUE Is a known one used by core.
140 @retval FALSE Not a known one.
148 if (Identifier
== MODULE_START_ID
||
149 Identifier
== MODULE_END_ID
||
150 Identifier
== MODULE_LOADIMAGE_START_ID
||
151 Identifier
== MODULE_LOADIMAGE_END_ID
||
152 Identifier
== MODULE_DB_START_ID
||
153 Identifier
== MODULE_DB_END_ID
||
154 Identifier
== MODULE_DB_SUPPORT_START_ID
||
155 Identifier
== MODULE_DB_SUPPORT_END_ID
||
156 Identifier
== MODULE_DB_STOP_START_ID
||
157 Identifier
== MODULE_DB_STOP_END_ID
) {
165 Allocate EfiReservedMemoryType below 4G memory address.
167 This function allocates EfiReservedMemoryType below 4G memory address.
169 @param[in] Size Size of memory to allocate.
171 @return Allocated address for output.
175 FpdtAllocateReservedMemoryBelow4G (
180 EFI_PHYSICAL_ADDRESS Address
;
185 Pages
= EFI_SIZE_TO_PAGES (Size
);
186 Address
= 0xffffffff;
188 Status
= gBS
->AllocatePages (
190 EfiReservedMemoryType
,
194 ASSERT_EFI_ERROR (Status
);
196 if (!EFI_ERROR (Status
)) {
197 Buffer
= (VOID
*) (UINTN
) Address
;
198 ZeroMem (Buffer
, Size
);
205 Allocate buffer for Boot Performance table.
211 AllocateBootPerformanceTable (
216 UINT8
*SmmBootRecordCommBuffer
;
217 EFI_SMM_COMMUNICATE_HEADER
*SmmCommBufferHeader
;
218 SMM_BOOT_RECORD_COMMUNICATE
*SmmCommData
;
220 UINTN BootPerformanceDataSize
;
221 UINT8
*BootPerformanceData
;
222 EFI_SMM_COMMUNICATION_PROTOCOL
*Communication
;
223 FIRMWARE_PERFORMANCE_VARIABLE PerformanceVariable
;
224 EDKII_PI_SMM_COMMUNICATION_REGION_TABLE
*SmmCommRegionTable
;
225 EFI_MEMORY_DESCRIPTOR
*SmmCommMemRegion
;
227 VOID
*SmmBootRecordData
;
228 UINTN SmmBootRecordDataSize
;
229 UINTN ReservedMemSize
;
232 // Collect boot records from SMM drivers.
234 SmmBootRecordCommBuffer
= NULL
;
236 SmmBootRecordData
= NULL
;
237 SmmBootRecordDataSize
= 0;
239 Status
= gBS
->LocateProtocol (&gEfiSmmCommunicationProtocolGuid
, NULL
, (VOID
**) &Communication
);
240 if (!EFI_ERROR (Status
)) {
242 // Initialize communicate buffer
243 // Get the prepared Reserved Memory Range
245 Status
= EfiGetSystemConfigurationTable (
246 &gEdkiiPiSmmCommunicationRegionTableGuid
,
247 (VOID
**) &SmmCommRegionTable
249 if (!EFI_ERROR (Status
)) {
250 ASSERT (SmmCommRegionTable
!= NULL
);
251 SmmCommMemRegion
= (EFI_MEMORY_DESCRIPTOR
*) (SmmCommRegionTable
+ 1);
252 for (Index
= 0; Index
< SmmCommRegionTable
->NumberOfEntries
; Index
++) {
253 if (SmmCommMemRegion
->Type
== EfiConventionalMemory
) {
256 SmmCommMemRegion
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) SmmCommMemRegion
+ SmmCommRegionTable
->DescriptorSize
);
258 ASSERT (Index
< SmmCommRegionTable
->NumberOfEntries
);
259 ASSERT (SmmCommMemRegion
->PhysicalStart
> 0);
260 ASSERT (SmmCommMemRegion
->NumberOfPages
> 0);
261 ReservedMemSize
= (UINTN
) SmmCommMemRegion
->NumberOfPages
* EFI_PAGE_SIZE
;
264 // Check enough reserved memory space
266 if (ReservedMemSize
> SMM_BOOT_RECORD_COMM_SIZE
) {
267 SmmBootRecordCommBuffer
= (VOID
*) (UINTN
) SmmCommMemRegion
->PhysicalStart
;
268 SmmCommBufferHeader
= (EFI_SMM_COMMUNICATE_HEADER
*)SmmBootRecordCommBuffer
;
269 SmmCommData
= (SMM_BOOT_RECORD_COMMUNICATE
*)SmmCommBufferHeader
->Data
;
270 ZeroMem((UINT8
*)SmmCommData
, sizeof(SMM_BOOT_RECORD_COMMUNICATE
));
272 CopyGuid (&SmmCommBufferHeader
->HeaderGuid
, &gEfiFirmwarePerformanceGuid
);
273 SmmCommBufferHeader
->MessageLength
= sizeof(SMM_BOOT_RECORD_COMMUNICATE
);
274 CommSize
= SMM_BOOT_RECORD_COMM_SIZE
;
277 // Get the size of boot records.
279 SmmCommData
->Function
= SMM_FPDT_FUNCTION_GET_BOOT_RECORD_SIZE
;
280 SmmCommData
->BootRecordData
= NULL
;
281 Status
= Communication
->Communicate (Communication
, SmmBootRecordCommBuffer
, &CommSize
);
282 ASSERT_EFI_ERROR (Status
);
284 if (!EFI_ERROR (SmmCommData
->ReturnStatus
) && SmmCommData
->BootRecordSize
!= 0) {
286 // Get all boot records
288 SmmCommData
->Function
= SMM_FPDT_FUNCTION_GET_BOOT_RECORD_DATA_BY_OFFSET
;
289 SmmBootRecordDataSize
= SmmCommData
->BootRecordSize
;
290 SmmBootRecordData
= AllocateZeroPool(SmmBootRecordDataSize
);
291 ASSERT (SmmBootRecordData
!= NULL
);
292 SmmCommData
->BootRecordOffset
= 0;
293 SmmCommData
->BootRecordData
= (VOID
*) ((UINTN
) SmmCommMemRegion
->PhysicalStart
+ SMM_BOOT_RECORD_COMM_SIZE
);
294 SmmCommData
->BootRecordSize
= ReservedMemSize
- SMM_BOOT_RECORD_COMM_SIZE
;
295 while (SmmCommData
->BootRecordOffset
< SmmBootRecordDataSize
) {
296 Status
= Communication
->Communicate (Communication
, SmmBootRecordCommBuffer
, &CommSize
);
297 ASSERT_EFI_ERROR (Status
);
298 ASSERT_EFI_ERROR(SmmCommData
->ReturnStatus
);
299 if (SmmCommData
->BootRecordOffset
+ SmmCommData
->BootRecordSize
> SmmBootRecordDataSize
) {
300 CopyMem ((UINT8
*) SmmBootRecordData
+ SmmCommData
->BootRecordOffset
, SmmCommData
->BootRecordData
, SmmBootRecordDataSize
- SmmCommData
->BootRecordOffset
);
302 CopyMem ((UINT8
*) SmmBootRecordData
+ SmmCommData
->BootRecordOffset
, SmmCommData
->BootRecordData
, SmmCommData
->BootRecordSize
);
304 SmmCommData
->BootRecordOffset
= SmmCommData
->BootRecordOffset
+ SmmCommData
->BootRecordSize
;
312 // Prepare memory for Boot Performance table.
313 // Boot Performance table includes BasicBoot record, and one or more appended Boot Records.
315 BootPerformanceDataSize
= sizeof (BOOT_PERFORMANCE_TABLE
) + mPerformanceLength
+ PcdGet32 (PcdExtFpdtBootRecordPadSize
);
316 if (SmmCommData
!= NULL
) {
317 BootPerformanceDataSize
+= SmmBootRecordDataSize
;
321 // Try to allocate the same runtime buffer as last time boot.
323 ZeroMem (&PerformanceVariable
, sizeof (PerformanceVariable
));
324 Size
= sizeof (PerformanceVariable
);
325 Status
= gRT
->GetVariable (
326 EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME
,
327 &gEfiFirmwarePerformanceGuid
,
332 if (!EFI_ERROR (Status
)) {
333 Status
= gBS
->AllocatePages (
335 EfiReservedMemoryType
,
336 EFI_SIZE_TO_PAGES (BootPerformanceDataSize
),
337 &PerformanceVariable
.BootPerformanceTablePointer
339 if (!EFI_ERROR (Status
)) {
340 mAcpiBootPerformanceTable
= (BOOT_PERFORMANCE_TABLE
*) (UINTN
) PerformanceVariable
.BootPerformanceTablePointer
;
344 if (mAcpiBootPerformanceTable
== NULL
) {
346 // Fail to allocate at specified address, continue to allocate at any address.
348 mAcpiBootPerformanceTable
= (BOOT_PERFORMANCE_TABLE
*) FpdtAllocateReservedMemoryBelow4G (BootPerformanceDataSize
);
350 DEBUG ((DEBUG_INFO
, "DxeCorePerformanceLib: ACPI Boot Performance Table address = 0x%x\n", mAcpiBootPerformanceTable
));
352 if (mAcpiBootPerformanceTable
== NULL
) {
353 if (SmmCommData
!= NULL
&& SmmBootRecordData
!= NULL
) {
354 FreePool (SmmBootRecordData
);
356 return EFI_OUT_OF_RESOURCES
;
360 // Prepare Boot Performance Table.
362 BootPerformanceData
= (UINT8
*) mAcpiBootPerformanceTable
;
364 // Fill Basic Boot record to Boot Performance Table.
366 CopyMem (mAcpiBootPerformanceTable
, &mBootPerformanceTableTemplate
, sizeof (mBootPerformanceTableTemplate
));
367 BootPerformanceData
= BootPerformanceData
+ mAcpiBootPerformanceTable
->Header
.Length
;
369 // Fill Boot records from boot drivers.
371 if (mPerformancePointer
!= NULL
) {
372 CopyMem (BootPerformanceData
, mPerformancePointer
, mPerformanceLength
);
373 mAcpiBootPerformanceTable
->Header
.Length
+= mPerformanceLength
;
374 BootPerformanceData
= BootPerformanceData
+ mPerformanceLength
;
375 FreePool (mPerformancePointer
);
376 mPerformancePointer
= NULL
;
377 mPerformanceLength
= 0;
378 mMaxPerformanceLength
= 0;
380 if (SmmCommData
!= NULL
&& SmmBootRecordData
!= NULL
) {
382 // Fill Boot records from SMM drivers.
384 CopyMem (BootPerformanceData
, SmmBootRecordData
, SmmBootRecordDataSize
);
385 FreePool (SmmBootRecordData
);
386 mAcpiBootPerformanceTable
->Header
.Length
= (UINT32
) (mAcpiBootPerformanceTable
->Header
.Length
+ SmmBootRecordDataSize
);
387 BootPerformanceData
= BootPerformanceData
+ SmmBootRecordDataSize
;
390 mBootRecordBuffer
= (UINT8
*) mAcpiBootPerformanceTable
;
391 mBootRecordSize
= mAcpiBootPerformanceTable
->Header
.Length
;
392 mBootRecordMaxSize
= mBootRecordSize
+ PcdGet32 (PcdExtFpdtBootRecordPadSize
);
398 Get a human readable module name and module guid for the given image handle.
399 If module name can't be found, "" string will return.
400 If module guid can't be found, Zero Guid will return.
402 @param Handle Image handle or Controller handle.
403 @param NameString The ascii string will be filled into it. If not found, null string will return.
404 @param BufferSize Size of the input NameString buffer.
405 @param ModuleGuid Point to the guid buffer to store the got module guid value.
407 @retval EFI_SUCCESS Successfully get module name and guid.
408 @retval EFI_INVALID_PARAMETER The input parameter NameString is NULL.
409 @retval other value Module Name can't be got.
412 GetModuleInfoFromHandle (
413 IN EFI_HANDLE Handle
,
414 OUT CHAR8
*NameString
,
416 OUT EFI_GUID
*ModuleGuid OPTIONAL
420 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
421 EFI_DRIVER_BINDING_PROTOCOL
*DriverBinding
;
427 BOOLEAN ModuleGuidIsGet
;
430 EFI_COMPONENT_NAME2_PROTOCOL
*ComponentName2
;
431 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FvFilePath
;
433 if (NameString
== NULL
|| BufferSize
== 0) {
434 return EFI_INVALID_PARAMETER
;
437 // Try to get the ModuleGuid and name string form the caached array.
439 if (mCachePairCount
> 0) {
440 for (Count
= mCachePairCount
-1; Count
>= 0; Count
--) {
441 if (Handle
== mCacheHandleGuidTable
[Count
].Handle
) {
442 CopyGuid (ModuleGuid
, &mCacheHandleGuidTable
[Count
].ModuleGuid
);
443 AsciiStrCpyS (NameString
, FPDT_STRING_EVENT_RECORD_NAME_LENGTH
, mCacheHandleGuidTable
[Count
].NameString
);
449 Status
= EFI_INVALID_PARAMETER
;
451 ModuleGuidIsGet
= FALSE
;
454 // Initialize GUID as zero value.
456 TempGuid
= &gZeroGuid
;
458 // Initialize it as "" string.
462 if (Handle
!= NULL
) {
464 // Try Handle as ImageHandle.
466 Status
= gBS
->HandleProtocol (
468 &gEfiLoadedImageProtocolGuid
,
469 (VOID
**) &LoadedImage
472 if (EFI_ERROR (Status
)) {
474 // Try Handle as Controller Handle
476 Status
= gBS
->OpenProtocol (
478 &gEfiDriverBindingProtocolGuid
,
479 (VOID
**) &DriverBinding
,
482 EFI_OPEN_PROTOCOL_GET_PROTOCOL
484 if (!EFI_ERROR (Status
)) {
486 // Get Image protocol from ImageHandle
488 Status
= gBS
->HandleProtocol (
489 DriverBinding
->ImageHandle
,
490 &gEfiLoadedImageProtocolGuid
,
491 (VOID
**) &LoadedImage
497 if (!EFI_ERROR (Status
) && LoadedImage
!= NULL
) {
499 // Get Module Guid from DevicePath.
501 if (LoadedImage
->FilePath
!= NULL
&&
502 LoadedImage
->FilePath
->Type
== MEDIA_DEVICE_PATH
&&
503 LoadedImage
->FilePath
->SubType
== MEDIA_PIWG_FW_FILE_DP
506 // Determine GUID associated with module logging performance
508 ModuleGuidIsGet
= TRUE
;
509 FvFilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) LoadedImage
->FilePath
;
510 TempGuid
= &FvFilePath
->FvFileName
;
514 // Method 1 Get Module Name from PDB string.
516 PdbFileName
= PeCoffLoaderGetPdbPointer (LoadedImage
->ImageBase
);
517 if (PdbFileName
!= NULL
&& BufferSize
> 0) {
519 for (Index
= 0; PdbFileName
[Index
] != 0; Index
++) {
520 if ((PdbFileName
[Index
] == '\\') || (PdbFileName
[Index
] == '/')) {
521 StartIndex
= Index
+ 1;
525 // Copy the PDB file name to our temporary string.
526 // If the length is bigger than BufferSize, trim the redudant characters to avoid overflow in array boundary.
528 for (Index
= 0; Index
< BufferSize
- 1; Index
++) {
529 NameString
[Index
] = PdbFileName
[Index
+ StartIndex
];
530 if (NameString
[Index
] == 0 || NameString
[Index
] == '.') {
531 NameString
[Index
] = 0;
536 if (Index
== BufferSize
- 1) {
537 NameString
[Index
] = 0;
540 // Module Name is got.
547 // Method 2: Get the name string from ComponentName2 protocol
549 Status
= gBS
->HandleProtocol (
551 &gEfiComponentName2ProtocolGuid
,
552 (VOID
**) &ComponentName2
554 if (!EFI_ERROR (Status
)) {
556 // Get the current platform language setting
558 if (mPlatformLanguage
== NULL
) {
559 GetEfiGlobalVariable2 (L
"PlatformLang", (VOID
**) &mPlatformLanguage
, NULL
);
561 if (mPlatformLanguage
!= NULL
) {
562 Status
= ComponentName2
->GetDriverName (
564 mPlatformLanguage
!= NULL
? mPlatformLanguage
: "en-US",
567 if (!EFI_ERROR (Status
)) {
568 for (Index
= 0; Index
< BufferSize
- 1 && StringPtr
[Index
] != 0; Index
++) {
569 NameString
[Index
] = (CHAR8
) StringPtr
[Index
];
571 NameString
[Index
] = 0;
573 // Module Name is got.
580 if (ModuleGuidIsGet
) {
582 // Method 3 Try to get the image's FFS UI section by image GUID
586 Status
= GetSectionFromAnyFv (
588 EFI_SECTION_USER_INTERFACE
,
590 (VOID
**) &StringPtr
,
594 if (!EFI_ERROR (Status
)) {
596 // Method 3. Get the name string from FFS UI section
598 for (Index
= 0; Index
< BufferSize
- 1 && StringPtr
[Index
] != 0; Index
++) {
599 NameString
[Index
] = (CHAR8
) StringPtr
[Index
];
601 NameString
[Index
] = 0;
602 FreePool (StringPtr
);
610 if (ModuleGuid
!= NULL
) {
611 CopyGuid (ModuleGuid
, TempGuid
);
612 if (IsZeroGuid(TempGuid
) && (Handle
!= NULL
) && !ModuleGuidIsGet
) {
614 CopyGuid (ModuleGuid
, (EFI_GUID
*) Handle
);
619 // Cache the Handle and Guid pairs.
621 if (mCachePairCount
< CACHE_HANDLE_GUID_COUNT
) {
622 mCacheHandleGuidTable
[mCachePairCount
].Handle
= Handle
;
623 CopyGuid (&mCacheHandleGuidTable
[mCachePairCount
].ModuleGuid
, ModuleGuid
);
624 AsciiStrCpyS (mCacheHandleGuidTable
[mCachePairCount
].NameString
, FPDT_STRING_EVENT_RECORD_NAME_LENGTH
, NameString
);
632 Get the FPDT record info.
634 @param IsStart TRUE if the performance log is start log.
635 @param Handle Pointer to environment specific context used
636 to identify the component being measured.
637 @param Token Pointer to a Null-terminated ASCII string
638 that identifies the component being measured.
639 @param Module Pointer to a Null-terminated ASCII string
640 that identifies the module being measured.
641 @param RecordInfo On return, pointer to the info of the record.
642 @param UseModuleName Only useful for FPDT_DYNAMIC_STRING_EVENT_TYPE, indicate that whether need use
643 Module name to fill the string field in the FPDT_DYNAMIC_STRING_EVENT_RECORD.
645 @retval EFI_SUCCESS Get record info successfully.
646 @retval EFI_UNSUPPORTED No matched FPDT record.
652 IN CONST VOID
*Handle
,
653 IN CONST CHAR8
*Token
,
654 IN CONST CHAR8
*Module
,
655 OUT FPDT_BASIC_RECORD_INFO
*RecordInfo
,
656 IN OUT BOOLEAN
*UseModuleName
662 RecordType
= FPDT_DYNAMIC_STRING_EVENT_TYPE
;
665 // Token to Type and Id.
668 if (AsciiStrCmp (Token
, START_IMAGE_TOK
) == 0) { // "StartImage:"
669 *UseModuleName
= TRUE
;
670 RecordType
= FPDT_GUID_EVENT_TYPE
;
672 RecordInfo
->ProgressID
= MODULE_START_ID
;
674 RecordInfo
->ProgressID
= MODULE_END_ID
;
676 } else if (AsciiStrCmp (Token
, LOAD_IMAGE_TOK
) == 0) { // "LoadImage:"
677 *UseModuleName
= TRUE
;
678 RecordType
= FPDT_GUID_QWORD_EVENT_TYPE
;
680 RecordInfo
->ProgressID
= MODULE_LOADIMAGE_START_ID
;
682 RecordInfo
->ProgressID
= MODULE_LOADIMAGE_END_ID
;
684 } else if (AsciiStrCmp (Token
, DRIVERBINDING_START_TOK
) == 0) { // "DB:Start:"
685 *UseModuleName
= TRUE
;
687 RecordInfo
->ProgressID
= MODULE_DB_START_ID
;
688 RecordType
= FPDT_GUID_QWORD_EVENT_TYPE
;
690 RecordInfo
->ProgressID
= MODULE_DB_END_ID
;
691 RecordType
= FPDT_GUID_QWORD_STRING_EVENT_TYPE
;
693 } else if (AsciiStrCmp (Token
, DRIVERBINDING_SUPPORT_TOK
) == 0) { // "DB:Support:"
694 *UseModuleName
= TRUE
;
695 if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly
)) {
696 return RETURN_UNSUPPORTED
;
698 RecordType
= FPDT_GUID_QWORD_EVENT_TYPE
;
700 RecordInfo
->ProgressID
= MODULE_DB_SUPPORT_START_ID
;
702 RecordInfo
->ProgressID
= MODULE_DB_SUPPORT_END_ID
;
704 } else if (AsciiStrCmp (Token
, DRIVERBINDING_STOP_TOK
) == 0) { // "DB:Stop:"
705 *UseModuleName
= TRUE
;
706 if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly
)) {
707 return RETURN_UNSUPPORTED
;
709 RecordType
= FPDT_GUID_QWORD_EVENT_TYPE
;
711 RecordInfo
->ProgressID
= MODULE_DB_STOP_START_ID
;
713 RecordInfo
->ProgressID
= MODULE_DB_STOP_END_ID
;
715 } else if (AsciiStrCmp (Token
, PEI_TOK
) == 0 || // "PEI"
716 AsciiStrCmp (Token
, DXE_TOK
) == 0 || // "DXE"
717 AsciiStrCmp (Token
, BDS_TOK
) == 0) { // "BDS"
719 RecordInfo
->ProgressID
= PERF_CROSSMODULE_START_ID
;
721 RecordInfo
->ProgressID
= PERF_CROSSMODULE_END_ID
;
723 } else { // Pref used in Modules.
725 RecordInfo
->ProgressID
= PERF_INMODULE_START_ID
;
727 RecordInfo
->ProgressID
= PERF_INMODULE_END_ID
;
730 } else if (Handle
!= NULL
|| Module
!= NULL
) { // Pref used in Modules.
732 RecordInfo
->ProgressID
= PERF_INMODULE_START_ID
;
734 RecordInfo
->ProgressID
= PERF_INMODULE_END_ID
;
737 return EFI_UNSUPPORTED
;
741 // Get Record size baesed on the record type.
742 // When PcdEdkiiFpdtStringRecordEnableOnly is TRUE, all records are with type of FPDT_DYNAMIC_STRING_EVENT_TYPE.
744 if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly
)) {
745 RecordType
= FPDT_DYNAMIC_STRING_EVENT_TYPE
;
746 RecordInfo
->RecordSize
= sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD
) + STRING_SIZE
;
748 switch (RecordType
) {
749 case FPDT_GUID_EVENT_TYPE
:
750 RecordInfo
->RecordSize
= sizeof (FPDT_GUID_EVENT_RECORD
);
753 case FPDT_DYNAMIC_STRING_EVENT_TYPE
:
754 if (*UseModuleName
) {
755 StringSize
= STRING_SIZE
;
756 } else if (Token
!= NULL
) {
757 StringSize
= AsciiStrSize (Token
);
758 } else if (Module
!= NULL
) {
759 StringSize
= AsciiStrSize (Module
);
761 StringSize
= STRING_SIZE
;
763 if (StringSize
> STRING_SIZE
) {
764 StringSize
= STRING_SIZE
;
766 RecordInfo
->RecordSize
= (UINT8
)(sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD
) + StringSize
);
769 case FPDT_GUID_QWORD_EVENT_TYPE
:
770 RecordInfo
->RecordSize
= (UINT8
)sizeof (FPDT_GUID_QWORD_EVENT_RECORD
);
773 case FPDT_GUID_QWORD_STRING_EVENT_TYPE
:
774 RecordInfo
->RecordSize
= (UINT8
)sizeof (FPDT_GUID_QWORD_STRING_EVENT_RECORD
);
779 // Record is unsupported yet, return EFI_UNSUPPORTED
781 return EFI_UNSUPPORTED
;
785 RecordInfo
->Type
= RecordType
;
790 Add performance log to FPDT boot record table.
792 @param IsStart TRUE if the performance log is start log.
793 @param Handle Pointer to environment specific context used
794 to identify the component being measured.
795 @param Token Pointer to a Null-terminated ASCII string
796 that identifies the component being measured.
797 @param Module Pointer to a Null-terminated ASCII string
798 that identifies the module being measured.
799 @param Ticker 64-bit time stamp.
800 @param Identifier 32-bit identifier. If the value is 0, the created record
801 is same as the one created by StartGauge of PERFORMANCE_PROTOCOL.
803 @retval EFI_SUCCESS Add FPDT boot record.
804 @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement.
805 @retval EFI_UNSUPPORTED No matched FPDT record.
809 InsertFpdtMeasurement (
811 IN CONST VOID
*Handle
, OPTIONAL
812 IN CONST CHAR8
*Token
, OPTIONAL
813 IN CONST CHAR8
*Module
, OPTIONAL
819 CHAR8 ModuleName
[FPDT_STRING_EVENT_RECORD_NAME_LENGTH
];
821 FPDT_RECORD_PTR FpdtRecordPtr
;
822 FPDT_BASIC_RECORD_INFO RecordInfo
;
826 CONST CHAR8
*StringPtr
;
827 BOOLEAN UseModuleName
;
830 UseModuleName
= FALSE
;
831 ZeroMem (ModuleName
, sizeof (ModuleName
));
833 if (mLockInsertRecord
) {
834 return EFI_UNSUPPORTED
;
837 mLockInsertRecord
= TRUE
;
840 // Get record info (type, size, ProgressID and Module Guid).
842 Status
= GetFpdtRecordInfo (IsStart
, Handle
, Token
, Module
, &RecordInfo
, &UseModuleName
);
843 if (EFI_ERROR (Status
)) {
844 mLockInsertRecord
= FALSE
;
849 // If PERF_START()/PERF_END() have specified the ProgressID,it has high priority.
850 // !!! Note: If the Pref is not the known Token used in the core but have same
851 // ID with the core Token, this case will not be supported.
852 // And in currtnt usage mode, for the unkown ID, there is a general rule:
853 // If it is start pref: the lower 4 bits of the ID should be 0.
854 // If it is end pref: the lower 4 bits of the ID should not be 0.
855 // If input ID doesn't follow the rule, we will adjust it.
857 if ((Identifier
!= 0) && (IsKnownID (Identifier
)) && (!IsKnownTokens (Token
))) {
858 mLockInsertRecord
= FALSE
;
859 return EFI_UNSUPPORTED
;
860 } else if ((Identifier
!= 0) && (!IsKnownID (Identifier
)) && (!IsKnownTokens (Token
))) {
861 if (IsStart
&& ((Identifier
& 0x000F) != 0)) {
862 Identifier
&= 0xFFF0;
863 } else if ((!IsStart
) && ((Identifier
& 0x000F) == 0)) {
866 RecordInfo
.ProgressID
= (UINT16
)Identifier
;
869 if (mFpdtBufferIsReported
) {
871 // Append Boot records to the boot performance table.
873 if (mBootRecordSize
+ RecordInfo
.RecordSize
> mBootRecordMaxSize
) {
874 if (!mLackSpaceIsReported
) {
875 DEBUG ((DEBUG_INFO
, "DxeCorePerformanceLib: No enough space to save boot records\n"));
876 mLackSpaceIsReported
= TRUE
;
878 mLockInsertRecord
= FALSE
;
879 return EFI_OUT_OF_RESOURCES
;
882 // Save boot record into BootPerformance table
884 FpdtRecordPtr
.RecordHeader
= (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER
*)(mBootRecordBuffer
+ mBootRecordSize
);
885 mBootRecordSize
+= RecordInfo
.RecordSize
;
886 mAcpiBootPerformanceTable
->Header
.Length
+= RecordInfo
.RecordSize
;
890 // Check if pre-allocated buffer is full
892 if (mPerformanceLength
+ RecordInfo
.RecordSize
> mMaxPerformanceLength
) {
893 mPerformancePointer
= ReallocatePool (
895 mPerformanceLength
+ RecordInfo
.RecordSize
+ FIRMWARE_RECORD_BUFFER
,
899 if (mPerformancePointer
== NULL
) {
900 mLockInsertRecord
= FALSE
;
901 return EFI_OUT_OF_RESOURCES
;
903 mMaxPerformanceLength
= mPerformanceLength
+ RecordInfo
.RecordSize
+ FIRMWARE_RECORD_BUFFER
;
906 // Covert buffer to FPDT Ptr Union type.
908 FpdtRecordPtr
.RecordHeader
= (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER
*)(mPerformancePointer
+ mPerformanceLength
);
909 mPerformanceLength
+= RecordInfo
.RecordSize
;
913 // Get the TimeStamp.
916 Ticker
= GetPerformanceCounter ();
917 TimeStamp
= GetTimeInNanoSecond (Ticker
);
918 } else if (Ticker
== 1) {
921 TimeStamp
= GetTimeInNanoSecond (Ticker
);
925 // Get the ModuleName and ModuleGuid form the handle.
927 GetModuleInfoFromHandle ((EFI_HANDLE
*)Handle
, ModuleName
, sizeof (ModuleName
), &ModuleGuid
);
930 // Fill in the record information.
932 switch (RecordInfo
.Type
) {
933 case FPDT_GUID_EVENT_TYPE
:
934 FpdtRecordPtr
.GuidEvent
->Header
.Type
= FPDT_GUID_EVENT_TYPE
;
935 FpdtRecordPtr
.GuidEvent
->Header
.Length
= RecordInfo
.RecordSize
;
936 FpdtRecordPtr
.GuidEvent
->Header
.Revision
= FPDT_RECORD_REVISION_1
;
937 FpdtRecordPtr
.GuidEvent
->ProgressID
= RecordInfo
.ProgressID
;
938 FpdtRecordPtr
.GuidEvent
->Timestamp
= TimeStamp
;
939 CopyMem (&FpdtRecordPtr
.GuidEvent
->Guid
, &ModuleGuid
, sizeof (FpdtRecordPtr
.GuidEvent
->Guid
));
942 case FPDT_DYNAMIC_STRING_EVENT_TYPE
:
943 FpdtRecordPtr
.DynamicStringEvent
->Header
.Type
= FPDT_DYNAMIC_STRING_EVENT_TYPE
;
944 FpdtRecordPtr
.DynamicStringEvent
->Header
.Length
= RecordInfo
.RecordSize
;
945 FpdtRecordPtr
.DynamicStringEvent
->Header
.Revision
= FPDT_RECORD_REVISION_1
;
946 FpdtRecordPtr
.DynamicStringEvent
->ProgressID
= RecordInfo
.ProgressID
;
947 FpdtRecordPtr
.DynamicStringEvent
->Timestamp
= TimeStamp
;
948 CopyMem (&FpdtRecordPtr
.DynamicStringEvent
->Guid
, &ModuleGuid
, sizeof (FpdtRecordPtr
.DynamicStringEvent
->Guid
));
951 StringPtr
= ModuleName
;
952 } else if (Token
!= NULL
) {
954 } else if (Module
!= NULL
) {
956 } else if (ModuleName
!= NULL
) {
957 StringPtr
= ModuleName
;
959 if (StringPtr
!= NULL
&& AsciiStrLen (StringPtr
) != 0) {
960 StrLength
= AsciiStrLen (StringPtr
);
961 DestMax
= (RecordInfo
.RecordSize
- sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD
)) / sizeof (CHAR8
);
962 if (StrLength
>= DestMax
) {
963 StrLength
= DestMax
-1;
965 AsciiStrnCpyS (FpdtRecordPtr
.DynamicStringEvent
->String
, DestMax
, StringPtr
, StrLength
);
967 AsciiStrCpyS (FpdtRecordPtr
.DynamicStringEvent
->String
, FPDT_STRING_EVENT_RECORD_NAME_LENGTH
, "unknown name");
971 case FPDT_GUID_QWORD_EVENT_TYPE
:
972 FpdtRecordPtr
.GuidQwordEvent
->Header
.Type
= FPDT_GUID_QWORD_EVENT_TYPE
;
973 FpdtRecordPtr
.GuidQwordEvent
->Header
.Length
= RecordInfo
.RecordSize
;
974 FpdtRecordPtr
.GuidQwordEvent
->Header
.Revision
= FPDT_RECORD_REVISION_1
;
975 FpdtRecordPtr
.GuidQwordEvent
->ProgressID
= RecordInfo
.ProgressID
;
976 FpdtRecordPtr
.GuidQwordEvent
->Timestamp
= TimeStamp
;
977 CopyMem (&FpdtRecordPtr
.GuidQwordEvent
->Guid
, &ModuleGuid
, sizeof (FpdtRecordPtr
.GuidQwordEvent
->Guid
));
978 if ((MODULE_LOADIMAGE_START_ID
== RecordInfo
.ProgressID
) && AsciiStrCmp (Token
, LOAD_IMAGE_TOK
) == 0) {
980 FpdtRecordPtr
.GuidQwordEvent
->Qword
= mLoadImageCount
;
984 case FPDT_GUID_QWORD_STRING_EVENT_TYPE
:
985 FpdtRecordPtr
.GuidQwordStringEvent
->Header
.Type
= FPDT_GUID_QWORD_STRING_EVENT_TYPE
;
986 FpdtRecordPtr
.GuidQwordStringEvent
->Header
.Length
= RecordInfo
.RecordSize
;
987 FpdtRecordPtr
.GuidQwordStringEvent
->Header
.Revision
= FPDT_RECORD_REVISION_1
;
988 FpdtRecordPtr
.GuidQwordStringEvent
->ProgressID
= RecordInfo
.ProgressID
;
989 FpdtRecordPtr
.GuidQwordStringEvent
->Timestamp
= TimeStamp
;
990 CopyMem (&FpdtRecordPtr
.GuidQwordStringEvent
->Guid
, &ModuleGuid
, sizeof (FpdtRecordPtr
.GuidQwordStringEvent
->Guid
));
995 // Record is not supported in current DXE phase, return EFI_ABORTED
997 mLockInsertRecord
= FALSE
;
998 return EFI_UNSUPPORTED
;
1001 mLockInsertRecord
= FALSE
;
1006 Dumps all the PEI performance.
1008 @param HobStart A pointer to a Guid.
1010 This internal function dumps all the PEI performance log to the DXE performance gauge array.
1011 It retrieves the optional GUID HOB for PEI performance and then saves the performance data
1012 to DXE performance data structures.
1016 InternalGetPeiPerformance (
1020 UINT8
*FirmwarePerformanceHob
;
1021 FPDT_PEI_EXT_PERF_HEADER
*PeiPerformanceLogHeader
;
1023 EFI_HOB_GUID_TYPE
*GuidHob
;
1025 GuidHob
= GetNextGuidHob (&gEdkiiFpdtExtendedFirmwarePerformanceGuid
, HobStart
);
1026 while (GuidHob
!= NULL
) {
1027 FirmwarePerformanceHob
= GET_GUID_HOB_DATA (GuidHob
);
1028 PeiPerformanceLogHeader
= (FPDT_PEI_EXT_PERF_HEADER
*)FirmwarePerformanceHob
;
1030 if (mPerformanceLength
+ PeiPerformanceLogHeader
->SizeOfAllEntries
> mMaxPerformanceLength
) {
1031 mPerformancePointer
= ReallocatePool (
1033 mPerformanceLength
+
1034 (UINTN
)PeiPerformanceLogHeader
->SizeOfAllEntries
+
1035 FIRMWARE_RECORD_BUFFER
,
1038 ASSERT (mPerformancePointer
!= NULL
);
1039 mMaxPerformanceLength
= mPerformanceLength
+
1040 (UINTN
)(PeiPerformanceLogHeader
->SizeOfAllEntries
) +
1041 FIRMWARE_RECORD_BUFFER
;
1044 EventRec
= mPerformancePointer
+ mPerformanceLength
;
1045 CopyMem (EventRec
, FirmwarePerformanceHob
+ sizeof (FPDT_PEI_EXT_PERF_HEADER
), (UINTN
)(PeiPerformanceLogHeader
->SizeOfAllEntries
));
1047 // Update the used buffer size.
1049 mPerformanceLength
+= (UINTN
)(PeiPerformanceLogHeader
->SizeOfAllEntries
);
1050 mLoadImageCount
+= PeiPerformanceLogHeader
->LoadImageCount
;
1053 // Get next performance guid hob
1055 GuidHob
= GetNextGuidHob (&gEdkiiFpdtExtendedFirmwarePerformanceGuid
, GET_NEXT_HOB (GuidHob
));
1060 Report Boot Perforamnce table address as report status code.
1062 @param Event The event of notify protocol.
1063 @param Context Notify event context.
1068 ReportFpdtRecordBuffer (
1076 if (!mFpdtBufferIsReported
) {
1077 Status
= AllocateBootPerformanceTable ();
1078 if (!EFI_ERROR(Status
)) {
1079 BPDTAddr
= (UINT64
)(UINTN
)mAcpiBootPerformanceTable
;
1080 REPORT_STATUS_CODE_EX (
1082 EFI_SOFTWARE_DXE_BS_DRIVER
,
1085 &gEdkiiFpdtExtendedFirmwarePerformanceGuid
,
1091 // Set FPDT report state to TRUE.
1093 mFpdtBufferIsReported
= TRUE
;
1098 Adds a record at the end of the performance measurement log
1099 that records the start time of a performance measurement.
1101 Adds a record to the end of the performance measurement log
1102 that contains the Handle, Token, Module and Identifier.
1103 The end time of the new record must be set to zero.
1104 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
1105 If TimeStamp is zero, the start time in the record is filled in with the value
1106 read from the current time stamp.
1108 @param Handle Pointer to environment specific context used
1109 to identify the component being measured.
1110 @param Token Pointer to a Null-terminated ASCII string
1111 that identifies the component being measured.
1112 @param Module Pointer to a Null-terminated ASCII string
1113 that identifies the module being measured.
1114 @param TimeStamp 64-bit time stamp.
1115 @param Identifier 32-bit identifier. If the value is 0, the created record
1116 is same as the one created by StartGauge of PERFORMANCE_PROTOCOL.
1118 @retval EFI_SUCCESS The data was read correctly from the device.
1119 @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement.
1125 IN CONST VOID
*Handle
, OPTIONAL
1126 IN CONST CHAR8
*Token
, OPTIONAL
1127 IN CONST CHAR8
*Module
, OPTIONAL
1128 IN UINT64 TimeStamp
,
1129 IN UINT32 Identifier
1132 return InsertFpdtMeasurement (TRUE
, Handle
, Token
, Module
, TimeStamp
, Identifier
);
1136 Searches the performance measurement log from the beginning of the log
1137 for the first matching record that contains a zero end time and fills in a valid end time.
1139 Searches the performance measurement log from the beginning of the log
1140 for the first record that matches Handle, Token, Module and Identifier and has an end time value of zero.
1141 If the record can not be found then return EFI_NOT_FOUND.
1142 If the record is found and TimeStamp is not zero,
1143 then the end time in the record is filled in with the value specified by TimeStamp.
1144 If the record is found and TimeStamp is zero, then the end time in the matching record
1145 is filled in with the current time stamp value.
1147 @param Handle Pointer to environment specific context used
1148 to identify the component being measured.
1149 @param Token Pointer to a Null-terminated ASCII string
1150 that identifies the component being measured.
1151 @param Module Pointer to a Null-terminated ASCII string
1152 that identifies the module being measured.
1153 @param TimeStamp 64-bit time stamp.
1154 @param Identifier 32-bit identifier. If the value is 0, the found record
1155 is same as the one found by EndGauge of PERFORMANCE_PROTOCOL.
1157 @retval EFI_SUCCESS The end of the measurement was recorded.
1158 @retval EFI_NOT_FOUND The specified measurement record could not be found.
1164 IN CONST VOID
*Handle
, OPTIONAL
1165 IN CONST CHAR8
*Token
, OPTIONAL
1166 IN CONST CHAR8
*Module
, OPTIONAL
1167 IN UINT64 TimeStamp
,
1168 IN UINT32 Identifier
1171 return InsertFpdtMeasurement (FALSE
, Handle
, Token
, Module
, TimeStamp
, Identifier
);
1175 Retrieves a previously logged performance measurement.
1176 It can also retrieve the log created by StartGauge and EndGauge of PERFORMANCE_PROTOCOL,
1177 and then assign the Identifier with 0.
1181 Retrieves the performance log entry from the performance log specified by LogEntryKey.
1182 If it stands for a valid entry, then EFI_SUCCESS is returned and
1183 GaugeDataEntryEx stores the pointer to that entry.
1185 @param LogEntryKey The key for the previous performance measurement log entry.
1186 If 0, then the first performance measurement log entry is retrieved.
1187 @param GaugeDataEntryEx The indirect pointer to the extended gauge data entry specified by LogEntryKey
1188 if the retrieval is successful.
1190 @retval EFI_SUCCESS The GuageDataEntryEx is successfully found based on LogEntryKey.
1191 @retval EFI_NOT_FOUND The LogEntryKey is the last entry (equals to the total entry number).
1192 @retval EFI_INVALIDE_PARAMETER The LogEntryKey is not a valid entry (greater than the total entry number).
1193 @retval EFI_INVALIDE_PARAMETER GaugeDataEntryEx is NULL.
1199 IN UINTN LogEntryKey
,
1200 OUT GAUGE_DATA_ENTRY_EX
**GaugeDataEntryEx
1203 return EFI_UNSUPPORTED
;
1207 Adds a record at the end of the performance measurement log
1208 that records the start time of a performance measurement.
1210 Adds a record to the end of the performance measurement log
1211 that contains the Handle, Token, and Module.
1212 The end time of the new record must be set to zero.
1213 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
1214 If TimeStamp is zero, the start time in the record is filled in with the value
1215 read from the current time stamp.
1217 @param Handle Pointer to environment specific context used
1218 to identify the component being measured.
1219 @param Token Pointer to a Null-terminated ASCII string
1220 that identifies the component being measured.
1221 @param Module Pointer to a Null-terminated ASCII string
1222 that identifies the module being measured.
1223 @param TimeStamp 64-bit time stamp.
1225 @retval EFI_SUCCESS The data was read correctly from the device.
1226 @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement.
1232 IN CONST VOID
*Handle
, OPTIONAL
1233 IN CONST CHAR8
*Token
, OPTIONAL
1234 IN CONST CHAR8
*Module
, OPTIONAL
1238 return StartGaugeEx (Handle
, Token
, Module
, TimeStamp
, 0);
1242 Searches the performance measurement log from the beginning of the log
1243 for the first matching record that contains a zero end time and fills in a valid end time.
1245 Searches the performance measurement log from the beginning of the log
1246 for the first record that matches Handle, Token, and Module and has an end time value of zero.
1247 If the record can not be found then return EFI_NOT_FOUND.
1248 If the record is found and TimeStamp is not zero,
1249 then the end time in the record is filled in with the value specified by TimeStamp.
1250 If the record is found and TimeStamp is zero, then the end time in the matching record
1251 is filled in with the current time stamp value.
1253 @param Handle Pointer to environment specific context used
1254 to identify the component being measured.
1255 @param Token Pointer to a Null-terminated ASCII string
1256 that identifies the component being measured.
1257 @param Module Pointer to a Null-terminated ASCII string
1258 that identifies the module being measured.
1259 @param TimeStamp 64-bit time stamp.
1261 @retval EFI_SUCCESS The end of the measurement was recorded.
1262 @retval EFI_NOT_FOUND The specified measurement record could not be found.
1268 IN CONST VOID
*Handle
, OPTIONAL
1269 IN CONST CHAR8
*Token
, OPTIONAL
1270 IN CONST CHAR8
*Module
, OPTIONAL
1274 return EndGaugeEx (Handle
, Token
, Module
, TimeStamp
, 0);
1278 Retrieves a previously logged performance measurement.
1279 It can also retrieve the log created by StartGaugeEx and EndGaugeEx of PERFORMANCE_EX_PROTOCOL,
1280 and then eliminate the Identifier.
1284 Retrieves the performance log entry from the performance log specified by LogEntryKey.
1285 If it stands for a valid entry, then EFI_SUCCESS is returned and
1286 GaugeDataEntry stores the pointer to that entry.
1288 @param LogEntryKey The key for the previous performance measurement log entry.
1289 If 0, then the first performance measurement log entry is retrieved.
1290 @param GaugeDataEntry The indirect pointer to the gauge data entry specified by LogEntryKey
1291 if the retrieval is successful.
1293 @retval EFI_SUCCESS The GuageDataEntry is successfully found based on LogEntryKey.
1294 @retval EFI_NOT_FOUND The LogEntryKey is the last entry (equals to the total entry number).
1295 @retval EFI_INVALIDE_PARAMETER The LogEntryKey is not a valid entry (greater than the total entry number).
1296 @retval EFI_INVALIDE_PARAMETER GaugeDataEntry is NULL.
1302 IN UINTN LogEntryKey
,
1303 OUT GAUGE_DATA_ENTRY
**GaugeDataEntry
1306 return EFI_UNSUPPORTED
;
1311 The constructor function initializes Performance infrastructure for DXE phase.
1313 The constructor function publishes Performance and PerformanceEx protocol, allocates memory to log DXE performance
1314 and merges PEI performance data to DXE performance log.
1315 It will ASSERT() if one of these operations fails and it will always return EFI_SUCCESS.
1317 @param ImageHandle The firmware allocated handle for the EFI image.
1318 @param SystemTable A pointer to the EFI System Table.
1320 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
1325 DxeCorePerformanceLibConstructor (
1326 IN EFI_HANDLE ImageHandle
,
1327 IN EFI_SYSTEM_TABLE
*SystemTable
1332 EFI_EVENT ReadyToBootEvent
;
1333 PERFORMANCE_PROPERTY
*PerformanceProperty
;
1335 if (!PerformanceMeasurementEnabled ()) {
1337 // Do not initialize performance infrastructure if not required.
1343 // Dump normal PEI performance records
1345 InternalGetPeiPerformance (GetHobList());
1348 // Install the protocol interfaces for DXE performance library instance.
1351 Status
= gBS
->InstallMultipleProtocolInterfaces (
1353 &gPerformanceProtocolGuid
,
1354 &mPerformanceInterface
,
1355 &gPerformanceExProtocolGuid
,
1356 &mPerformanceExInterface
,
1359 ASSERT_EFI_ERROR (Status
);
1362 // Register ReadyToBoot event to report StatusCode data
1364 Status
= gBS
->CreateEventEx (
1367 ReportFpdtRecordBuffer
,
1369 &gEfiEventReadyToBootGuid
,
1373 ASSERT_EFI_ERROR (Status
);
1375 Status
= EfiGetSystemConfigurationTable (&gPerformanceProtocolGuid
, (VOID
**) &PerformanceProperty
);
1376 if (EFI_ERROR (Status
)) {
1378 // Install configuration table for performance property.
1380 mPerformanceProperty
.Revision
= PERFORMANCE_PROPERTY_REVISION
;
1381 mPerformanceProperty
.Reserved
= 0;
1382 mPerformanceProperty
.Frequency
= GetPerformanceCounterProperties (
1383 &mPerformanceProperty
.TimerStartValue
,
1384 &mPerformanceProperty
.TimerEndValue
1386 Status
= gBS
->InstallConfigurationTable (&gPerformanceProtocolGuid
, &mPerformanceProperty
);
1387 ASSERT_EFI_ERROR (Status
);
1394 Adds a record at the end of the performance measurement log
1395 that records the start time of a performance measurement.
1397 Adds a record to the end of the performance measurement log
1398 that contains the Handle, Token, Module and Identifier.
1399 The end time of the new record must be set to zero.
1400 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
1401 If TimeStamp is zero, the start time in the record is filled in with the value
1402 read from the current time stamp.
1404 @param Handle Pointer to environment specific context used
1405 to identify the component being measured.
1406 @param Token Pointer to a Null-terminated ASCII string
1407 that identifies the component being measured.
1408 @param Module Pointer to a Null-terminated ASCII string
1409 that identifies the module being measured.
1410 @param TimeStamp 64-bit time stamp.
1411 @param Identifier 32-bit identifier. If the value is 0, the created record
1412 is same as the one created by StartPerformanceMeasurement.
1414 @retval RETURN_SUCCESS The start of the measurement was recorded.
1415 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.
1420 StartPerformanceMeasurementEx (
1421 IN CONST VOID
*Handle
, OPTIONAL
1422 IN CONST CHAR8
*Token
, OPTIONAL
1423 IN CONST CHAR8
*Module
, OPTIONAL
1424 IN UINT64 TimeStamp
,
1425 IN UINT32 Identifier
1428 return InsertFpdtMeasurement (TRUE
, Handle
, Token
, Module
, TimeStamp
, Identifier
);
1432 Searches the performance measurement log from the beginning of the log
1433 for the first matching record that contains a zero end time and fills in a valid end time.
1435 Searches the performance measurement log from the beginning of the log
1436 for the first record that matches Handle, Token, Module and Identifier and has an end time value of zero.
1437 If the record can not be found then return RETURN_NOT_FOUND.
1438 If the record is found and TimeStamp is not zero,
1439 then the end time in the record is filled in with the value specified by TimeStamp.
1440 If the record is found and TimeStamp is zero, then the end time in the matching record
1441 is filled in with the current time stamp value.
1443 @param Handle Pointer to environment specific context used
1444 to identify the component being measured.
1445 @param Token Pointer to a Null-terminated ASCII string
1446 that identifies the component being measured.
1447 @param Module Pointer to a Null-terminated ASCII string
1448 that identifies the module being measured.
1449 @param TimeStamp 64-bit time stamp.
1450 @param Identifier 32-bit identifier. If the value is 0, the found record
1451 is same as the one found by EndPerformanceMeasurement.
1453 @retval RETURN_SUCCESS The end of the measurement was recorded.
1454 @retval RETURN_NOT_FOUND The specified measurement record could not be found.
1459 EndPerformanceMeasurementEx (
1460 IN CONST VOID
*Handle
, OPTIONAL
1461 IN CONST CHAR8
*Token
, OPTIONAL
1462 IN CONST CHAR8
*Module
, OPTIONAL
1463 IN UINT64 TimeStamp
,
1464 IN UINT32 Identifier
1467 return InsertFpdtMeasurement (FALSE
, Handle
, Token
, Module
, TimeStamp
, Identifier
);
1471 Attempts to retrieve a performance measurement log entry from the performance measurement log.
1472 It can also retrieve the log created by StartPerformanceMeasurement and EndPerformanceMeasurement,
1473 and then assign the Identifier with 0.
1477 Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is
1478 zero on entry, then an attempt is made to retrieve the first entry from the performance log,
1479 and the key for the second entry in the log is returned. If the performance log is empty,
1480 then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance
1481 log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
1482 returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is
1483 retrieved and an implementation specific non-zero key value that specifies the end of the performance
1484 log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry
1485 is retrieved and zero is returned. In the cases where a performance log entry can be returned,
1486 the log entry is returned in Handle, Token, Module, StartTimeStamp, EndTimeStamp and Identifier.
1487 If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().
1488 If Handle is NULL, then ASSERT().
1489 If Token is NULL, then ASSERT().
1490 If Module is NULL, then ASSERT().
1491 If StartTimeStamp is NULL, then ASSERT().
1492 If EndTimeStamp is NULL, then ASSERT().
1493 If Identifier is NULL, then ASSERT().
1495 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.
1496 0, then the first performance measurement log entry is retrieved.
1497 On exit, the key of the next performance log entry.
1498 @param Handle Pointer to environment specific context used to identify the component
1500 @param Token Pointer to a Null-terminated ASCII string that identifies the component
1502 @param Module Pointer to a Null-terminated ASCII string that identifies the module
1504 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
1506 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
1508 @param Identifier Pointer to the 32-bit identifier that was recorded when the measurement
1511 @return The key for the next performance log entry (in general case).
1516 GetPerformanceMeasurementEx (
1517 IN UINTN LogEntryKey
,
1518 OUT CONST VOID
**Handle
,
1519 OUT CONST CHAR8
**Token
,
1520 OUT CONST CHAR8
**Module
,
1521 OUT UINT64
*StartTimeStamp
,
1522 OUT UINT64
*EndTimeStamp
,
1523 OUT UINT32
*Identifier
1530 Adds a record at the end of the performance measurement log
1531 that records the start time of a performance measurement.
1533 Adds a record to the end of the performance measurement log
1534 that contains the Handle, Token, and Module.
1535 The end time of the new record must be set to zero.
1536 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
1537 If TimeStamp is zero, the start time in the record is filled in with the value
1538 read from the current time stamp.
1540 @param Handle Pointer to environment specific context used
1541 to identify the component being measured.
1542 @param Token Pointer to a Null-terminated ASCII string
1543 that identifies the component being measured.
1544 @param Module Pointer to a Null-terminated ASCII string
1545 that identifies the module being measured.
1546 @param TimeStamp 64-bit time stamp.
1548 @retval RETURN_SUCCESS The start of the measurement was recorded.
1549 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.
1554 StartPerformanceMeasurement (
1555 IN CONST VOID
*Handle
, OPTIONAL
1556 IN CONST CHAR8
*Token
, OPTIONAL
1557 IN CONST CHAR8
*Module
, OPTIONAL
1561 return InsertFpdtMeasurement (TRUE
, Handle
, Token
, Module
, TimeStamp
, 0);
1565 Searches the performance measurement log from the beginning of the log
1566 for the first matching record that contains a zero end time and fills in a valid end time.
1568 Searches the performance measurement log from the beginning of the log
1569 for the first record that matches Handle, Token, and Module and has an end time value of zero.
1570 If the record can not be found then return RETURN_NOT_FOUND.
1571 If the record is found and TimeStamp is not zero,
1572 then the end time in the record is filled in with the value specified by TimeStamp.
1573 If the record is found and TimeStamp is zero, then the end time in the matching record
1574 is filled in with the current time stamp value.
1576 @param Handle Pointer to environment specific context used
1577 to identify the component being measured.
1578 @param Token Pointer to a Null-terminated ASCII string
1579 that identifies the component being measured.
1580 @param Module Pointer to a Null-terminated ASCII string
1581 that identifies the module being measured.
1582 @param TimeStamp 64-bit time stamp.
1584 @retval RETURN_SUCCESS The end of the measurement was recorded.
1585 @retval RETURN_NOT_FOUND The specified measurement record could not be found.
1590 EndPerformanceMeasurement (
1591 IN CONST VOID
*Handle
, OPTIONAL
1592 IN CONST CHAR8
*Token
, OPTIONAL
1593 IN CONST CHAR8
*Module
, OPTIONAL
1597 return InsertFpdtMeasurement (FALSE
, Handle
, Token
, Module
, TimeStamp
, 0);
1601 Attempts to retrieve a performance measurement log entry from the performance measurement log.
1602 It can also retrieve the log created by StartPerformanceMeasurementEx and EndPerformanceMeasurementEx,
1603 and then eliminate the Identifier.
1607 Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is
1608 zero on entry, then an attempt is made to retrieve the first entry from the performance log,
1609 and the key for the second entry in the log is returned. If the performance log is empty,
1610 then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance
1611 log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
1612 returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is
1613 retrieved and an implementation specific non-zero key value that specifies the end of the performance
1614 log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry
1615 is retrieved and zero is returned. In the cases where a performance log entry can be returned,
1616 the log entry is returned in Handle, Token, Module, StartTimeStamp, and EndTimeStamp.
1617 If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().
1618 If Handle is NULL, then ASSERT().
1619 If Token is NULL, then ASSERT().
1620 If Module is NULL, then ASSERT().
1621 If StartTimeStamp is NULL, then ASSERT().
1622 If EndTimeStamp is NULL, then ASSERT().
1624 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.
1625 0, then the first performance measurement log entry is retrieved.
1626 On exit, the key of the next performance log entry.
1627 @param Handle Pointer to environment specific context used to identify the component
1629 @param Token Pointer to a Null-terminated ASCII string that identifies the component
1631 @param Module Pointer to a Null-terminated ASCII string that identifies the module
1633 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
1635 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
1638 @return The key for the next performance log entry (in general case).
1643 GetPerformanceMeasurement (
1644 IN UINTN LogEntryKey
,
1645 OUT CONST VOID
**Handle
,
1646 OUT CONST CHAR8
**Token
,
1647 OUT CONST CHAR8
**Module
,
1648 OUT UINT64
*StartTimeStamp
,
1649 OUT UINT64
*EndTimeStamp
1656 Returns TRUE if the performance measurement macros are enabled.
1658 This function returns TRUE if the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
1659 PcdPerformanceLibraryPropertyMask is set. Otherwise FALSE is returned.
1661 @retval TRUE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
1662 PcdPerformanceLibraryPropertyMask is set.
1663 @retval FALSE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
1664 PcdPerformanceLibraryPropertyMask is clear.
1669 PerformanceMeasurementEnabled (
1673 return (BOOLEAN
) ((PcdGet8(PcdPerformanceLibraryPropertyMask
) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED
) != 0);