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