]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/UefiBootManagerLib/BmPerformance.c
MdeModulePkg: Update UefiBootManagerLib to support HTTP boot option creation
[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 // Retrieve time stamp count as early as possible
190 //
191 Ticker = GetPerformanceCounter ();
192
193 Freq = GetPerformanceCounterProperties (&StartValue, &EndValue);
194
195 Freq = DivU64x32 (Freq, 1000);
196
197 mBmPerfHeader.CpuFreq = Freq;
198
199 //
200 // Record BDS raw performance data
201 //
202 if (EndValue >= StartValue) {
203 mBmPerfHeader.BDSRaw = Ticker - StartValue;
204 CountUp = TRUE;
205 } else {
206 mBmPerfHeader.BDSRaw = StartValue - Ticker;
207 CountUp = FALSE;
208 }
209
210 if (mBmAcpiLowMemoryBase == 0x0FFFFFFFF) {
211 VarSize = sizeof (EFI_PHYSICAL_ADDRESS);
212 Status = gRT->GetVariable (
213 L"PerfDataMemAddr",
214 &gPerformanceProtocolGuid,
215 NULL,
216 &VarSize,
217 &mBmAcpiLowMemoryBase
218 );
219 if (EFI_ERROR (Status)) {
220 //
221 // Fail to get the variable, return.
222 //
223 return;
224 }
225 }
226
227 //
228 // Put Detailed performance data into memory
229 //
230 Handles = NULL;
231 Status = gBS->LocateHandleBuffer (
232 AllHandles,
233 NULL,
234 NULL,
235 &NoHandles,
236 &Handles
237 );
238 if (EFI_ERROR (Status)) {
239 return ;
240 }
241
242 Ptr = (UINT8 *) ((UINT32) mBmAcpiLowMemoryBase + sizeof (PERF_HEADER));
243 LimitCount = (UINT32) (PERF_DATA_MAX_LENGTH - sizeof (PERF_HEADER)) / sizeof (PERF_DATA);
244
245 NumPerfEntries = 0;
246 LogEntryKey = 0;
247 while ((LogEntryKey = GetPerformanceMeasurement (
248 LogEntryKey,
249 &Handle,
250 &Token,
251 &Module,
252 &StartTicker,
253 &EndTicker)) != 0) {
254 NumPerfEntries++;
255 }
256 PerfEntriesAsDxeHandle = AllocateZeroPool (NumPerfEntries * sizeof (BOOLEAN));
257 ASSERT (PerfEntriesAsDxeHandle != NULL);
258
259 //
260 // Get DXE drivers performance
261 //
262 for (Index = 0; Index < NoHandles; Index++) {
263 Ticker = 0;
264 LogEntryKey = 0;
265 EntryIndex = 0;
266 while ((LogEntryKey = GetPerformanceMeasurement (
267 LogEntryKey,
268 &Handle,
269 &Token,
270 &Module,
271 &StartTicker,
272 &EndTicker)) != 0) {
273 if (Handle == Handles[Index] && !PerfEntriesAsDxeHandle[EntryIndex]) {
274 PerfEntriesAsDxeHandle[EntryIndex] = TRUE;
275 }
276 EntryIndex++;
277 if ((Handle == Handles[Index]) && (EndTicker != 0)) {
278 if (StartTicker == 1) {
279 StartTicker = StartValue;
280 }
281 if (EndTicker == 1) {
282 EndTicker = StartValue;
283 }
284 Ticker += CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);
285 }
286 }
287
288 Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);
289
290 if (Duration > 0) {
291
292 BmGetNameFromHandle (Handles[Index], GaugeString, PERF_TOKEN_LENGTH);
293
294 AsciiStrCpyS (mBmPerfData.Token, PERF_TOKEN_SIZE, GaugeString);
295 mBmPerfData.Duration = Duration;
296
297 CopyMem (Ptr, &mBmPerfData, sizeof (PERF_DATA));
298 Ptr += sizeof (PERF_DATA);
299
300 mBmPerfHeader.Count++;
301 if (mBmPerfHeader.Count == LimitCount) {
302 goto Done;
303 }
304 }
305 }
306
307 //
308 // Get inserted performance data
309 //
310 LogEntryKey = 0;
311 EntryIndex = 0;
312 while ((LogEntryKey = GetPerformanceMeasurement (
313 LogEntryKey,
314 &Handle,
315 &Token,
316 &Module,
317 &StartTicker,
318 &EndTicker)) != 0) {
319 if (!PerfEntriesAsDxeHandle[EntryIndex] && EndTicker != 0) {
320
321 ZeroMem (&mBmPerfData, sizeof (PERF_DATA));
322
323 AsciiStrnCpyS (mBmPerfData.Token, PERF_TOKEN_SIZE, Token, PERF_TOKEN_LENGTH);
324 if (StartTicker == 1) {
325 StartTicker = StartValue;
326 }
327 if (EndTicker == 1) {
328 EndTicker = StartValue;
329 }
330 Ticker = CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);
331
332 mBmPerfData.Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);
333
334 CopyMem (Ptr, &mBmPerfData, sizeof (PERF_DATA));
335 Ptr += sizeof (PERF_DATA);
336
337 mBmPerfHeader.Count++;
338 if (mBmPerfHeader.Count == LimitCount) {
339 goto Done;
340 }
341 }
342 EntryIndex++;
343 }
344
345 Done:
346
347 FreePool (Handles);
348 FreePool (PerfEntriesAsDxeHandle);
349
350 mBmPerfHeader.Signiture = PERFORMANCE_SIGNATURE;
351
352 //
353 // Put performance data to Reserved memory
354 //
355 CopyMem (
356 (UINTN *) (UINTN) mBmAcpiLowMemoryBase,
357 &mBmPerfHeader,
358 sizeof (PERF_HEADER)
359 );
360
361 return ;
362 }