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
122 if (AsciiStrCmp (Token
, SEC_TOK
) == 0 ||
123 AsciiStrCmp (Token
, PEI_TOK
) == 0 ||
124 AsciiStrCmp (Token
, DXE_TOK
) == 0 ||
125 AsciiStrCmp (Token
, BDS_TOK
) == 0 ||
126 AsciiStrCmp (Token
, DRIVERBINDING_START_TOK
) == 0 ||
127 AsciiStrCmp (Token
, DRIVERBINDING_SUPPORT_TOK
) == 0 ||
128 AsciiStrCmp (Token
, DRIVERBINDING_STOP_TOK
) == 0 ||
129 AsciiStrCmp (Token
, LOAD_IMAGE_TOK
) == 0 ||
130 AsciiStrCmp (Token
, START_IMAGE_TOK
) == 0 ||
131 AsciiStrCmp (Token
, PEIM_TOK
) == 0) {
139 Check whether the ID is a known one which map to the known Token.
141 @param Identifier 32-bit identifier.
143 @retval TRUE Is a known one used by core.
144 @retval FALSE Not a known one.
152 if (Identifier
== MODULE_START_ID
||
153 Identifier
== MODULE_END_ID
||
154 Identifier
== MODULE_LOADIMAGE_START_ID
||
155 Identifier
== MODULE_LOADIMAGE_END_ID
||
156 Identifier
== MODULE_DB_START_ID
||
157 Identifier
== MODULE_DB_END_ID
||
158 Identifier
== MODULE_DB_SUPPORT_START_ID
||
159 Identifier
== MODULE_DB_SUPPORT_END_ID
||
160 Identifier
== MODULE_DB_STOP_START_ID
||
161 Identifier
== MODULE_DB_STOP_END_ID
) {
169 Allocate EfiReservedMemoryType below 4G memory address.
171 This function allocates EfiReservedMemoryType below 4G memory address.
173 @param[in] Size Size of memory to allocate.
175 @return Allocated address for output.
179 FpdtAllocateReservedMemoryBelow4G (
184 EFI_PHYSICAL_ADDRESS Address
;
189 Pages
= EFI_SIZE_TO_PAGES (Size
);
190 Address
= 0xffffffff;
192 Status
= gBS
->AllocatePages (
194 EfiReservedMemoryType
,
198 ASSERT_EFI_ERROR (Status
);
200 if (!EFI_ERROR (Status
)) {
201 Buffer
= (VOID
*) (UINTN
) Address
;
202 ZeroMem (Buffer
, Size
);
209 Allocate buffer for Boot Performance table.
215 AllocateBootPerformanceTable (
220 UINT8
*SmmBootRecordCommBuffer
;
221 EFI_SMM_COMMUNICATE_HEADER
*SmmCommBufferHeader
;
222 SMM_BOOT_RECORD_COMMUNICATE
*SmmCommData
;
224 UINTN BootPerformanceDataSize
;
225 UINT8
*BootPerformanceData
;
226 EFI_SMM_COMMUNICATION_PROTOCOL
*Communication
;
227 FIRMWARE_PERFORMANCE_VARIABLE PerformanceVariable
;
228 EDKII_PI_SMM_COMMUNICATION_REGION_TABLE
*SmmCommRegionTable
;
229 EFI_MEMORY_DESCRIPTOR
*SmmCommMemRegion
;
231 VOID
*SmmBootRecordData
;
232 UINTN SmmBootRecordDataSize
;
233 UINTN ReservedMemSize
;
236 // Collect boot records from SMM drivers.
238 SmmBootRecordCommBuffer
= NULL
;
240 SmmBootRecordData
= NULL
;
241 SmmBootRecordDataSize
= 0;
243 Status
= gBS
->LocateProtocol (&gEfiSmmCommunicationProtocolGuid
, NULL
, (VOID
**) &Communication
);
244 if (!EFI_ERROR (Status
)) {
246 // Initialize communicate buffer
247 // Get the prepared Reserved Memory Range
249 Status
= EfiGetSystemConfigurationTable (
250 &gEdkiiPiSmmCommunicationRegionTableGuid
,
251 (VOID
**) &SmmCommRegionTable
253 if (!EFI_ERROR (Status
)) {
254 ASSERT (SmmCommRegionTable
!= NULL
);
255 SmmCommMemRegion
= (EFI_MEMORY_DESCRIPTOR
*) (SmmCommRegionTable
+ 1);
256 for (Index
= 0; Index
< SmmCommRegionTable
->NumberOfEntries
; Index
++) {
257 if (SmmCommMemRegion
->Type
== EfiConventionalMemory
) {
260 SmmCommMemRegion
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) SmmCommMemRegion
+ SmmCommRegionTable
->DescriptorSize
);
262 ASSERT (Index
< SmmCommRegionTable
->NumberOfEntries
);
263 ASSERT (SmmCommMemRegion
->PhysicalStart
> 0);
264 ASSERT (SmmCommMemRegion
->NumberOfPages
> 0);
265 ReservedMemSize
= (UINTN
) SmmCommMemRegion
->NumberOfPages
* EFI_PAGE_SIZE
;
268 // Check enough reserved memory space
270 if (ReservedMemSize
> SMM_BOOT_RECORD_COMM_SIZE
) {
271 SmmBootRecordCommBuffer
= (VOID
*) (UINTN
) SmmCommMemRegion
->PhysicalStart
;
272 SmmCommBufferHeader
= (EFI_SMM_COMMUNICATE_HEADER
*)SmmBootRecordCommBuffer
;
273 SmmCommData
= (SMM_BOOT_RECORD_COMMUNICATE
*)SmmCommBufferHeader
->Data
;
274 ZeroMem((UINT8
*)SmmCommData
, sizeof(SMM_BOOT_RECORD_COMMUNICATE
));
276 CopyGuid (&SmmCommBufferHeader
->HeaderGuid
, &gEfiFirmwarePerformanceGuid
);
277 SmmCommBufferHeader
->MessageLength
= sizeof(SMM_BOOT_RECORD_COMMUNICATE
);
278 CommSize
= SMM_BOOT_RECORD_COMM_SIZE
;
281 // Get the size of boot records.
283 SmmCommData
->Function
= SMM_FPDT_FUNCTION_GET_BOOT_RECORD_SIZE
;
284 SmmCommData
->BootRecordData
= NULL
;
285 Status
= Communication
->Communicate (Communication
, SmmBootRecordCommBuffer
, &CommSize
);
287 if (!EFI_ERROR (Status
) && !EFI_ERROR (SmmCommData
->ReturnStatus
) && SmmCommData
->BootRecordSize
!= 0) {
289 // Get all boot records
291 SmmCommData
->Function
= SMM_FPDT_FUNCTION_GET_BOOT_RECORD_DATA_BY_OFFSET
;
292 SmmBootRecordDataSize
= SmmCommData
->BootRecordSize
;
293 SmmBootRecordData
= AllocateZeroPool(SmmBootRecordDataSize
);
294 ASSERT (SmmBootRecordData
!= NULL
);
295 SmmCommData
->BootRecordOffset
= 0;
296 SmmCommData
->BootRecordData
= (VOID
*) ((UINTN
) SmmCommMemRegion
->PhysicalStart
+ SMM_BOOT_RECORD_COMM_SIZE
);
297 SmmCommData
->BootRecordSize
= ReservedMemSize
- SMM_BOOT_RECORD_COMM_SIZE
;
298 while (SmmCommData
->BootRecordOffset
< SmmBootRecordDataSize
) {
299 Status
= Communication
->Communicate (Communication
, SmmBootRecordCommBuffer
, &CommSize
);
300 ASSERT_EFI_ERROR (Status
);
301 ASSERT_EFI_ERROR(SmmCommData
->ReturnStatus
);
302 if (SmmCommData
->BootRecordOffset
+ SmmCommData
->BootRecordSize
> SmmBootRecordDataSize
) {
303 CopyMem ((UINT8
*) SmmBootRecordData
+ SmmCommData
->BootRecordOffset
, SmmCommData
->BootRecordData
, SmmBootRecordDataSize
- SmmCommData
->BootRecordOffset
);
305 CopyMem ((UINT8
*) SmmBootRecordData
+ SmmCommData
->BootRecordOffset
, SmmCommData
->BootRecordData
, SmmCommData
->BootRecordSize
);
307 SmmCommData
->BootRecordOffset
= SmmCommData
->BootRecordOffset
+ SmmCommData
->BootRecordSize
;
315 // Prepare memory for Boot Performance table.
316 // Boot Performance table includes BasicBoot record, and one or more appended Boot Records.
318 BootPerformanceDataSize
= sizeof (BOOT_PERFORMANCE_TABLE
) + mPerformanceLength
+ PcdGet32 (PcdExtFpdtBootRecordPadSize
);
319 if (SmmCommData
!= NULL
&& SmmBootRecordData
!= NULL
) {
320 BootPerformanceDataSize
+= SmmBootRecordDataSize
;
324 // Try to allocate the same runtime buffer as last time boot.
326 ZeroMem (&PerformanceVariable
, sizeof (PerformanceVariable
));
327 Size
= sizeof (PerformanceVariable
);
328 Status
= gRT
->GetVariable (
329 EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME
,
330 &gEfiFirmwarePerformanceGuid
,
335 if (!EFI_ERROR (Status
)) {
336 Status
= gBS
->AllocatePages (
338 EfiReservedMemoryType
,
339 EFI_SIZE_TO_PAGES (BootPerformanceDataSize
),
340 &PerformanceVariable
.BootPerformanceTablePointer
342 if (!EFI_ERROR (Status
)) {
343 mAcpiBootPerformanceTable
= (BOOT_PERFORMANCE_TABLE
*) (UINTN
) PerformanceVariable
.BootPerformanceTablePointer
;
347 if (mAcpiBootPerformanceTable
== NULL
) {
349 // Fail to allocate at specified address, continue to allocate at any address.
351 mAcpiBootPerformanceTable
= (BOOT_PERFORMANCE_TABLE
*) FpdtAllocateReservedMemoryBelow4G (BootPerformanceDataSize
);
353 DEBUG ((DEBUG_INFO
, "DxeCorePerformanceLib: ACPI Boot Performance Table address = 0x%x\n", mAcpiBootPerformanceTable
));
355 if (mAcpiBootPerformanceTable
== NULL
) {
356 if (SmmCommData
!= NULL
&& SmmBootRecordData
!= NULL
) {
357 FreePool (SmmBootRecordData
);
359 return EFI_OUT_OF_RESOURCES
;
363 // Prepare Boot Performance Table.
365 BootPerformanceData
= (UINT8
*) mAcpiBootPerformanceTable
;
367 // Fill Basic Boot record to Boot Performance Table.
369 CopyMem (mAcpiBootPerformanceTable
, &mBootPerformanceTableTemplate
, sizeof (mBootPerformanceTableTemplate
));
370 BootPerformanceData
= BootPerformanceData
+ mAcpiBootPerformanceTable
->Header
.Length
;
372 // Fill Boot records from boot drivers.
374 if (mPerformancePointer
!= NULL
) {
375 CopyMem (BootPerformanceData
, mPerformancePointer
, mPerformanceLength
);
376 mAcpiBootPerformanceTable
->Header
.Length
+= mPerformanceLength
;
377 BootPerformanceData
= BootPerformanceData
+ mPerformanceLength
;
378 FreePool (mPerformancePointer
);
379 mPerformancePointer
= NULL
;
380 mPerformanceLength
= 0;
381 mMaxPerformanceLength
= 0;
383 if (SmmCommData
!= NULL
&& SmmBootRecordData
!= NULL
) {
385 // Fill Boot records from SMM drivers.
387 CopyMem (BootPerformanceData
, SmmBootRecordData
, SmmBootRecordDataSize
);
388 FreePool (SmmBootRecordData
);
389 mAcpiBootPerformanceTable
->Header
.Length
= (UINT32
) (mAcpiBootPerformanceTable
->Header
.Length
+ SmmBootRecordDataSize
);
390 BootPerformanceData
= BootPerformanceData
+ SmmBootRecordDataSize
;
393 mBootRecordBuffer
= (UINT8
*) mAcpiBootPerformanceTable
;
394 mBootRecordSize
= mAcpiBootPerformanceTable
->Header
.Length
;
395 mBootRecordMaxSize
= mBootRecordSize
+ PcdGet32 (PcdExtFpdtBootRecordPadSize
);
401 Get a human readable module name and module guid for the given image handle.
402 If module name can't be found, "" string will return.
403 If module guid can't be found, Zero Guid will return.
405 @param Handle Image handle or Controller handle.
406 @param NameString The ascii string will be filled into it. If not found, null string will return.
407 @param BufferSize Size of the input NameString buffer.
408 @param ModuleGuid Point to the guid buffer to store the got module guid value.
410 @retval EFI_SUCCESS Successfully get module name and guid.
411 @retval EFI_INVALID_PARAMETER The input parameter NameString is NULL.
412 @retval other value Module Name can't be got.
415 GetModuleInfoFromHandle (
416 IN EFI_HANDLE Handle
,
417 OUT CHAR8
*NameString
,
419 OUT EFI_GUID
*ModuleGuid OPTIONAL
423 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
424 EFI_DRIVER_BINDING_PROTOCOL
*DriverBinding
;
430 BOOLEAN ModuleGuidIsGet
;
433 EFI_COMPONENT_NAME2_PROTOCOL
*ComponentName2
;
434 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FvFilePath
;
436 if (NameString
== NULL
|| BufferSize
== 0) {
437 return EFI_INVALID_PARAMETER
;
440 // Try to get the ModuleGuid and name string form the caached array.
442 if (mCachePairCount
> 0) {
443 for (Count
= mCachePairCount
-1; Count
>= 0; Count
--) {
444 if (Handle
== mCacheHandleGuidTable
[Count
].Handle
) {
445 CopyGuid (ModuleGuid
, &mCacheHandleGuidTable
[Count
].ModuleGuid
);
446 AsciiStrCpyS (NameString
, FPDT_STRING_EVENT_RECORD_NAME_LENGTH
, mCacheHandleGuidTable
[Count
].NameString
);
452 Status
= EFI_INVALID_PARAMETER
;
454 ModuleGuidIsGet
= FALSE
;
457 // Initialize GUID as zero value.
459 TempGuid
= &gZeroGuid
;
461 // Initialize it as "" string.
465 if (Handle
!= NULL
) {
467 // Try Handle as ImageHandle.
469 Status
= gBS
->HandleProtocol (
471 &gEfiLoadedImageProtocolGuid
,
472 (VOID
**) &LoadedImage
475 if (EFI_ERROR (Status
)) {
477 // Try Handle as Controller Handle
479 Status
= gBS
->OpenProtocol (
481 &gEfiDriverBindingProtocolGuid
,
482 (VOID
**) &DriverBinding
,
485 EFI_OPEN_PROTOCOL_GET_PROTOCOL
487 if (!EFI_ERROR (Status
)) {
489 // Get Image protocol from ImageHandle
491 Status
= gBS
->HandleProtocol (
492 DriverBinding
->ImageHandle
,
493 &gEfiLoadedImageProtocolGuid
,
494 (VOID
**) &LoadedImage
500 if (!EFI_ERROR (Status
) && LoadedImage
!= NULL
) {
502 // Get Module Guid from DevicePath.
504 if (LoadedImage
->FilePath
!= NULL
&&
505 LoadedImage
->FilePath
->Type
== MEDIA_DEVICE_PATH
&&
506 LoadedImage
->FilePath
->SubType
== MEDIA_PIWG_FW_FILE_DP
509 // Determine GUID associated with module logging performance
511 ModuleGuidIsGet
= TRUE
;
512 FvFilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) LoadedImage
->FilePath
;
513 TempGuid
= &FvFilePath
->FvFileName
;
517 // Method 1 Get Module Name from PDB string.
519 PdbFileName
= PeCoffLoaderGetPdbPointer (LoadedImage
->ImageBase
);
520 if (PdbFileName
!= NULL
&& BufferSize
> 0) {
522 for (Index
= 0; PdbFileName
[Index
] != 0; Index
++) {
523 if ((PdbFileName
[Index
] == '\\') || (PdbFileName
[Index
] == '/')) {
524 StartIndex
= Index
+ 1;
528 // Copy the PDB file name to our temporary string.
529 // If the length is bigger than BufferSize, trim the redudant characters to avoid overflow in array boundary.
531 for (Index
= 0; Index
< BufferSize
- 1; Index
++) {
532 NameString
[Index
] = PdbFileName
[Index
+ StartIndex
];
533 if (NameString
[Index
] == 0 || NameString
[Index
] == '.') {
534 NameString
[Index
] = 0;
539 if (Index
== BufferSize
- 1) {
540 NameString
[Index
] = 0;
543 // Module Name is got.
550 // Method 2: Get the name string from ComponentName2 protocol
552 Status
= gBS
->HandleProtocol (
554 &gEfiComponentName2ProtocolGuid
,
555 (VOID
**) &ComponentName2
557 if (!EFI_ERROR (Status
)) {
559 // Get the current platform language setting
561 if (mPlatformLanguage
== NULL
) {
562 GetEfiGlobalVariable2 (L
"PlatformLang", (VOID
**) &mPlatformLanguage
, NULL
);
564 if (mPlatformLanguage
!= NULL
) {
565 Status
= ComponentName2
->GetDriverName (
567 mPlatformLanguage
!= NULL
? mPlatformLanguage
: "en-US",
570 if (!EFI_ERROR (Status
)) {
571 for (Index
= 0; Index
< BufferSize
- 1 && StringPtr
[Index
] != 0; Index
++) {
572 NameString
[Index
] = (CHAR8
) StringPtr
[Index
];
574 NameString
[Index
] = 0;
576 // Module Name is got.
583 if (ModuleGuidIsGet
) {
585 // Method 3 Try to get the image's FFS UI section by image GUID
589 Status
= GetSectionFromAnyFv (
591 EFI_SECTION_USER_INTERFACE
,
593 (VOID
**) &StringPtr
,
597 if (!EFI_ERROR (Status
)) {
599 // Method 3. Get the name string from FFS UI section
601 for (Index
= 0; Index
< BufferSize
- 1 && StringPtr
[Index
] != 0; Index
++) {
602 NameString
[Index
] = (CHAR8
) StringPtr
[Index
];
604 NameString
[Index
] = 0;
605 FreePool (StringPtr
);
613 if (ModuleGuid
!= NULL
) {
614 CopyGuid (ModuleGuid
, TempGuid
);
615 if (IsZeroGuid(TempGuid
) && (Handle
!= NULL
) && !ModuleGuidIsGet
) {
617 CopyGuid (ModuleGuid
, (EFI_GUID
*) Handle
);
622 // Cache the Handle and Guid pairs.
624 if (mCachePairCount
< CACHE_HANDLE_GUID_COUNT
) {
625 mCacheHandleGuidTable
[mCachePairCount
].Handle
= Handle
;
626 CopyGuid (&mCacheHandleGuidTable
[mCachePairCount
].ModuleGuid
, ModuleGuid
);
627 AsciiStrCpyS (mCacheHandleGuidTable
[mCachePairCount
].NameString
, FPDT_STRING_EVENT_RECORD_NAME_LENGTH
, NameString
);
635 Get the FPDT record info.
637 @param IsStart TRUE if the performance log is start log.
638 @param Handle Pointer to environment specific context used
639 to identify the component being measured.
640 @param Token Pointer to a Null-terminated ASCII string
641 that identifies the component being measured.
642 @param Module Pointer to a Null-terminated ASCII string
643 that identifies the module being measured.
644 @param RecordInfo On return, pointer to the info of the record.
645 @param UseModuleName Only useful for FPDT_DYNAMIC_STRING_EVENT_TYPE, indicate that whether need use
646 Module name to fill the string field in the FPDT_DYNAMIC_STRING_EVENT_RECORD.
648 @retval EFI_SUCCESS Get record info successfully.
649 @retval EFI_UNSUPPORTED No matched FPDT record.
655 IN CONST VOID
*Handle
,
656 IN CONST CHAR8
*Token
,
657 IN CONST CHAR8
*Module
,
658 OUT FPDT_BASIC_RECORD_INFO
*RecordInfo
,
659 IN OUT BOOLEAN
*UseModuleName
665 RecordType
= FPDT_DYNAMIC_STRING_EVENT_TYPE
;
668 // Token to Type and Id.
671 if (AsciiStrCmp (Token
, START_IMAGE_TOK
) == 0) { // "StartImage:"
672 *UseModuleName
= TRUE
;
673 RecordType
= FPDT_GUID_EVENT_TYPE
;
675 RecordInfo
->ProgressID
= MODULE_START_ID
;
677 RecordInfo
->ProgressID
= MODULE_END_ID
;
679 } else if (AsciiStrCmp (Token
, LOAD_IMAGE_TOK
) == 0) { // "LoadImage:"
680 *UseModuleName
= TRUE
;
681 RecordType
= FPDT_GUID_QWORD_EVENT_TYPE
;
683 RecordInfo
->ProgressID
= MODULE_LOADIMAGE_START_ID
;
685 RecordInfo
->ProgressID
= MODULE_LOADIMAGE_END_ID
;
687 } else if (AsciiStrCmp (Token
, DRIVERBINDING_START_TOK
) == 0) { // "DB:Start:"
688 *UseModuleName
= TRUE
;
690 RecordInfo
->ProgressID
= MODULE_DB_START_ID
;
691 RecordType
= FPDT_GUID_QWORD_EVENT_TYPE
;
693 RecordInfo
->ProgressID
= MODULE_DB_END_ID
;
694 RecordType
= FPDT_GUID_QWORD_STRING_EVENT_TYPE
;
696 } else if (AsciiStrCmp (Token
, DRIVERBINDING_SUPPORT_TOK
) == 0) { // "DB:Support:"
697 *UseModuleName
= TRUE
;
698 if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly
)) {
699 return RETURN_UNSUPPORTED
;
701 RecordType
= FPDT_GUID_QWORD_EVENT_TYPE
;
703 RecordInfo
->ProgressID
= MODULE_DB_SUPPORT_START_ID
;
705 RecordInfo
->ProgressID
= MODULE_DB_SUPPORT_END_ID
;
707 } else if (AsciiStrCmp (Token
, DRIVERBINDING_STOP_TOK
) == 0) { // "DB:Stop:"
708 *UseModuleName
= TRUE
;
709 if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly
)) {
710 return RETURN_UNSUPPORTED
;
712 RecordType
= FPDT_GUID_QWORD_EVENT_TYPE
;
714 RecordInfo
->ProgressID
= MODULE_DB_STOP_START_ID
;
716 RecordInfo
->ProgressID
= MODULE_DB_STOP_END_ID
;
718 } else if (AsciiStrCmp (Token
, PEI_TOK
) == 0 || // "PEI"
719 AsciiStrCmp (Token
, DXE_TOK
) == 0 || // "DXE"
720 AsciiStrCmp (Token
, BDS_TOK
) == 0) { // "BDS"
722 RecordInfo
->ProgressID
= PERF_CROSSMODULE_START_ID
;
724 RecordInfo
->ProgressID
= PERF_CROSSMODULE_END_ID
;
726 } else { // Pref used in Modules.
728 RecordInfo
->ProgressID
= PERF_INMODULE_START_ID
;
730 RecordInfo
->ProgressID
= PERF_INMODULE_END_ID
;
733 } else if (Handle
!= NULL
|| Module
!= NULL
) { // Pref used in Modules.
735 RecordInfo
->ProgressID
= PERF_INMODULE_START_ID
;
737 RecordInfo
->ProgressID
= PERF_INMODULE_END_ID
;
740 return EFI_UNSUPPORTED
;
744 // Get Record size baesed on the record type.
745 // When PcdEdkiiFpdtStringRecordEnableOnly is TRUE, all records are with type of FPDT_DYNAMIC_STRING_EVENT_TYPE.
747 if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly
)) {
748 RecordType
= FPDT_DYNAMIC_STRING_EVENT_TYPE
;
749 RecordInfo
->RecordSize
= sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD
) + STRING_SIZE
;
751 switch (RecordType
) {
752 case FPDT_GUID_EVENT_TYPE
:
753 RecordInfo
->RecordSize
= sizeof (FPDT_GUID_EVENT_RECORD
);
756 case FPDT_DYNAMIC_STRING_EVENT_TYPE
:
757 if (*UseModuleName
) {
758 StringSize
= STRING_SIZE
;
759 } else if (Token
!= NULL
) {
760 StringSize
= AsciiStrSize (Token
);
761 } else if (Module
!= NULL
) {
762 StringSize
= AsciiStrSize (Module
);
764 StringSize
= STRING_SIZE
;
766 if (StringSize
> STRING_SIZE
) {
767 StringSize
= STRING_SIZE
;
769 RecordInfo
->RecordSize
= (UINT8
)(sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD
) + StringSize
);
772 case FPDT_GUID_QWORD_EVENT_TYPE
:
773 RecordInfo
->RecordSize
= (UINT8
)sizeof (FPDT_GUID_QWORD_EVENT_RECORD
);
776 case FPDT_GUID_QWORD_STRING_EVENT_TYPE
:
777 RecordInfo
->RecordSize
= (UINT8
)sizeof (FPDT_GUID_QWORD_STRING_EVENT_RECORD
);
782 // Record is unsupported yet, return EFI_UNSUPPORTED
784 return EFI_UNSUPPORTED
;
788 RecordInfo
->Type
= RecordType
;
793 Add performance log to FPDT boot record table.
795 @param IsStart TRUE if the performance log is start log.
796 @param Handle Pointer to environment specific context used
797 to identify the component being measured.
798 @param Token Pointer to a Null-terminated ASCII string
799 that identifies the component being measured.
800 @param Module Pointer to a Null-terminated ASCII string
801 that identifies the module being measured.
802 @param Ticker 64-bit time stamp.
803 @param Identifier 32-bit identifier. If the value is 0, the created record
804 is same as the one created by StartGauge of PERFORMANCE_PROTOCOL.
806 @retval EFI_SUCCESS Add FPDT boot record.
807 @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement.
808 @retval EFI_UNSUPPORTED No matched FPDT record.
812 InsertFpdtMeasurement (
814 IN CONST VOID
*Handle
, OPTIONAL
815 IN CONST CHAR8
*Token
, OPTIONAL
816 IN CONST CHAR8
*Module
, OPTIONAL
822 CHAR8 ModuleName
[FPDT_STRING_EVENT_RECORD_NAME_LENGTH
];
824 FPDT_RECORD_PTR FpdtRecordPtr
;
825 FPDT_BASIC_RECORD_INFO RecordInfo
;
829 CONST CHAR8
*StringPtr
;
830 BOOLEAN UseModuleName
;
833 UseModuleName
= FALSE
;
834 ZeroMem (ModuleName
, sizeof (ModuleName
));
836 if (mLockInsertRecord
) {
837 return EFI_UNSUPPORTED
;
840 mLockInsertRecord
= TRUE
;
843 // Get record info (type, size, ProgressID and Module Guid).
845 Status
= GetFpdtRecordInfo (IsStart
, Handle
, Token
, Module
, &RecordInfo
, &UseModuleName
);
846 if (EFI_ERROR (Status
)) {
847 mLockInsertRecord
= FALSE
;
852 // If PERF_START()/PERF_END() have specified the ProgressID,it has high priority.
853 // !!! Note: If the Perf is not the known Token used in the core but have same
854 // ID with the core Token, this case will not be supported.
855 // And in currtnt usage mode, for the unkown ID, there is a general rule:
856 // If it is start pref: the lower 4 bits of the ID should be 0.
857 // If it is end pref: the lower 4 bits of the ID should not be 0.
858 // If input ID doesn't follow the rule, we will adjust it.
860 if ((Identifier
!= 0) && (IsKnownID (Identifier
)) && (!IsKnownTokens (Token
))) {
861 mLockInsertRecord
= FALSE
;
862 return EFI_UNSUPPORTED
;
863 } else if ((Identifier
!= 0) && (!IsKnownID (Identifier
)) && (!IsKnownTokens (Token
))) {
864 if (IsStart
&& ((Identifier
& 0x000F) != 0)) {
865 Identifier
&= 0xFFF0;
866 } else if ((!IsStart
) && ((Identifier
& 0x000F) == 0)) {
869 RecordInfo
.ProgressID
= (UINT16
)Identifier
;
872 if (mFpdtBufferIsReported
) {
874 // Append Boot records to the boot performance table.
876 if (mBootRecordSize
+ RecordInfo
.RecordSize
> mBootRecordMaxSize
) {
877 if (!mLackSpaceIsReported
) {
878 DEBUG ((DEBUG_INFO
, "DxeCorePerformanceLib: No enough space to save boot records\n"));
879 mLackSpaceIsReported
= TRUE
;
881 mLockInsertRecord
= FALSE
;
882 return EFI_OUT_OF_RESOURCES
;
885 // Save boot record into BootPerformance table
887 FpdtRecordPtr
.RecordHeader
= (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER
*)(mBootRecordBuffer
+ mBootRecordSize
);
888 mBootRecordSize
+= RecordInfo
.RecordSize
;
889 mAcpiBootPerformanceTable
->Header
.Length
+= RecordInfo
.RecordSize
;
893 // Check if pre-allocated buffer is full
895 if (mPerformanceLength
+ RecordInfo
.RecordSize
> mMaxPerformanceLength
) {
896 mPerformancePointer
= ReallocatePool (
898 mPerformanceLength
+ RecordInfo
.RecordSize
+ FIRMWARE_RECORD_BUFFER
,
902 if (mPerformancePointer
== NULL
) {
903 mLockInsertRecord
= FALSE
;
904 return EFI_OUT_OF_RESOURCES
;
906 mMaxPerformanceLength
= mPerformanceLength
+ RecordInfo
.RecordSize
+ FIRMWARE_RECORD_BUFFER
;
909 // Covert buffer to FPDT Ptr Union type.
911 FpdtRecordPtr
.RecordHeader
= (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER
*)(mPerformancePointer
+ mPerformanceLength
);
912 mPerformanceLength
+= RecordInfo
.RecordSize
;
916 // Get the TimeStamp.
919 Ticker
= GetPerformanceCounter ();
920 TimeStamp
= GetTimeInNanoSecond (Ticker
);
921 } else if (Ticker
== 1) {
924 TimeStamp
= GetTimeInNanoSecond (Ticker
);
928 // Get the ModuleName and ModuleGuid form the handle.
930 GetModuleInfoFromHandle ((EFI_HANDLE
*)Handle
, ModuleName
, sizeof (ModuleName
), &ModuleGuid
);
933 // Fill in the record information.
935 switch (RecordInfo
.Type
) {
936 case FPDT_GUID_EVENT_TYPE
:
937 FpdtRecordPtr
.GuidEvent
->Header
.Type
= FPDT_GUID_EVENT_TYPE
;
938 FpdtRecordPtr
.GuidEvent
->Header
.Length
= RecordInfo
.RecordSize
;
939 FpdtRecordPtr
.GuidEvent
->Header
.Revision
= FPDT_RECORD_REVISION_1
;
940 FpdtRecordPtr
.GuidEvent
->ProgressID
= RecordInfo
.ProgressID
;
941 FpdtRecordPtr
.GuidEvent
->Timestamp
= TimeStamp
;
942 CopyMem (&FpdtRecordPtr
.GuidEvent
->Guid
, &ModuleGuid
, sizeof (FpdtRecordPtr
.GuidEvent
->Guid
));
945 case FPDT_DYNAMIC_STRING_EVENT_TYPE
:
946 FpdtRecordPtr
.DynamicStringEvent
->Header
.Type
= FPDT_DYNAMIC_STRING_EVENT_TYPE
;
947 FpdtRecordPtr
.DynamicStringEvent
->Header
.Length
= RecordInfo
.RecordSize
;
948 FpdtRecordPtr
.DynamicStringEvent
->Header
.Revision
= FPDT_RECORD_REVISION_1
;
949 FpdtRecordPtr
.DynamicStringEvent
->ProgressID
= RecordInfo
.ProgressID
;
950 FpdtRecordPtr
.DynamicStringEvent
->Timestamp
= TimeStamp
;
951 CopyMem (&FpdtRecordPtr
.DynamicStringEvent
->Guid
, &ModuleGuid
, sizeof (FpdtRecordPtr
.DynamicStringEvent
->Guid
));
954 StringPtr
= ModuleName
;
955 } else if (Token
!= NULL
) {
957 } else if (Module
!= NULL
) {
959 } else if (ModuleName
!= NULL
) {
960 StringPtr
= ModuleName
;
962 if (StringPtr
!= NULL
&& AsciiStrLen (StringPtr
) != 0) {
963 StrLength
= AsciiStrLen (StringPtr
);
964 DestMax
= (RecordInfo
.RecordSize
- sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD
)) / sizeof (CHAR8
);
965 if (StrLength
>= DestMax
) {
966 StrLength
= DestMax
-1;
968 AsciiStrnCpyS (FpdtRecordPtr
.DynamicStringEvent
->String
, DestMax
, StringPtr
, StrLength
);
970 AsciiStrCpyS (FpdtRecordPtr
.DynamicStringEvent
->String
, FPDT_STRING_EVENT_RECORD_NAME_LENGTH
, "unknown name");
974 case FPDT_GUID_QWORD_EVENT_TYPE
:
975 FpdtRecordPtr
.GuidQwordEvent
->Header
.Type
= FPDT_GUID_QWORD_EVENT_TYPE
;
976 FpdtRecordPtr
.GuidQwordEvent
->Header
.Length
= RecordInfo
.RecordSize
;
977 FpdtRecordPtr
.GuidQwordEvent
->Header
.Revision
= FPDT_RECORD_REVISION_1
;
978 FpdtRecordPtr
.GuidQwordEvent
->ProgressID
= RecordInfo
.ProgressID
;
979 FpdtRecordPtr
.GuidQwordEvent
->Timestamp
= TimeStamp
;
980 CopyMem (&FpdtRecordPtr
.GuidQwordEvent
->Guid
, &ModuleGuid
, sizeof (FpdtRecordPtr
.GuidQwordEvent
->Guid
));
981 if ((MODULE_LOADIMAGE_START_ID
== RecordInfo
.ProgressID
) && AsciiStrCmp (Token
, LOAD_IMAGE_TOK
) == 0) {
983 FpdtRecordPtr
.GuidQwordEvent
->Qword
= mLoadImageCount
;
987 case FPDT_GUID_QWORD_STRING_EVENT_TYPE
:
988 FpdtRecordPtr
.GuidQwordStringEvent
->Header
.Type
= FPDT_GUID_QWORD_STRING_EVENT_TYPE
;
989 FpdtRecordPtr
.GuidQwordStringEvent
->Header
.Length
= RecordInfo
.RecordSize
;
990 FpdtRecordPtr
.GuidQwordStringEvent
->Header
.Revision
= FPDT_RECORD_REVISION_1
;
991 FpdtRecordPtr
.GuidQwordStringEvent
->ProgressID
= RecordInfo
.ProgressID
;
992 FpdtRecordPtr
.GuidQwordStringEvent
->Timestamp
= TimeStamp
;
993 CopyMem (&FpdtRecordPtr
.GuidQwordStringEvent
->Guid
, &ModuleGuid
, sizeof (FpdtRecordPtr
.GuidQwordStringEvent
->Guid
));
998 // Record is not supported in current DXE phase, return EFI_ABORTED
1000 mLockInsertRecord
= FALSE
;
1001 return EFI_UNSUPPORTED
;
1004 mLockInsertRecord
= FALSE
;
1009 Dumps all the PEI performance.
1011 @param HobStart A pointer to a Guid.
1013 This internal function dumps all the PEI performance log to the DXE performance gauge array.
1014 It retrieves the optional GUID HOB for PEI performance and then saves the performance data
1015 to DXE performance data structures.
1019 InternalGetPeiPerformance (
1023 UINT8
*FirmwarePerformanceHob
;
1024 FPDT_PEI_EXT_PERF_HEADER
*PeiPerformanceLogHeader
;
1026 EFI_HOB_GUID_TYPE
*GuidHob
;
1028 GuidHob
= GetNextGuidHob (&gEdkiiFpdtExtendedFirmwarePerformanceGuid
, HobStart
);
1029 while (GuidHob
!= NULL
) {
1030 FirmwarePerformanceHob
= GET_GUID_HOB_DATA (GuidHob
);
1031 PeiPerformanceLogHeader
= (FPDT_PEI_EXT_PERF_HEADER
*)FirmwarePerformanceHob
;
1033 if (mPerformanceLength
+ PeiPerformanceLogHeader
->SizeOfAllEntries
> mMaxPerformanceLength
) {
1034 mPerformancePointer
= ReallocatePool (
1036 mPerformanceLength
+
1037 (UINTN
)PeiPerformanceLogHeader
->SizeOfAllEntries
+
1038 FIRMWARE_RECORD_BUFFER
,
1041 ASSERT (mPerformancePointer
!= NULL
);
1042 mMaxPerformanceLength
= mPerformanceLength
+
1043 (UINTN
)(PeiPerformanceLogHeader
->SizeOfAllEntries
) +
1044 FIRMWARE_RECORD_BUFFER
;
1047 EventRec
= mPerformancePointer
+ mPerformanceLength
;
1048 CopyMem (EventRec
, FirmwarePerformanceHob
+ sizeof (FPDT_PEI_EXT_PERF_HEADER
), (UINTN
)(PeiPerformanceLogHeader
->SizeOfAllEntries
));
1050 // Update the used buffer size.
1052 mPerformanceLength
+= (UINTN
)(PeiPerformanceLogHeader
->SizeOfAllEntries
);
1053 mLoadImageCount
+= PeiPerformanceLogHeader
->LoadImageCount
;
1056 // Get next performance guid hob
1058 GuidHob
= GetNextGuidHob (&gEdkiiFpdtExtendedFirmwarePerformanceGuid
, GET_NEXT_HOB (GuidHob
));
1063 Report Boot Perforamnce table address as report status code.
1065 @param Event The event of notify protocol.
1066 @param Context Notify event context.
1071 ReportFpdtRecordBuffer (
1079 if (!mFpdtBufferIsReported
) {
1080 Status
= AllocateBootPerformanceTable ();
1081 if (!EFI_ERROR(Status
)) {
1082 BPDTAddr
= (UINT64
)(UINTN
)mAcpiBootPerformanceTable
;
1083 REPORT_STATUS_CODE_EX (
1085 EFI_SOFTWARE_DXE_BS_DRIVER
,
1088 &gEdkiiFpdtExtendedFirmwarePerformanceGuid
,
1094 // Set FPDT report state to TRUE.
1096 mFpdtBufferIsReported
= TRUE
;
1101 Adds a record at the end of the performance measurement log
1102 that records the start time of a performance measurement.
1104 Adds a record to the end of the performance measurement log
1105 that contains the Handle, Token, Module and Identifier.
1106 The end time of the new record must be set to zero.
1107 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
1108 If TimeStamp is zero, the start time in the record is filled in with the value
1109 read from the current time stamp.
1111 @param Handle Pointer to environment specific context used
1112 to identify the component being measured.
1113 @param Token Pointer to a Null-terminated ASCII string
1114 that identifies the component being measured.
1115 @param Module Pointer to a Null-terminated ASCII string
1116 that identifies the module being measured.
1117 @param TimeStamp 64-bit time stamp.
1118 @param Identifier 32-bit identifier. If the value is 0, the created record
1119 is same as the one created by StartGauge of PERFORMANCE_PROTOCOL.
1121 @retval EFI_SUCCESS The data was read correctly from the device.
1122 @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement.
1128 IN CONST VOID
*Handle
, OPTIONAL
1129 IN CONST CHAR8
*Token
, OPTIONAL
1130 IN CONST CHAR8
*Module
, OPTIONAL
1131 IN UINT64 TimeStamp
,
1132 IN UINT32 Identifier
1135 return InsertFpdtMeasurement (TRUE
, Handle
, Token
, Module
, TimeStamp
, Identifier
);
1139 Searches the performance measurement log from the beginning of the log
1140 for the first matching record that contains a zero end time and fills in a valid end time.
1142 Searches the performance measurement log from the beginning of the log
1143 for the first record that matches Handle, Token, Module and Identifier and has an end time value of zero.
1144 If the record can not be found then return EFI_NOT_FOUND.
1145 If the record is found and TimeStamp is not zero,
1146 then the end time in the record is filled in with the value specified by TimeStamp.
1147 If the record is found and TimeStamp is zero, then the end time in the matching record
1148 is filled in with the current time stamp value.
1150 @param Handle Pointer to environment specific context used
1151 to identify the component being measured.
1152 @param Token Pointer to a Null-terminated ASCII string
1153 that identifies the component being measured.
1154 @param Module Pointer to a Null-terminated ASCII string
1155 that identifies the module being measured.
1156 @param TimeStamp 64-bit time stamp.
1157 @param Identifier 32-bit identifier. If the value is 0, the found record
1158 is same as the one found by EndGauge of PERFORMANCE_PROTOCOL.
1160 @retval EFI_SUCCESS The end of the measurement was recorded.
1161 @retval EFI_NOT_FOUND The specified measurement record could not be found.
1167 IN CONST VOID
*Handle
, OPTIONAL
1168 IN CONST CHAR8
*Token
, OPTIONAL
1169 IN CONST CHAR8
*Module
, OPTIONAL
1170 IN UINT64 TimeStamp
,
1171 IN UINT32 Identifier
1174 return InsertFpdtMeasurement (FALSE
, Handle
, Token
, Module
, TimeStamp
, Identifier
);
1178 Retrieves a previously logged performance measurement.
1179 It can also retrieve the log created by StartGauge and EndGauge of PERFORMANCE_PROTOCOL,
1180 and then assign the Identifier with 0.
1184 Retrieves the performance log entry from the performance log specified by LogEntryKey.
1185 If it stands for a valid entry, then EFI_SUCCESS is returned and
1186 GaugeDataEntryEx stores the pointer to that entry.
1188 @param LogEntryKey The key for the previous performance measurement log entry.
1189 If 0, then the first performance measurement log entry is retrieved.
1190 @param GaugeDataEntryEx The indirect pointer to the extended gauge data entry specified by LogEntryKey
1191 if the retrieval is successful.
1193 @retval EFI_SUCCESS The GuageDataEntryEx is successfully found based on LogEntryKey.
1194 @retval EFI_NOT_FOUND The LogEntryKey is the last entry (equals to the total entry number).
1195 @retval EFI_INVALIDE_PARAMETER The LogEntryKey is not a valid entry (greater than the total entry number).
1196 @retval EFI_INVALIDE_PARAMETER GaugeDataEntryEx is NULL.
1202 IN UINTN LogEntryKey
,
1203 OUT GAUGE_DATA_ENTRY_EX
**GaugeDataEntryEx
1206 return EFI_UNSUPPORTED
;
1210 Adds a record at the end of the performance measurement log
1211 that records the start time of a performance measurement.
1213 Adds a record to the end of the performance measurement log
1214 that contains the Handle, Token, and Module.
1215 The end time of the new record must be set to zero.
1216 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
1217 If TimeStamp is zero, the start time in the record is filled in with the value
1218 read from the current time stamp.
1220 @param Handle Pointer to environment specific context used
1221 to identify the component being measured.
1222 @param Token Pointer to a Null-terminated ASCII string
1223 that identifies the component being measured.
1224 @param Module Pointer to a Null-terminated ASCII string
1225 that identifies the module being measured.
1226 @param TimeStamp 64-bit time stamp.
1228 @retval EFI_SUCCESS The data was read correctly from the device.
1229 @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement.
1235 IN CONST VOID
*Handle
, OPTIONAL
1236 IN CONST CHAR8
*Token
, OPTIONAL
1237 IN CONST CHAR8
*Module
, OPTIONAL
1241 return StartGaugeEx (Handle
, Token
, Module
, TimeStamp
, 0);
1245 Searches the performance measurement log from the beginning of the log
1246 for the first matching record that contains a zero end time and fills in a valid end time.
1248 Searches the performance measurement log from the beginning of the log
1249 for the first record that matches Handle, Token, and Module and has an end time value of zero.
1250 If the record can not be found then return EFI_NOT_FOUND.
1251 If the record is found and TimeStamp is not zero,
1252 then the end time in the record is filled in with the value specified by TimeStamp.
1253 If the record is found and TimeStamp is zero, then the end time in the matching record
1254 is filled in with the current time stamp value.
1256 @param Handle Pointer to environment specific context used
1257 to identify the component being measured.
1258 @param Token Pointer to a Null-terminated ASCII string
1259 that identifies the component being measured.
1260 @param Module Pointer to a Null-terminated ASCII string
1261 that identifies the module being measured.
1262 @param TimeStamp 64-bit time stamp.
1264 @retval EFI_SUCCESS The end of the measurement was recorded.
1265 @retval EFI_NOT_FOUND The specified measurement record could not be found.
1271 IN CONST VOID
*Handle
, OPTIONAL
1272 IN CONST CHAR8
*Token
, OPTIONAL
1273 IN CONST CHAR8
*Module
, OPTIONAL
1277 return EndGaugeEx (Handle
, Token
, Module
, TimeStamp
, 0);
1281 Retrieves a previously logged performance measurement.
1282 It can also retrieve the log created by StartGaugeEx and EndGaugeEx of PERFORMANCE_EX_PROTOCOL,
1283 and then eliminate the Identifier.
1287 Retrieves the performance log entry from the performance log specified by LogEntryKey.
1288 If it stands for a valid entry, then EFI_SUCCESS is returned and
1289 GaugeDataEntry stores the pointer to that entry.
1291 @param LogEntryKey The key for the previous performance measurement log entry.
1292 If 0, then the first performance measurement log entry is retrieved.
1293 @param GaugeDataEntry The indirect pointer to the gauge data entry specified by LogEntryKey
1294 if the retrieval is successful.
1296 @retval EFI_SUCCESS The GuageDataEntry is successfully found based on LogEntryKey.
1297 @retval EFI_NOT_FOUND The LogEntryKey is the last entry (equals to the total entry number).
1298 @retval EFI_INVALIDE_PARAMETER The LogEntryKey is not a valid entry (greater than the total entry number).
1299 @retval EFI_INVALIDE_PARAMETER GaugeDataEntry is NULL.
1305 IN UINTN LogEntryKey
,
1306 OUT GAUGE_DATA_ENTRY
**GaugeDataEntry
1309 return EFI_UNSUPPORTED
;
1314 The constructor function initializes Performance infrastructure for DXE phase.
1316 The constructor function publishes Performance and PerformanceEx protocol, allocates memory to log DXE performance
1317 and merges PEI performance data to DXE performance log.
1318 It will ASSERT() if one of these operations fails and it will always return EFI_SUCCESS.
1320 @param ImageHandle The firmware allocated handle for the EFI image.
1321 @param SystemTable A pointer to the EFI System Table.
1323 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
1328 DxeCorePerformanceLibConstructor (
1329 IN EFI_HANDLE ImageHandle
,
1330 IN EFI_SYSTEM_TABLE
*SystemTable
1335 EFI_EVENT ReadyToBootEvent
;
1336 PERFORMANCE_PROPERTY
*PerformanceProperty
;
1338 if (!PerformanceMeasurementEnabled ()) {
1340 // Do not initialize performance infrastructure if not required.
1346 // Dump normal PEI performance records
1348 InternalGetPeiPerformance (GetHobList());
1351 // Install the protocol interfaces for DXE performance library instance.
1354 Status
= gBS
->InstallMultipleProtocolInterfaces (
1356 &gPerformanceProtocolGuid
,
1357 &mPerformanceInterface
,
1358 &gPerformanceExProtocolGuid
,
1359 &mPerformanceExInterface
,
1362 ASSERT_EFI_ERROR (Status
);
1365 // Register ReadyToBoot event to report StatusCode data
1367 Status
= gBS
->CreateEventEx (
1370 ReportFpdtRecordBuffer
,
1372 &gEfiEventReadyToBootGuid
,
1376 ASSERT_EFI_ERROR (Status
);
1378 Status
= EfiGetSystemConfigurationTable (&gPerformanceProtocolGuid
, (VOID
**) &PerformanceProperty
);
1379 if (EFI_ERROR (Status
)) {
1381 // Install configuration table for performance property.
1383 mPerformanceProperty
.Revision
= PERFORMANCE_PROPERTY_REVISION
;
1384 mPerformanceProperty
.Reserved
= 0;
1385 mPerformanceProperty
.Frequency
= GetPerformanceCounterProperties (
1386 &mPerformanceProperty
.TimerStartValue
,
1387 &mPerformanceProperty
.TimerEndValue
1389 Status
= gBS
->InstallConfigurationTable (&gPerformanceProtocolGuid
, &mPerformanceProperty
);
1390 ASSERT_EFI_ERROR (Status
);
1397 Adds a record at the end of the performance measurement log
1398 that records the start time of a performance measurement.
1400 Adds a record to the end of the performance measurement log
1401 that contains the Handle, Token, Module and Identifier.
1402 The end time of the new record must be set to zero.
1403 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
1404 If TimeStamp is zero, the start time in the record is filled in with the value
1405 read from the current time stamp.
1407 @param Handle Pointer to environment specific context used
1408 to identify the component being measured.
1409 @param Token Pointer to a Null-terminated ASCII string
1410 that identifies the component being measured.
1411 @param Module Pointer to a Null-terminated ASCII string
1412 that identifies the module being measured.
1413 @param TimeStamp 64-bit time stamp.
1414 @param Identifier 32-bit identifier. If the value is 0, the created record
1415 is same as the one created by StartPerformanceMeasurement.
1417 @retval RETURN_SUCCESS The start of the measurement was recorded.
1418 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.
1423 StartPerformanceMeasurementEx (
1424 IN CONST VOID
*Handle
, OPTIONAL
1425 IN CONST CHAR8
*Token
, OPTIONAL
1426 IN CONST CHAR8
*Module
, OPTIONAL
1427 IN UINT64 TimeStamp
,
1428 IN UINT32 Identifier
1431 return InsertFpdtMeasurement (TRUE
, Handle
, Token
, Module
, TimeStamp
, Identifier
);
1435 Searches the performance measurement log from the beginning of the log
1436 for the first matching record that contains a zero end time and fills in a valid end time.
1438 Searches the performance measurement log from the beginning of the log
1439 for the first record that matches Handle, Token, Module and Identifier and has an end time value of zero.
1440 If the record can not be found then return RETURN_NOT_FOUND.
1441 If the record is found and TimeStamp is not zero,
1442 then the end time in the record is filled in with the value specified by TimeStamp.
1443 If the record is found and TimeStamp is zero, then the end time in the matching record
1444 is filled in with the current time stamp value.
1446 @param Handle Pointer to environment specific context used
1447 to identify the component being measured.
1448 @param Token Pointer to a Null-terminated ASCII string
1449 that identifies the component being measured.
1450 @param Module Pointer to a Null-terminated ASCII string
1451 that identifies the module being measured.
1452 @param TimeStamp 64-bit time stamp.
1453 @param Identifier 32-bit identifier. If the value is 0, the found record
1454 is same as the one found by EndPerformanceMeasurement.
1456 @retval RETURN_SUCCESS The end of the measurement was recorded.
1457 @retval RETURN_NOT_FOUND The specified measurement record could not be found.
1462 EndPerformanceMeasurementEx (
1463 IN CONST VOID
*Handle
, OPTIONAL
1464 IN CONST CHAR8
*Token
, OPTIONAL
1465 IN CONST CHAR8
*Module
, OPTIONAL
1466 IN UINT64 TimeStamp
,
1467 IN UINT32 Identifier
1470 return InsertFpdtMeasurement (FALSE
, Handle
, Token
, Module
, TimeStamp
, Identifier
);
1474 Attempts to retrieve a performance measurement log entry from the performance measurement log.
1475 It can also retrieve the log created by StartPerformanceMeasurement and EndPerformanceMeasurement,
1476 and then assign the Identifier with 0.
1480 Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is
1481 zero on entry, then an attempt is made to retrieve the first entry from the performance log,
1482 and the key for the second entry in the log is returned. If the performance log is empty,
1483 then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance
1484 log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
1485 returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is
1486 retrieved and an implementation specific non-zero key value that specifies the end of the performance
1487 log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry
1488 is retrieved and zero is returned. In the cases where a performance log entry can be returned,
1489 the log entry is returned in Handle, Token, Module, StartTimeStamp, EndTimeStamp and Identifier.
1490 If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().
1491 If Handle is NULL, then ASSERT().
1492 If Token is NULL, then ASSERT().
1493 If Module is NULL, then ASSERT().
1494 If StartTimeStamp is NULL, then ASSERT().
1495 If EndTimeStamp is NULL, then ASSERT().
1496 If Identifier is NULL, then ASSERT().
1498 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.
1499 0, then the first performance measurement log entry is retrieved.
1500 On exit, the key of the next performance log entry.
1501 @param Handle Pointer to environment specific context used to identify the component
1503 @param Token Pointer to a Null-terminated ASCII string that identifies the component
1505 @param Module Pointer to a Null-terminated ASCII string that identifies the module
1507 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
1509 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
1511 @param Identifier Pointer to the 32-bit identifier that was recorded when the measurement
1514 @return The key for the next performance log entry (in general case).
1519 GetPerformanceMeasurementEx (
1520 IN UINTN LogEntryKey
,
1521 OUT CONST VOID
**Handle
,
1522 OUT CONST CHAR8
**Token
,
1523 OUT CONST CHAR8
**Module
,
1524 OUT UINT64
*StartTimeStamp
,
1525 OUT UINT64
*EndTimeStamp
,
1526 OUT UINT32
*Identifier
1533 Adds a record at the end of the performance measurement log
1534 that records the start time of a performance measurement.
1536 Adds a record to the end of the performance measurement log
1537 that contains the Handle, Token, and Module.
1538 The end time of the new record must be set to zero.
1539 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
1540 If TimeStamp is zero, the start time in the record is filled in with the value
1541 read from the current time stamp.
1543 @param Handle Pointer to environment specific context used
1544 to identify the component being measured.
1545 @param Token Pointer to a Null-terminated ASCII string
1546 that identifies the component being measured.
1547 @param Module Pointer to a Null-terminated ASCII string
1548 that identifies the module being measured.
1549 @param TimeStamp 64-bit time stamp.
1551 @retval RETURN_SUCCESS The start of the measurement was recorded.
1552 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.
1557 StartPerformanceMeasurement (
1558 IN CONST VOID
*Handle
, OPTIONAL
1559 IN CONST CHAR8
*Token
, OPTIONAL
1560 IN CONST CHAR8
*Module
, OPTIONAL
1564 return InsertFpdtMeasurement (TRUE
, Handle
, Token
, Module
, TimeStamp
, 0);
1568 Searches the performance measurement log from the beginning of the log
1569 for the first matching record that contains a zero end time and fills in a valid end time.
1571 Searches the performance measurement log from the beginning of the log
1572 for the first record that matches Handle, Token, and Module and has an end time value of zero.
1573 If the record can not be found then return RETURN_NOT_FOUND.
1574 If the record is found and TimeStamp is not zero,
1575 then the end time in the record is filled in with the value specified by TimeStamp.
1576 If the record is found and TimeStamp is zero, then the end time in the matching record
1577 is filled in with the current time stamp value.
1579 @param Handle Pointer to environment specific context used
1580 to identify the component being measured.
1581 @param Token Pointer to a Null-terminated ASCII string
1582 that identifies the component being measured.
1583 @param Module Pointer to a Null-terminated ASCII string
1584 that identifies the module being measured.
1585 @param TimeStamp 64-bit time stamp.
1587 @retval RETURN_SUCCESS The end of the measurement was recorded.
1588 @retval RETURN_NOT_FOUND The specified measurement record could not be found.
1593 EndPerformanceMeasurement (
1594 IN CONST VOID
*Handle
, OPTIONAL
1595 IN CONST CHAR8
*Token
, OPTIONAL
1596 IN CONST CHAR8
*Module
, OPTIONAL
1600 return InsertFpdtMeasurement (FALSE
, Handle
, Token
, Module
, TimeStamp
, 0);
1604 Attempts to retrieve a performance measurement log entry from the performance measurement log.
1605 It can also retrieve the log created by StartPerformanceMeasurementEx and EndPerformanceMeasurementEx,
1606 and then eliminate the Identifier.
1610 Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is
1611 zero on entry, then an attempt is made to retrieve the first entry from the performance log,
1612 and the key for the second entry in the log is returned. If the performance log is empty,
1613 then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance
1614 log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
1615 returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is
1616 retrieved and an implementation specific non-zero key value that specifies the end of the performance
1617 log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry
1618 is retrieved and zero is returned. In the cases where a performance log entry can be returned,
1619 the log entry is returned in Handle, Token, Module, StartTimeStamp, and EndTimeStamp.
1620 If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().
1621 If Handle is NULL, then ASSERT().
1622 If Token is NULL, then ASSERT().
1623 If Module is NULL, then ASSERT().
1624 If StartTimeStamp is NULL, then ASSERT().
1625 If EndTimeStamp is NULL, then ASSERT().
1627 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.
1628 0, then the first performance measurement log entry is retrieved.
1629 On exit, the key of the next performance log entry.
1630 @param Handle Pointer to environment specific context used to identify the component
1632 @param Token Pointer to a Null-terminated ASCII string that identifies the component
1634 @param Module Pointer to a Null-terminated ASCII string that identifies the module
1636 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
1638 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
1641 @return The key for the next performance log entry (in general case).
1646 GetPerformanceMeasurement (
1647 IN UINTN LogEntryKey
,
1648 OUT CONST VOID
**Handle
,
1649 OUT CONST CHAR8
**Token
,
1650 OUT CONST CHAR8
**Module
,
1651 OUT UINT64
*StartTimeStamp
,
1652 OUT UINT64
*EndTimeStamp
1659 Returns TRUE if the performance measurement macros are enabled.
1661 This function returns TRUE if the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
1662 PcdPerformanceLibraryPropertyMask is set. Otherwise FALSE is returned.
1664 @retval TRUE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
1665 PcdPerformanceLibraryPropertyMask is set.
1666 @retval FALSE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
1667 PcdPerformanceLibraryPropertyMask is clear.
1672 PerformanceMeasurementEnabled (
1676 return (BOOLEAN
) ((PcdGet8(PcdPerformanceLibraryPropertyMask
) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED
) != 0);