]> git.proxmox.com Git - mirror_edk2.git/blame - Nt32Pkg/Library/EdkGenericBdsLib/Performance.c
Add FatBinary to Nt32Pkg.fdf
[mirror_edk2.git] / Nt32Pkg / Library / EdkGenericBdsLib / Performance.c
CommitLineData
869f8e34 1/*++\r
2\r
3Copyright (c) 2006 - 2007, Intel Corporation\r
4All rights reserved. This program and the accompanying materials\r
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 Performance.c\r
15\r
16Abstract:\r
17\r
18 This file include the file which can help to get the system\r
19 performance, all the function will only include if the performance\r
20 switch is set.\r
21\r
22--*/\r
23\r
24//\r
25// Include common header file for this module.\r
26//\r
27#include "CommonHeader.h"\r
28\r
29#include "Performance.h"\r
30\r
31\r
32STATIC\r
33VOID\r
34GetShortPdbFileName (\r
35 CHAR8 *PdbFileName,\r
36 CHAR8 *GaugeString\r
37 )\r
38/*++\r
39\r
40Routine Description:\r
41\r
42Arguments:\r
43\r
44Returns:\r
45\r
46--*/\r
47{\r
48 UINTN Index;\r
49 UINTN Index1;\r
50 UINTN StartIndex;\r
51 UINTN EndIndex;\r
52\r
53 if (PdbFileName == NULL) {\r
54 AsciiStrCpy (GaugeString, " ");\r
55 } else {\r
56 StartIndex = 0;\r
57 for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++)\r
58 ;\r
59\r
60 for (Index = 0; PdbFileName[Index] != 0; Index++) {\r
61 if (PdbFileName[Index] == '\\') {\r
62 StartIndex = Index + 1;\r
63 }\r
64\r
65 if (PdbFileName[Index] == '.') {\r
66 EndIndex = Index;\r
67 }\r
68 }\r
69\r
70 Index1 = 0;\r
71 for (Index = StartIndex; Index < EndIndex; Index++) {\r
72 GaugeString[Index1] = PdbFileName[Index];\r
73 Index1++;\r
74 if (Index1 == PERF_TOKEN_LENGTH - 1) {\r
75 break;\r
76 }\r
77 }\r
78\r
79 GaugeString[Index1] = 0;\r
80 }\r
81\r
82 return ;\r
83}\r
84\r
85\r
86\r
87STATIC\r
88CHAR8 *\r
89GetPdbPath (\r
90 VOID *ImageBase\r
91 )\r
92/*++\r
93\r
94Routine Description:\r
95\r
96 Located PDB path name in PE image\r
97\r
98Arguments:\r
99\r
100 ImageBase - base of PE to search\r
101\r
102Returns:\r
103\r
104 Pointer into image at offset of PDB file name if PDB file name is found,\r
105 Otherwise a pointer to an empty string.\r
106\r
107--*/\r
108{\r
109 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
110\r
111 ZeroMem (&ImageContext, sizeof (ImageContext));\r
112 ImageContext.Handle = ImageBase;\r
113 ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;\r
114\r
115 PeCoffLoaderGetImageInfo (&ImageContext);\r
116\r
117 return ImageContext.PdbPointer;\r
118}\r
119\r
120\r
121STATIC\r
122VOID\r
123GetNameFromHandle (\r
124 IN EFI_HANDLE Handle,\r
125 OUT CHAR8 *GaugeString\r
126 )\r
127{\r
128 EFI_STATUS Status;\r
129 EFI_LOADED_IMAGE_PROTOCOL *Image;\r
130 CHAR8 *PdbFileName;\r
131 EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;\r
132\r
133 AsciiStrCpy (GaugeString, " ");\r
134\r
135 //\r
136 // Get handle name from image protocol\r
137 //\r
138 Status = gBS->HandleProtocol (\r
139 Handle,\r
140 &gEfiLoadedImageProtocolGuid,\r
141 &Image\r
142 );\r
143\r
144 if (EFI_ERROR (Status)) {\r
145 Status = gBS->OpenProtocol (\r
146 Handle,\r
147 &gEfiDriverBindingProtocolGuid,\r
148 (VOID **) &DriverBinding,\r
149 NULL,\r
150 NULL,\r
151 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
152 );\r
153 if (EFI_ERROR (Status)) {\r
154 return ;\r
155 }\r
156 //\r
157 // Get handle name from image protocol\r
158 //\r
159 Status = gBS->HandleProtocol (\r
160 DriverBinding->ImageHandle,\r
161 &gEfiLoadedImageProtocolGuid,\r
162 &Image\r
163 );\r
164 }\r
165\r
166 PdbFileName = GetPdbPath (Image->ImageBase);\r
167\r
168 if (PdbFileName != NULL) {\r
169 GetShortPdbFileName (PdbFileName, GaugeString);\r
170 }\r
171\r
172 return ;\r
173}\r
174\r
175\r
176\r
177VOID\r
178WriteBootToOsPerformanceData (\r
179 VOID\r
180 )\r
181/*++\r
182\r
183Routine Description:\r
184\r
185 Allocates a block of memory and writes performance data of booting to OS into it.\r
186\r
187Arguments:\r
188\r
189 None\r
190\r
191Returns:\r
192\r
193 None\r
194\r
195--*/\r
196{\r
197 EFI_STATUS Status;\r
198 EFI_CPU_ARCH_PROTOCOL *Cpu;\r
199 EFI_PHYSICAL_ADDRESS mAcpiLowMemoryBase;\r
200 UINT32 mAcpiLowMemoryLength;\r
201 UINT32 LimitCount;\r
202 PERF_HEADER mPerfHeader;\r
203 PERF_DATA mPerfData;\r
204 EFI_HANDLE *Handles;\r
205 UINTN NoHandles;\r
206 CHAR8 GaugeString[PERF_TOKEN_LENGTH];\r
207 UINT8 *Ptr;\r
208 UINT32 mIndex;\r
209 UINT64 Ticker;\r
210 UINT64 Freq;\r
211 UINT32 Duration;\r
212 UINT64 CurrentTicker;\r
213 UINT64 TimerPeriod;\r
214 UINTN LogEntryKey;\r
215 CONST VOID *Handle;\r
216 CONST CHAR8 *Token;\r
217 CONST CHAR8 *Module;\r
218 UINT64 StartTicker;\r
219 UINT64 EndTicker;\r
220\r
221 //\r
222 // Retrive time stamp count as early as possilbe\r
223 //\r
224 Ticker = AsmReadTsc ();\r
225\r
226 //\r
227 // Allocate a block of memory that contain performance data to OS\r
228 //\r
229 mAcpiLowMemoryBase = 0xFFFFFFFF;\r
230 Status = gBS->AllocatePages (\r
231 AllocateMaxAddress,\r
232 EfiReservedMemoryType,\r
233 4,\r
234 &mAcpiLowMemoryBase\r
235 );\r
236 if (EFI_ERROR (Status)) {\r
237 return ;\r
238 }\r
239\r
240 mAcpiLowMemoryLength = EFI_PAGES_TO_SIZE(4);\r
241\r
242 Ptr = (UINT8 *) ((UINT32) mAcpiLowMemoryBase + sizeof (PERF_HEADER));\r
243 LimitCount = (mAcpiLowMemoryLength - sizeof (PERF_HEADER)) / sizeof (PERF_DATA);\r
244\r
245 //\r
246 // Initialize performance data structure\r
247 //\r
248 ZeroMem (&mPerfHeader, sizeof (PERF_HEADER));\r
249\r
250 //\r
251 // Get CPU frequency\r
252 //\r
253 Status = gBS->LocateProtocol (\r
254 &gEfiCpuArchProtocolGuid,\r
255 NULL,\r
256 &Cpu\r
257 );\r
258 if (EFI_ERROR (Status)) {\r
259 gBS->FreePages (mAcpiLowMemoryBase, 4);\r
260 return ;\r
261 }\r
262 //\r
263 // Get Cpu Frequency\r
264 //\r
265 Status = Cpu->GetTimerValue (Cpu, 0, &(CurrentTicker), &TimerPeriod);\r
266 if (EFI_ERROR (Status)) {\r
267 gBS->FreePages (mAcpiLowMemoryBase, 4);\r
268 return ;\r
269 }\r
270\r
271 Freq = DivU64x32 (1000000000000, (UINTN) TimerPeriod);\r
272\r
273 mPerfHeader.CpuFreq = Freq;\r
274\r
275 //\r
276 // Record BDS raw performance data\r
277 //\r
278 mPerfHeader.BDSRaw = Ticker;\r
279\r
280 //\r
281 // Put Detailed performance data into memory\r
282 //\r
283 Handles = NULL;\r
284 Status = gBS->LocateHandleBuffer (\r
285 AllHandles,\r
286 NULL,\r
287 NULL,\r
288 &NoHandles,\r
289 &Handles\r
290 );\r
291 if (EFI_ERROR (Status)) {\r
292 gBS->FreePages (mAcpiLowMemoryBase, 4);\r
293 return ;\r
294 }\r
295 //\r
296 // Get DXE drivers performance\r
297 //\r
298 for (mIndex = 0; mIndex < NoHandles; mIndex++) {\r
299 Ticker = 0;\r
300 LogEntryKey = 0;\r
301 while ((LogEntryKey = GetPerformanceMeasurement (\r
302 LogEntryKey,\r
303 &Handle,\r
304 &Token,\r
305 &Module,\r
306 &StartTicker,\r
307 &EndTicker)) != 0) {\r
308 if ((Handle == Handles[mIndex]) && (StartTicker < EndTicker)) {\r
309 Ticker += (EndTicker - StartTicker);\r
310 }\r
311 }\r
312\r
313 Duration = (UINT32) DivU64x32 (\r
314 Ticker,\r
315 (UINT32) Freq\r
316 );\r
317\r
318 if (Duration > 0) {\r
319 ZeroMem (&mPerfData, sizeof (PERF_DATA));\r
320\r
321 GetNameFromHandle (Handles[mIndex], GaugeString);\r
322\r
323 AsciiStrCpy (mPerfData.Token, GaugeString);\r
324 mPerfData.Duration = Duration;\r
325\r
326 CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));\r
327 Ptr += sizeof (PERF_DATA);\r
328\r
329 mPerfHeader.Count++;\r
330 if (mPerfHeader.Count == LimitCount) {\r
331 goto Done;\r
332 }\r
333 }\r
334 }\r
335\r
336 FreePool (Handles);\r
337\r
338 //\r
339 // Get inserted performance data\r
340 //\r
341 LogEntryKey = 0;\r
342 while ((LogEntryKey = GetPerformanceMeasurement (\r
343 LogEntryKey,\r
344 &Handle,\r
345 &Token,\r
346 &Module,\r
347 &StartTicker,\r
348 &EndTicker)) != 0) {\r
349 if ((Handle == NULL) && (StartTicker <= EndTicker)) {\r
350\r
351 ZeroMem (&mPerfData, sizeof (PERF_DATA));\r
352\r
353 AsciiStrnCpy (mPerfData.Token, Token, DXE_PERFORMANCE_STRING_SIZE);\r
354 mPerfData.Duration = (UINT32) DivU64x32 (\r
355 EndTicker - StartTicker,\r
356 (UINT32) Freq\r
357 );\r
358\r
359 CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));\r
360 Ptr += sizeof (PERF_DATA);\r
361\r
362 mPerfHeader.Count++;\r
363 if (mPerfHeader.Count == LimitCount) {\r
364 goto Done;\r
365 }\r
366 }\r
367 }\r
368\r
369Done:\r
370\r
371 mPerfHeader.Signiture = 0x66726550;\r
372\r
373 //\r
374 // Put performance data to memory\r
375 //\r
376 CopyMem (\r
377 (UINT32 *) (UINT32) mAcpiLowMemoryBase,\r
378 &mPerfHeader,\r
379 sizeof (PERF_HEADER)\r
380 );\r
381\r
382 gRT->SetVariable (\r
383 L"PerfDataMemAddr",\r
384 &gEfiGenericPlatformVariableGuid,\r
385 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
386 sizeof (UINT32),\r
387 (VOID *) &mAcpiLowMemoryBase\r
388 );\r
389\r
390 return ;\r
391}\r