1 /** @file 2 Main file for DrvDiag shell Driver1 function. 3 4 (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR> 5 Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR> 6 This program and the accompanying materials 7 are licensed and made available under the terms and conditions of the BSD License 8 which accompanies this distribution. The full text of the license may be found at 9 http://opensource.org/licenses/bsd-license.php 10 11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13 14 **/ 15 16 #include "UefiShellDriver1CommandsLib.h" 17 18 STATIC CONST EFI_GUID *DiagGuidList[] = {&gEfiDriverDiagnosticsProtocolGuid, &gEfiDriverDiagnostics2ProtocolGuid, NULL}; 19 // 20 // We need 1 more item on the list... 21 // 22 typedef enum { 23 TestModeStandard = EfiDriverDiagnosticTypeStandard, 24 TestModeExtended = EfiDriverDiagnosticTypeExtended, 25 TestModeManufacturing = EfiDriverDiagnosticTypeManufacturing, 26 TestModeList, 27 TestModeMax 28 } DRV_DIAG_TEST_MODE; 29 30 /** 31 Do the diagnostics call for some set of handles. 32 33 @param[in] Mode The type of diagnostic test to run. 34 @param[in] Lang The language code to use. 35 @param[in] AllChilds Should the test be on all children. 36 @param[in] DriverHandle The driver handle to test with. 37 @param[in] ControllerHandle The specific controller handle to test. 38 @param[in] ChildHandle The specific child handle to test. 39 40 @retval EFI_SUCCESS The operation was successful. 41 @retval EFI_INVALID_PARAMETER A parameter had an invalid value. 42 @retval EFI_NOT_FOUND No diagnostic handle could be found. 43 **/ 44 EFI_STATUS 45 EFIAPI 46 DoDiagnostics ( 47 IN CONST DRV_DIAG_TEST_MODE Mode, 48 IN CONST CHAR8 *Lang, 49 IN CONST BOOLEAN AllChilds, 50 IN CONST EFI_HANDLE DriverHandle, 51 IN CONST EFI_HANDLE ControllerHandle, 52 IN CONST EFI_HANDLE ChildHandle 53 ) 54 { 55 EFI_DRIVER_DIAGNOSTICS_PROTOCOL *DriverDiagnostics; 56 EFI_DRIVER_DIAGNOSTICS2_PROTOCOL *DriverDiagnostics2; 57 EFI_HANDLE *DriverHandleList; 58 EFI_HANDLE *ControllerHandleList; 59 EFI_HANDLE *ChildHandleList; 60 EFI_HANDLE *Walker; 61 UINTN DriverHandleListCount; 62 UINTN ControllerHandleListCount; 63 UINTN ChildHandleListCount; 64 UINTN DriverHandleListLoop; 65 UINTN ControllerHandleListLoop; 66 UINTN ChildHandleListLoop; 67 EFI_STATUS Status; 68 EFI_STATUS Status2; 69 EFI_GUID *ErrorType; 70 UINTN OutBufferSize; 71 CHAR16 *OutBuffer; 72 UINTN HandleIndex1; 73 UINTN HandleIndex2; 74 CHAR8 *Language; 75 BOOLEAN Found; 76 77 if ((ChildHandle != NULL && AllChilds) || (Mode >= TestModeMax)){ 78 return (EFI_INVALID_PARAMETER); 79 } 80 81 DriverDiagnostics = NULL; 82 DriverDiagnostics2 = NULL; 83 Status = EFI_SUCCESS; 84 Status2 = EFI_SUCCESS; 85 DriverHandleList = NULL; 86 ControllerHandleList = NULL; 87 ChildHandleList = NULL; 88 Language = NULL; 89 OutBuffer = NULL; 90 ErrorType = NULL; 91 DriverHandleListCount = 0; 92 ControllerHandleListCount = 0; 93 ChildHandleListCount = 0; 94 95 if (DriverHandle != NULL) { 96 DriverHandleList = AllocateZeroPool(2*sizeof(EFI_HANDLE)); 97 ASSERT(DriverHandleList!=NULL); 98 DriverHandleList[0] = DriverHandle; 99 DriverHandleListCount = 1; 100 } else { 101 DriverHandleList = GetHandleListByProtocolList(DiagGuidList); 102 if (DriverHandleList == NULL) { 103 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROTOCOL_NF), gShellDriver1HiiHandle, L"drvdiag", L"gEfiDriverDiagnosticsProtocolGuid", &gEfiDriverDiagnosticsProtocolGuid); 104 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROTOCOL_NF), gShellDriver1HiiHandle, L"drvdiag", L"gEfiDriverDiagnostics2ProtocolGuid", &gEfiDriverDiagnostics2ProtocolGuid); 105 return (EFI_NOT_FOUND); 106 } 107 for (Walker = DriverHandleList ; Walker != NULL && *Walker != NULL ; DriverHandleListCount++, Walker++); 108 } 109 110 if (ControllerHandle != NULL) { 111 ControllerHandleList = AllocateZeroPool(2*sizeof(EFI_HANDLE)); 112 ASSERT(ControllerHandleList!=NULL); 113 ControllerHandleList[0] = ControllerHandle; 114 ControllerHandleListCount = 1; 115 } else { 116 ControllerHandleList = NULL; 117 } 118 119 if (ChildHandle != NULL) { 120 ChildHandleList = AllocateZeroPool(2*sizeof(EFI_HANDLE)); 121 ASSERT(ChildHandleList!=NULL); 122 ChildHandleList[0] = ChildHandle; 123 ChildHandleListCount = 1; 124 } else if (AllChilds) { 125 ChildHandleList = NULL; 126 // 127 // This gets handled in the loop below. 128 // 129 } else { 130 ChildHandleList = NULL; 131 } 132 133 if (Mode == TestModeList) { 134 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DRVDIAG_HEADER), gShellDriver1HiiHandle); 135 } 136 for (DriverHandleListLoop = 0 137 ; DriverHandleListLoop < DriverHandleListCount 138 ; DriverHandleListLoop++ 139 ){ 140 if (Mode == TestModeList) { 141 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DRVDIAG_DRIVER_HEADER), gShellDriver1HiiHandle, ConvertHandleToHandleIndex(DriverHandleList[DriverHandleListLoop])); 142 } 143 if (ControllerHandle == NULL) { 144 PARSE_HANDLE_DATABASE_DEVICES(DriverHandleList[DriverHandleListLoop], &ControllerHandleListCount, &ControllerHandleList); 145 } 146 if (ControllerHandleListCount == 0) { 147 if (Mode == TestModeList) { 148 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DRVDIAG_DRIVER_NO_HANDLES), gShellDriver1HiiHandle); 149 } 150 } else { 151 if (Mode == TestModeList) { 152 ShellPrintEx(-1, -1, L"\r\n"); 153 } 154 for (ControllerHandleListLoop = 0 155 ; ControllerHandleListLoop < ControllerHandleListCount 156 ; ControllerHandleListLoop++ 157 ){ 158 if (AllChilds) { 159 ASSERT(ChildHandleList == NULL); 160 PARSE_HANDLE_DATABASE_MANAGED_CHILDREN( 161 DriverHandleList[DriverHandleListLoop], 162 ControllerHandleList[ControllerHandleListLoop], 163 &ChildHandleListCount, 164 &ChildHandleList); 165 } 166 for (ChildHandleListLoop = 0 167 ; (ChildHandleListLoop < ChildHandleListCount || ChildHandleList == NULL) 168 ; ChildHandleListLoop++ 169 ){ 170 Found = FALSE; 171 if (Mode != TestModeList) { 172 if (Lang == NULL || Lang[2] == '-') { 173 // 174 // Get the protocol pointer and call the function 175 // 176 Status = gBS->OpenProtocol( 177 DriverHandleList[DriverHandleListLoop], 178 &gEfiDriverDiagnostics2ProtocolGuid, 179 (VOID**)&DriverDiagnostics2, 180 gImageHandle, 181 NULL, 182 EFI_OPEN_PROTOCOL_GET_PROTOCOL); 183 if (!EFI_ERROR(Status) && (DriverDiagnostics2 != NULL)) { 184 Language = GetBestLanguageForDriver(DriverDiagnostics2->SupportedLanguages, Lang, FALSE); 185 Found = TRUE; 186 Status = DriverDiagnostics2->RunDiagnostics( 187 DriverDiagnostics2, 188 ControllerHandleList[ControllerHandleListLoop], 189 ChildHandleList == NULL?NULL:ChildHandleList[ChildHandleListLoop], 190 (EFI_DRIVER_DIAGNOSTIC_TYPE)Mode, 191 Language, 192 &ErrorType, 193 &OutBufferSize, 194 &OutBuffer); 195 FreePool(Language); 196 } 197 } 198 if (!Found && (Lang == NULL||(Lang!=NULL&&(Lang[2]!='-')))){ 199 Status = gBS->OpenProtocol( 200 DriverHandleList[DriverHandleListLoop], 201 &gEfiDriverDiagnosticsProtocolGuid, 202 (VOID**)&DriverDiagnostics, 203 gImageHandle, 204 NULL, 205 EFI_OPEN_PROTOCOL_GET_PROTOCOL); 206 if (!EFI_ERROR(Status)) { 207 Language = GetBestLanguageForDriver(DriverDiagnostics->SupportedLanguages, Lang, FALSE); 208 Status = DriverDiagnostics->RunDiagnostics( 209 DriverDiagnostics, 210 ControllerHandleList[ControllerHandleListLoop], 211 ChildHandleList == NULL?NULL:ChildHandleList[ChildHandleListLoop], 212 (EFI_DRIVER_DIAGNOSTIC_TYPE)Mode, 213 Language, 214 &ErrorType, 215 &OutBufferSize, 216 &OutBuffer); 217 FreePool(Language); 218 } 219 } 220 if (EFI_ERROR(Status)) { 221 Status2 = Status; 222 } 223 HandleIndex1 = ConvertHandleToHandleIndex(DriverHandleList[DriverHandleListLoop]); 224 HandleIndex2 = ConvertHandleToHandleIndex(ControllerHandleList[ControllerHandleListLoop]); 225 ShellPrintHiiEx( 226 -1, 227 -1, 228 NULL, 229 STRING_TOKEN (STR_3P_RESULT), 230 gShellDriver1HiiHandle, 231 L"DrvDiag", 232 HandleIndex1, 233 HandleIndex2, 234 ChildHandleList == NULL?0:ConvertHandleToHandleIndex(ChildHandleList[ChildHandleListLoop]), 235 Status); 236 if (OutBuffer!=NULL) { 237 FreePool(OutBuffer); 238 OutBuffer = NULL; 239 } 240 if (ErrorType!=NULL) { 241 FreePool(ErrorType); 242 ErrorType = NULL; 243 } 244 } else { 245 HandleIndex1 = ConvertHandleToHandleIndex(DriverHandleList[DriverHandleListLoop]); 246 HandleIndex2 = ConvertHandleToHandleIndex(ControllerHandleList[ControllerHandleListLoop]); 247 // 248 // Print out the information that this set can be tested 249 // 250 ShellPrintHiiEx( 251 -1, 252 -1, 253 NULL, 254 STRING_TOKEN (STR_DRV_DIAG_ITEM_LINE), 255 gShellDriver1HiiHandle, 256 HandleIndex1, 257 HandleIndex2, 258 ChildHandleList == NULL?0:ConvertHandleToHandleIndex(ChildHandleList[ChildHandleListLoop]) 259 ); 260 } 261 262 // 263 // If we are doing a single pass with NULL child jump out after a single loop 264 // 265 if (ChildHandleList == NULL) { 266 break; 267 } 268 } 269 if (AllChilds) { 270 SHELL_FREE_NON_NULL(ChildHandleList); 271 ChildHandleList = NULL; 272 ChildHandleListCount = 0; 273 } 274 } 275 if (ControllerHandle == NULL) { 276 SHELL_FREE_NON_NULL(ControllerHandleList); 277 ControllerHandleList = NULL; 278 ControllerHandleListCount = 0; 279 } 280 } 281 } 282 283 if (DriverHandleList != NULL) { 284 FreePool(DriverHandleList); 285 } 286 if (ControllerHandleList != NULL) { 287 FreePool(ControllerHandleList); 288 } 289 if (ChildHandleList != NULL) { 290 FreePool(ChildHandleList); 291 } 292 return (Status2); 293 } 294 295 296 STATIC CONST SHELL_PARAM_ITEM ParamList[] = { 297 {L"-c", TypeFlag}, 298 {L"-s", TypeFlag}, 299 {L"-e", TypeFlag}, 300 {L"-m", TypeFlag}, 301 {L"-l", TypeValue}, 302 {NULL, TypeMax} 303 }; 304 305 /** 306 Function for 'drvdiag' command. 307 308 @param[in] ImageHandle Handle to the Image (NULL if Internal). 309 @param[in] SystemTable Pointer to the System Table (NULL if Internal). 310 **/ 311 SHELL_STATUS 312 EFIAPI 313 ShellCommandRunDrvDiag ( 314 IN EFI_HANDLE ImageHandle, 315 IN EFI_SYSTEM_TABLE *SystemTable 316 ) 317 { 318 EFI_STATUS Status; 319 LIST_ENTRY *Package; 320 CHAR16 *ProblemParam; 321 SHELL_STATUS ShellStatus; 322 DRV_DIAG_TEST_MODE Mode; 323 CHAR8 *Language; 324 CONST CHAR16 *DriverHandleStr; 325 CONST CHAR16 *ControllerHandleStr; 326 CONST CHAR16 *ChildHandleStr; 327 CONST CHAR16 *Lang; 328 EFI_HANDLE Handle1; 329 EFI_HANDLE Handle2; 330 EFI_HANDLE Handle3; 331 UINT64 Intermediate; 332 333 ShellStatus = SHELL_SUCCESS; 334 Mode = TestModeMax; 335 Language = NULL; 336 337 // 338 // initialize the shell lib (we must be in non-auto-init...) 339 // 340 Status = ShellInitialize(); 341 ASSERT_EFI_ERROR(Status); 342 343 Status = CommandInit(); 344 ASSERT_EFI_ERROR(Status); 345 346 // 347 // parse the command line 348 // 349 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); 350 if (EFI_ERROR(Status)) { 351 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { 352 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, L"drvdiag", ProblemParam); 353 FreePool(ProblemParam); 354 ShellStatus = SHELL_INVALID_PARAMETER; 355 } else { 356 ASSERT(FALSE); 357 } 358 } else { 359 // 360 // if more than 3 'value' parameters (plus the name one) or we have any 2 mode flags 361 // 362 if ((ShellCommandLineGetCount(Package) > 4) 363 ||(ShellCommandLineGetFlag(Package, L"-s") && ShellCommandLineGetFlag(Package, L"-e")) 364 ||(ShellCommandLineGetFlag(Package, L"-s") && ShellCommandLineGetFlag(Package, L"-m")) 365 ||(ShellCommandLineGetFlag(Package, L"-e") && ShellCommandLineGetFlag(Package, L"-m")) 366 ){ 367 // 368 // error for too many parameters 369 // 370 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"drvdiag"); 371 ShellStatus = SHELL_INVALID_PARAMETER; 372 } else if ((ShellCommandLineGetFlag(Package, L"-s")) 373 || (ShellCommandLineGetFlag(Package, L"-e")) 374 || (ShellCommandLineGetFlag(Package, L"-m")) 375 ){ 376 // 377 // Run the apropriate test 378 // 379 if (ShellCommandLineGetFlag(Package, L"-s")) { 380 Mode = TestModeStandard; 381 } else if (ShellCommandLineGetFlag(Package, L"-e")) { 382 Mode = TestModeExtended; 383 } else if (ShellCommandLineGetFlag(Package, L"-m")) { 384 Mode = TestModeManufacturing; 385 } else { 386 ASSERT(FALSE); 387 } 388 } else { 389 // 390 // Do a listing of what's available to test 391 // 392 Mode = TestModeList; 393 } 394 395 Lang = ShellCommandLineGetValue(Package, L"-l"); 396 if (ShellCommandLineGetFlag(Package, L"-l") && Lang == NULL) { 397 ASSERT(Language == NULL); 398 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDriver1HiiHandle, L"drvdiag", L"-l"); 399 ShellCommandLineFreeVarList (Package); 400 return (SHELL_INVALID_PARAMETER); 401 } else if (Lang != NULL) { 402 Language = AllocateZeroPool(StrSize(Lang)); 403 AsciiSPrint(Language, StrSize(Lang), "%S", Lang); 404 } 405 406 DriverHandleStr = ShellCommandLineGetRawValue(Package, 1); 407 ControllerHandleStr = ShellCommandLineGetRawValue(Package, 2); 408 ChildHandleStr = ShellCommandLineGetRawValue(Package, 3); 409 410 if (DriverHandleStr == NULL) { 411 Handle1 = NULL; 412 } else { 413 ShellConvertStringToUint64(DriverHandleStr, &Intermediate, TRUE, FALSE); 414 Handle1 = ConvertHandleIndexToHandle((UINTN)Intermediate); 415 } 416 if (ControllerHandleStr == NULL) { 417 Handle2 = NULL; 418 } else { 419 ShellConvertStringToUint64(ControllerHandleStr, &Intermediate, TRUE, FALSE); 420 Handle2 = ConvertHandleIndexToHandle((UINTN)Intermediate); 421 } 422 if (ChildHandleStr == NULL) { 423 Handle3 = NULL; 424 } else { 425 ShellConvertStringToUint64(ChildHandleStr, &Intermediate, TRUE, FALSE); 426 Handle3 = ConvertHandleIndexToHandle((UINTN)Intermediate); 427 } 428 429 Status = DoDiagnostics ( 430 Mode, 431 Language, 432 ShellCommandLineGetFlag(Package, L"-c"), 433 Handle1, 434 Handle2, 435 Handle3 436 ); 437 438 SHELL_FREE_NON_NULL(Language); 439 ShellCommandLineFreeVarList (Package); 440 441 } 442 if (ShellStatus == SHELL_SUCCESS) { 443 if (Status == EFI_SECURITY_VIOLATION) { 444 ShellStatus = SHELL_SECURITY_VIOLATION; 445 } else if (Status == EFI_INVALID_PARAMETER) { 446 ShellStatus = SHELL_INVALID_PARAMETER; 447 } else if (Status == EFI_NOT_FOUND) { 448 ShellStatus = SHELL_NOT_FOUND; 449 } else if (EFI_ERROR(Status)) { 450 ShellStatus = SHELL_NOT_FOUND; 451 } 452 } 453 454 return (ShellStatus); 455 } 456