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