]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Foundation/Library/Dxe/EfiDriverLib/Perf.c
Update the copyright notice format
[mirror_edk2.git] / EdkCompatibilityPkg / Foundation / Library / Dxe / EfiDriverLib / Perf.c
1 /*++
2
3 Copyright (c) 2004 - 2005, 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
8
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.
11
12 Module Name:
13
14 Perf.c
15
16 Abstract:
17
18 Support for Performance primatives.
19
20 --*/
21
22 #include "Tiano.h"
23 #include "EfiDriverLib.h"
24 #include EFI_PROTOCOL_DEFINITION (Performance)
25 #include EFI_PROTOCOL_DEFINITION (LoadedImage)
26 #include EFI_GUID_DEFINITION (Hob)
27 #include EFI_GUID_DEFINITION (PeiPerformanceHob)
28 #include "LinkedList.h"
29 #include "EfiHobLib.h"
30 #include "EfiImage.h"
31
32 EFI_STATUS
33 GetTimerValue (
34 OUT UINT64 *TimerValue
35 );
36
37 EFI_STATUS
38 GetPeiPerformance (
39 IN EFI_HANDLE ImageHandle,
40 IN EFI_SYSTEM_TABLE *SystemTable,
41 IN UINT64 Ticker
42 );
43
44 #define EFI_PERFORMANCE_DATA_SIGNATURE EFI_SIGNATURE_32 ('P', 'E', 'D', 'A')
45
46 typedef struct {
47 UINT32 Signature;
48 EFI_LIST_ENTRY Link;
49 EFI_GAUGE_DATA GaugeData;
50 } EFI_PERF_DATA_LIST;
51
52 #define GAUGE_DATA_FROM_LINK(_link) \
53 CR(_link, EFI_PERF_DATA_LIST, Link, EFI_PERFORMANCE_DATA_SIGNATURE)
54
55 #define GAUGE_DATA_FROM_GAUGE(_GaugeData) \
56 CR(_GaugeData, EFI_PERF_DATA_LIST, GaugeData, EFI_PERFORMANCE_DATA_SIGNATURE)
57
58 #define EFI_PERFORMANCE_SIGNATURE EFI_SIGNATURE_32 ('P', 'E', 'R', 'F')
59
60 //
61 // Performance protocol instance data structure
62 //
63 typedef struct {
64 UINTN Signature;
65 EFI_HANDLE Handle;
66 EFI_PERFORMANCE_PROTOCOL Perf;
67 UINT8 Phase;
68 } EFI_PERFORMANCE_INSTANCE;
69
70 //
71 // Performace protocol instance containing record macro
72 //
73
74 #define EFI_PERFORMANCE_FROM_THIS(a) \
75 CR(a, EFI_PERFORMANCE_INSTANCE, Perf, EFI_PERFORMANCE_SIGNATURE)
76
77 EFI_LIST_ENTRY mPerfDataHead = INITIALIZE_LIST_HEAD_VARIABLE(mPerfDataHead);
78
79 STATIC
80 VOID
81 GetShortPdbFileName (
82 CHAR8 *PdbFileName,
83 CHAR8 *GaugeString
84 )
85 /*++
86
87 Routine Description:
88
89 Arguments:
90
91 Returns:
92
93 --*/
94 {
95 UINTN Index;
96 UINTN Index1;
97 UINTN StartIndex;
98 UINTN EndIndex;
99
100 if (PdbFileName == NULL) {
101 EfiAsciiStrCpy (GaugeString, (CHAR8 *)" ");
102 } else {
103 StartIndex = 0;
104 for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++)
105 ;
106
107 for (Index = 0; PdbFileName[Index] != 0; Index++) {
108 if (PdbFileName[Index] == '\\') {
109 StartIndex = Index + 1;
110 }
111
112 if (PdbFileName[Index] == '.') {
113 EndIndex = Index;
114 }
115 }
116
117 Index1 = 0;
118 for (Index = StartIndex; Index < EndIndex; Index++) {
119 GaugeString[Index1] = PdbFileName[Index];
120 Index1++;
121 if (Index1 == EFI_PERF_PDBFILENAME_LENGTH - 1) {
122 break;
123 }
124 }
125
126 GaugeString[Index1] = 0;
127 }
128
129 return ;
130 }
131
132 STATIC
133 CHAR8 *
134 GetPdbPath (
135 VOID *ImageBase
136 )
137 /*++
138
139 Routine Description:
140
141 Located PDB path name in PE image
142
143 Arguments:
144
145 ImageBase - base of PE to search
146
147 Returns:
148
149 Pointer into image at offset of PDB file name if PDB file name is found,
150 Otherwise a pointer to an empty string.
151
152 --*/
153 {
154 CHAR8 *PdbPath;
155 UINT32 DirCount;
156 EFI_IMAGE_DOS_HEADER *DosHdr;
157 EFI_IMAGE_NT_HEADERS *NtHdr;
158 UINT16 Magic;
159 EFI_IMAGE_OPTIONAL_HEADER32 *OptionalHdr32;
160 EFI_IMAGE_OPTIONAL_HEADER64 *OptionalHdr64;
161 EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry;
162 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;
163 VOID *CodeViewEntryPointer;
164
165 CodeViewEntryPointer = NULL;
166 PdbPath = NULL;
167 DosHdr = ImageBase;
168 if (DosHdr && DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
169 NtHdr = (EFI_IMAGE_NT_HEADERS *) ((UINT8 *) DosHdr + DosHdr->e_lfanew);
170 //
171 // NOTE: We use Machine to identify PE32/PE32+, instead of Magic.
172 // It is for backward-compatibility consideration, because
173 // some system will generate PE32+ image with PE32 Magic.
174 //
175 if (NtHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32) {
176 Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;
177 } else if (NtHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64) {
178 Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
179 } else if (NtHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_X64) {
180 Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
181 } else {
182 Magic = NtHdr->OptionalHeader.Magic;
183 }
184 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
185 OptionalHdr32 = (VOID *) &NtHdr->OptionalHeader;
186 DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(OptionalHdr32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
187 } else {
188 OptionalHdr64 = (VOID *) &NtHdr->OptionalHeader;
189 DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(OptionalHdr64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
190 }
191
192 if (DirectoryEntry->VirtualAddress != 0) {
193 for (DirCount = 0;
194 (DirCount < DirectoryEntry->Size / sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)) && CodeViewEntryPointer == NULL;
195 DirCount++
196 ) {
197 DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (DirectoryEntry->VirtualAddress + (UINTN) ImageBase + DirCount * sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY));
198 if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
199 CodeViewEntryPointer = (VOID *) ((UINTN) DebugEntry->RVA + (UINTN) ImageBase);
200 switch (*(UINT32 *) CodeViewEntryPointer) {
201 case CODEVIEW_SIGNATURE_NB10:
202 PdbPath = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);
203 break;
204
205 case CODEVIEW_SIGNATURE_RSDS:
206 PdbPath = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);
207 break;
208
209 default:
210 break;
211 }
212 }
213 }
214 }
215 }
216
217 return PdbPath;
218 }
219
220 STATIC
221 VOID
222 GetNameFromHandle (
223 IN EFI_HANDLE Handle,
224 OUT CHAR8 *GaugeString
225 )
226 {
227 EFI_STATUS Status;
228 EFI_LOADED_IMAGE_PROTOCOL *Image;
229 CHAR8 *PdbFileName;
230 EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
231
232 EfiAsciiStrCpy (GaugeString, (CHAR8 *)" ");
233
234 //
235 // Get handle name from image protocol
236 //
237 Status = gBS->HandleProtocol (
238 Handle,
239 &gEfiLoadedImageProtocolGuid,
240 (VOID**)&Image
241 );
242
243 if (EFI_ERROR (Status)) {
244 Status = gBS->OpenProtocol (
245 Handle,
246 &gEfiDriverBindingProtocolGuid,
247 (VOID **) &DriverBinding,
248 NULL,
249 NULL,
250 EFI_OPEN_PROTOCOL_GET_PROTOCOL
251 );
252 if (EFI_ERROR (Status)) {
253 return ;
254 }
255 //
256 // Get handle name from image protocol
257 //
258 Status = gBS->HandleProtocol (
259 DriverBinding->ImageHandle,
260 &gEfiLoadedImageProtocolGuid,
261 (VOID**)&Image
262 );
263 }
264
265 PdbFileName = GetPdbPath (Image->ImageBase);
266
267 if (PdbFileName != NULL) {
268 GetShortPdbFileName (PdbFileName, GaugeString);
269 }
270
271 return ;
272 }
273
274 EFI_PERF_DATA_LIST *
275 CreateDataNode (
276 IN EFI_HANDLE Handle,
277 IN UINT16 *Token,
278 IN UINT16 *Host
279 )
280 /*++
281
282 Routine Description:
283
284 Create a EFI_PERF_DATA_LIST data node.
285
286 Arguments:
287
288 Handle - Handle of gauge data
289 Token - Token of gauge data
290 Host - Host of gauge data
291
292 Returns:
293
294 Pointer to a data node created.
295
296 --*/
297 {
298 EFI_PERF_DATA_LIST *Node;
299
300 //
301 // Al\ a new image structure
302 //
303 Node = EfiLibAllocateZeroPool (sizeof (EFI_PERF_DATA_LIST));
304 if (Node != NULL) {
305
306 Node->Signature = EFI_PERFORMANCE_DATA_SIGNATURE;
307
308 Node->GaugeData.Handle = Handle;
309
310 if (Token != NULL) {
311 EfiStrCpy ((Node->GaugeData).Token, Token);
312 }
313
314 if (Host != NULL) {
315 EfiStrCpy ((Node->GaugeData).Host, Host);
316 }
317
318 if (Handle != NULL) {
319 GetNameFromHandle (Handle, Node->GaugeData.PdbFileName);
320 }
321 }
322
323 return Node;
324 }
325
326
327 EFI_PERF_DATA_LIST *
328 GetDataNode (
329 IN EFI_HANDLE Handle,
330 IN UINT16 *Token,
331 IN UINT16 *Host,
332 IN EFI_GUID *GuidName,
333 IN EFI_GAUGE_DATA *PrevGauge
334 )
335 /*++
336
337 Routine Description:
338
339 Search gauge node list to find one node with matched handle, token, host and Guid name.
340
341 Arguments:
342
343 Handle - Handle to match
344 Token - Token to match
345 Host - Host to match
346 GuidName - Guid name to match
347 PrevGauge - Start node, start from list head if NULL
348
349 Returns:
350
351 Return pointer to the node found, NULL if not found.
352
353 --*/
354 {
355 EFI_PERF_DATA_LIST *Node;
356 EFI_PERF_DATA_LIST *Temp;
357 EFI_PERF_DATA_LIST *Temp2;
358 EFI_LIST_ENTRY *CurrentLink;
359 EFI_GUID NullGuid = EFI_NULL_GUID;
360
361 Node = NULL;
362 Temp = NULL;
363 Temp2 = NULL;
364
365 if (PrevGauge == NULL) {
366 CurrentLink = mPerfDataHead.ForwardLink;
367 } else {
368 Temp2 = GAUGE_DATA_FROM_GAUGE (PrevGauge);
369 CurrentLink = (Temp2->Link).ForwardLink;
370 }
371
372 while (CurrentLink && CurrentLink != &mPerfDataHead) {
373 Node = GAUGE_DATA_FROM_LINK (CurrentLink);
374
375 if (Handle == 0 && Token == NULL && Host == NULL && GuidName == NULL) {
376 return Node;
377 }
378
379 if (Handle != (Node->GaugeData).Handle) {
380 CurrentLink = CurrentLink->ForwardLink;
381 continue;
382 }
383
384 if (GuidName == NULL && !EfiCompareGuid (&((Node->GaugeData).GuidName), &NullGuid)) {
385 CurrentLink = CurrentLink->ForwardLink;
386 continue;
387 }
388
389 if (GuidName && !EfiCompareGuid (&((Node->GaugeData).GuidName), GuidName)) {
390 CurrentLink = CurrentLink->ForwardLink;
391 continue;
392 }
393
394 if (Token == NULL && EfiStrCmp (Node->GaugeData.Token, L"")) {
395 CurrentLink = CurrentLink->ForwardLink;
396 continue;
397 }
398
399 if (Token && EfiStrCmp (Node->GaugeData.Token, Token)) {
400 CurrentLink = CurrentLink->ForwardLink;
401 continue;
402 }
403
404 if (Host == NULL && EfiStrCmp (Node->GaugeData.Host, L"")) {
405 CurrentLink = CurrentLink->ForwardLink;
406 continue;
407 }
408
409 if (Host && EfiStrCmp (Node->GaugeData.Host, Host)) {
410 CurrentLink = CurrentLink->ForwardLink;
411 continue;
412 }
413
414 Temp = Node;
415 break;
416 }
417
418 return Temp;
419 }
420
421
422 EFI_STATUS
423 EFIAPI
424 StartGauge (
425 IN EFI_PERFORMANCE_PROTOCOL *This,
426 IN EFI_HANDLE Handle,
427 IN UINT16 *Token,
428 IN UINT16 *Host,
429 IN UINT64 Ticker
430 )
431 /*++
432
433 Routine Description:
434
435 Create a guage data node and initialized it.
436
437 Arguments:
438
439 This - Calling context
440 Handle - Handle of gauge data
441 Token - Token of gauge data
442 Host - Host of gauge data
443 Ticker - Set gauge data's StartTick. If 0, StartTick is current timer.
444
445 Returns:
446
447 EFI_SUCCESS - Successfully create and initialized a guage data node.
448 EFI_OUT_OF_RESOURCES - No enough resource to create a guage data node.
449
450 --*/
451 {
452 EFI_PERFORMANCE_INSTANCE *PerfInstance;
453 EFI_PERF_DATA_LIST *Node;
454 UINT64 TimerValue;
455
456 TimerValue = 0;
457 PerfInstance = EFI_PERFORMANCE_FROM_THIS (This);
458
459 Node = CreateDataNode (Handle, Token, Host);
460 if (!Node) {
461 return EFI_OUT_OF_RESOURCES;
462 }
463
464 if (Ticker != 0) {
465 TimerValue = Ticker;
466 } else {
467 GetTimerValue (&TimerValue);
468 }
469
470 Node->GaugeData.StartTick = TimerValue;
471
472 if (!EfiStrCmp (Token, DXE_TOK)) {
473 PerfInstance->Phase = DXE_PHASE;
474 }
475
476 if (!EfiStrCmp (Token, SHELL_TOK)) {
477 PerfInstance->Phase = SHELL_PHASE;
478 }
479
480 Node->GaugeData.Phase = PerfInstance->Phase;
481
482 InsertTailList (&mPerfDataHead, &(Node->Link));
483
484 return EFI_SUCCESS;
485 }
486
487
488 EFI_STATUS
489 EFIAPI
490 EndGauge (
491 IN EFI_PERFORMANCE_PROTOCOL *This,
492 IN EFI_HANDLE Handle,
493 IN UINT16 *Token,
494 IN UINT16 *Host,
495 IN UINT64 Ticker
496 )
497 /*++
498
499 Routine Description:
500
501 End all unfinished gauge data node that match specified handle, token and host.
502
503 Arguments:
504
505 This - Calling context
506 Handle - Handle to stop
507 Token - Token to stop
508 Host - Host to stop
509 Ticker - End tick, if 0 then get current timer
510
511 Returns:
512
513 EFI_NOT_FOUND - Node not found
514 EFI_SUCCESS - Gauge data node successfully ended.
515
516 --*/
517 {
518 EFI_PERFORMANCE_INSTANCE *PerfInstance;
519 EFI_PERF_DATA_LIST *Node;
520 UINT64 TimerValue;
521
522 TimerValue = 0;
523 PerfInstance = EFI_PERFORMANCE_FROM_THIS (This);
524
525 Node = GetDataNode (Handle, Token, Host, NULL, NULL);
526 if (!Node) {
527 return EFI_NOT_FOUND;
528 }
529
530 while (Node->GaugeData.EndTick != 0) {
531 Node = GetDataNode (Handle, Token, Host, NULL, &(Node->GaugeData));
532 if (!Node) {
533 return EFI_NOT_FOUND;
534 }
535 }
536
537 if (Ticker != 0) {
538 TimerValue = Ticker;
539 } else {
540 GetTimerValue (&TimerValue);
541 }
542
543 Node->GaugeData.EndTick = TimerValue;
544
545 return EFI_SUCCESS;
546 }
547
548
549 EFI_GAUGE_DATA *
550 EFIAPI
551 GetGauge (
552 IN EFI_PERFORMANCE_PROTOCOL *This,
553 IN EFI_HANDLE Handle,
554 IN UINT16 *Token,
555 IN UINT16 *Host,
556 IN EFI_GAUGE_DATA *PrevGauge
557 )
558 /*++
559
560 Routine Description:
561 Get gauge.
562
563 Arguments:
564 This - A pointer to the EFI_PERFORMANCE_PROTOCOL.
565 Handle - A pointer of a efi handle.
566 Token - A pointer to the token.
567 Host - A pointer to the host.
568 PrevGauge - A pointer to the EFI_GAUGE_DATA structure.
569
570
571 Returns:
572 Status code.
573
574 --*/
575 {
576 EFI_PERFORMANCE_INSTANCE *PerfInstance;
577 EFI_PERF_DATA_LIST *Node;
578
579 PerfInstance = EFI_PERFORMANCE_FROM_THIS (This);
580
581 Node = GetDataNode (Handle, Token, Host, NULL, PrevGauge);
582 if (Node != NULL) {
583 return &(Node->GaugeData);
584 } else {
585 return NULL;
586 }
587 }
588
589 //
590 // Driver entry point
591 //
592 EFI_STATUS
593 InitializePerformanceInfrastructure (
594 IN EFI_HANDLE ImageHandle,
595 IN EFI_SYSTEM_TABLE *SystemTable,
596 IN UINT64 Ticker
597 )
598 /*++
599
600 Routine Description:
601
602 Install gEfiPerformanceProtocolGuid protocol and transfer PEI performance to gauge data nodes.
603
604 Arguments:
605
606 ImageHandle - Standard driver entry point parameter
607 SystemTable - Standard driver entry point parameter
608 Ticker - End tick for PEI performance
609
610 Returns:
611
612 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
613 EFI_SUCCESS - Protocol installed.
614
615 --*/
616 {
617 EFI_STATUS Status;
618 EFI_PERFORMANCE_INSTANCE *PerfInstance;
619
620 //
621 // Allocate a new image structure
622 //
623 PerfInstance = EfiLibAllocateZeroPool (sizeof (EFI_PERFORMANCE_INSTANCE));
624 if (PerfInstance == NULL) {
625 return EFI_OUT_OF_RESOURCES;
626 }
627
628 PerfInstance->Signature = EFI_PERFORMANCE_SIGNATURE;
629 PerfInstance->Perf.StartGauge = StartGauge;
630 PerfInstance->Perf.EndGauge = EndGauge;
631 PerfInstance->Perf.GetGauge = GetGauge;
632
633 //
634 // Install the protocol interfaces
635 //
636 Status = gBS->InstallProtocolInterface (
637 &PerfInstance->Handle,
638 &gEfiPerformanceProtocolGuid,
639 EFI_NATIVE_INTERFACE,
640 &PerfInstance->Perf
641 );
642
643 if (!EFI_ERROR (Status)) {
644 GetPeiPerformance (ImageHandle, SystemTable, Ticker);
645 }
646
647 return EFI_SUCCESS;
648 }
649
650
651 EFI_STATUS
652 StartMeasure (
653 EFI_HANDLE Handle,
654 IN UINT16 *Token,
655 IN UINT16 *Host,
656 IN UINT64 Ticker
657 )
658 /*++
659
660 Routine Description:
661
662 Start to gauge on a specified handle, token and host, with Ticker as start tick.
663
664 Arguments:
665
666 Handle - Handle to measure
667 Token - Token to measure
668 Host - Host to measure
669 Ticker - Ticker as start tick
670
671 Returns:
672
673 Status code.
674
675 --*/
676 {
677 EFI_STATUS Status;
678 EFI_PERFORMANCE_PROTOCOL *Perf;
679
680 Status = gBS->LocateProtocol (&gEfiPerformanceProtocolGuid, NULL, (VOID **) &Perf);
681 if (EFI_ERROR (Status)) {
682 return Status;
683 }
684
685 return Perf->StartGauge (Perf, Handle, Token, Host, Ticker);
686
687 }
688
689
690 EFI_STATUS
691 EndMeasure (
692 EFI_HANDLE Handle,
693 IN UINT16 *Token,
694 IN UINT16 *Host,
695 IN UINT64 Ticker
696 )
697 /*++
698
699 Routine Description:
700
701 End gauging on a specified handle, token and host, with Ticker as end tick.
702
703 Arguments:
704
705 Handle - Handle to stop
706 Token - Token to stop
707 Host - Host to stop
708 Ticker - Ticker as end tick
709
710 Returns:
711
712 Status code.
713
714 --*/
715 {
716 EFI_STATUS Status;
717 EFI_PERFORMANCE_PROTOCOL *Perf;
718
719 Status = gBS->LocateProtocol (&gEfiPerformanceProtocolGuid, NULL, (VOID **) &Perf);
720 if (Status != EFI_SUCCESS) {
721 return Status;
722 }
723
724 return (Perf->EndGauge( Perf, Handle, Token, Host, Ticker)) ;
725 }
726
727
728 EFI_STATUS
729 UpdateMeasure (
730 EFI_HANDLE Handle,
731 IN UINT16 *Token,
732 IN UINT16 *Host,
733 EFI_HANDLE HandleNew,
734 IN UINT16 *TokenNew,
735 IN UINT16 *HostNew
736 )
737 /*++
738
739 Routine Description:
740 Update measure.
741
742 Arguments:
743 Handle - A pointer of an efi handle.
744 Token - A pointer to the token.
745 Host - A pointer to the host.
746 HandleNew - A pointer of an new efi handle.
747 TokenNew - A pointer to the new token.
748 HostNew - A pointer to the new host.
749
750 Returns:
751 Status code.
752
753 EFI_NOT_FOUND - The speicified gauge data node not found.
754
755 EFI_SUCCESS - Update successfully.
756
757 --*/
758 {
759 EFI_STATUS Status;
760 EFI_GAUGE_DATA *GaugeData;
761 EFI_PERFORMANCE_PROTOCOL *Perf;
762
763 Status = gBS->LocateProtocol (&gEfiPerformanceProtocolGuid, NULL, (VOID **) &Perf);
764 if (EFI_ERROR (Status)) {
765 return Status;
766 }
767
768 GaugeData = Perf->GetGauge (Perf, Handle, Token, Host, NULL);
769 if (!GaugeData) {
770 return EFI_NOT_FOUND;
771 }
772
773 GaugeData->Handle = HandleNew;
774 if (HostNew != NULL) {
775 EfiStrCpy (GaugeData->Host, HostNew);
776 } else {
777 EfiStrCpy (GaugeData->Host, L"");
778 }
779
780 if (TokenNew != NULL) {
781 EfiStrCpy (GaugeData->Token, TokenNew);
782 } else {
783 EfiStrCpy (GaugeData->Token, L"");
784 }
785
786 return EFI_SUCCESS;
787 }
788
789
790 EFI_STATUS
791 GetPeiPerformance (
792 IN EFI_HANDLE ImageHandle,
793 IN EFI_SYSTEM_TABLE *SystemTable,
794 IN UINT64 Ticker
795 )
796 /*++
797
798 Routine Description:
799
800 Transfer PEI performance data to gauge data node.
801
802 Arguments:
803
804 ImageHandle - Standard entry point parameter
805 SystemTable - Standard entry point parameter
806 Ticker - Start tick
807
808 Returns:
809
810 EFI_OUT_OF_RESOURCES - No enough resource to create data node.
811 EFI_SUCCESS - Transfer done successfully.
812
813 --*/
814 {
815 EFI_STATUS Status;
816 VOID *HobList;
817 EFI_HOB_GUID_DATA_PERFORMANCE_LOG *LogHob;
818 PEI_PERFORMANCE_MEASURE_LOG_ENTRY *LogEntry;
819 UINT32 Index;
820 EFI_PERF_DATA_LIST *Node;
821 UINT64 TimerValue;
822
823 Node = CreateDataNode (0, PEI_TOK, NULL);
824 if (!Node) {
825 return EFI_OUT_OF_RESOURCES;
826 }
827
828 if (Ticker != 0) {
829 TimerValue = Ticker;
830 } else {
831 GetTimerValue (&TimerValue);
832 }
833 (Node->GaugeData).EndTick = TimerValue;
834
835 InsertTailList (&mPerfDataHead, &(Node->Link));
836
837 EfiLibGetSystemConfigurationTable (&gEfiHobListGuid, &HobList);
838 do {
839 Status = GetNextGuidHob (&HobList, &gEfiPeiPerformanceHobGuid, (VOID **) &LogHob, NULL);
840 if (EFI_ERROR (Status)) {
841 break;
842 }
843
844 for (Index = 0; Index < LogHob->NumberOfEntries; Index++) {
845 LogEntry = &(LogHob->Log[Index]);
846 Node = CreateDataNode (0, LogEntry->DescriptionString, NULL);
847 if (!Node) {
848 return EFI_OUT_OF_RESOURCES;
849 }
850 (Node->GaugeData).StartTick = LogEntry->StartTimeCount;
851
852 EfiCopyMem (&(Node->GaugeData.GuidName), &LogEntry->Name, sizeof (EFI_GUID));
853
854 InsertTailList (&mPerfDataHead, &(Node->Link));
855
856 (Node->GaugeData).EndTick = LogEntry->StopTimeCount;
857 }
858 } while (!EFI_ERROR (Status));
859
860 return EFI_SUCCESS;
861 }