]> git.proxmox.com Git - mirror_edk2.git/blame - EdkCompatibilityPkg/Foundation/Library/Dxe/EfiDriverLib/Perf.c
Update the copyright notice format
[mirror_edk2.git] / EdkCompatibilityPkg / Foundation / Library / Dxe / EfiDriverLib / Perf.c
CommitLineData
3eb9473e 1/*++\r
2\r
4ea9375a
HT
3Copyright (c) 2004 - 2005, Intel Corporation. All rights reserved.<BR>\r
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
593InitializePerformanceInfrastructure (\r
594 IN EFI_HANDLE ImageHandle,\r
595 IN EFI_SYSTEM_TABLE *SystemTable,\r
596 IN UINT64 Ticker\r
597 )\r
598/*++\r
599\r
600Routine Description:\r
601\r
602 Install gEfiPerformanceProtocolGuid protocol and transfer PEI performance to gauge data nodes.\r
603\r
604Arguments:\r
605\r
606 ImageHandle - Standard driver entry point parameter\r
607 SystemTable - Standard driver entry point parameter\r
608 Ticker - End tick for PEI performance\r
609\r
610Returns:\r
611\r
612 EFI_OUT_OF_RESOURCES - No enough buffer to allocate\r
613 EFI_SUCCESS - Protocol installed.\r
614\r
615--*/\r
616{\r
617 EFI_STATUS Status;\r
618 EFI_PERFORMANCE_INSTANCE *PerfInstance;\r
619\r
620 //\r
621 // Allocate a new image structure\r
622 //\r
623 PerfInstance = EfiLibAllocateZeroPool (sizeof (EFI_PERFORMANCE_INSTANCE));\r
624 if (PerfInstance == NULL) {\r
625 return EFI_OUT_OF_RESOURCES;\r
626 }\r
627\r
628 PerfInstance->Signature = EFI_PERFORMANCE_SIGNATURE;\r
629 PerfInstance->Perf.StartGauge = StartGauge;\r
630 PerfInstance->Perf.EndGauge = EndGauge;\r
631 PerfInstance->Perf.GetGauge = GetGauge;\r
632\r
633 //\r
634 // Install the protocol interfaces\r
635 //\r
636 Status = gBS->InstallProtocolInterface (\r
637 &PerfInstance->Handle,\r
638 &gEfiPerformanceProtocolGuid,\r
639 EFI_NATIVE_INTERFACE,\r
640 &PerfInstance->Perf\r
641 );\r
642\r
643 if (!EFI_ERROR (Status)) {\r
644 GetPeiPerformance (ImageHandle, SystemTable, Ticker);\r
645 }\r
646\r
647 return EFI_SUCCESS;\r
648}\r
649\r
650\r
651EFI_STATUS\r
652StartMeasure (\r
653 EFI_HANDLE Handle,\r
654 IN UINT16 *Token,\r
655 IN UINT16 *Host,\r
656 IN UINT64 Ticker\r
657 )\r
658/*++\r
659\r
660Routine Description:\r
661\r
662 Start to gauge on a specified handle, token and host, with Ticker as start tick.\r
663\r
664Arguments:\r
665\r
666 Handle - Handle to measure\r
667 Token - Token to measure\r
668 Host - Host to measure\r
669 Ticker - Ticker as start tick\r
670\r
671Returns:\r
672\r
673 Status code.\r
674\r
675--*/\r
676{\r
677 EFI_STATUS Status;\r
678 EFI_PERFORMANCE_PROTOCOL *Perf;\r
679\r
680 Status = gBS->LocateProtocol (&gEfiPerformanceProtocolGuid, NULL, (VOID **) &Perf);\r
681 if (EFI_ERROR (Status)) {\r
682 return Status;\r
683 }\r
684\r
685 return Perf->StartGauge (Perf, Handle, Token, Host, Ticker);\r
686\r
687}\r
688\r
689\r
690EFI_STATUS\r
691EndMeasure (\r
692 EFI_HANDLE Handle,\r
693 IN UINT16 *Token,\r
694 IN UINT16 *Host,\r
695 IN UINT64 Ticker\r
696 )\r
697/*++\r
698\r
699Routine Description:\r
700\r
701 End gauging on a specified handle, token and host, with Ticker as end tick.\r
702\r
703Arguments:\r
704\r
705 Handle - Handle to stop\r
706 Token - Token to stop\r
707 Host - Host to stop\r
708 Ticker - Ticker as end tick\r
709\r
710Returns:\r
711\r
712 Status code.\r
713\r
714--*/\r
715{\r
716 EFI_STATUS Status;\r
717 EFI_PERFORMANCE_PROTOCOL *Perf;\r
718\r
719 Status = gBS->LocateProtocol (&gEfiPerformanceProtocolGuid, NULL, (VOID **) &Perf);\r
720 if (Status != EFI_SUCCESS) {\r
721 return Status;\r
722 }\r
723\r
724 return (Perf->EndGauge( Perf, Handle, Token, Host, Ticker)) ;\r
725}\r
726\r
727\r
728EFI_STATUS\r
729UpdateMeasure (\r
730 EFI_HANDLE Handle,\r
731 IN UINT16 *Token,\r
732 IN UINT16 *Host,\r
733 EFI_HANDLE HandleNew,\r
734 IN UINT16 *TokenNew,\r
735 IN UINT16 *HostNew\r
736 )\r
737/*++\r
738\r
739Routine Description:\r
740 Update measure.\r
741\r
742Arguments:\r
743 Handle - A pointer of an efi handle.\r
744 Token - A pointer to the token.\r
745 Host - A pointer to the host.\r
746 HandleNew - A pointer of an new efi handle.\r
747 TokenNew - A pointer to the new token.\r
748 HostNew - A pointer to the new host.\r
749\r
750Returns:\r
751 Status code.\r
752\r
753 EFI_NOT_FOUND - The speicified gauge data node not found.\r
754 \r
755 EFI_SUCCESS - Update successfully.\r
756\r
757--*/\r
758{\r
759 EFI_STATUS Status;\r
760 EFI_GAUGE_DATA *GaugeData;\r
761 EFI_PERFORMANCE_PROTOCOL *Perf;\r
762\r
763 Status = gBS->LocateProtocol (&gEfiPerformanceProtocolGuid, NULL, (VOID **) &Perf);\r
764 if (EFI_ERROR (Status)) {\r
765 return Status;\r
766 }\r
767\r
768 GaugeData = Perf->GetGauge (Perf, Handle, Token, Host, NULL);\r
769 if (!GaugeData) {\r
770 return EFI_NOT_FOUND;\r
771 }\r
772\r
773 GaugeData->Handle = HandleNew;\r
774 if (HostNew != NULL) {\r
775 EfiStrCpy (GaugeData->Host, HostNew);\r
776 } else {\r
777 EfiStrCpy (GaugeData->Host, L"");\r
778 }\r
779\r
780 if (TokenNew != NULL) {\r
781 EfiStrCpy (GaugeData->Token, TokenNew);\r
782 } else {\r
783 EfiStrCpy (GaugeData->Token, L"");\r
784 }\r
785\r
786 return EFI_SUCCESS;\r
787}\r
788\r
789\r
790EFI_STATUS\r
791GetPeiPerformance (\r
792 IN EFI_HANDLE ImageHandle,\r
793 IN EFI_SYSTEM_TABLE *SystemTable,\r
794 IN UINT64 Ticker\r
795 )\r
796/*++\r
797\r
798Routine Description:\r
799\r
800 Transfer PEI performance data to gauge data node.\r
801\r
802Arguments:\r
803\r
804 ImageHandle - Standard entry point parameter\r
805 SystemTable - Standard entry point parameter\r
806 Ticker - Start tick\r
807\r
808Returns:\r
809\r
810 EFI_OUT_OF_RESOURCES - No enough resource to create data node.\r
811 EFI_SUCCESS - Transfer done successfully.\r
812\r
813--*/\r
814{\r
815 EFI_STATUS Status;\r
816 VOID *HobList;\r
817 EFI_HOB_GUID_DATA_PERFORMANCE_LOG *LogHob;\r
818 PEI_PERFORMANCE_MEASURE_LOG_ENTRY *LogEntry;\r
819 UINT32 Index;\r
820 EFI_PERF_DATA_LIST *Node;\r
821 UINT64 TimerValue;\r
822\r
823 Node = CreateDataNode (0, PEI_TOK, NULL);\r
824 if (!Node) {\r
825 return EFI_OUT_OF_RESOURCES;\r
826 }\r
827\r
828 if (Ticker != 0) {\r
829 TimerValue = Ticker;\r
830 } else {\r
831 GetTimerValue (&TimerValue);\r
832 }\r
833 (Node->GaugeData).EndTick = TimerValue;\r
834\r
835 InsertTailList (&mPerfDataHead, &(Node->Link));\r
836\r
837 EfiLibGetSystemConfigurationTable (&gEfiHobListGuid, &HobList);\r
838 do {\r
839 Status = GetNextGuidHob (&HobList, &gEfiPeiPerformanceHobGuid, (VOID **) &LogHob, NULL);\r
840 if (EFI_ERROR (Status)) {\r
841 break;\r
842 }\r
843\r
844 for (Index = 0; Index < LogHob->NumberOfEntries; Index++) {\r
845 LogEntry = &(LogHob->Log[Index]);\r
846 Node = CreateDataNode (0, LogEntry->DescriptionString, NULL);\r
847 if (!Node) {\r
848 return EFI_OUT_OF_RESOURCES;\r
849 }\r
850 (Node->GaugeData).StartTick = LogEntry->StartTimeCount;\r
851\r
852 EfiCopyMem (&(Node->GaugeData.GuidName), &LogEntry->Name, sizeof (EFI_GUID));\r
853\r
854 InsertTailList (&mPerfDataHead, &(Node->Link));\r
855\r
856 (Node->GaugeData).EndTick = LogEntry->StopTimeCount;\r
857 }\r
858 } while (!EFI_ERROR (Status));\r
859\r
860 return EFI_SUCCESS;\r
861}\r