]> git.proxmox.com Git - mirror_edk2.git/blame - EdkCompatibilityPkg/Foundation/Library/Dxe/EfiDriverLib/Perf.c
Sync all bug fixes between EDK1.04 and EDK1.06 into EdkCompatibilityPkg.
[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
518 EFI_PERFORMANCE_INSTANCE *PerfInstance;\r
519 EFI_PERF_DATA_LIST *Node;\r
520 UINT64 TimerValue;\r
521\r
522 TimerValue = 0;\r
523 PerfInstance = EFI_PERFORMANCE_FROM_THIS (This);\r
524\r
525 Node = GetDataNode (Handle, Token, Host, NULL, NULL);\r
526 if (!Node) {\r
527 return EFI_NOT_FOUND;\r
528 }\r
529\r
530 while (Node->GaugeData.EndTick != 0) {\r
531 Node = GetDataNode (Handle, Token, Host, NULL, &(Node->GaugeData));\r
532 if (!Node) {\r
533 return EFI_NOT_FOUND;\r
534 }\r
535 }\r
536\r
537 if (Ticker != 0) {\r
538 TimerValue = Ticker;\r
539 } else {\r
540 GetTimerValue (&TimerValue);\r
541 }\r
542\r
543 Node->GaugeData.EndTick = TimerValue;\r
544\r
545 return EFI_SUCCESS;\r
546}\r
547\r
548\r
549EFI_GAUGE_DATA *\r
550EFIAPI\r
551GetGauge (\r
552 IN EFI_PERFORMANCE_PROTOCOL *This,\r
553 IN EFI_HANDLE Handle,\r
554 IN UINT16 *Token,\r
555 IN UINT16 *Host,\r
556 IN EFI_GAUGE_DATA *PrevGauge\r
557 )\r
558/*++\r
559\r
560Routine Description:\r
561 Get gauge.\r
562\r
563Arguments:\r
564 This - A pointer to the EFI_PERFORMANCE_PROTOCOL.\r
565 Handle - A pointer of a efi handle.\r
566 Token - A pointer to the token.\r
567 Host - A pointer to the host.\r
568 PrevGauge - A pointer to the EFI_GAUGE_DATA structure.\r
569\r
570\r
571Returns:\r
572 Status code.\r
573\r
574--*/\r
575{\r
576 EFI_PERFORMANCE_INSTANCE *PerfInstance;\r
577 EFI_PERF_DATA_LIST *Node;\r
578\r
579 PerfInstance = EFI_PERFORMANCE_FROM_THIS (This);\r
580\r
581 Node = GetDataNode (Handle, Token, Host, NULL, PrevGauge);\r
582 if (Node != NULL) {\r
583 return &(Node->GaugeData);\r
584 } else {\r
585 return NULL;\r
586 }\r
587}\r
588\r
589//\r
590// Driver entry point\r
591//\r
592EFI_STATUS\r
12496963 593EFIAPI\r
3eb9473e 594InitializePerformanceInfrastructure (\r
595 IN EFI_HANDLE ImageHandle,\r
596 IN EFI_SYSTEM_TABLE *SystemTable,\r
597 IN UINT64 Ticker\r
598 )\r
599/*++\r
600\r
601Routine Description:\r
602\r
603 Install gEfiPerformanceProtocolGuid protocol and transfer PEI performance to gauge data nodes.\r
604\r
605Arguments:\r
606\r
607 ImageHandle - Standard driver entry point parameter\r
608 SystemTable - Standard driver entry point parameter\r
609 Ticker - End tick for PEI performance\r
610\r
611Returns:\r
612\r
613 EFI_OUT_OF_RESOURCES - No enough buffer to allocate\r
614 EFI_SUCCESS - Protocol installed.\r
615\r
616--*/\r
617{\r
618 EFI_STATUS Status;\r
619 EFI_PERFORMANCE_INSTANCE *PerfInstance;\r
620\r
621 //\r
622 // Allocate a new image structure\r
623 //\r
624 PerfInstance = EfiLibAllocateZeroPool (sizeof (EFI_PERFORMANCE_INSTANCE));\r
625 if (PerfInstance == NULL) {\r
626 return EFI_OUT_OF_RESOURCES;\r
627 }\r
628\r
629 PerfInstance->Signature = EFI_PERFORMANCE_SIGNATURE;\r
630 PerfInstance->Perf.StartGauge = StartGauge;\r
631 PerfInstance->Perf.EndGauge = EndGauge;\r
632 PerfInstance->Perf.GetGauge = GetGauge;\r
633\r
634 //\r
635 // Install the protocol interfaces\r
636 //\r
637 Status = gBS->InstallProtocolInterface (\r
638 &PerfInstance->Handle,\r
639 &gEfiPerformanceProtocolGuid,\r
640 EFI_NATIVE_INTERFACE,\r
641 &PerfInstance->Perf\r
642 );\r
643\r
644 if (!EFI_ERROR (Status)) {\r
645 GetPeiPerformance (ImageHandle, SystemTable, Ticker);\r
646 }\r
647\r
648 return EFI_SUCCESS;\r
649}\r
650\r
651\r
652EFI_STATUS\r
12496963 653EFIAPI\r
3eb9473e 654StartMeasure (\r
655 EFI_HANDLE Handle,\r
656 IN UINT16 *Token,\r
657 IN UINT16 *Host,\r
658 IN UINT64 Ticker\r
659 )\r
660/*++\r
661\r
662Routine Description:\r
663\r
664 Start to gauge on a specified handle, token and host, with Ticker as start tick.\r
665\r
666Arguments:\r
667\r
668 Handle - Handle to measure\r
669 Token - Token to measure\r
670 Host - Host to measure\r
671 Ticker - Ticker as start tick\r
672\r
673Returns:\r
674\r
675 Status code.\r
676\r
677--*/\r
678{\r
679 EFI_STATUS Status;\r
680 EFI_PERFORMANCE_PROTOCOL *Perf;\r
681\r
682 Status = gBS->LocateProtocol (&gEfiPerformanceProtocolGuid, NULL, (VOID **) &Perf);\r
683 if (EFI_ERROR (Status)) {\r
684 return Status;\r
685 }\r
686\r
687 return Perf->StartGauge (Perf, Handle, Token, Host, Ticker);\r
688\r
689}\r
690\r
691\r
692EFI_STATUS\r
12496963 693EFIAPI\r
3eb9473e 694EndMeasure (\r
695 EFI_HANDLE Handle,\r
696 IN UINT16 *Token,\r
697 IN UINT16 *Host,\r
698 IN UINT64 Ticker\r
699 )\r
700/*++\r
701\r
702Routine Description:\r
703\r
704 End gauging on a specified handle, token and host, with Ticker as end tick.\r
705\r
706Arguments:\r
707\r
708 Handle - Handle to stop\r
709 Token - Token to stop\r
710 Host - Host to stop\r
711 Ticker - Ticker as end tick\r
712\r
713Returns:\r
714\r
715 Status code.\r
716\r
717--*/\r
718{\r
719 EFI_STATUS Status;\r
720 EFI_PERFORMANCE_PROTOCOL *Perf;\r
721\r
722 Status = gBS->LocateProtocol (&gEfiPerformanceProtocolGuid, NULL, (VOID **) &Perf);\r
723 if (Status != EFI_SUCCESS) {\r
724 return Status;\r
725 }\r
726\r
727 return (Perf->EndGauge( Perf, Handle, Token, Host, Ticker)) ;\r
728}\r
729\r
730\r
731EFI_STATUS\r
12496963 732EFIAPI\r
3eb9473e 733UpdateMeasure (\r
734 EFI_HANDLE Handle,\r
735 IN UINT16 *Token,\r
736 IN UINT16 *Host,\r
737 EFI_HANDLE HandleNew,\r
738 IN UINT16 *TokenNew,\r
739 IN UINT16 *HostNew\r
740 )\r
741/*++\r
742\r
743Routine Description:\r
744 Update measure.\r
745\r
746Arguments:\r
747 Handle - A pointer of an efi handle.\r
748 Token - A pointer to the token.\r
749 Host - A pointer to the host.\r
750 HandleNew - A pointer of an new efi handle.\r
751 TokenNew - A pointer to the new token.\r
752 HostNew - A pointer to the new host.\r
753\r
754Returns:\r
755 Status code.\r
756\r
757 EFI_NOT_FOUND - The speicified gauge data node not found.\r
758 \r
759 EFI_SUCCESS - Update successfully.\r
760\r
761--*/\r
762{\r
763 EFI_STATUS Status;\r
764 EFI_GAUGE_DATA *GaugeData;\r
765 EFI_PERFORMANCE_PROTOCOL *Perf;\r
766\r
767 Status = gBS->LocateProtocol (&gEfiPerformanceProtocolGuid, NULL, (VOID **) &Perf);\r
768 if (EFI_ERROR (Status)) {\r
769 return Status;\r
770 }\r
771\r
772 GaugeData = Perf->GetGauge (Perf, Handle, Token, Host, NULL);\r
773 if (!GaugeData) {\r
774 return EFI_NOT_FOUND;\r
775 }\r
776\r
777 GaugeData->Handle = HandleNew;\r
778 if (HostNew != NULL) {\r
779 EfiStrCpy (GaugeData->Host, HostNew);\r
780 } else {\r
781 EfiStrCpy (GaugeData->Host, L"");\r
782 }\r
783\r
784 if (TokenNew != NULL) {\r
785 EfiStrCpy (GaugeData->Token, TokenNew);\r
786 } else {\r
787 EfiStrCpy (GaugeData->Token, L"");\r
788 }\r
789\r
790 return EFI_SUCCESS;\r
791}\r
792\r
793\r
794EFI_STATUS\r
795GetPeiPerformance (\r
796 IN EFI_HANDLE ImageHandle,\r
797 IN EFI_SYSTEM_TABLE *SystemTable,\r
798 IN UINT64 Ticker\r
799 )\r
800/*++\r
801\r
802Routine Description:\r
803\r
804 Transfer PEI performance data to gauge data node.\r
805\r
806Arguments:\r
807\r
808 ImageHandle - Standard entry point parameter\r
809 SystemTable - Standard entry point parameter\r
810 Ticker - Start tick\r
811\r
812Returns:\r
813\r
814 EFI_OUT_OF_RESOURCES - No enough resource to create data node.\r
815 EFI_SUCCESS - Transfer done successfully.\r
816\r
817--*/\r
818{\r
819 EFI_STATUS Status;\r
820 VOID *HobList;\r
821 EFI_HOB_GUID_DATA_PERFORMANCE_LOG *LogHob;\r
822 PEI_PERFORMANCE_MEASURE_LOG_ENTRY *LogEntry;\r
823 UINT32 Index;\r
824 EFI_PERF_DATA_LIST *Node;\r
825 UINT64 TimerValue;\r
826\r
827 Node = CreateDataNode (0, PEI_TOK, NULL);\r
828 if (!Node) {\r
829 return EFI_OUT_OF_RESOURCES;\r
830 }\r
831\r
4ac4deb7
LG
832 //\r
833 // Initialize 'LogHob' to NULL before usage.\r
834 //\r
835 LogHob = NULL;\r
836\r
3eb9473e 837 if (Ticker != 0) {\r
838 TimerValue = Ticker;\r
839 } else {\r
840 GetTimerValue (&TimerValue);\r
841 }\r
842 (Node->GaugeData).EndTick = TimerValue;\r
843\r
844 InsertTailList (&mPerfDataHead, &(Node->Link));\r
845\r
846 EfiLibGetSystemConfigurationTable (&gEfiHobListGuid, &HobList);\r
847 do {\r
848 Status = GetNextGuidHob (&HobList, &gEfiPeiPerformanceHobGuid, (VOID **) &LogHob, NULL);\r
4ac4deb7
LG
849 if (EFI_ERROR (Status) || (LogHob == NULL)) {\r
850 //\r
851 // Failed to get HOB for ProtocolGuid.\r
852 //\r
3eb9473e 853 break;\r
854 }\r
855\r
856 for (Index = 0; Index < LogHob->NumberOfEntries; Index++) {\r
857 LogEntry = &(LogHob->Log[Index]);\r
858 Node = CreateDataNode (0, LogEntry->DescriptionString, NULL);\r
859 if (!Node) {\r
860 return EFI_OUT_OF_RESOURCES;\r
861 }\r
862 (Node->GaugeData).StartTick = LogEntry->StartTimeCount;\r
863\r
864 EfiCopyMem (&(Node->GaugeData.GuidName), &LogEntry->Name, sizeof (EFI_GUID));\r
865\r
866 InsertTailList (&mPerfDataHead, &(Node->Link));\r
867\r
868 (Node->GaugeData).EndTick = LogEntry->StopTimeCount;\r
869 }\r
870 } while (!EFI_ERROR (Status));\r
871\r
872 return EFI_SUCCESS;\r
873}\r