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