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