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