3 Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 Routines used by START_PERF() and END_PERF()
23 #include "EdkIIGlueDxe.h"
26 #define EFI_PERFORMANCE_SIGNATURE EFI_SIGNATURE_32 ('P', 'E', 'R', 'F')
27 #define EFI_PERFORMANCE_DATA_SIGNATURE EFI_SIGNATURE_32 ('P', 'E', 'D', 'A')
29 #define GAUGE_DATA_FROM_GAUGE(_GaugeData) \
30 CR(_GaugeData, EFI_PERF_DATA_LIST, GaugeData, EFI_PERFORMANCE_DATA_SIGNATURE)
32 #define GAUGE_DATA_FROM_LINK(_link) \
33 CR(_link, EFI_PERF_DATA_LIST, Link, EFI_PERFORMANCE_DATA_SIGNATURE)
36 // Performace protocol instance containing record macro
38 #define EFI_PERFORMANCE_FROM_THIS(a) \
39 CR(a, EFI_PERFORMANCE_INSTANCE, Perf, EFI_PERFORMANCE_SIGNATURE)
45 EFI_GAUGE_DATA GaugeData
;
49 // Performance protocol instance data structure
54 EFI_PERFORMANCE_PROTOCOL Perf
;
56 } EFI_PERFORMANCE_INSTANCE
;
59 LIST_ENTRY mPerfDataHead
= INITIALIZE_LIST_HEAD_VARIABLE(mPerfDataHead
);
64 InternalGetTimerValue (
65 OUT UINT64
*TimerValue
71 Set TimerValue with current tick.
75 TimerValue - Timer value to be set
79 EFI_SUCCESS - TimerValue is set.
83 *TimerValue
= AsmReadTsc ();
108 if (PdbFileName
== NULL
) {
109 AsciiStrCpy (GaugeString
, " ");
112 for (EndIndex
= 0; PdbFileName
[EndIndex
] != 0; EndIndex
++)
115 for (Index
= 0; PdbFileName
[Index
] != 0; Index
++) {
116 if (PdbFileName
[Index
] == '\\') {
117 StartIndex
= Index
+ 1;
120 if (PdbFileName
[Index
] == '.') {
126 for (Index
= StartIndex
; Index
< EndIndex
; Index
++) {
127 GaugeString
[Index1
] = PdbFileName
[Index
];
129 if (Index1
== EFI_PERF_PDBFILENAME_LENGTH
- 1) {
134 GaugeString
[Index1
] = 0;
150 Located PDB path name in PE image
154 ImageBase - base of PE to search
158 Pointer into image at offset of PDB file name if PDB file name is found,
159 Otherwise a pointer to an empty string.
165 EFI_IMAGE_DOS_HEADER
*DosHdr
;
166 EFI_IMAGE_NT_HEADERS
*NtHdr
;
168 EFI_IMAGE_OPTIONAL_HEADER32
*OptionalHdr32
;
169 EFI_IMAGE_OPTIONAL_HEADER64
*OptionalHdr64
;
170 EFI_IMAGE_DATA_DIRECTORY
*DirectoryEntry
;
171 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*DebugEntry
;
172 VOID
*CodeViewEntryPointer
;
174 CodeViewEntryPointer
= NULL
;
177 if (DosHdr
&& DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
178 NtHdr
= (EFI_IMAGE_NT_HEADERS
*) ((UINT8
*) DosHdr
+ DosHdr
->e_lfanew
);
180 // NOTE: We use Machine to identify PE32/PE32+, instead of Magic.
181 // It is for backward-compatibility consideration, because
182 // some system will generate PE32+ image with PE32 Magic.
184 if (NtHdr
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_I386
) {
185 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
;
186 } else if (NtHdr
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
) {
187 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
188 } else if (NtHdr
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_X64
) {
189 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
191 Magic
= NtHdr
->OptionalHeader
.Magic
;
193 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
194 OptionalHdr32
= (VOID
*) &NtHdr
->OptionalHeader
;
195 DirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*) &(OptionalHdr32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
]);
197 OptionalHdr64
= (VOID
*) &NtHdr
->OptionalHeader
;
198 DirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*) &(OptionalHdr64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
]);
201 if (DirectoryEntry
->VirtualAddress
!= 0) {
203 (DirCount
< DirectoryEntry
->Size
/ sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
)) && CodeViewEntryPointer
== NULL
;
206 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*) (DirectoryEntry
->VirtualAddress
+ (UINTN
) ImageBase
+ DirCount
* sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
));
207 if (DebugEntry
->Type
== EFI_IMAGE_DEBUG_TYPE_CODEVIEW
) {
208 CodeViewEntryPointer
= (VOID
*) ((UINTN
) DebugEntry
->RVA
+ (UINTN
) ImageBase
);
209 switch (*(UINT32
*) CodeViewEntryPointer
) {
210 case CODEVIEW_SIGNATURE_NB10
:
211 PdbPath
= (CHAR8
*) CodeViewEntryPointer
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
);
214 case CODEVIEW_SIGNATURE_RSDS
:
215 PdbPath
= (CHAR8
*) CodeViewEntryPointer
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY
);
233 IN EFI_HANDLE Handle
,
234 OUT CHAR8
*GaugeString
238 EFI_LOADED_IMAGE_PROTOCOL
*Image
;
240 EFI_DRIVER_BINDING_PROTOCOL
*DriverBinding
;
242 AsciiStrCpy (GaugeString
, " ");
245 // Get handle name from image protocol
247 Status
= gBS
->HandleProtocol (
249 &gEfiLoadedImageProtocolGuid
,
253 if (EFI_ERROR (Status
)) {
254 Status
= gBS
->OpenProtocol (
256 &gEfiDriverBindingProtocolGuid
,
257 (VOID
**) &DriverBinding
,
260 EFI_OPEN_PROTOCOL_GET_PROTOCOL
262 if (EFI_ERROR (Status
)) {
266 // Get handle name from image protocol
268 Status
= gBS
->HandleProtocol (
269 DriverBinding
->ImageHandle
,
270 &gEfiLoadedImageProtocolGuid
,
275 PdbFileName
= GetPdbPath (Image
->ImageBase
);
277 if (PdbFileName
!= NULL
) {
278 GetShortPdbFileName (PdbFileName
, GaugeString
);
287 IN EFI_HANDLE Handle
,
295 Create a EFI_PERF_DATA_LIST data node.
299 Handle - Handle of gauge data
300 Token - Token of gauge data
301 Host - Host of gauge data
305 Pointer to a data node created.
309 EFI_PERF_DATA_LIST
*Node
;
312 // Allocate a new image structure
314 Node
= AllocateZeroPool (sizeof (EFI_PERF_DATA_LIST
));
317 Node
->Signature
= EFI_PERFORMANCE_DATA_SIGNATURE
;
319 Node
->GaugeData
.Handle
= Handle
;
322 StrCpy ((Node
->GaugeData
).Token
, Token
);
326 StrCpy ((Node
->GaugeData
).Host
, Host
);
329 if (Handle
!= NULL
) {
330 GetNameFromHandle (Handle
, Node
->GaugeData
.PdbFileName
);
340 IN EFI_HANDLE Handle
,
343 IN EFI_GUID
*GuidName
,
344 IN EFI_GAUGE_DATA
*PrevGauge
350 Search gauge node list to find one node with matched handle, token, host and Guid name.
354 Handle - Handle to match
355 Token - Token to match
357 GuidName - Guid name to match
358 PrevGauge - Start node, start from list head if NULL
362 Return pointer to the node found, NULL if not found.
366 EFI_PERF_DATA_LIST
*Node
;
367 EFI_PERF_DATA_LIST
*Temp
;
368 EFI_PERF_DATA_LIST
*Temp2
;
369 LIST_ENTRY
*CurrentLink
;
370 EFI_GUID NullGuid
= EFI_NULL_GUID
;
376 if (PrevGauge
== NULL
) {
377 CurrentLink
= mPerfDataHead
.ForwardLink
;
379 Temp2
= GAUGE_DATA_FROM_GAUGE (PrevGauge
);
380 CurrentLink
= (Temp2
->Link
).ForwardLink
;
383 while (CurrentLink
&& CurrentLink
!= &mPerfDataHead
) {
384 Node
= GAUGE_DATA_FROM_LINK (CurrentLink
);
386 if (Handle
== 0 && Token
== NULL
&& Host
== NULL
&& GuidName
== NULL
) {
390 if (Handle
!= (Node
->GaugeData
).Handle
) {
391 CurrentLink
= CurrentLink
->ForwardLink
;
395 if (GuidName
== NULL
&& !CompareGuid (&((Node
->GaugeData
).GuidName
), &NullGuid
)) {
396 CurrentLink
= CurrentLink
->ForwardLink
;
400 if (GuidName
&& !CompareGuid (&((Node
->GaugeData
).GuidName
), GuidName
)) {
401 CurrentLink
= CurrentLink
->ForwardLink
;
405 if (Token
== NULL
&& StrCmp (Node
->GaugeData
.Token
, L
"")) {
406 CurrentLink
= CurrentLink
->ForwardLink
;
410 if (Token
&& StrCmp (Node
->GaugeData
.Token
, Token
)) {
411 CurrentLink
= CurrentLink
->ForwardLink
;
415 if (Host
== NULL
&& StrCmp (Node
->GaugeData
.Host
, L
"")) {
416 CurrentLink
= CurrentLink
->ForwardLink
;
420 if (Host
&& StrCmp (Node
->GaugeData
.Host
, Host
)) {
421 CurrentLink
= CurrentLink
->ForwardLink
;
435 IN EFI_HANDLE ImageHandle
,
436 IN EFI_SYSTEM_TABLE
*SystemTable
,
443 Transfer PEI performance data to gauge data node.
447 ImageHandle - Standard entry point parameter
448 SystemTable - Standard entry point parameter
453 EFI_OUT_OF_RESOURCES - No enough resource to create data node.
454 EFI_SUCCESS - Transfer done successfully.
460 EFI_HOB_GUID_TYPE
*GuidHob
;
461 EFI_HOB_GUID_DATA_PERFORMANCE_LOG
*LogHob
;
462 PEI_PERFORMANCE_MEASURE_LOG_ENTRY
*LogEntry
;
464 EFI_PERF_DATA_LIST
*Node
;
467 Node
= CreateDataNode (0, PEI_TOK
, NULL
);
469 return EFI_OUT_OF_RESOURCES
;
475 InternalGetTimerValue (&TimerValue
);
477 (Node
->GaugeData
).EndTick
= TimerValue
;
479 InsertTailList (&mPerfDataHead
, &(Node
->Link
));
481 Status
= EfiGetSystemConfigurationTable (&gEfiHobListGuid
, &HobList
);
482 ASSERT_EFI_ERROR (Status
);
485 GuidHob
= (EFI_HOB_GUID_TYPE
*)GlueGetNextGuidHob (&gEfiPeiPerformanceHobGuid
, &HobList
);
486 if (GuidHob
== NULL
) {
489 LogHob
= (EFI_HOB_GUID_DATA_PERFORMANCE_LOG
*)GET_GUID_HOB_DATA (GuidHob
);
491 for (Index
= 0; Index
< LogHob
->NumberOfEntries
; Index
++) {
492 LogEntry
= &(LogHob
->Log
[Index
]);
493 Node
= CreateDataNode (0, LogEntry
->DescriptionString
, NULL
);
495 return EFI_OUT_OF_RESOURCES
;
497 (Node
->GaugeData
).StartTick
= LogEntry
->StartTimeCount
;
499 CopyMem (&(Node
->GaugeData
.GuidName
), &LogEntry
->Name
, sizeof (EFI_GUID
));
501 InsertTailList (&mPerfDataHead
, &(Node
->Link
));
503 (Node
->GaugeData
).EndTick
= LogEntry
->StopTimeCount
;
505 } while (!EFI_ERROR (Status
));
514 IN EFI_PERFORMANCE_PROTOCOL
*This
,
515 IN EFI_HANDLE Handle
,
524 Create a guage data node and initialized it.
528 This - Calling context
529 Handle - Handle of gauge data
530 Token - Token of gauge data
531 Host - Host of gauge data
532 Ticker - Set gauge data's StartTick. If 0, StartTick is current timer.
536 EFI_SUCCESS - Successfully create and initialized a guage data node.
537 EFI_OUT_OF_RESOURCES - No enough resource to create a guage data node.
541 EFI_PERFORMANCE_INSTANCE
*PerfInstance
;
542 EFI_PERF_DATA_LIST
*Node
;
546 PerfInstance
= EFI_PERFORMANCE_FROM_THIS (This
);
548 Node
= CreateDataNode (Handle
, Token
, Host
);
550 return EFI_OUT_OF_RESOURCES
;
556 InternalGetTimerValue (&TimerValue
);
559 Node
->GaugeData
.StartTick
= TimerValue
;
561 if (!StrCmp (Token
, DXE_TOK
)) {
562 PerfInstance
->Phase
= DXE_PHASE
;
565 if (!StrCmp (Token
, SHELL_TOK
)) {
566 PerfInstance
->Phase
= SHELL_PHASE
;
569 Node
->GaugeData
.Phase
= PerfInstance
->Phase
;
571 InsertTailList (&mPerfDataHead
, &(Node
->Link
));
580 IN EFI_PERFORMANCE_PROTOCOL
*This
,
581 IN EFI_HANDLE Handle
,
590 End all unfinished gauge data node that match specified handle, token and host.
594 This - Calling context
595 Handle - Handle to stop
596 Token - Token to stop
598 Ticker - End tick, if 0 then get current timer
602 EFI_NOT_FOUND - Node not found
603 EFI_SUCCESS - Gauge data node successfully ended.
607 EFI_PERFORMANCE_INSTANCE
*PerfInstance
;
608 EFI_PERF_DATA_LIST
*Node
;
612 PerfInstance
= EFI_PERFORMANCE_FROM_THIS (This
);
614 Node
= GetDataNode (Handle
, Token
, Host
, NULL
, NULL
);
616 return EFI_NOT_FOUND
;
619 while (Node
->GaugeData
.EndTick
!= 0) {
620 Node
= GetDataNode (Handle
, Token
, Host
, NULL
, &(Node
->GaugeData
));
622 return EFI_NOT_FOUND
;
629 InternalGetTimerValue (&TimerValue
);
632 Node
->GaugeData
.EndTick
= TimerValue
;
641 IN EFI_PERFORMANCE_PROTOCOL
*This
,
642 IN EFI_HANDLE Handle
,
645 IN EFI_GAUGE_DATA
*PrevGauge
653 This - A pointer to the EFI_PERFORMANCE_PROTOCOL.
654 Handle - A pointer of a efi handle.
655 Token - A pointer to the token.
656 Host - A pointer to the host.
657 PrevGauge - A pointer to the EFI_GAUGE_DATA structure.
665 EFI_PERFORMANCE_INSTANCE
*PerfInstance
;
666 EFI_PERF_DATA_LIST
*Node
;
668 PerfInstance
= EFI_PERFORMANCE_FROM_THIS (This
);
670 Node
= GetDataNode (Handle
, Token
, Host
, NULL
, PrevGauge
);
672 return &(Node
->GaugeData
);
680 // Install Performance Protocol
682 // This is the support routine for PERF_ENABLE() which is called on
683 // an user's demand. This function isn't necessary to be called
688 InitializePerformanceInfrastructure (
689 IN EFI_HANDLE ImageHandle
,
690 IN EFI_SYSTEM_TABLE
*SystemTable
,
697 Install gEfiPerformanceProtocolGuid protocol and transfer PEI performance to gauge data nodes.
701 ImageHandle - Standard driver entry point parameter
702 SystemTable - Standard driver entry point parameter
703 Ticker - End tick for PEI performance
707 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
708 EFI_SUCCESS - Protocol installed.
713 EFI_PERFORMANCE_INSTANCE
*PerfInstance
;
716 // Allocate a new image structure
718 PerfInstance
= AllocateZeroPool (sizeof (EFI_PERFORMANCE_INSTANCE
));
719 if (PerfInstance
== NULL
) {
720 return EFI_OUT_OF_RESOURCES
;
723 PerfInstance
->Signature
= EFI_PERFORMANCE_SIGNATURE
;
724 PerfInstance
->Perf
.StartGauge
= StartGauge
;
725 PerfInstance
->Perf
.EndGauge
= EndGauge
;
726 PerfInstance
->Perf
.GetGauge
= GetGauge
;
729 // Install the protocol interfaces
731 Status
= gBS
->InstallProtocolInterface (
732 &PerfInstance
->Handle
,
733 &gEfiPerformanceProtocolGuid
,
734 EFI_NATIVE_INTERFACE
,
738 if (!EFI_ERROR (Status
)) {
739 GetPeiPerformance (ImageHandle
, SystemTable
, Ticker
);
758 Start to gauge on a specified handle, token and host, with Ticker as start tick.
762 Handle - Handle to measure
763 Token - Token to measure
764 Host - Host to measure
765 Ticker - Ticker as start tick
774 EFI_PERFORMANCE_PROTOCOL
*Perf
;
776 Status
= gBS
->LocateProtocol (&gEfiPerformanceProtocolGuid
, NULL
, (VOID
**) &Perf
);
777 if (EFI_ERROR (Status
)) {
781 return Perf
->StartGauge (Perf
, Handle
, Token
, Host
, Ticker
);
798 End gauging on a specified handle, token and host, with Ticker as end tick.
802 Handle - Handle to stop
803 Token - Token to stop
805 Ticker - Ticker as end tick
814 EFI_PERFORMANCE_PROTOCOL
*Perf
;
816 Status
= gBS
->LocateProtocol (&gEfiPerformanceProtocolGuid
, NULL
, (VOID
**) &Perf
);
817 if (Status
!= EFI_SUCCESS
) {
821 return (Perf
->EndGauge( Perf
, Handle
, Token
, Host
, Ticker
)) ;
831 EFI_HANDLE HandleNew
,
841 Handle - A pointer of an efi handle.
842 Token - A pointer to the token.
843 Host - A pointer to the host.
844 HandleNew - A pointer of an new efi handle.
845 TokenNew - A pointer to the new token.
846 HostNew - A pointer to the new host.
851 EFI_NOT_FOUND - The speicified gauge data node not found.
853 EFI_SUCCESS - Update successfully.
858 EFI_GAUGE_DATA
*GaugeData
;
859 EFI_PERFORMANCE_PROTOCOL
*Perf
;
861 Status
= gBS
->LocateProtocol (&gEfiPerformanceProtocolGuid
, NULL
, (VOID
**) &Perf
);
862 if (EFI_ERROR (Status
)) {
866 GaugeData
= Perf
->GetGauge (Perf
, Handle
, Token
, Host
, NULL
);
868 return EFI_NOT_FOUND
;
871 GaugeData
->Handle
= HandleNew
;
872 if (HostNew
!= NULL
) {
873 StrCpy (GaugeData
->Host
, HostNew
);
875 StrCpy (GaugeData
->Host
, L
"");
878 if (TokenNew
!= NULL
) {
879 StrCpy (GaugeData
->Token
, TokenNew
);
881 StrCpy (GaugeData
->Token
, L
"");