1 /** @file 2 Performance Library used in SMM phase. 3 4 This library instance provides infrastructure for SMM drivers to log performance 5 data. It consumes SMM PerformanceEx or Performance Protocol published by SmmCorePerformanceLib 6 to log performance data. If both SMM PerformanceEx and Performance Protocol are not available, it does not log any 7 performance information. 8 9 Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR> 10 This program and the accompanying materials 11 are licensed and made available under the terms and conditions of the BSD License 12 which accompanies this distribution. The full text of the license may be found at 13 http://opensource.org/licenses/bsd-license.php 14 15 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 16 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 17 18 **/ 19 20 21 #include <Guid/Performance.h> 22 23 #include <Library/PerformanceLib.h> 24 #include <Library/DebugLib.h> 25 #include <Library/SmmServicesTableLib.h> 26 #include <Library/PcdLib.h> 27 #include <Library/BaseMemoryLib.h> 28 29 // 30 // The cached SMM Performance Protocol and SMM PerformanceEx Protocol interface. 31 // 32 PERFORMANCE_PROTOCOL *mPerformance = NULL; 33 PERFORMANCE_EX_PROTOCOL *mPerformanceEx = NULL; 34 BOOLEAN mPerformanceMeasurementEnabled; 35 36 /** 37 The constructor function initializes the Performance Measurement Enable flag 38 39 @param ImageHandle The firmware allocated handle for the EFI image. 40 @param SystemTable A pointer to the EFI System Table. 41 42 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS. 43 44 **/ 45 EFI_STATUS 46 EFIAPI 47 SmmPerformanceLibConstructor ( 48 IN EFI_HANDLE ImageHandle, 49 IN EFI_SYSTEM_TABLE *SystemTable 50 ) 51 { 52 53 mPerformanceMeasurementEnabled = (BOOLEAN) ((PcdGet8(PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0); 54 55 return EFI_SUCCESS; 56 } 57 58 /** 59 The function caches the pointers to SMM PerformanceEx protocol and Performance Protocol. 60 61 The function locates SMM PerformanceEx protocol and Performance Protocol from protocol database. 62 63 @retval EFI_SUCCESS SMM PerformanceEx protocol or Performance Protocol is successfully located. 64 @retval EFI_NOT_FOUND Both SMM PerformanceEx protocol and Performance Protocol are not located to log performance. 65 66 **/ 67 EFI_STATUS 68 GetPerformanceProtocol ( 69 VOID 70 ) 71 { 72 EFI_STATUS Status; 73 PERFORMANCE_PROTOCOL *Performance; 74 PERFORMANCE_EX_PROTOCOL *PerformanceEx; 75 76 if (mPerformanceEx != NULL || mPerformance != NULL) { 77 return EFI_SUCCESS; 78 } 79 80 Status = gSmst->SmmLocateProtocol (&gSmmPerformanceExProtocolGuid, NULL, (VOID **) &PerformanceEx); 81 if (!EFI_ERROR (Status)) { 82 ASSERT (PerformanceEx != NULL); 83 // 84 // Cache PerformanceEx Protocol. 85 // 86 mPerformanceEx = PerformanceEx; 87 return EFI_SUCCESS; 88 } 89 90 Status = gSmst->SmmLocateProtocol (&gSmmPerformanceProtocolGuid, NULL, (VOID **) &Performance); 91 if (!EFI_ERROR (Status)) { 92 ASSERT (Performance != NULL); 93 // 94 // Cache performance protocol. 95 // 96 mPerformance = Performance; 97 return EFI_SUCCESS; 98 } 99 100 return EFI_NOT_FOUND; 101 } 102 103 /** 104 Creates a record for the beginning of a performance measurement. 105 106 Creates a record that contains the Handle, Token, Module and Identifier. 107 If TimeStamp is not zero, then TimeStamp is added to the record as the start time. 108 If TimeStamp is zero, then this function reads the current time stamp 109 and adds that time stamp value to the record as the start time. 110 111 @param Handle Pointer to environment specific context used 112 to identify the component being measured. 113 @param Token Pointer to a Null-terminated ASCII string 114 that identifies the component being measured. 115 @param Module Pointer to a Null-terminated ASCII string 116 that identifies the module being measured. 117 @param TimeStamp 64-bit time stamp. 118 @param Identifier 32-bit identifier. If the value is 0, the created record 119 is same as the one created by StartPerformanceMeasurement. 120 121 @retval RETURN_SUCCESS The start of the measurement was recorded. 122 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement. 123 124 **/ 125 RETURN_STATUS 126 EFIAPI 127 StartPerformanceMeasurementEx ( 128 IN CONST VOID *Handle, OPTIONAL 129 IN CONST CHAR8 *Token, OPTIONAL 130 IN CONST CHAR8 *Module, OPTIONAL 131 IN UINT64 TimeStamp, 132 IN UINT32 Identifier 133 ) 134 { 135 EFI_STATUS Status; 136 137 Status = GetPerformanceProtocol (); 138 if (EFI_ERROR (Status)) { 139 return RETURN_OUT_OF_RESOURCES; 140 } 141 142 if (mPerformanceEx != NULL) { 143 Status = mPerformanceEx->StartGaugeEx (Handle, Token, Module, TimeStamp, Identifier); 144 } else if (mPerformance != NULL) { 145 Status = mPerformance->StartGauge (Handle, Token, Module, TimeStamp); 146 } else { 147 ASSERT (FALSE); 148 } 149 150 return (RETURN_STATUS) Status; 151 } 152 153 /** 154 Fills in the end time of a performance measurement. 155 156 Looks up the record that matches Handle, Token, Module and Identifier. 157 If the record can not be found then return RETURN_NOT_FOUND. 158 If the record is found and TimeStamp is not zero, 159 then TimeStamp is added to the record as the end time. 160 If the record is found and TimeStamp is zero, then this function reads 161 the current time stamp and adds that time stamp value to the record as the end time. 162 163 @param Handle Pointer to environment specific context used 164 to identify the component being measured. 165 @param Token Pointer to a Null-terminated ASCII string 166 that identifies the component being measured. 167 @param Module Pointer to a Null-terminated ASCII string 168 that identifies the module being measured. 169 @param TimeStamp 64-bit time stamp. 170 @param Identifier 32-bit identifier. If the value is 0, the found record 171 is same as the one found by EndPerformanceMeasurement. 172 173 @retval RETURN_SUCCESS The end of the measurement was recorded. 174 @retval RETURN_NOT_FOUND The specified measurement record could not be found. 175 176 **/ 177 RETURN_STATUS 178 EFIAPI 179 EndPerformanceMeasurementEx ( 180 IN CONST VOID *Handle, OPTIONAL 181 IN CONST CHAR8 *Token, OPTIONAL 182 IN CONST CHAR8 *Module, OPTIONAL 183 IN UINT64 TimeStamp, 184 IN UINT32 Identifier 185 ) 186 { 187 EFI_STATUS Status; 188 189 Status = GetPerformanceProtocol (); 190 if (EFI_ERROR (Status)) { 191 return RETURN_NOT_FOUND; 192 } 193 194 if (mPerformanceEx != NULL) { 195 Status = mPerformanceEx->EndGaugeEx (Handle, Token, Module, TimeStamp, Identifier); 196 } else if (mPerformance != NULL) { 197 Status = mPerformance->EndGauge (Handle, Token, Module, TimeStamp); 198 } else { 199 ASSERT (FALSE); 200 } 201 202 return (RETURN_STATUS) Status; 203 } 204 205 /** 206 Attempts to retrieve a performance measurement log entry from the performance measurement log. 207 It can also retrieve the log created by StartPerformanceMeasurement and EndPerformanceMeasurement, 208 and then assign the Identifier with 0. 209 210 Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is 211 zero on entry, then an attempt is made to retrieve the first entry from the performance log, 212 and the key for the second entry in the log is returned. If the performance log is empty, 213 then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance 214 log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is 215 returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is 216 retrieved and an implementation specific non-zero key value that specifies the end of the performance 217 log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry 218 is retrieved and zero is returned. In the cases where a performance log entry can be returned, 219 the log entry is returned in Handle, Token, Module, StartTimeStamp, EndTimeStamp and Identifier. 220 If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT(). 221 If Handle is NULL, then ASSERT(). 222 If Token is NULL, then ASSERT(). 223 If Module is NULL, then ASSERT(). 224 If StartTimeStamp is NULL, then ASSERT(). 225 If EndTimeStamp is NULL, then ASSERT(). 226 If Identifier is NULL, then ASSERT(). 227 228 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve. 229 0, then the first performance measurement log entry is retrieved. 230 On exit, the key of the next performance log entry. 231 @param Handle Pointer to environment specific context used to identify the component 232 being measured. 233 @param Token Pointer to a Null-terminated ASCII string that identifies the component 234 being measured. 235 @param Module Pointer to a Null-terminated ASCII string that identifies the module 236 being measured. 237 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement 238 was started. 239 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement 240 was ended. 241 @param Identifier Pointer to the 32-bit identifier that was recorded. 242 243 @return The key for the next performance log entry (in general case). 244 245 **/ 246 UINTN 247 EFIAPI 248 GetPerformanceMeasurementEx ( 249 IN UINTN LogEntryKey, 250 OUT CONST VOID **Handle, 251 OUT CONST CHAR8 **Token, 252 OUT CONST CHAR8 **Module, 253 OUT UINT64 *StartTimeStamp, 254 OUT UINT64 *EndTimeStamp, 255 OUT UINT32 *Identifier 256 ) 257 { 258 EFI_STATUS Status; 259 GAUGE_DATA_ENTRY_EX *GaugeData; 260 261 GaugeData = NULL; 262 263 ASSERT (Handle != NULL); 264 ASSERT (Token != NULL); 265 ASSERT (Module != NULL); 266 ASSERT (StartTimeStamp != NULL); 267 ASSERT (EndTimeStamp != NULL); 268 ASSERT (Identifier != NULL); 269 270 Status = GetPerformanceProtocol (); 271 if (EFI_ERROR (Status)) { 272 return 0; 273 } 274 275 if (mPerformanceEx != NULL) { 276 Status = mPerformanceEx->GetGaugeEx (LogEntryKey++, &GaugeData); 277 } else if (mPerformance != NULL) { 278 Status = mPerformance->GetGauge (LogEntryKey++, (GAUGE_DATA_ENTRY **) &GaugeData); 279 } else { 280 ASSERT (FALSE); 281 return 0; 282 } 283 284 // 285 // Make sure that LogEntryKey is a valid log entry key, 286 // 287 ASSERT (Status != EFI_INVALID_PARAMETER); 288 289 if (EFI_ERROR (Status)) { 290 // 291 // The LogEntryKey is the last entry (equals to the total entry number). 292 // 293 return 0; 294 } 295 296 ASSERT (GaugeData != NULL); 297 298 *Handle = (VOID *) (UINTN) GaugeData->Handle; 299 *Token = GaugeData->Token; 300 *Module = GaugeData->Module; 301 *StartTimeStamp = GaugeData->StartTimeStamp; 302 *EndTimeStamp = GaugeData->EndTimeStamp; 303 if (mPerformanceEx != NULL) { 304 *Identifier = GaugeData->Identifier; 305 } else { 306 *Identifier = 0; 307 } 308 309 return LogEntryKey; 310 } 311 312 /** 313 Creates a record for the beginning of a performance measurement. 314 315 Creates a record that contains the Handle, Token, and Module. 316 If TimeStamp is not zero, then TimeStamp is added to the record as the start time. 317 If TimeStamp is zero, then this function reads the current time stamp 318 and adds that time stamp value to the record as the start time. 319 320 @param Handle Pointer to environment specific context used 321 to identify the component being measured. 322 @param Token Pointer to a Null-terminated ASCII string 323 that identifies the component being measured. 324 @param Module Pointer to a Null-terminated ASCII string 325 that identifies the module being measured. 326 @param TimeStamp 64-bit time stamp. 327 328 @retval RETURN_SUCCESS The start of the measurement was recorded. 329 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement. 330 331 **/ 332 RETURN_STATUS 333 EFIAPI 334 StartPerformanceMeasurement ( 335 IN CONST VOID *Handle, OPTIONAL 336 IN CONST CHAR8 *Token, OPTIONAL 337 IN CONST CHAR8 *Module, OPTIONAL 338 IN UINT64 TimeStamp 339 ) 340 { 341 return StartPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0); 342 } 343 344 /** 345 Fills in the end time of a performance measurement. 346 347 Looks up the record that matches Handle, Token, and Module. 348 If the record can not be found then return RETURN_NOT_FOUND. 349 If the record is found and TimeStamp is not zero, 350 then TimeStamp is added to the record as the end time. 351 If the record is found and TimeStamp is zero, then this function reads 352 the current time stamp and adds that time stamp value to the record as the end time. 353 354 @param Handle Pointer to environment specific context used 355 to identify the component being measured. 356 @param Token Pointer to a Null-terminated ASCII string 357 that identifies the component being measured. 358 @param Module Pointer to a Null-terminated ASCII string 359 that identifies the module being measured. 360 @param TimeStamp 64-bit time stamp. 361 362 @retval RETURN_SUCCESS The end of the measurement was recorded. 363 @retval RETURN_NOT_FOUND The specified measurement record could not be found. 364 365 **/ 366 RETURN_STATUS 367 EFIAPI 368 EndPerformanceMeasurement ( 369 IN CONST VOID *Handle, OPTIONAL 370 IN CONST CHAR8 *Token, OPTIONAL 371 IN CONST CHAR8 *Module, OPTIONAL 372 IN UINT64 TimeStamp 373 ) 374 { 375 return EndPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0); 376 } 377 378 /** 379 Attempts to retrieve a performance measurement log entry from the performance measurement log. 380 It can also retrieve the log created by StartPerformanceMeasurementEx and EndPerformanceMeasurementEx, 381 and then eliminate the Identifier. 382 383 Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is 384 zero on entry, then an attempt is made to retrieve the first entry from the performance log, 385 and the key for the second entry in the log is returned. If the performance log is empty, 386 then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance 387 log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is 388 returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is 389 retrieved and an implementation specific non-zero key value that specifies the end of the performance 390 log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry 391 is retrieved and zero is returned. In the cases where a performance log entry can be returned, 392 the log entry is returned in Handle, Token, Module, StartTimeStamp, and EndTimeStamp. 393 If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT(). 394 If Handle is NULL, then ASSERT(). 395 If Token is NULL, then ASSERT(). 396 If Module is NULL, then ASSERT(). 397 If StartTimeStamp is NULL, then ASSERT(). 398 If EndTimeStamp is NULL, then ASSERT(). 399 400 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve. 401 0, then the first performance measurement log entry is retrieved. 402 On exit, the key of the next performance log entry. 403 @param Handle Pointer to environment specific context used to identify the component 404 being measured. 405 @param Token Pointer to a Null-terminated ASCII string that identifies the component 406 being measured. 407 @param Module Pointer to a Null-terminated ASCII string that identifies the module 408 being measured. 409 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement 410 was started. 411 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement 412 was ended. 413 414 @return The key for the next performance log entry (in general case). 415 416 **/ 417 UINTN 418 EFIAPI 419 GetPerformanceMeasurement ( 420 IN UINTN LogEntryKey, 421 OUT CONST VOID **Handle, 422 OUT CONST CHAR8 **Token, 423 OUT CONST CHAR8 **Module, 424 OUT UINT64 *StartTimeStamp, 425 OUT UINT64 *EndTimeStamp 426 ) 427 { 428 UINT32 Identifier; 429 return GetPerformanceMeasurementEx (LogEntryKey, Handle, Token, Module, StartTimeStamp, EndTimeStamp, &Identifier); 430 } 431 432 /** 433 Returns TRUE if the performance measurement macros are enabled. 434 435 This function returns TRUE if the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of 436 PcdPerformanceLibraryPropertyMask is set. Otherwise FALSE is returned. 437 438 @retval TRUE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of 439 PcdPerformanceLibraryPropertyMask is set. 440 @retval FALSE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of 441 PcdPerformanceLibraryPropertyMask is clear. 442 443 **/ 444 BOOLEAN 445 EFIAPI 446 PerformanceMeasurementEnabled ( 447 VOID 448 ) 449 { 450 return mPerformanceMeasurementEnabled; 451 } 452