3 Copyright (c) 2004 - 2006, 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 LogHob
= (EFI_HOB_GUID_DATA_PERFORMANCE_LOG
*)GET_GUID_HOB_DATA (GuidHob
);
488 for (Index
= 0; Index
< LogHob
->NumberOfEntries
; Index
++) {
489 LogEntry
= &(LogHob
->Log
[Index
]);
490 Node
= CreateDataNode (0, LogEntry
->DescriptionString
, NULL
);
492 return EFI_OUT_OF_RESOURCES
;
494 (Node
->GaugeData
).StartTick
= LogEntry
->StartTimeCount
;
496 CopyMem (&(Node
->GaugeData
.GuidName
), &LogEntry
->Name
, sizeof (EFI_GUID
));
498 InsertTailList (&mPerfDataHead
, &(Node
->Link
));
500 (Node
->GaugeData
).EndTick
= LogEntry
->StopTimeCount
;
502 } while (!EFI_ERROR (Status
));
511 IN EFI_PERFORMANCE_PROTOCOL
*This
,
512 IN EFI_HANDLE Handle
,
521 Create a guage data node and initialized it.
525 This - Calling context
526 Handle - Handle of gauge data
527 Token - Token of gauge data
528 Host - Host of gauge data
529 Ticker - Set gauge data's StartTick. If 0, StartTick is current timer.
533 EFI_SUCCESS - Successfully create and initialized a guage data node.
534 EFI_OUT_OF_RESOURCES - No enough resource to create a guage data node.
538 EFI_PERFORMANCE_INSTANCE
*PerfInstance
;
539 EFI_PERF_DATA_LIST
*Node
;
543 PerfInstance
= EFI_PERFORMANCE_FROM_THIS (This
);
545 Node
= CreateDataNode (Handle
, Token
, Host
);
547 return EFI_OUT_OF_RESOURCES
;
553 InternalGetTimerValue (&TimerValue
);
556 Node
->GaugeData
.StartTick
= TimerValue
;
558 if (!StrCmp (Token
, DXE_TOK
)) {
559 PerfInstance
->Phase
= DXE_PHASE
;
562 if (!StrCmp (Token
, SHELL_TOK
)) {
563 PerfInstance
->Phase
= SHELL_PHASE
;
566 Node
->GaugeData
.Phase
= PerfInstance
->Phase
;
568 InsertTailList (&mPerfDataHead
, &(Node
->Link
));
577 IN EFI_PERFORMANCE_PROTOCOL
*This
,
578 IN EFI_HANDLE Handle
,
587 End all unfinished gauge data node that match specified handle, token and host.
591 This - Calling context
592 Handle - Handle to stop
593 Token - Token to stop
595 Ticker - End tick, if 0 then get current timer
599 EFI_NOT_FOUND - Node not found
600 EFI_SUCCESS - Gauge data node successfully ended.
604 EFI_PERFORMANCE_INSTANCE
*PerfInstance
;
605 EFI_PERF_DATA_LIST
*Node
;
609 PerfInstance
= EFI_PERFORMANCE_FROM_THIS (This
);
611 Node
= GetDataNode (Handle
, Token
, Host
, NULL
, NULL
);
613 return EFI_NOT_FOUND
;
616 while (Node
->GaugeData
.EndTick
!= 0) {
617 Node
= GetDataNode (Handle
, Token
, Host
, NULL
, &(Node
->GaugeData
));
619 return EFI_NOT_FOUND
;
626 InternalGetTimerValue (&TimerValue
);
629 Node
->GaugeData
.EndTick
= TimerValue
;
638 IN EFI_PERFORMANCE_PROTOCOL
*This
,
639 IN EFI_HANDLE Handle
,
642 IN EFI_GAUGE_DATA
*PrevGauge
650 This - A pointer to the EFI_PERFORMANCE_PROTOCOL.
651 Handle - A pointer of a efi handle.
652 Token - A pointer to the token.
653 Host - A pointer to the host.
654 PrevGauge - A pointer to the EFI_GAUGE_DATA structure.
662 EFI_PERFORMANCE_INSTANCE
*PerfInstance
;
663 EFI_PERF_DATA_LIST
*Node
;
665 PerfInstance
= EFI_PERFORMANCE_FROM_THIS (This
);
667 Node
= GetDataNode (Handle
, Token
, Host
, NULL
, PrevGauge
);
669 return &(Node
->GaugeData
);
677 // Install Performance Protocol
679 // This is the support routine for PERF_ENABLE() which is called on
680 // an user's demand. This function isn't necessary to be called
685 InitializePerformanceInfrastructure (
686 IN EFI_HANDLE ImageHandle
,
687 IN EFI_SYSTEM_TABLE
*SystemTable
,
694 Install gEfiPerformanceProtocolGuid protocol and transfer PEI performance to gauge data nodes.
698 ImageHandle - Standard driver entry point parameter
699 SystemTable - Standard driver entry point parameter
700 Ticker - End tick for PEI performance
704 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
705 EFI_SUCCESS - Protocol installed.
710 EFI_PERFORMANCE_INSTANCE
*PerfInstance
;
713 // Allocate a new image structure
715 PerfInstance
= AllocateZeroPool (sizeof (EFI_PERFORMANCE_INSTANCE
));
716 if (PerfInstance
== NULL
) {
717 return EFI_OUT_OF_RESOURCES
;
720 PerfInstance
->Signature
= EFI_PERFORMANCE_SIGNATURE
;
721 PerfInstance
->Perf
.StartGauge
= StartGauge
;
722 PerfInstance
->Perf
.EndGauge
= EndGauge
;
723 PerfInstance
->Perf
.GetGauge
= GetGauge
;
726 // Install the protocol interfaces
728 Status
= gBS
->InstallProtocolInterface (
729 &PerfInstance
->Handle
,
730 &gEfiPerformanceProtocolGuid
,
731 EFI_NATIVE_INTERFACE
,
735 if (!EFI_ERROR (Status
)) {
736 GetPeiPerformance (ImageHandle
, SystemTable
, Ticker
);
755 Start to gauge on a specified handle, token and host, with Ticker as start tick.
759 Handle - Handle to measure
760 Token - Token to measure
761 Host - Host to measure
762 Ticker - Ticker as start tick
771 EFI_PERFORMANCE_PROTOCOL
*Perf
;
773 Status
= gBS
->LocateProtocol (&gEfiPerformanceProtocolGuid
, NULL
, (VOID
**) &Perf
);
774 if (EFI_ERROR (Status
)) {
778 return Perf
->StartGauge (Perf
, Handle
, Token
, Host
, Ticker
);
795 End gauging on a specified handle, token and host, with Ticker as end tick.
799 Handle - Handle to stop
800 Token - Token to stop
802 Ticker - Ticker as end tick
811 EFI_PERFORMANCE_PROTOCOL
*Perf
;
813 Status
= gBS
->LocateProtocol (&gEfiPerformanceProtocolGuid
, NULL
, (VOID
**) &Perf
);
814 if (Status
!= EFI_SUCCESS
) {
818 return (Perf
->EndGauge( Perf
, Handle
, Token
, Host
, Ticker
)) ;
828 EFI_HANDLE HandleNew
,
838 Handle - A pointer of an efi handle.
839 Token - A pointer to the token.
840 Host - A pointer to the host.
841 HandleNew - A pointer of an new efi handle.
842 TokenNew - A pointer to the new token.
843 HostNew - A pointer to the new host.
848 EFI_NOT_FOUND - The speicified gauge data node not found.
850 EFI_SUCCESS - Update successfully.
855 EFI_GAUGE_DATA
*GaugeData
;
856 EFI_PERFORMANCE_PROTOCOL
*Perf
;
858 Status
= gBS
->LocateProtocol (&gEfiPerformanceProtocolGuid
, NULL
, (VOID
**) &Perf
);
859 if (EFI_ERROR (Status
)) {
863 GaugeData
= Perf
->GetGauge (Perf
, Handle
, Token
, Host
, NULL
);
865 return EFI_NOT_FOUND
;
868 GaugeData
->Handle
= HandleNew
;
869 if (HostNew
!= NULL
) {
870 StrCpy (GaugeData
->Host
, HostNew
);
872 StrCpy (GaugeData
->Host
, L
"");
875 if (TokenNew
!= NULL
) {
876 StrCpy (GaugeData
->Token
, TokenNew
);
878 StrCpy (GaugeData
->Token
, L
"");