summaryrefslogtreecommitdiff
path: root/EDK/Foundation/Library/Dxe/EfiDriverLib/Perf.c
diff options
context:
space:
mode:
Diffstat (limited to 'EDK/Foundation/Library/Dxe/EfiDriverLib/Perf.c')
-rw-r--r--EDK/Foundation/Library/Dxe/EfiDriverLib/Perf.c946
1 files changed, 946 insertions, 0 deletions
diff --git a/EDK/Foundation/Library/Dxe/EfiDriverLib/Perf.c b/EDK/Foundation/Library/Dxe/EfiDriverLib/Perf.c
new file mode 100644
index 0000000..9bed854
--- /dev/null
+++ b/EDK/Foundation/Library/Dxe/EfiDriverLib/Perf.c
@@ -0,0 +1,946 @@
+/*++
+
+Copyright (c) 2004 - 2012, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Perf.c
+
+Abstract:
+
+ Support library for DXE Firmware Performance logging.
+
+--*/
+
+#include "Tiano.h"
+
+#include EFI_PROTOCOL_DEFINITION (FirmwarePerformance)
+#include EFI_GUID_DEFINITION (PeiPerformanceHob)
+#include EFI_PROTOCOL_DEFINITION (LoadedImage)
+#include EFI_PROTOCOL_DEFINITION (DriverBinding)
+#include EFI_GUID_DEFINITION (Hob)
+
+#include "EfiDriverLib.h"
+#include "EfiHobLib.h"
+#include "EfiImage.h"
+#include "EfiCommonLib.h"
+#include "CpuIA32.h"
+
+EFI_GUID gNullGuid = EFI_NULL_GUID;
+FIRMWARE_PERFORMANCE_PROTOCOL *FirmwarePerformance;
+
+static UINT32 *mPerformancePointer;
+static UINT32 mPerformanceLength;
+UINT16 BdsAttemptNumber = 0;
+
+#define LOCAL_APIC_BASE 0xfee00000
+#define APIC_ID_REGISTER 0x20
+#define MSR_EXT_XAPIC_LOGICAL_APIC_ID 0x802
+#define MSR_XAPIC_BASE 0x1B
+#define MSR_XAPIC_BASE_MASK 0x0c00
+#define MAX_NON_TURBO_RATIO_OFFSET 8
+#define MAX_NON_TURBO_RATIO_MASK 0xff
+#define PLATFORM_INFO_MSR 0xce
+
+EFI_STATUS
+GetTimerValue (
+ OUT UINT64 *TimerValue
+ );
+
+EFI_STATUS
+GetPeiFirmwarePerformanceHob (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+UINT64 GetTimeInNanoSec (
+ UINT64 Ticker
+ )
+/*++
+
+Routine Description:
+
+ Internal routine to convert TSC value into nano second value
+
+Arguments:
+
+ Ticker - OPTIONAL. TSC value supplied by caller function
+
+Returns:
+
+ UINT64 - returns calculated timer value
+
+--*/
+{
+ UINT64 Tick, pi;
+ UINT8 Ratio;
+
+ if(Ticker != 0){
+ Tick = Ticker;
+ } else {
+ GetTimerValue (&Tick);
+ }
+
+ pi = EfiReadMsr(PLATFORM_INFO_MSR);
+ Ratio = (UINT8)( ((UINT32)(UINTN)RShiftU64(pi, MAX_NON_TURBO_RATIO_OFFSET)) & MAX_NON_TURBO_RATIO_MASK);
+
+ return (UINT64)DivU64x32((UINT64)MultU64x32(Tick, 10), (UINTN)(Ratio), NULL);
+}
+
+UINT32 GetApicId (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Internal routine to retrieve current APIC Id
+
+Arguments:
+
+ None
+
+Returns:
+
+ UINT32 - returns Apic Id value
+
+--*/
+{
+ BOOLEAN x2ApicEnabled;
+ UINT32 ApicId;
+
+ x2ApicEnabled = (BOOLEAN)(((EfiReadMsr (MSR_XAPIC_BASE)) & (MSR_XAPIC_BASE_MASK)) == MSR_XAPIC_BASE_MASK);
+ if (x2ApicEnabled) {
+ ApicId = (UINT32) EfiReadMsr (MSR_EXT_XAPIC_LOGICAL_APIC_ID);
+ } else {
+ ApicId = (UINT8) (*(volatile UINT32 *) (UINTN) (LOCAL_APIC_BASE + APIC_ID_REGISTER) >> 24);
+ }
+
+ return ApicId;
+}
+
+STATIC
+VOID
+GetShortPdbFileName (
+ CHAR8 *PdbFileName,
+ CHAR8 *GaugeString
+ )
+/*++
+
+Routine Description:
+
+ Shotens PDB path name
+
+Arguments:
+
+ PdbFileName - PdbFileName
+
+Returns:
+ GaugeString - GaugeString
+
+--*/
+{
+ UINTN Index;
+ UINTN Index1;
+ UINTN StartIndex;
+ UINTN EndIndex;
+
+ if (PdbFileName == NULL) {
+ EfiAsciiStrCpy (GaugeString, " ");
+ } else {
+ StartIndex = 0;
+ for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++)
+ ;
+
+ for (Index = 0; PdbFileName[Index] != 0; Index++) {
+ if (PdbFileName[Index] == '\\') {
+ StartIndex = Index + 1;
+ }
+
+ if (PdbFileName[Index] == '.') {
+ EndIndex = Index;
+ }
+ }
+
+ Index1 = 0;
+ for (Index = StartIndex; Index < EndIndex; Index++) {
+ GaugeString[Index1] = PdbFileName[Index];
+ Index1++;
+ if (Index1 == STRING_EVENT_RECORD_NAME_LENGTH - 1) {
+ break;
+ }
+ }
+
+ GaugeString[Index1] = 0;
+ }
+
+ return ;
+}
+
+STATIC
+CHAR8 *
+GetPdbPath (
+ VOID *ImageBase
+ )
+/*++
+
+Routine Description:
+
+ Locate PDB path name in PE image
+
+Arguments:
+
+ ImageBase - base of PE to search
+
+Returns:
+
+ Pointer into image at offset of PDB file name if PDB file name is found,
+ Otherwise a pointer to an empty string.
+
+--*/
+{
+ CHAR8 *PdbPath;
+ UINT32 DirCount;
+ EFI_IMAGE_DOS_HEADER *DosHdr;
+ EFI_IMAGE_NT_HEADERS *NtHdr;
+ UINT16 Magic;
+ EFI_IMAGE_OPTIONAL_HEADER32 *OptionalHdr32;
+ EFI_IMAGE_OPTIONAL_HEADER64 *OptionalHdr64;
+ EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry;
+ EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;
+ VOID *CodeViewEntryPointer;
+
+ CodeViewEntryPointer = NULL;
+ PdbPath = NULL;
+ DosHdr = ImageBase;
+ if (DosHdr && DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
+ NtHdr = (EFI_IMAGE_NT_HEADERS *) ((UINT8 *) DosHdr + DosHdr->e_lfanew);
+ //
+ // NOTE: We use Machine to identify PE32/PE32+, instead of Magic.
+ // It is for backward-compatibility consideration, because
+ // some system will generate PE32+ image with PE32 Magic.
+ //
+ if (NtHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32) {
+ Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;
+ } else if (NtHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64) {
+ Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
+ } else if (NtHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_X64) {
+ Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
+ } else {
+ Magic = NtHdr->OptionalHeader.Magic;
+ }
+ if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ OptionalHdr32 = (VOID *) &NtHdr->OptionalHeader;
+ DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(OptionalHdr32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
+ } else {
+ OptionalHdr64 = (VOID *) &NtHdr->OptionalHeader;
+ DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(OptionalHdr64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
+ }
+
+ if (DirectoryEntry->VirtualAddress != 0) {
+ for (DirCount = 0;
+ (DirCount < DirectoryEntry->Size / sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)) && CodeViewEntryPointer == NULL;
+ DirCount++
+ ) {
+ DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (DirectoryEntry->VirtualAddress + (UINTN) ImageBase + DirCount * sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY));
+ if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
+ CodeViewEntryPointer = (VOID *) ((UINTN) DebugEntry->RVA + (UINTN) ImageBase);
+ switch (*(UINT32 *) CodeViewEntryPointer) {
+ case CODEVIEW_SIGNATURE_NB10:
+ PdbPath = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);
+ break;
+
+ case CODEVIEW_SIGNATURE_RSDS:
+ PdbPath = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return PdbPath;
+}
+
+STATIC
+VOID
+GetNameFromHandle (
+ IN EFI_HANDLE Handle,
+ OUT CHAR8 *GaugeString
+ )
+/*++
+
+Routine Description:
+
+ retrieves PDB path name from Handle
+
+Arguments:
+
+ Handle - Handle of image
+
+Returns:
+
+ Pointer to PDB Filename
+--*/
+{
+ EFI_STATUS Status;
+ EFI_LOADED_IMAGE_PROTOCOL *Image;
+ CHAR8 *PdbFileName;
+ EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
+
+ EfiAsciiStrCpy (GaugeString, " ");
+
+ //
+ // Get handle name from image protocol
+ //
+ Status = gBS->HandleProtocol (
+ Handle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID**)&Image
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = gBS->OpenProtocol (
+ Handle,
+ &gEfiDriverBindingProtocolGuid,
+ (VOID **) &DriverBinding,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return ;
+ }
+ //
+ // Get handle name from image protocol
+ //
+ Status = gBS->HandleProtocol (
+ DriverBinding->ImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID**)&Image
+ );
+ }
+
+ PdbFileName = GetPdbPath (Image->ImageBase);
+
+ if (PdbFileName != NULL) {
+ GetShortPdbFileName (PdbFileName, GaugeString);
+ }
+
+ return ;
+}
+
+EFI_GUID *
+GetGuidFromHandle (
+ EFI_HANDLE Handle
+ )
+/*++
+
+Routine Description:
+
+ retrieves GUID name from Handle
+
+Arguments:
+
+ Handle - Handle of image
+
+Returns:
+
+ Pointer to GUID name
+--*/
+{
+ EFI_STATUS Status;
+ EFI_LOADED_IMAGE_PROTOCOL *pImage;
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFilePath;
+
+ if (Handle!=NULL){
+ Status = gBS->HandleProtocol(Handle,
+ &gEfiLoadedImageProtocolGuid,
+ &pImage
+ );
+ if (!EFI_ERROR(Status)){
+ if (pImage->FilePath->Type==MEDIA_DEVICE_PATH && pImage->FilePath->SubType==MEDIA_FV_FILEPATH_DP) {
+ //
+ // Determine GUID associated with module logging performance
+ //
+ FvFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH*)pImage->FilePath;
+
+ return &FvFilePath->NameGuid;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+EFI_STATUS
+LocatePerformanceProtocol(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ locates Performance protocol interface
+
+Arguments:
+
+ None
+
+Returns:
+ EFI_STATUS
+
+--*/
+{
+ EFI_STATUS Status;
+
+ FirmwarePerformance = NULL;
+ Status = gBS->LocateProtocol (&gFirmwarePerformanceProtocolGuid, NULL, (VOID **) &FirmwarePerformance);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+InsertMeasurement (
+ IN FIRMWARE_PERFORMANCE_PROTOCOL *This,
+ IN EFI_HANDLE Handle,
+ IN UINT16 RecordType,
+ IN UINT64 Ticker,
+ IN UINT16 Identifier OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Logs performance data according to Record Type into pre-allocated buffer
+
+Arguments:
+
+ This - Calling context
+ Handle - Handle of gauge data
+ RecordType - Type of FPDT record
+ Ticker - Set event's Tick. If 0, Tick is current timer.
+ Identifier - Identifier of event records and other types of records
+
+Returns:
+
+ EFI_SUCCESS - Successfully create and initialized a guage data node.
+ EFI_OUT_OF_RESOURCES - No enough resource to create a guage data node.
+
+--*/
+{
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ HARDWARE_BOOT_REC *HardwareBootRec;
+ STRING_EVENT_REC *StringEvent;
+ GUID_EVENT_REC *GuidEvent;
+ BDS_ATTEMPT_REC *BdsAttemptRec;
+ EFI_GUID *GuidName;
+
+ UINT8 PdbFileName[STRING_EVENT_RECORD_NAME_LENGTH] = {0};
+ UINT8 NullFileName[STRING_EVENT_RECORD_NAME_LENGTH] = {0};
+ DevicePath = NULL;
+
+ //
+ // buffer overflow check
+ //
+ if (mPerformanceLength + sizeof(STRING_EVENT_REC) > FIRMWARE_MAX_BUFFER) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ switch (RecordType) {
+ case HARDWARE_BOOT_TYPE:
+ //
+ // Hardware Boot Record Table
+ //
+ HardwareBootRec = (HARDWARE_BOOT_REC*) ((UINT8*)mPerformancePointer + mPerformanceLength);
+
+ HardwareBootRec->RecType = RecordType;
+ HardwareBootRec->RecLength = sizeof(HARDWARE_BOOT_REC);
+ HardwareBootRec->Revision = RECORD_REVISION_1;
+ HardwareBootRec->HardwareBoot = GetTimeInNanoSec(Ticker);
+
+ mPerformanceLength += sizeof(HARDWARE_BOOT_REC);
+ break;
+
+ case GUID_EVENT_REC_TYPE:
+ case STRING_EVENT_REC_TYPE:
+ //
+ // Determine Pdb FileName associated with module logging performance
+ //
+ if (Handle != NULL){
+ GetNameFromHandle (Handle, PdbFileName);
+ }
+
+ GuidName = GetGuidFromHandle(Handle);
+ if (EfiCompareMem (PdbFileName,NullFileName, STRING_EVENT_RECORD_NAME_LENGTH)){
+ //
+ // String Event Record
+ //
+ StringEvent = (STRING_EVENT_REC*) ((UINT8*)mPerformancePointer + mPerformanceLength);
+ StringEvent->RecType = STRING_EVENT_REC_TYPE;
+ StringEvent->RecLength = sizeof(STRING_EVENT_REC);
+ StringEvent->Revision = RECORD_REVISION_1;
+ StringEvent->ProgressID = Identifier;
+ StringEvent->ApicID = GetApicId();
+ StringEvent->Timestamp = GetTimeInNanoSec(Ticker);
+ if (GuidName != NULL) {
+ gBS->CopyMem(&(StringEvent->Guid),GuidName,sizeof(EFI_GUID));
+ }
+
+ (gBS->CopyMem) (StringEvent->NameString, PdbFileName, STRING_EVENT_RECORD_NAME_LENGTH);
+
+ mPerformanceLength += sizeof(STRING_EVENT_REC);
+
+ } else {
+ //
+ // GUID Event Record
+ //
+ GuidEvent = (GUID_EVENT_REC*) ((UINT8*)mPerformancePointer + mPerformanceLength);
+ GuidEvent->RecType = GUID_EVENT_REC_TYPE;
+ GuidEvent->RecLength = sizeof(GUID_EVENT_REC);
+ GuidEvent->Revision = RECORD_REVISION_1;
+ GuidEvent->ProgressID = Identifier;
+ GuidEvent->ApicID = GetApicId();
+ GuidEvent->Timestamp = GetTimeInNanoSec(Ticker);
+ if (GuidName != NULL) {
+ gBS->CopyMem(&(GuidEvent->Guid),GuidName,sizeof(EFI_GUID));
+ }
+
+ mPerformanceLength += sizeof(GUID_EVENT_REC);
+ }
+ break;
+
+ case BDS_ATTEMPT_EVENT_REC_TYPE:
+ //
+ // BDS Boot Attempt Record
+ //
+ DevicePath = EfiDevicePathFromHandle (Handle);
+
+ BdsAttemptRec = (BDS_ATTEMPT_REC*) ((UINT8*)mPerformancePointer + mPerformanceLength);
+ BdsAttemptRec->RecType = BDS_ATTEMPT_EVENT_REC_TYPE;
+ BdsAttemptRec->RecLength = sizeof(BDS_ATTEMPT_REC);
+ BdsAttemptRec->Revision = RECORD_REVISION_1;
+ BdsAttemptRec->ApicID = GetApicId();
+ BdsAttemptRec->BdsAttemptNo = BdsAttemptNumber + 1;
+ BdsAttemptRec->Timestamp = GetTimeInNanoSec(Ticker);
+ ASPrint ((CHAR8*)(&BdsAttemptRec->UEFIBootVar), sizeof(BdsAttemptRec->UEFIBootVar)+1, "BOOT%04x", Identifier);
+ BdsAttemptRec->DevicePathString = '0';
+ mPerformanceLength += sizeof(BDS_ATTEMPT_REC);
+ break;
+
+ default:
+ //
+ // Record is undefined, return EFI_ABORTED
+ //
+ return EFI_ABORTED;
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetPerfBufferAddr (
+ IN FIRMWARE_PERFORMANCE_PROTOCOL *This,
+ OUT UINT32 *PerformanceBuffer
+ )
+{
+ EFI_STATUS Status;
+
+ *PerformanceBuffer = 0;
+
+ Status = LocatePerformanceProtocol();
+ if(EFI_ERROR(Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (mPerformancePointer == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ *PerformanceBuffer = (UINT32)((UINTN)mPerformancePointer);
+
+ return Status;
+}
+
+
+UINT32
+GetPerfBufferLength (
+ IN FIRMWARE_PERFORMANCE_PROTOCOL *This
+ )
+{
+ EFI_STATUS Status;
+
+ Status = LocatePerformanceProtocol();
+ if(EFI_ERROR(Status)) {
+ return 0;
+ }
+
+ return mPerformanceLength;
+}
+
+FIRMWARE_PERFORMANCE_PROTOCOL FirmwarePerformanceProtocol = {
+ InsertMeasurement,
+ GetPerfBufferAddr,
+ GetPerfBufferLength
+};
+
+//
+// Driver entry point
+//
+EFI_STATUS
+InitializePerformanceInfrastructure (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable,
+ IN UINT64 Ticker
+ )
+/*++
+
+Routine Description:
+
+ Install gFirmwarePerformanceProtocolGuid protocol and transfer PEI performance to gauge data nodes.
+
+Arguments:
+
+ ImageHandle - Standard driver entry point parameter
+ SystemTable - Standard driver entry point parameter
+ Ticker - End tick for PEI performance
+
+Returns:
+
+ EFI_OUT_OF_RESOURCES - No enough buffer to allocate
+ EFI_SUCCESS - Protocol installed.
+
+--*/
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ //
+ //A buffer of MAX size
+ //
+ mPerformancePointer = EfiLibAllocateZeroPool (FIRMWARE_MAX_BUFFER);
+ if (mPerformancePointer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ mPerformanceLength = 0;
+ //
+ // Install the protocol interfaces
+ //
+ Status = gBS->InstallProtocolInterface (
+ &ImageHandle,
+ &gFirmwarePerformanceProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &FirmwarePerformanceProtocol
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Get PEI performance hob and convert into FPDT structure
+ //
+ GetPeiFirmwarePerformanceHob (ImageHandle, SystemTable);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+StartMeasure (
+ EFI_HANDLE Handle,
+ IN UINT16 *Token,
+ IN UINT16 *Host,
+ IN UINT64 Ticker
+ )
+/*++
+
+Routine Description:
+
+ Start measurement according to token field and insert into pre-allocated buffer
+
+Arguments:
+
+ Handle - Handle to measure
+ Token - Token to measure
+ Host - Host to measure
+ Ticker - Ticker as start tick
+
+Returns:
+
+ Status code.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT16 RecordType;
+ UINT16 Identifier;
+
+ Status = LocatePerformanceProtocol();
+ if(EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ if (!EfiStrCmp (Token, START_IMAGE_TOK)) {
+ RecordType = STRING_EVENT_REC_TYPE;
+ Identifier = MODULE_START_ID;
+ } else if (!EfiStrCmp (Token, LOAD_IMAGE_TOK)) {
+ RecordType = STRING_EVENT_REC_TYPE;
+ Identifier = MODULE_LOADIMAGE_START_ID;
+ } else if (!EfiStrCmp (Token, DRIVERBINDING_START_TOK)) {
+ RecordType = STRING_EVENT_REC_TYPE;
+ Identifier = MODULE_DRIVERBINDING_START_ID;
+ } else if (!EfiStrCmp (Token, DXE_TOK)) {
+ RecordType = STRING_EVENT_REC_TYPE;
+ Identifier = DXE_START_ID;
+ } else if (!EfiStrCmp (Token, DXE_CORE_DISP_INIT_TOK)) {
+ RecordType = STRING_EVENT_REC_TYPE;
+ Identifier = DXE_CORE_DISP_START_ID;
+ } else if (!EfiStrCmp (Token, COREDISPATCHER_TOK)) {
+ RecordType = STRING_EVENT_REC_TYPE;
+ Identifier = COREDISPATCHER_START_ID;
+ } else {
+ RecordType = PERFORMANCE_RECORD_TYPE_MAX;
+ Identifier = 0;
+ }
+
+ Status = FirmwarePerformance->InsertMeasurement (FirmwarePerformance, Handle, RecordType, Ticker, Identifier);
+
+ return Status;
+}
+
+EFI_STATUS
+EndMeasure (
+ EFI_HANDLE Handle,
+ IN UINT16 *Token,
+ IN UINT16 *Host,
+ IN UINT64 Ticker
+ )
+/*++
+
+Routine Description:
+
+ End measurement according to token field and insert into pre-allocated buffer
+
+Arguments:
+
+ Handle - Handle to stop
+ Token - Token to stop
+ Host - Host to stop
+ Ticker - Ticker as end tick
+
+Returns:
+
+ Status code.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT16 RecordType;
+ UINT16 Identifier;
+
+ Status = LocatePerformanceProtocol();
+ if(EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ if (!EfiStrCmp (Token, START_IMAGE_TOK)) {
+ RecordType = STRING_EVENT_REC_TYPE;
+ Identifier = MODULE_END_ID;
+ } else if (!EfiStrCmp (Token, LOAD_IMAGE_TOK)) {
+ RecordType = STRING_EVENT_REC_TYPE;
+ Identifier = MODULE_LOADIMAGE_END_ID;
+ } else if (!EfiStrCmp (Token, DRIVERBINDING_START_TOK)) {
+ RecordType = STRING_EVENT_REC_TYPE;
+ Identifier = MODULE_DRIVERBINDING_END_ID;
+ } else if (!EfiStrCmp (Token, DXE_TOK)) {
+ RecordType = STRING_EVENT_REC_TYPE;
+ Identifier = DXE_END_ID;
+ } else if (!EfiStrCmp (Token, DXE_CORE_DISP_INIT_TOK)) {
+ RecordType = STRING_EVENT_REC_TYPE;
+ Identifier = DXE_CORE_DISP_END_ID;
+ } else if (!EfiStrCmp (Token, COREDISPATCHER_TOK)) {
+ RecordType = STRING_EVENT_REC_TYPE;
+ Identifier = COREDISPATCHER_END_ID;
+ } else {
+ RecordType = PERFORMANCE_RECORD_TYPE_MAX;
+ Identifier = 0;
+ }
+
+ Status = FirmwarePerformance->InsertMeasurement (FirmwarePerformance, Handle, RecordType, Ticker, Identifier);
+
+ return Status;
+}
+
+EFI_STATUS
+StartMeasureEx (
+ IN EFI_HANDLE Handle,
+ IN UINT16 *Token,
+ IN UINT16 *Host,
+ IN UINT64 Ticker,
+ IN UINT16 Identifier
+ )
+/*++
+
+Routine Description:
+
+ Start extended measurement according to token field and insert into pre-allocated buffer
+
+Arguments:
+
+ Handle - Handle to stop
+ Token - Token to stop
+ Host - Host to stop
+ Ticker - Ticker as end tick
+ Identifier - Identifier for a given record
+Returns:
+
+ Status code.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT16 RecordType;
+
+ Status = LocatePerformanceProtocol();
+ if(EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ if (!EfiStrCmp (Token, EVENT_REC_TOK)) {
+ RecordType = STRING_EVENT_REC_TYPE;
+ } else if (!EfiStrCmp (Token, BDS_ATTEMPT_TOK)) {
+ RecordType = BDS_ATTEMPT_EVENT_REC_TYPE;
+ } else if (!EfiStrCmp (Token, HARDWARE_BOOT_TOK)) {
+ RecordType = HARDWARE_BOOT_TYPE;
+ } else {
+ RecordType = PERFORMANCE_RECORD_TYPE_MAX;
+ }
+ Status = FirmwarePerformance->InsertMeasurement (FirmwarePerformance, Handle, RecordType, Ticker, Identifier);
+
+ return Status;
+}
+
+EFI_STATUS
+EndMeasureEx (
+ IN EFI_HANDLE Handle,
+ IN UINT16 *Token,
+ IN UINT16 *Host,
+ IN UINT64 Ticker,
+ IN UINT16 Identifier
+ )
+/*++
+
+Routine Description:
+
+ End extended measurement according to token field and insert into pre-allocated buffer
+
+Arguments:
+
+ Handle - Handle to stop
+ Token - Token to stop
+ Host - Host to stop
+ Ticker - Ticker as end tick
+ Identifier - Identifier for a given record
+Returns:
+
+ Status code.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT16 RecordType;
+
+ Status = LocatePerformanceProtocol();
+ if(EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ if (!EfiStrCmp (Token, EVENT_REC_TOK)) {
+ RecordType = STRING_EVENT_REC_TYPE;
+ } else if (!EfiStrCmp (Token, BDS_ATTEMPT_TOK)) {
+ RecordType = BDS_ATTEMPT_EVENT_REC_TYPE;
+ } else if (!EfiStrCmp (Token, HARDWARE_BOOT_TOK)) {
+ RecordType = HARDWARE_BOOT_TYPE;
+ } else {
+ RecordType = PERFORMANCE_RECORD_TYPE_MAX;
+ }
+
+ Status = FirmwarePerformance->InsertMeasurement (FirmwarePerformance, Handle, RecordType, Ticker, Identifier);
+
+ return Status;
+}
+
+EFI_STATUS
+GetPeiFirmwarePerformanceHob (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+
+ Transfer PEI performance data to pre-allocated memory into FPDT format.
+
+Arguments:
+
+ ImageHandle - Standard entry point parameter
+ SystemTable - Standard entry point parameter
+
+Returns:
+
+ EFI_OUT_OF_RESOURCES - No enough resource to create data node.
+ EFI_SUCCESS - Transfer done successfully.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+ VOID *HobList;
+ PEI_FIRMWARE_PERFORMANCE_HOB *PeiFirmwarePerformanceHob;
+ PEI_GUID_EVENT_REC *PeiGuidRec;
+ GUID_EVENT_REC *GuidEvent;
+
+ //
+ // Locate installed Performance HOB
+ //
+ PeiFirmwarePerformanceHob = NULL;
+
+ EfiLibGetSystemConfigurationTable (&gEfiHobListGuid, &HobList);
+
+ do {
+ Status = GetNextGuidHob (&HobList, &gPeiFirmwarePerformanceGuid, (VOID **) &PeiFirmwarePerformanceHob, NULL);
+ if (EFI_ERROR (Status) || (PeiFirmwarePerformanceHob == NULL)) {
+ break;
+ }
+
+ for (Index = 0; Index < PeiFirmwarePerformanceHob->NumberOfEntries; Index++) {
+ PeiGuidRec = &(PeiFirmwarePerformanceHob->GuidEventRecord[Index]);
+ //
+ // GUID Event Records from PEI phase
+ //
+ GuidEvent = (GUID_EVENT_REC*)((UINT8*)mPerformancePointer + mPerformanceLength);
+ GuidEvent->RecType = GUID_EVENT_REC_TYPE;
+ GuidEvent->RecLength = sizeof(GUID_EVENT_REC);
+ GuidEvent->Revision = RECORD_REVISION_1;
+ GuidEvent->ProgressID = PeiGuidRec->ProgressID;
+ GuidEvent->ApicID = PeiGuidRec->ApicID;
+ GuidEvent->Timestamp = PeiGuidRec->Timestamp;
+ GuidEvent->Guid = PeiGuidRec->Guid;
+
+ mPerformanceLength += sizeof(GUID_EVENT_REC);
+ }
+ } while (!EFI_ERROR (Status));
+
+ return Status;
+} \ No newline at end of file