]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/GenericBdsLib/Performance.c
Clean up Device Manager module in BdsDxe.
[mirror_edk2.git] / MdeModulePkg / Library / GenericBdsLib / Performance.c
CommitLineData
897f0eee 1/** @file\r
2 This file include the file which can help to get the system\r
3 performance, all the function will only include if the performance\r
4 switch is set.\r
5\r
6Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
7All rights reserved. This program and the accompanying materials\r
8are licensed and made available under the terms and conditions of the BSD License\r
9which accompanies this distribution. The full text of the license may be found at\r
10http://opensource.org/licenses/bsd-license.php\r
11\r
12THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
16\r
17#include "InternalBdsLib.h"\r
18\r
19STATIC PERF_HEADER mPerfHeader;\r
20STATIC PERF_DATA mPerfData;\r
21\r
22STATIC\r
23VOID\r
24GetShortPdbFileName (\r
25 CHAR8 *PdbFileName,\r
26 CHAR8 *GaugeString\r
27 )\r
28/*++\r
29\r
30Routine Description:\r
31 \r
32Arguments:\r
33\r
34Returns:\r
35\r
36--*/\r
37{\r
38 UINTN Index;\r
39 UINTN Index1;\r
40 UINTN StartIndex;\r
41 UINTN EndIndex;\r
42\r
43 if (PdbFileName == NULL) {\r
44 AsciiStrCpy (GaugeString, " ");\r
45 } else {\r
46 StartIndex = 0;\r
47 for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++)\r
48 ;\r
49\r
50 for (Index = 0; PdbFileName[Index] != 0; Index++) {\r
51 if (PdbFileName[Index] == '\\') {\r
52 StartIndex = Index + 1;\r
53 }\r
54\r
55 if (PdbFileName[Index] == '.') {\r
56 EndIndex = Index;\r
57 }\r
58 }\r
59\r
60 Index1 = 0;\r
61 for (Index = StartIndex; Index < EndIndex; Index++) {\r
62 GaugeString[Index1] = PdbFileName[Index];\r
63 Index1++;\r
64 if (Index1 == PERF_TOKEN_LENGTH - 1) {\r
65 break;\r
66 }\r
67 }\r
68\r
69 GaugeString[Index1] = 0;\r
70 }\r
71\r
72 return ;\r
73}\r
74\r
75STATIC\r
76VOID\r
77GetNameFromHandle (\r
78 IN EFI_HANDLE Handle,\r
79 OUT CHAR8 *GaugeString\r
80 )\r
81{\r
82 EFI_STATUS Status;\r
83 EFI_LOADED_IMAGE_PROTOCOL *Image;\r
84 CHAR8 *PdbFileName;\r
85 EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;\r
86\r
87 AsciiStrCpy (GaugeString, " ");\r
88\r
89 //\r
90 // Get handle name from image protocol\r
91 //\r
92 Status = gBS->HandleProtocol (\r
93 Handle,\r
94 &gEfiLoadedImageProtocolGuid,\r
95 (VOID **) &Image\r
96 );\r
97\r
98 if (EFI_ERROR (Status)) {\r
99 Status = gBS->OpenProtocol (\r
100 Handle,\r
101 &gEfiDriverBindingProtocolGuid,\r
102 (VOID **) &DriverBinding,\r
103 NULL,\r
104 NULL,\r
105 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
106 );\r
107 if (EFI_ERROR (Status)) {\r
108 return ;\r
109 }\r
110 //\r
111 // Get handle name from image protocol\r
112 //\r
113 Status = gBS->HandleProtocol (\r
114 DriverBinding->ImageHandle,\r
115 &gEfiLoadedImageProtocolGuid,\r
116 (VOID **) &Image\r
117 );\r
118 }\r
119\r
120 PdbFileName = PeCoffLoaderGetPdbPointer (Image->ImageBase);\r
121\r
122 if (PdbFileName != NULL) {\r
123 GetShortPdbFileName (PdbFileName, GaugeString);\r
124 }\r
125\r
126 return ;\r
127}\r
128\r
129VOID\r
130WriteBootToOsPerformanceData (\r
131 VOID\r
132 )\r
133/*++\r
134\r
135Routine Description:\r
136 \r
137 Allocates a block of memory and writes performance data of booting to OS into it.\r
138\r
139Arguments:\r
140 \r
141 None\r
142 \r
143Returns:\r
144\r
145 None\r
146\r
147--*/\r
148{\r
149 EFI_STATUS Status;\r
150 EFI_PHYSICAL_ADDRESS AcpiLowMemoryBase;\r
151 UINT32 AcpiLowMemoryLength;\r
152 UINT32 LimitCount;\r
153 EFI_HANDLE *Handles;\r
154 UINTN NoHandles;\r
155 CHAR8 GaugeString[PERF_TOKEN_LENGTH];\r
156 UINT8 *Ptr;\r
157 UINT32 Index;\r
158 UINT64 Ticker;\r
159 UINT64 Freq;\r
160 UINT32 Duration;\r
161 UINTN LogEntryKey;\r
162 CONST VOID *Handle;\r
163 CONST CHAR8 *Token;\r
164 CONST CHAR8 *Module;\r
165 UINT64 StartTicker;\r
166 UINT64 EndTicker;\r
167 UINT64 StartValue;\r
168 UINT64 EndValue;\r
169 BOOLEAN CountUp;\r
170\r
171 //\r
172 // Retrive time stamp count as early as possilbe\r
173 //\r
174 Ticker = GetPerformanceCounter ();\r
175\r
176 Freq = GetPerformanceCounterProperties (&StartValue, &EndValue);\r
177 \r
178 Freq = DivU64x32 (Freq, 1000);\r
179\r
180 mPerfHeader.CpuFreq = Freq;\r
181\r
182 //\r
183 // Record BDS raw performance data\r
184 //\r
185 if (EndValue >= StartValue) {\r
186 mPerfHeader.BDSRaw = Ticker - StartValue;\r
187 CountUp = TRUE;\r
188 } else {\r
189 mPerfHeader.BDSRaw = StartValue - Ticker;\r
190 CountUp = FALSE;\r
191 }\r
192\r
193 AcpiLowMemoryLength = 0x2000;\r
194\r
195 //\r
196 // Allocate a block of memory that contain performance data to OS\r
197 //\r
198 Status = gBS->AllocatePages (\r
199 AllocateAnyPages,\r
200 EfiACPIReclaimMemory,\r
201 EFI_SIZE_TO_PAGES (AcpiLowMemoryLength),\r
202 &AcpiLowMemoryBase\r
203 );\r
204 if (EFI_ERROR (Status)) {\r
205 return ;\r
206 }\r
207\r
208\r
209 Ptr = (UINT8 *) ((UINT32) AcpiLowMemoryBase + sizeof (PERF_HEADER));\r
210 LimitCount = (AcpiLowMemoryLength - sizeof (PERF_HEADER)) / sizeof (PERF_DATA);\r
211\r
212 //\r
213 // Put Detailed performance data into memory\r
214 //\r
215 Handles = NULL;\r
216 Status = gBS->LocateHandleBuffer (\r
217 AllHandles,\r
218 NULL,\r
219 NULL,\r
220 &NoHandles,\r
221 &Handles\r
222 );\r
223 if (EFI_ERROR (Status)) {\r
224 gBS->FreePages (AcpiLowMemoryBase, 1);\r
225 return ;\r
226 }\r
227 //\r
228 // Get DXE drivers performance\r
229 //\r
230 for (Index = 0; Index < NoHandles; Index++) {\r
231 Ticker = 0;\r
232 LogEntryKey = 0;\r
233 while ((LogEntryKey = GetPerformanceMeasurement (\r
234 LogEntryKey,\r
235 &Handle,\r
236 &Token,\r
237 &Module,\r
238 &StartTicker,\r
239 &EndTicker)) != 0) {\r
240 if ((Handle == Handles[Index]) && (EndTicker != 0)) {\r
241 Ticker += CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);\r
242 }\r
243 }\r
244\r
245 Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);\r
246\r
247 if (Duration > 0) {\r
248\r
249 GetNameFromHandle (Handles[Index], GaugeString);\r
250\r
251 AsciiStrCpy (mPerfData.Token, GaugeString);\r
252 mPerfData.Duration = Duration;\r
253\r
254 CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));\r
255 Ptr += sizeof (PERF_DATA);\r
256\r
257 mPerfHeader.Count++;\r
258 if (mPerfHeader.Count == LimitCount) {\r
259 goto Done;\r
260 }\r
261 }\r
262 }\r
263\r
264 FreePool (Handles);\r
265\r
266 //\r
267 // Get inserted performance data\r
268 //\r
269 LogEntryKey = 0;\r
270 while ((LogEntryKey = GetPerformanceMeasurement (\r
271 LogEntryKey,\r
272 &Handle,\r
273 &Token,\r
274 &Module,\r
275 &StartTicker,\r
276 &EndTicker)) != 0) {\r
277 if (Handle == NULL && EndTicker != 0) {\r
278\r
279 ZeroMem (&mPerfData, sizeof (PERF_DATA));\r
280\r
281 AsciiStrnCpy (mPerfData.Token, Token, PERF_TOKEN_LENGTH);\r
282 Ticker = CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);\r
283\r
284 mPerfData.Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);\r
285\r
286 CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));\r
287 Ptr += sizeof (PERF_DATA);\r
288\r
289 mPerfHeader.Count++;\r
290 if (mPerfHeader.Count == LimitCount) {\r
291 goto Done;\r
292 }\r
293 }\r
294 }\r
295\r
296Done:\r
297\r
298 mPerfHeader.Signiture = PERFORMANCE_SIGNATURE;\r
299\r
300 //\r
301 // Put performance data to memory\r
302 //\r
303 CopyMem (\r
304 (UINTN *) (UINTN) AcpiLowMemoryBase,\r
305 &mPerfHeader,\r
306 sizeof (PERF_HEADER)\r
307 );\r
308\r
309 gRT->SetVariable (\r
310 L"PerfDataMemAddr",\r
311 &gEfiGenericPlatformVariableGuid,\r
312 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
313 sizeof (EFI_PHYSICAL_ADDRESS),\r
314 &AcpiLowMemoryBase\r
315 );\r
316\r
317 return ;\r
318}\r