]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/GenericBdsLib/Performance.c
UEFI HII: Merge UEFI HII support changes from branch.
[mirror_edk2.git] / MdeModulePkg / Library / GenericBdsLib / Performance.c
1 /** @file
2
3 Copyright (c) 2004 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 Performance.c
15
16 Abstract:
17
18 This file include the file which can help to get the system
19 performance, all the function will only include if the performance
20 switch is set.
21
22
23 **/
24
25 #include "InternalBdsLib.h"
26
27 STATIC PERF_HEADER mPerfHeader;
28 STATIC PERF_DATA mPerfData;
29
30 STATIC
31 VOID
32 GetShortPdbFileName (
33 CHAR8 *PdbFileName,
34 CHAR8 *GaugeString
35 )
36 /*++
37
38 Routine Description:
39
40 Arguments:
41
42 Returns:
43
44 --*/
45 {
46 UINTN Index;
47 UINTN Index1;
48 UINTN StartIndex;
49 UINTN EndIndex;
50
51 if (PdbFileName == NULL) {
52 AsciiStrCpy (GaugeString, " ");
53 } else {
54 StartIndex = 0;
55 for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++)
56 ;
57
58 for (Index = 0; PdbFileName[Index] != 0; Index++) {
59 if (PdbFileName[Index] == '\\') {
60 StartIndex = Index + 1;
61 }
62
63 if (PdbFileName[Index] == '.') {
64 EndIndex = Index;
65 }
66 }
67
68 Index1 = 0;
69 for (Index = StartIndex; Index < EndIndex; Index++) {
70 GaugeString[Index1] = PdbFileName[Index];
71 Index1++;
72 if (Index1 == PERF_TOKEN_LENGTH - 1) {
73 break;
74 }
75 }
76
77 GaugeString[Index1] = 0;
78 }
79
80 return ;
81 }
82
83 STATIC
84 VOID
85 GetNameFromHandle (
86 IN EFI_HANDLE Handle,
87 OUT CHAR8 *GaugeString
88 )
89 {
90 EFI_STATUS Status;
91 EFI_LOADED_IMAGE_PROTOCOL *Image;
92 CHAR8 *PdbFileName;
93 EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
94
95 AsciiStrCpy (GaugeString, " ");
96
97 //
98 // Get handle name from image protocol
99 //
100 Status = gBS->HandleProtocol (
101 Handle,
102 &gEfiLoadedImageProtocolGuid,
103 (VOID **) &Image
104 );
105
106 if (EFI_ERROR (Status)) {
107 Status = gBS->OpenProtocol (
108 Handle,
109 &gEfiDriverBindingProtocolGuid,
110 (VOID **) &DriverBinding,
111 NULL,
112 NULL,
113 EFI_OPEN_PROTOCOL_GET_PROTOCOL
114 );
115 if (EFI_ERROR (Status)) {
116 return ;
117 }
118 //
119 // Get handle name from image protocol
120 //
121 Status = gBS->HandleProtocol (
122 DriverBinding->ImageHandle,
123 &gEfiLoadedImageProtocolGuid,
124 (VOID **) &Image
125 );
126 }
127
128 PdbFileName = PeCoffLoaderGetPdbPointer (Image->ImageBase);
129
130 if (PdbFileName != NULL) {
131 GetShortPdbFileName (PdbFileName, GaugeString);
132 }
133
134 return ;
135 }
136
137 VOID
138 WriteBootToOsPerformanceData (
139 VOID
140 )
141 /*++
142
143 Routine Description:
144
145 Allocates a block of memory and writes performance data of booting to OS into it.
146
147 Arguments:
148
149 None
150
151 Returns:
152
153 None
154
155 --*/
156 {
157 EFI_STATUS Status;
158 EFI_PHYSICAL_ADDRESS AcpiLowMemoryBase;
159 UINT32 AcpiLowMemoryLength;
160 UINT32 LimitCount;
161 EFI_HANDLE *Handles;
162 UINTN NoHandles;
163 CHAR8 GaugeString[PERF_TOKEN_LENGTH];
164 UINT8 *Ptr;
165 UINT32 Index;
166 UINT64 Ticker;
167 UINT64 Freq;
168 UINT32 Duration;
169 UINTN LogEntryKey;
170 CONST VOID *Handle;
171 CONST CHAR8 *Token;
172 CONST CHAR8 *Module;
173 UINT64 StartTicker;
174 UINT64 EndTicker;
175 UINT64 StartValue;
176 UINT64 EndValue;
177 BOOLEAN CountUp;
178
179 //
180 // Retrive time stamp count as early as possilbe
181 //
182 Ticker = GetPerformanceCounter ();
183
184 Freq = GetPerformanceCounterProperties (&StartValue, &EndValue);
185
186 Freq = DivU64x32 (Freq, 1000);
187
188 mPerfHeader.CpuFreq = Freq;
189
190 //
191 // Record BDS raw performance data
192 //
193 if (EndValue >= StartValue) {
194 mPerfHeader.BDSRaw = Ticker - StartValue;
195 CountUp = TRUE;
196 } else {
197 mPerfHeader.BDSRaw = StartValue - Ticker;
198 CountUp = FALSE;
199 }
200
201 AcpiLowMemoryLength = 0x2000;
202
203 //
204 // Allocate a block of memory that contain performance data to OS
205 //
206 Status = gBS->AllocatePages (
207 AllocateAnyPages,
208 EfiACPIReclaimMemory,
209 EFI_SIZE_TO_PAGES (AcpiLowMemoryLength),
210 &AcpiLowMemoryBase
211 );
212 if (EFI_ERROR (Status)) {
213 return ;
214 }
215
216
217 Ptr = (UINT8 *) ((UINT32) AcpiLowMemoryBase + sizeof (PERF_HEADER));
218 LimitCount = (AcpiLowMemoryLength - sizeof (PERF_HEADER)) / sizeof (PERF_DATA);
219
220 //
221 // Put Detailed performance data into memory
222 //
223 Handles = NULL;
224 Status = gBS->LocateHandleBuffer (
225 AllHandles,
226 NULL,
227 NULL,
228 &NoHandles,
229 &Handles
230 );
231 if (EFI_ERROR (Status)) {
232 gBS->FreePages (AcpiLowMemoryBase, 1);
233 return ;
234 }
235 //
236 // Get DXE drivers performance
237 //
238 for (Index = 0; Index < NoHandles; Index++) {
239 Ticker = 0;
240 LogEntryKey = 0;
241 while ((LogEntryKey = GetPerformanceMeasurement (
242 LogEntryKey,
243 &Handle,
244 &Token,
245 &Module,
246 &StartTicker,
247 &EndTicker)) != 0) {
248 if ((Handle == Handles[Index]) && (EndTicker != 0)) {
249 Ticker += CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);
250 }
251 }
252
253 Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);
254
255 if (Duration > 0) {
256
257 GetNameFromHandle (Handles[Index], GaugeString);
258
259 AsciiStrCpy (mPerfData.Token, GaugeString);
260 mPerfData.Duration = Duration;
261
262 CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));
263 Ptr += sizeof (PERF_DATA);
264
265 mPerfHeader.Count++;
266 if (mPerfHeader.Count == LimitCount) {
267 goto Done;
268 }
269 }
270 }
271
272 FreePool (Handles);
273
274 //
275 // Get inserted performance data
276 //
277 LogEntryKey = 0;
278 while ((LogEntryKey = GetPerformanceMeasurement (
279 LogEntryKey,
280 &Handle,
281 &Token,
282 &Module,
283 &StartTicker,
284 &EndTicker)) != 0) {
285 if (Handle == NULL && EndTicker != 0) {
286
287 ZeroMem (&mPerfData, sizeof (PERF_DATA));
288
289 AsciiStrnCpy (mPerfData.Token, Token, PERF_TOKEN_LENGTH);
290 Ticker = CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);
291
292 mPerfData.Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);
293
294 CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));
295 Ptr += sizeof (PERF_DATA);
296
297 mPerfHeader.Count++;
298 if (mPerfHeader.Count == LimitCount) {
299 goto Done;
300 }
301 }
302 }
303
304 Done:
305
306 mPerfHeader.Signiture = PERFORMANCE_SIGNATURE;
307
308 //
309 // Put performance data to memory
310 //
311 CopyMem (
312 (UINTN *) (UINTN) AcpiLowMemoryBase,
313 &mPerfHeader,
314 sizeof (PERF_HEADER)
315 );
316
317 gRT->SetVariable (
318 L"PerfDataMemAddr",
319 &gEfiGenericPlatformVariableGuid,
320 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
321 sizeof (EFI_PHYSICAL_ADDRESS),
322 &AcpiLowMemoryBase
323 );
324
325 return ;
326 }