]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/UefiBootManagerLib/BmPerformance.c
MdeModulePkg UefiBootManagerLib: Do not assume perf entry count has no change
[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
2f931dda 65 if (Index1 == StringSize - 1) {\r
067ed98a
RN
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
2f931dda 160 CHAR8 GaugeString[PERF_TOKEN_SIZE];\r
067ed98a
RN
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
067ed98a 175 UINTN VarSize;\r
2f931dda 176 BOOLEAN Found;\r
067ed98a
RN
177\r
178 //\r
179 // Record the performance data for End of BDS\r
180 //\r
181 PERF_END(NULL, "BDS", NULL, 0);\r
182\r
183 //\r
184 // Retrieve time stamp count as early as possible\r
185 //\r
186 Ticker = GetPerformanceCounter ();\r
187\r
188 Freq = GetPerformanceCounterProperties (&StartValue, &EndValue);\r
189 \r
190 Freq = DivU64x32 (Freq, 1000);\r
191\r
192 mBmPerfHeader.CpuFreq = Freq;\r
193\r
194 //\r
195 // Record BDS raw performance data\r
196 //\r
197 if (EndValue >= StartValue) {\r
198 mBmPerfHeader.BDSRaw = Ticker - StartValue;\r
199 CountUp = TRUE;\r
200 } else {\r
201 mBmPerfHeader.BDSRaw = StartValue - Ticker;\r
202 CountUp = FALSE;\r
203 }\r
204\r
2f931dda
SZ
205 //\r
206 // Reset the entry count\r
207 //\r
208 mBmPerfHeader.Count = 0;\r
209\r
067ed98a
RN
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
067ed98a 245 //\r
2f931dda 246 // Get performance data\r
067ed98a
RN
247 //\r
248 LogEntryKey = 0;\r
067ed98a
RN
249 while ((LogEntryKey = GetPerformanceMeasurement (\r
250 LogEntryKey,\r
251 &Handle,\r
252 &Token,\r
253 &Module,\r
254 &StartTicker,\r
255 &EndTicker)) != 0) {\r
2f931dda 256 if (EndTicker != 0) {\r
067ed98a
RN
257 if (StartTicker == 1) {\r
258 StartTicker = StartValue;\r
259 }\r
260 if (EndTicker == 1) {\r
261 EndTicker = StartValue;\r
262 }\r
263 Ticker = CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);\r
264\r
2f931dda
SZ
265 Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);\r
266 if (Duration == 0) {\r
267 continue;\r
268 }\r
269\r
270 ZeroMem (&mBmPerfData, sizeof (PERF_DATA));\r
271\r
272 mBmPerfData.Duration = Duration;\r
273\r
274 //\r
275 // See if the Handle is in the handle buffer\r
276 //\r
277 Found = FALSE;\r
278 for (Index = 0; Index < NoHandles; Index++) {\r
279 if (Handle == Handles[Index]) {\r
280 BmGetNameFromHandle (Handles[Index], GaugeString, PERF_TOKEN_SIZE);\r
281 AsciiStrCpyS (mBmPerfData.Token, PERF_TOKEN_SIZE, GaugeString);\r
282 Found = TRUE;\r
283 break;\r
284 }\r
285 }\r
286\r
287 if (!Found) {\r
288 AsciiStrnCpyS (mBmPerfData.Token, PERF_TOKEN_SIZE, Token, PERF_TOKEN_LENGTH);\r
289 }\r
067ed98a
RN
290\r
291 CopyMem (Ptr, &mBmPerfData, sizeof (PERF_DATA));\r
292 Ptr += sizeof (PERF_DATA);\r
293\r
294 mBmPerfHeader.Count++;\r
295 if (mBmPerfHeader.Count == LimitCount) {\r
296 goto Done;\r
297 }\r
298 }\r
067ed98a
RN
299 }\r
300\r
301Done:\r
302\r
303 FreePool (Handles);\r
067ed98a
RN
304\r
305 mBmPerfHeader.Signiture = PERFORMANCE_SIGNATURE;\r
306\r
307 //\r
308 // Put performance data to Reserved memory\r
309 //\r
310 CopyMem (\r
311 (UINTN *) (UINTN) mBmAcpiLowMemoryBase,\r
312 &mBmPerfHeader,\r
313 sizeof (PERF_HEADER)\r
314 );\r
315\r
316 return ;\r
317}\r