Home | History | Annotate | Download | only in UefiShellDriver1CommandsLib
      1 /** @file
      2   Main file for DevTree shell Driver1 function.
      3 
      4   (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.<BR>
      5   Copyright (c) 2010 - 2012, 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 SHELL_PARAM_ITEM ParamList[] = {
     19   {L"-d", TypeFlag},
     20   {L"-l", TypeValue},
     21   {NULL, TypeMax}
     22   };
     23 
     24 /**
     25   Display a tree starting from this handle.
     26 
     27   @param[in] TheHandle      The handle to start with.
     28   @param[in] Lang           Optionally, a UEFI defined language code.
     29   @param[in] UseDevPaths    TRUE to display info from DevPath as identifiers.
     30                             FALSE will use component name protocol instead.
     31   @param[in] IndentCharCount   How many characters to indent (allows for recursion).
     32   @param[in] HiiString      The string from HII to use for output.
     33 
     34   @retval SHELL_SUCCESS     The operation was successful.
     35 **/
     36 SHELL_STATUS
     37 EFIAPI
     38 DoDevTreeForHandle(
     39   IN CONST EFI_HANDLE TheHandle,
     40   IN CONST CHAR8      *Lang OPTIONAL,
     41   IN CONST BOOLEAN    UseDevPaths,
     42   IN CONST UINTN      IndentCharCount,
     43   IN CONST CHAR16     *HiiString
     44   )
     45 {
     46   SHELL_STATUS        ShellStatus;
     47   EFI_STATUS          Status;
     48   CHAR16              *FormatString;
     49   CHAR16              *Name;
     50   EFI_HANDLE          *ChildHandleBuffer;
     51   UINTN               ChildCount;
     52   UINTN               LoopVar;
     53 
     54   Status              = EFI_SUCCESS;
     55   ShellStatus         = SHELL_SUCCESS;
     56   Name                = NULL;
     57   ChildHandleBuffer   = NULL;
     58   ChildCount          = 0;
     59 
     60   ASSERT(TheHandle    != NULL);
     61 
     62   if (ShellGetExecutionBreakFlag()) {
     63     ShellStatus = SHELL_ABORTED;
     64     return ShellStatus;
     65   }
     66 
     67   //
     68   // We want controller handles.  they will not have LoadedImage or DriverBinding (or others...)
     69   //
     70   Status = gBS->OpenProtocol (
     71                 TheHandle,
     72                 &gEfiDriverBindingProtocolGuid,
     73                 NULL,
     74                 NULL,
     75                 NULL,
     76                 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
     77                );
     78   if (!EFI_ERROR (Status)) {
     79     return SHELL_SUCCESS;
     80   }
     81 
     82   Status = gBS->OpenProtocol (
     83                 TheHandle,
     84                 &gEfiLoadedImageProtocolGuid,
     85                 NULL,
     86                 NULL,
     87                 NULL,
     88                 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
     89                );
     90   if (!EFI_ERROR (Status)) {
     91     return SHELL_SUCCESS;
     92   }
     93 
     94   FormatString        = AllocateZeroPool(StrSize(HiiString) + (10)*sizeof(FormatString[0]));
     95 
     96   ASSERT(HiiString    != NULL);
     97   ASSERT(FormatString != NULL);
     98 
     99   //
    100   // we generate the format string on the fly so that we can control the
    101   // number of space characters that the first (empty) string has.  this
    102   // handles the indenting.
    103   //
    104 
    105   UnicodeSPrint(FormatString, StrSize(HiiString) + (10)*sizeof(FormatString[0]), L"%%%ds %s", IndentCharCount, HiiString);
    106   gEfiShellProtocol->GetDeviceName((EFI_HANDLE)TheHandle, !UseDevPaths?EFI_DEVICE_NAME_USE_COMPONENT_NAME|EFI_DEVICE_NAME_USE_DEVICE_PATH:EFI_DEVICE_NAME_USE_DEVICE_PATH, (CHAR8*)Lang, &Name);
    107   //
    108   // print out the information for ourselves
    109   //
    110   ShellPrintEx(
    111     -1,
    112     -1,
    113     FormatString,
    114     L"",
    115     ConvertHandleToHandleIndex(TheHandle),
    116     Name==NULL?L"Unknown":Name);
    117 
    118   FreePool(FormatString);
    119   if (Name != NULL) {
    120     FreePool(Name);
    121   }
    122 
    123   //
    124   // recurse on each child handle with IndentCharCount + 2
    125   //
    126   ParseHandleDatabaseForChildControllers(TheHandle, &ChildCount, &ChildHandleBuffer);
    127   for (LoopVar = 0 ; LoopVar < ChildCount && ShellStatus == SHELL_SUCCESS; LoopVar++){
    128     ShellStatus = DoDevTreeForHandle(ChildHandleBuffer[LoopVar], Lang, UseDevPaths, IndentCharCount+2, HiiString);
    129     if (ShellStatus == SHELL_ABORTED) {
    130       break;
    131     }
    132   }
    133 
    134   if (ChildHandleBuffer != NULL) {
    135     FreePool(ChildHandleBuffer);
    136   }
    137 
    138   return (ShellStatus);
    139 }
    140 
    141 /**
    142   Function for 'devtree' command.
    143 
    144   @param[in] ImageHandle  Handle to the Image (NULL if Internal).
    145   @param[in] SystemTable  Pointer to the System Table (NULL if Internal).
    146 **/
    147 SHELL_STATUS
    148 EFIAPI
    149 ShellCommandRunDevTree (
    150   IN EFI_HANDLE        ImageHandle,
    151   IN EFI_SYSTEM_TABLE  *SystemTable
    152   )
    153 {
    154   EFI_STATUS          Status;
    155   LIST_ENTRY          *Package;
    156   CHAR16              *ProblemParam;
    157   SHELL_STATUS        ShellStatus;
    158   CHAR8               *Language;
    159   CONST CHAR16        *Lang;
    160   CHAR16              *HiiString;
    161   UINTN               LoopVar;
    162   EFI_HANDLE          TheHandle;
    163   BOOLEAN             FlagD;
    164   UINT64              Intermediate;
    165   UINTN               ParentControllerHandleCount;
    166   EFI_HANDLE          *ParentControllerHandleBuffer;
    167 
    168   ShellStatus         = SHELL_SUCCESS;
    169   Status              = EFI_SUCCESS;
    170   Language                = NULL;
    171 
    172   //
    173   // initialize the shell lib (we must be in non-auto-init...)
    174   //
    175   Status = ShellInitialize();
    176   ASSERT_EFI_ERROR(Status);
    177 
    178   Status = CommandInit();
    179   ASSERT_EFI_ERROR(Status);
    180 
    181   //
    182   // parse the command line
    183   //
    184   Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
    185   if (EFI_ERROR(Status)) {
    186     if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
    187       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, L"devtree", ProblemParam);
    188       FreePool(ProblemParam);
    189       ShellStatus = SHELL_INVALID_PARAMETER;
    190     } else {
    191       ASSERT(FALSE);
    192     }
    193   } else {
    194     if (ShellCommandLineGetCount(Package) > 2) {
    195       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"devtree");
    196       ShellCommandLineFreeVarList (Package);
    197       return (SHELL_INVALID_PARAMETER);
    198     }
    199     Lang = ShellCommandLineGetValue(Package, L"-l");
    200     if (Lang != NULL) {
    201       Language = AllocateZeroPool(StrSize(Lang));
    202       AsciiSPrint(Language, StrSize(Lang), "%S", Lang);
    203     } else if (!ShellCommandLineGetFlag(Package, L"-l")){
    204       ASSERT(Language == NULL);
    205 //      Language = AllocateZeroPool(10);
    206 //      AsciiSPrint(Language, 10, "en-us");
    207     } else {
    208       ASSERT(Language == NULL);
    209       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDriver1HiiHandle, L"devtree",  L"-l");
    210       ShellCommandLineFreeVarList (Package);
    211       return (SHELL_INVALID_PARAMETER);
    212     }
    213     FlagD = ShellCommandLineGetFlag(Package, L"-d");
    214 
    215     Lang = ShellCommandLineGetRawValue(Package, 1);
    216     HiiString = HiiGetString(gShellDriver1HiiHandle, STRING_TOKEN (STR_DEV_TREE_OUTPUT), Language);
    217 
    218     if (Lang == NULL) {
    219       for (LoopVar = 1 ; ; LoopVar++){
    220         TheHandle = ConvertHandleIndexToHandle(LoopVar);
    221         if (TheHandle == NULL){
    222           break;
    223         }
    224 
    225         //
    226         // Skip handles that do not have device path protocol
    227         //
    228         Status = gBS->OpenProtocol (
    229                       TheHandle,
    230                       &gEfiDevicePathProtocolGuid,
    231                       NULL,
    232                       NULL,
    233                       NULL,
    234                       EFI_OPEN_PROTOCOL_TEST_PROTOCOL
    235                      );
    236         if (EFI_ERROR (Status)) {
    237           continue;
    238         }
    239 
    240         //
    241         // Skip handles that do have parents
    242         //
    243         ParentControllerHandleBuffer = NULL;
    244         Status = PARSE_HANDLE_DATABASE_PARENTS (
    245                    TheHandle,
    246                    &ParentControllerHandleCount,
    247                    &ParentControllerHandleBuffer
    248                    );
    249         SHELL_FREE_NON_NULL (ParentControllerHandleBuffer);
    250         if (ParentControllerHandleCount > 0) {
    251           continue;
    252         }
    253 
    254         //
    255         // Start a devtree from TheHandle that has a device path and no parents
    256         //
    257         ShellStatus = DoDevTreeForHandle(TheHandle, Language, FlagD, 0, HiiString);
    258       }
    259     } else {
    260       Status = ShellConvertStringToUint64(Lang, &Intermediate, TRUE, FALSE);
    261       if (EFI_ERROR(Status) || ConvertHandleIndexToHandle((UINTN)Intermediate) == NULL) {
    262         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"devtree", Lang);
    263         ShellStatus = SHELL_INVALID_PARAMETER;
    264       } else {
    265         ShellStatus = DoDevTreeForHandle(ConvertHandleIndexToHandle((UINTN)Intermediate), Language, FlagD, 0, HiiString);
    266       }
    267     }
    268 
    269     if (HiiString != NULL) {
    270       FreePool(HiiString);
    271     }
    272     SHELL_FREE_NON_NULL(Language);
    273     ShellCommandLineFreeVarList (Package);
    274   }
    275 
    276   return (ShellStatus);
    277 }
    278