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