]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/DynamicCommand/DpDynamicCommand/DpUtilities.c
ShellPkg: Change use of EFI_D_* to DEBUG_*
[mirror_edk2.git] / ShellPkg / DynamicCommand / DpDynamicCommand / DpUtilities.c
CommitLineData
d41bc92c 1/** @file\r
2 Utility functions used by the Dp application.\r
3\r
115eae65 4 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.\r
69af8476 5 (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR>\r
56ba3746 6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
d41bc92c 7**/\r
8\r
9#include <Library/BaseLib.h>\r
10#include <Library/BaseMemoryLib.h>\r
11#include <Library/MemoryAllocationLib.h>\r
12#include <Library/DebugLib.h>\r
13#include <Library/UefiBootServicesTableLib.h>\r
d41bc92c 14#include <Library/PeCoffGetEntryPointLib.h>\r
15#include <Library/PrintLib.h>\r
16#include <Library/HiiLib.h>\r
17#include <Library/PcdLib.h>\r
18#include <Library/UefiLib.h>\r
19#include <Library/DevicePathLib.h>\r
a71003f2 20#include <Library/HandleParsingLib.h>\r
d41bc92c 21\r
22#include <Pi/PiFirmwareFile.h>\r
23#include <Library/DxeServicesLib.h>\r
24\r
25#include <Protocol/LoadedImage.h>\r
26#include <Protocol/DriverBinding.h>\r
27#include <Protocol/ComponentName2.h>\r
28#include <Protocol/DevicePath.h>\r
d41bc92c 29\r
30#include <Guid/Performance.h>\r
31\r
32#include "Dp.h"\r
33#include "Literals.h"\r
34#include "DpInternal.h"\r
35\r
ba0014b9 36/**\r
d41bc92c 37 Calculate an event's duration in timer ticks.\r
ba0014b9 38\r
d41bc92c 39 Given the count direction and the event's start and end timer values,\r
40 calculate the duration of the event in timer ticks. Information for\r
41 the current measurement is pointed to by the parameter.\r
ba0014b9 42\r
d41bc92c 43 If the measurement's start time is 1, it indicates that the developer\r
44 is indicating that the measurement began at the release of reset.\r
45 The start time is adjusted to the timer's starting count before performing\r
46 the elapsed time calculation.\r
ba0014b9 47\r
d41bc92c 48 The calculated duration, in ticks, is the absolute difference between\r
49 the measurement's ending and starting counts.\r
ba0014b9 50\r
d41bc92c 51 @param Measurement Pointer to a MEASUREMENT_RECORD structure containing\r
52 data for the current measurement.\r
ba0014b9 53\r
d41bc92c 54 @return The 64-bit duration of the event.\r
55**/\r
56UINT64\r
57GetDuration (\r
58 IN OUT MEASUREMENT_RECORD *Measurement\r
59 )\r
60{\r
61 UINT64 Duration;\r
62 BOOLEAN Error;\r
63\r
69af8476
CS
64 if (Measurement->EndTimeStamp == 0) {\r
65 return 0;\r
66 }\r
67\r
115eae65
DB
68 Duration = Measurement->EndTimeStamp - Measurement->StartTimeStamp;\r
69 Error = (BOOLEAN)(Duration > Measurement->EndTimeStamp);\r
d41bc92c 70\r
71 if (Error) {\r
4a1aee13 72 DEBUG ((DEBUG_ERROR, ALit_TimerLibError));\r
d41bc92c 73 Duration = 0;\r
74 }\r
75 return Duration;\r
76}\r
77\r
ba0014b9 78/**\r
d41bc92c 79 Determine whether the Measurement record is for an EFI Phase.\r
ba0014b9 80\r
d41bc92c 81 The Token and Module members of the measurement record are checked.\r
82 Module must be empty and Token must be one of SEC, PEI, DXE, BDS, or SHELL.\r
ba0014b9 83\r
d41bc92c 84 @param[in] Measurement A pointer to the Measurement record to test.\r
ba0014b9 85\r
d41bc92c 86 @retval TRUE The measurement record is for an EFI Phase.\r
87 @retval FALSE The measurement record is NOT for an EFI Phase.\r
88**/\r
89BOOLEAN\r
90IsPhase(\r
91 IN MEASUREMENT_RECORD *Measurement\r
92 )\r
93{\r
94 BOOLEAN RetVal;\r
95\r
115eae65
DB
96 RetVal = (BOOLEAN)(\r
97 ((AsciiStrCmp (Measurement->Token, ALit_SEC) == 0) ||\r
98 (AsciiStrCmp (Measurement->Token, ALit_PEI) == 0) ||\r
99 (AsciiStrCmp (Measurement->Token, ALit_DXE) == 0) ||\r
100 (AsciiStrCmp (Measurement->Token, ALit_BDS) == 0))\r
d41bc92c 101 );\r
102 return RetVal;\r
103}\r
104\r
f45dd2dd
BD
105/**\r
106 Determine whether the Measurement record is for core code.\r
107\r
108 @param[in] Measurement A pointer to the Measurement record to test.\r
109\r
110 @retval TRUE The measurement record is used for core.\r
111 @retval FALSE The measurement record is NOT used for core.\r
112\r
113**/\r
114BOOLEAN\r
115IsCorePerf(\r
116 IN MEASUREMENT_RECORD *Measurement\r
117 )\r
118{\r
119 BOOLEAN RetVal;\r
120\r
121 RetVal = (BOOLEAN)(\r
122 ((Measurement->Identifier == MODULE_START_ID) ||\r
123 (Measurement->Identifier == MODULE_END_ID) ||\r
124 (Measurement->Identifier == MODULE_LOADIMAGE_START_ID) ||\r
125 (Measurement->Identifier == MODULE_LOADIMAGE_END_ID) ||\r
126 (Measurement->Identifier == MODULE_DB_START_ID) ||\r
127 (Measurement->Identifier == MODULE_DB_END_ID) ||\r
128 (Measurement->Identifier == MODULE_DB_SUPPORT_START_ID) ||\r
129 (Measurement->Identifier == MODULE_DB_SUPPORT_END_ID) ||\r
130 (Measurement->Identifier == MODULE_DB_STOP_START_ID) ||\r
131 (Measurement->Identifier == MODULE_DB_STOP_START_ID))\r
132 );\r
133 return RetVal;\r
134}\r
135\r
ba0014b9 136/**\r
d41bc92c 137 Get the file name portion of the Pdb File Name.\r
ba0014b9 138\r
d41bc92c 139 The portion of the Pdb File Name between the last backslash and\r
140 either a following period or the end of the string is converted\r
141 to Unicode and copied into UnicodeBuffer. The name is truncated,\r
142 if necessary, to ensure that UnicodeBuffer is not overrun.\r
ba0014b9 143\r
d41bc92c 144 @param[in] PdbFileName Pdb file name.\r
145 @param[out] UnicodeBuffer The resultant Unicode File Name.\r
ba0014b9 146\r
d41bc92c 147**/\r
148VOID\r
2c55a81a 149DpGetShortPdbFileName (\r
d41bc92c 150 IN CHAR8 *PdbFileName,\r
151 OUT CHAR16 *UnicodeBuffer\r
152 )\r
153{\r
154 UINTN IndexA; // Current work location within an ASCII string.\r
155 UINTN IndexU; // Current work location within a Unicode string.\r
156 UINTN StartIndex;\r
157 UINTN EndIndex;\r
158\r
e75390f0 159 ZeroMem (UnicodeBuffer, (DP_GAUGE_STRING_LENGTH + 1) * sizeof (CHAR16));\r
d41bc92c 160\r
161 if (PdbFileName == NULL) {\r
e75390f0 162 StrnCpyS (UnicodeBuffer, DP_GAUGE_STRING_LENGTH + 1, L" ", 1);\r
d41bc92c 163 } else {\r
164 StartIndex = 0;\r
165 for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++)\r
166 ;\r
167 for (IndexA = 0; PdbFileName[IndexA] != 0; IndexA++) {\r
9248d551 168 if ((PdbFileName[IndexA] == '\\') || (PdbFileName[IndexA] == '/')) {\r
d41bc92c 169 StartIndex = IndexA + 1;\r
170 }\r
171\r
172 if (PdbFileName[IndexA] == '.') {\r
173 EndIndex = IndexA;\r
174 }\r
175 }\r
176\r
177 IndexU = 0;\r
178 for (IndexA = StartIndex; IndexA < EndIndex; IndexA++) {\r
179 UnicodeBuffer[IndexU] = (CHAR16) PdbFileName[IndexA];\r
180 IndexU++;\r
b9ffeab7
SZ
181 if (IndexU >= DP_GAUGE_STRING_LENGTH) {\r
182 UnicodeBuffer[DP_GAUGE_STRING_LENGTH] = 0;\r
d41bc92c 183 break;\r
184 }\r
185 }\r
186 }\r
187}\r
188\r
ba0014b9 189/**\r
d41bc92c 190 Get a human readable name for an image handle.\r
191 The following methods will be tried orderly:\r
192 1. Image PDB\r
193 2. ComponentName2 protocol\r
194 3. FFS UI section\r
195 4. Image GUID\r
196 5. Image DevicePath\r
197 6. Unknown Driver Name\r
198\r
199 @param[in] Handle\r
200\r
201 @post The resulting Unicode name string is stored in the\r
202 mGaugeString global array.\r
203\r
204**/\r
205VOID\r
2c55a81a 206DpGetNameFromHandle (\r
d41bc92c 207 IN EFI_HANDLE Handle\r
208 )\r
209{\r
92034c4c
RN
210 EFI_STATUS Status;\r
211 EFI_LOADED_IMAGE_PROTOCOL *Image;\r
212 CHAR8 *PdbFileName;\r
213 EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;\r
214 EFI_STRING StringPtr;\r
215 EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath;\r
216 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
217 EFI_GUID *NameGuid;\r
218 CHAR16 *NameString;\r
219 UINTN StringSize;\r
220 CHAR8 *PlatformLanguage;\r
221 CHAR8 *BestLanguage;\r
222 EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2;\r
d41bc92c 223\r
3b672240
SZ
224 Image = NULL;\r
225 LoadedImageDevicePath = NULL;\r
226 DevicePath = NULL;\r
227\r
d41bc92c 228 //\r
229 // Method 1: Get the name string from image PDB\r
230 //\r
231 Status = gBS->HandleProtocol (\r
232 Handle,\r
233 &gEfiLoadedImageProtocolGuid,\r
234 (VOID **) &Image\r
235 );\r
236\r
237 if (EFI_ERROR (Status)) {\r
238 Status = gBS->OpenProtocol (\r
239 Handle,\r
240 &gEfiDriverBindingProtocolGuid,\r
241 (VOID **) &DriverBinding,\r
242 NULL,\r
243 NULL,\r
244 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
245 );\r
246 if (!EFI_ERROR (Status)) {\r
247 Status = gBS->HandleProtocol (\r
248 DriverBinding->ImageHandle,\r
249 &gEfiLoadedImageProtocolGuid,\r
250 (VOID **) &Image\r
251 );\r
252 }\r
253 }\r
254\r
255 if (!EFI_ERROR (Status)) {\r
256 PdbFileName = PeCoffLoaderGetPdbPointer (Image->ImageBase);\r
257\r
258 if (PdbFileName != NULL) {\r
2c55a81a 259 DpGetShortPdbFileName (PdbFileName, mGaugeString);\r
d41bc92c 260 return;\r
261 }\r
262 }\r
263\r
264 //\r
265 // Method 2: Get the name string from ComponentName2 protocol\r
266 //\r
267 Status = gBS->HandleProtocol (\r
268 Handle,\r
269 &gEfiComponentName2ProtocolGuid,\r
270 (VOID **) &ComponentName2\r
271 );\r
272 if (!EFI_ERROR (Status)) {\r
273 //\r
92034c4c 274 // Firstly use platform language setting, secondly use driver's first supported language.\r
d41bc92c 275 //\r
92034c4c
RN
276 GetVariable2 (L"PlatformLang", &gEfiGlobalVariableGuid, (VOID**)&PlatformLanguage, NULL);\r
277 BestLanguage = GetBestLanguage(\r
278 ComponentName2->SupportedLanguages,\r
279 FALSE,\r
280 (PlatformLanguage != NULL) ? PlatformLanguage : "",\r
281 ComponentName2->SupportedLanguages,\r
282 NULL\r
283 );\r
284 SHELL_FREE_NON_NULL (PlatformLanguage);\r
285\r
d41bc92c 286 Status = ComponentName2->GetDriverName (\r
287 ComponentName2,\r
92034c4c 288 BestLanguage != NULL ? BestLanguage : "en-US",\r
d41bc92c 289 &StringPtr\r
290 );\r
291 if (!EFI_ERROR (Status)) {\r
92034c4c 292 SHELL_FREE_NON_NULL (BestLanguage);\r
4dc0d578 293 StrnCpyS (mGaugeString, DP_GAUGE_STRING_LENGTH + 1, StringPtr, DP_GAUGE_STRING_LENGTH);\r
d41bc92c 294 mGaugeString[DP_GAUGE_STRING_LENGTH] = 0;\r
295 return;\r
296 }\r
297 }\r
298\r
299 Status = gBS->HandleProtocol (\r
300 Handle,\r
301 &gEfiLoadedImageDevicePathProtocolGuid,\r
302 (VOID **) &LoadedImageDevicePath\r
303 );\r
304 if (!EFI_ERROR (Status) && (LoadedImageDevicePath != NULL)) {\r
305 DevicePath = LoadedImageDevicePath;\r
3b672240
SZ
306 } else if (Image != NULL) {\r
307 DevicePath = Image->FilePath;\r
308 }\r
d41bc92c 309\r
3b672240 310 if (DevicePath != NULL) {\r
d41bc92c 311 //\r
3b672240 312 // Try to get image GUID from image DevicePath\r
d41bc92c 313 //\r
314 NameGuid = NULL;\r
315 while (!IsDevicePathEndType (DevicePath)) {\r
316 NameGuid = EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) DevicePath);\r
317 if (NameGuid != NULL) {\r
318 break;\r
319 }\r
320 DevicePath = NextDevicePathNode (DevicePath);\r
321 }\r
322\r
323 if (NameGuid != NULL) {\r
324 //\r
325 // Try to get the image's FFS UI section by image GUID\r
326 //\r
327 NameString = NULL;\r
328 StringSize = 0;\r
329 Status = GetSectionFromAnyFv (\r
330 NameGuid,\r
331 EFI_SECTION_USER_INTERFACE,\r
332 0,\r
333 (VOID **) &NameString,\r
334 &StringSize\r
335 );\r
336\r
337 if (!EFI_ERROR (Status)) {\r
338 //\r
339 // Method 3. Get the name string from FFS UI section\r
340 //\r
4dc0d578 341 StrnCpyS (mGaugeString, DP_GAUGE_STRING_LENGTH + 1, NameString, DP_GAUGE_STRING_LENGTH);\r
d41bc92c 342 mGaugeString[DP_GAUGE_STRING_LENGTH] = 0;\r
343 FreePool (NameString);\r
344 } else {\r
345 //\r
346 // Method 4: Get the name string from image GUID\r
347 //\r
348 UnicodeSPrint (mGaugeString, sizeof (mGaugeString), L"%g", NameGuid);\r
349 }\r
350 return;\r
351 } else {\r
352 //\r
353 // Method 5: Get the name string from image DevicePath\r
354 //\r
3b672240 355 NameString = ConvertDevicePathToText (DevicePath, TRUE, FALSE);\r
863986b3 356 if (NameString != NULL) {\r
4dc0d578 357 StrnCpyS (mGaugeString, DP_GAUGE_STRING_LENGTH + 1, NameString, DP_GAUGE_STRING_LENGTH);\r
863986b3
RN
358 mGaugeString[DP_GAUGE_STRING_LENGTH] = 0;\r
359 FreePool (NameString);\r
360 return;\r
d41bc92c 361 }\r
362 }\r
363 }\r
364\r
365 //\r
366 // Method 6: Unknown Driver Name\r
367 //\r
92034c4c 368 StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_ERROR_NAME), NULL);\r
d41bc92c 369 ASSERT (StringPtr != NULL);\r
4dc0d578 370 StrnCpyS (mGaugeString, DP_GAUGE_STRING_LENGTH + 1, StringPtr, DP_GAUGE_STRING_LENGTH);\r
d41bc92c 371 FreePool (StringPtr);\r
372}\r
373\r
ba0014b9 374/**\r
d41bc92c 375 Calculate the Duration in microseconds.\r
ba0014b9 376\r
d41bc92c 377 Duration is multiplied by 1000, instead of Frequency being divided by 1000 or\r
378 multiplying the result by 1000, in order to maintain precision. Since Duration is\r
379 a 64-bit value, multiplying it by 1000 is unlikely to produce an overflow.\r
ba0014b9 380\r
d41bc92c 381 The time is calculated as (Duration * 1000) / Timer_Frequency.\r
ba0014b9 382\r
d41bc92c 383 @param[in] Duration The event duration in timer ticks.\r
ba0014b9 384\r
d41bc92c 385 @return A 64-bit value which is the Elapsed time in microseconds.\r
386**/\r
387UINT64\r
388DurationInMicroSeconds (\r
389 IN UINT64 Duration\r
390 )\r
391{\r
115eae65 392 return DivU64x32 (Duration, 1000);\r
d41bc92c 393}\r
394\r
ba0014b9 395/**\r
d41bc92c 396 Get index of Measurement Record's match in the CumData array.\r
ba0014b9 397\r
d41bc92c 398 If the Measurement's Token value matches a Token in one of the CumData\r
399 records, the index of the matching record is returned. The returned\r
400 index is a signed value so that negative values can indicate that\r
401 the Measurement didn't match any entry in the CumData array.\r
ba0014b9 402\r
d41bc92c 403 @param[in] Measurement A pointer to a Measurement Record to match against the CumData array.\r
ba0014b9 404\r
d41bc92c 405 @retval <0 Token is not in the CumData array.\r
406 @retval >=0 Return value is the index into CumData where Token is found.\r
407**/\r
408INTN\r
409GetCumulativeItem(\r
410 IN MEASUREMENT_RECORD *Measurement\r
411 )\r
412{\r
413 INTN Index;\r
414\r
415 for( Index = 0; Index < (INTN)NumCum; ++Index) {\r
115eae65 416 if (AsciiStrCmp (Measurement->Token, CumData[Index].Name) == 0) {\r
d41bc92c 417 return Index; // Exit, we found a match\r
418 }\r
419 }\r
420 // If the for loop exits, Token was not found.\r
421 return -1; // Indicate failure\r
422}\r