Home | History | Annotate | Download | only in UefiShellDriver1CommandsLib
      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