]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/UefiBootManagerLib/BmPerformance.c
MdeModulePkg: Fix UefiBootManagerLib.inf license header.
[mirror_edk2.git] / MdeModulePkg / Library / UefiBootManagerLib / BmPerformance.c
CommitLineData
067ed98a
RN
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 - 2015, Intel Corporation. All rights reserved.<BR>\r
7This 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 "InternalBm.h"\r
18\r
19PERF_HEADER mBmPerfHeader;\r
20PERF_DATA mBmPerfData;\r
21EFI_PHYSICAL_ADDRESS mBmAcpiLowMemoryBase = 0x0FFFFFFFFULL;\r
22\r
23/**\r
24 Get the short verion of PDB file name to be\r
25 used in performance data logging.\r
26\r
27 @param PdbFileName The long PDB file name.\r
28 @param GaugeString The output string to be logged by performance logger.\r
b6344b37 29 @param StringSize The buffer size of GaugeString in bytes.\r
067ed98a
RN
30\r
31**/\r
32VOID\r
33BmGetShortPdbFileName (\r
34 IN CONST CHAR8 *PdbFileName,\r
b6344b37
QS
35 OUT CHAR8 *GaugeString,\r
36 IN UINTN StringSize\r
067ed98a
RN
37 )\r
38{\r
39 UINTN Index;\r
40 UINTN Index1;\r
41 UINTN StartIndex;\r
42 UINTN EndIndex;\r
43\r
44 if (PdbFileName == NULL) {\r
b6344b37 45 AsciiStrCpyS (GaugeString, StringSize, " ");\r
067ed98a
RN
46 } else {\r
47 StartIndex = 0;\r
48 for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++)\r
49 ;\r
50\r
51 for (Index = 0; PdbFileName[Index] != 0; Index++) {\r
52 if (PdbFileName[Index] == '\\') {\r
53 StartIndex = Index + 1;\r
54 }\r
55\r
56 if (PdbFileName[Index] == '.') {\r
57 EndIndex = Index;\r
58 }\r
59 }\r
60\r
61 Index1 = 0;\r
62 for (Index = StartIndex; Index < EndIndex; Index++) {\r
63 GaugeString[Index1] = PdbFileName[Index];\r
64 Index1++;\r
65 if (Index1 == PERF_TOKEN_LENGTH - 1) {\r
66 break;\r
67 }\r
68 }\r
69\r
70 GaugeString[Index1] = 0;\r
71 }\r
72\r
73 return ;\r
74}\r
75\r
76/**\r
77 Get the name from the Driver handle, which can be a handle with\r
78 EFI_LOADED_IMAGE_PROTOCOL or EFI_DRIVER_BINDING_PROTOCOL installed.\r
79 This name can be used in performance data logging.\r
80\r
81 @param Handle Driver handle.\r
82 @param GaugeString The output string to be logged by performance logger.\r
b6344b37 83 @param StringSize The buffer size of GaugeString in bytes.\r
067ed98a
RN
84\r
85**/\r
86VOID\r
87BmGetNameFromHandle (\r
88 IN EFI_HANDLE Handle,\r
b6344b37
QS
89 OUT CHAR8 *GaugeString,\r
90 IN UINTN StringSize\r
067ed98a
RN
91 )\r
92{\r
93 EFI_STATUS Status;\r
94 EFI_LOADED_IMAGE_PROTOCOL *Image;\r
95 CHAR8 *PdbFileName;\r
96 EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;\r
97\r
b6344b37 98 AsciiStrCpyS (GaugeString, StringSize, " ");\r
067ed98a
RN
99\r
100 //\r
101 // Get handle name from image protocol\r
102 //\r
103 Status = gBS->HandleProtocol (\r
104 Handle,\r
105 &gEfiLoadedImageProtocolGuid,\r
106 (VOID **) &Image\r
107 );\r
108\r
109 if (EFI_ERROR (Status)) {\r
110 Status = gBS->OpenProtocol (\r
111 Handle,\r
112 &gEfiDriverBindingProtocolGuid,\r
113 (VOID **) &DriverBinding,\r
114 NULL,\r
115 NULL,\r
116 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
117 );\r
118 if (EFI_ERROR (Status)) {\r
119 return ;\r
120 }\r
121 //\r
122 // Get handle name from image protocol\r
123 //\r
124 Status = gBS->HandleProtocol (\r
125 DriverBinding->ImageHandle,\r
126 &gEfiLoadedImageProtocolGuid,\r
127 (VOID **) &Image\r
128 );\r
129 }\r
130\r
131 PdbFileName = PeCoffLoaderGetPdbPointer (Image->ImageBase);\r
132\r
133 if (PdbFileName != NULL) {\r
b6344b37 134 BmGetShortPdbFileName (PdbFileName, GaugeString, StringSize);\r
067ed98a
RN
135 }\r
136\r
137 return ;\r
138}\r
139\r
140/**\r
141\r
142 Writes performance data of booting into the allocated memory.\r
143 OS can process these records.\r
144\r
145 @param Event The triggered event.\r
146 @param Context Context for this event.\r
147\r
148**/\r
149VOID\r
150EFIAPI\r
151BmWriteBootToOsPerformanceData (\r
152 IN EFI_EVENT Event,\r
153 IN VOID *Context\r
154 )\r
155{\r
156 EFI_STATUS Status;\r
157 UINT32 LimitCount;\r
158 EFI_HANDLE *Handles;\r
159 UINTN NoHandles;\r
160 CHAR8 GaugeString[PERF_TOKEN_LENGTH];\r
161 UINT8 *Ptr;\r
162 UINT32 Index;\r
163 UINT64 Ticker;\r
164 UINT64 Freq;\r
165 UINT32 Duration;\r
166 UINTN LogEntryKey;\r
167 CONST VOID *Handle;\r
168 CONST CHAR8 *Token;\r
169 CONST CHAR8 *Module;\r
170 UINT64 StartTicker;\r
171 UINT64 EndTicker;\r
172 UINT64 StartValue;\r
173 UINT64 EndValue;\r
174 BOOLEAN CountUp;\r
175 UINTN EntryIndex;\r
176 UINTN NumPerfEntries;\r
177 //\r
178 // List of flags indicating PerfEntry contains DXE handle\r
179 //\r
180 BOOLEAN *PerfEntriesAsDxeHandle;\r
181 UINTN VarSize;\r
182\r
183 //\r
184 // Record the performance data for End of BDS\r
185 //\r
186 PERF_END(NULL, "BDS", NULL, 0);\r
187\r
188 //\r
189 // Retrieve time stamp count as early as possible\r
190 //\r
191 Ticker = GetPerformanceCounter ();\r
192\r
193 Freq = GetPerformanceCounterProperties (&StartValue, &EndValue);\r
194 \r
195 Freq = DivU64x32 (Freq, 1000);\r
196\r
197 mBmPerfHeader.CpuFreq = Freq;\r
198\r
199 //\r
200 // Record BDS raw performance data\r
201 //\r
202 if (EndValue >= StartValue) {\r
203 mBmPerfHeader.BDSRaw = Ticker - StartValue;\r
204 CountUp = TRUE;\r
205 } else {\r
206 mBmPerfHeader.BDSRaw = StartValue - Ticker;\r
207 CountUp = FALSE;\r
208 }\r
209\r
210 if (mBmAcpiLowMemoryBase == 0x0FFFFFFFF) {\r
211 VarSize = sizeof (EFI_PHYSICAL_ADDRESS);\r
212 Status = gRT->GetVariable (\r
213 L"PerfDataMemAddr",\r
214 &gPerformanceProtocolGuid,\r
215 NULL,\r
216 &VarSize,\r
217 &mBmAcpiLowMemoryBase\r
218 );\r
219 if (EFI_ERROR (Status)) {\r
220 //\r
221 // Fail to get the variable, return.\r
222 //\r
223 return;\r
224 }\r
225 }\r
226\r
227 //\r
228 // Put Detailed performance data into memory\r
229 //\r
230 Handles = NULL;\r
231 Status = gBS->LocateHandleBuffer (\r
232 AllHandles,\r
233 NULL,\r
234 NULL,\r
235 &NoHandles,\r
236 &Handles\r
237 );\r
238 if (EFI_ERROR (Status)) {\r
239 return ;\r
240 }\r
241\r
242 Ptr = (UINT8 *) ((UINT32) mBmAcpiLowMemoryBase + sizeof (PERF_HEADER));\r
243 LimitCount = (UINT32) (PERF_DATA_MAX_LENGTH - sizeof (PERF_HEADER)) / sizeof (PERF_DATA);\r
244\r
245 NumPerfEntries = 0;\r
246 LogEntryKey = 0;\r
247 while ((LogEntryKey = GetPerformanceMeasurement (\r
248 LogEntryKey,\r
249 &Handle,\r
250 &Token,\r
251 &Module,\r
252 &StartTicker,\r
253 &EndTicker)) != 0) {\r
254 NumPerfEntries++;\r
255 }\r
256 PerfEntriesAsDxeHandle = AllocateZeroPool (NumPerfEntries * sizeof (BOOLEAN));\r
257 ASSERT (PerfEntriesAsDxeHandle != NULL);\r
258 \r
259 //\r
260 // Get DXE drivers performance\r
261 //\r
262 for (Index = 0; Index < NoHandles; Index++) {\r
263 Ticker = 0;\r
264 LogEntryKey = 0;\r
265 EntryIndex = 0;\r
266 while ((LogEntryKey = GetPerformanceMeasurement (\r
267 LogEntryKey,\r
268 &Handle,\r
269 &Token,\r
270 &Module,\r
271 &StartTicker,\r
272 &EndTicker)) != 0) {\r
273 if (Handle == Handles[Index] && !PerfEntriesAsDxeHandle[EntryIndex]) {\r
274 PerfEntriesAsDxeHandle[EntryIndex] = TRUE;\r
275 }\r
276 EntryIndex++;\r
277 if ((Handle == Handles[Index]) && (EndTicker != 0)) {\r
278 if (StartTicker == 1) {\r
279 StartTicker = StartValue;\r
280 }\r
281 if (EndTicker == 1) {\r
282 EndTicker = StartValue;\r
283 }\r
284 Ticker += CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);\r
285 }\r
286 }\r
287\r
288 Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);\r
289\r
290 if (Duration > 0) {\r
291\r
b6344b37 292 BmGetNameFromHandle (Handles[Index], GaugeString, PERF_TOKEN_LENGTH);\r
067ed98a 293\r
b6344b37 294 AsciiStrCpyS (mBmPerfData.Token, PERF_TOKEN_SIZE, GaugeString);\r
067ed98a
RN
295 mBmPerfData.Duration = Duration;\r
296\r
297 CopyMem (Ptr, &mBmPerfData, sizeof (PERF_DATA));\r
298 Ptr += sizeof (PERF_DATA);\r
299\r
300 mBmPerfHeader.Count++;\r
301 if (mBmPerfHeader.Count == LimitCount) {\r
302 goto Done;\r
303 }\r
304 }\r
305 }\r
306\r
307 //\r
308 // Get inserted performance data\r
309 //\r
310 LogEntryKey = 0;\r
311 EntryIndex = 0;\r
312 while ((LogEntryKey = GetPerformanceMeasurement (\r
313 LogEntryKey,\r
314 &Handle,\r
315 &Token,\r
316 &Module,\r
317 &StartTicker,\r
318 &EndTicker)) != 0) {\r
319 if (!PerfEntriesAsDxeHandle[EntryIndex] && EndTicker != 0) {\r
320\r
321 ZeroMem (&mBmPerfData, sizeof (PERF_DATA));\r
322\r
0ec2bfc8 323 AsciiStrnCpyS (mBmPerfData.Token, PERF_TOKEN_SIZE, Token, PERF_TOKEN_LENGTH);\r
067ed98a
RN
324 if (StartTicker == 1) {\r
325 StartTicker = StartValue;\r
326 }\r
327 if (EndTicker == 1) {\r
328 EndTicker = StartValue;\r
329 }\r
330 Ticker = CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);\r
331\r
332 mBmPerfData.Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);\r
333\r
334 CopyMem (Ptr, &mBmPerfData, sizeof (PERF_DATA));\r
335 Ptr += sizeof (PERF_DATA);\r
336\r
337 mBmPerfHeader.Count++;\r
338 if (mBmPerfHeader.Count == LimitCount) {\r
339 goto Done;\r
340 }\r
341 }\r
342 EntryIndex++;\r
343 }\r
344\r
345Done:\r
346\r
347 FreePool (Handles);\r
348 FreePool (PerfEntriesAsDxeHandle);\r
349\r
350 mBmPerfHeader.Signiture = PERFORMANCE_SIGNATURE;\r
351\r
352 //\r
353 // Put performance data to Reserved memory\r
354 //\r
355 CopyMem (\r
356 (UINTN *) (UINTN) mBmAcpiLowMemoryBase,\r
357 &mBmPerfHeader,\r
358 sizeof (PERF_HEADER)\r
359 );\r
360\r
361 return ;\r
362}\r