Home | History | Annotate | Download | only in UefiShellLevel2CommandsLib
      1 /** @file
      2   Main file for NULL named library for level 2 shell command functions.
      3 
      4   these functions are:
      5   attrib,
      6   cd,
      7   cp,
      8   date*,
      9   time*,
     10   load,
     11   ls,
     12   map,
     13   mkdir,
     14   mv,
     15   parse,
     16   rm,
     17   reset,
     18   set,
     19   timezone*,
     20   vol
     21 
     22   * functions are non-interactive only
     23 
     24   Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
     25   Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
     26   This program and the accompanying materials
     27   are licensed and made available under the terms and conditions of the BSD License
     28   which accompanies this distribution.  The full text of the license may be found at
     29   http://opensource.org/licenses/bsd-license.php
     30 
     31   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     32   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     33 
     34 **/
     35 #include "UefiShellLevel2CommandsLib.h"
     36 
     37 CONST CHAR16 mFileName[] = L"ShellCommands";
     38 EFI_HANDLE gShellLevel2HiiHandle = NULL;
     39 
     40 /**
     41   Get the filename to get help text from if not using HII.
     42 
     43   @retval The filename.
     44 **/
     45 CONST CHAR16*
     46 EFIAPI
     47 ShellCommandGetManFileNameLevel2 (
     48   VOID
     49   )
     50 {
     51   return (mFileName);
     52 }
     53 
     54 /**
     55   Constructor for the Shell Level 2 Commands library.
     56 
     57   Install the handlers for level 2 UEFI Shell 2.0 commands.
     58 
     59   @param ImageHandle    the image handle of the process
     60   @param SystemTable    the EFI System Table pointer
     61 
     62   @retval EFI_SUCCESS        the shell command handlers were installed sucessfully
     63   @retval EFI_UNSUPPORTED    the shell level required was not found.
     64 **/
     65 EFI_STATUS
     66 EFIAPI
     67 ShellLevel2CommandsLibConstructor (
     68   IN EFI_HANDLE        ImageHandle,
     69   IN EFI_SYSTEM_TABLE  *SystemTable
     70   )
     71 {
     72   //
     73   // if shell level is less than 2 do nothing
     74   //
     75   if (PcdGet8(PcdShellSupportLevel) < 2) {
     76     return (EFI_SUCCESS);
     77   }
     78 
     79   gShellLevel2HiiHandle = HiiAddPackages (&gShellLevel2HiiGuid, gImageHandle, UefiShellLevel2CommandsLibStrings, NULL);
     80   if (gShellLevel2HiiHandle == NULL) {
     81     return (EFI_DEVICE_ERROR);
     82   }
     83 
     84   //
     85   // install our shell command handlers that are always installed
     86   //
     87   ShellCommandRegisterCommandName(L"attrib",   ShellCommandRunAttrib  , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_ATTRIB) );
     88   ShellCommandRegisterCommandName(L"cd",       ShellCommandRunCd      , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_CD)     );
     89   ShellCommandRegisterCommandName(L"cp",       ShellCommandRunCp      , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_CP)     );
     90   ShellCommandRegisterCommandName(L"load",     ShellCommandRunLoad    , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_LOAD)   );
     91   ShellCommandRegisterCommandName(L"map",      ShellCommandRunMap     , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_MAP)    );
     92   ShellCommandRegisterCommandName(L"mkdir",    ShellCommandRunMkDir   , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_MKDIR)  );
     93   ShellCommandRegisterCommandName(L"mv",       ShellCommandRunMv      , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_MV)     );
     94   ShellCommandRegisterCommandName(L"parse",    ShellCommandRunParse   , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_PARSE)  );
     95   ShellCommandRegisterCommandName(L"reset",    ShellCommandRunReset   , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_RESET)  );
     96   ShellCommandRegisterCommandName(L"set",      ShellCommandRunSet     , ShellCommandGetManFileNameLevel2, 2, L"",FALSE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_SET)    );
     97   ShellCommandRegisterCommandName(L"ls",       ShellCommandRunLs      , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_LS)     );
     98   ShellCommandRegisterCommandName(L"rm",       ShellCommandRunRm      , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_RM)     );
     99   ShellCommandRegisterCommandName(L"vol",      ShellCommandRunVol     , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_VOL)    );
    100 
    101   //
    102   // support for permenant (built in) aliases
    103   //
    104   ShellCommandRegisterAlias(L"rm", L"del");
    105   ShellCommandRegisterAlias(L"ls", L"dir");
    106   ShellCommandRegisterAlias(L"cp", L"copy");
    107   ShellCommandRegisterAlias(L"mkdir", L"md");
    108   ShellCommandRegisterAlias(L"cd ..", L"cd..");
    109   ShellCommandRegisterAlias(L"cd \\", L"cd\\");
    110   ShellCommandRegisterAlias(L"mv", L"ren");
    111   ShellCommandRegisterAlias(L"mv", L"move");
    112   ShellCommandRegisterAlias(L"map", L"mount");
    113   //
    114   // These are installed in level 2 or 3...
    115   //
    116   if (PcdGet8(PcdShellSupportLevel) == 2 || PcdGet8(PcdShellSupportLevel) == 3) {
    117     ShellCommandRegisterCommandName(L"date",     ShellCommandRunDate    , ShellCommandGetManFileNameLevel2, PcdGet8(PcdShellSupportLevel), L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_DATE)   );
    118     ShellCommandRegisterCommandName(L"time",     ShellCommandRunTime    , ShellCommandGetManFileNameLevel2, PcdGet8(PcdShellSupportLevel), L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_TIME)   );
    119     ShellCommandRegisterCommandName(L"timezone", ShellCommandRunTimeZone, ShellCommandGetManFileNameLevel2, PcdGet8(PcdShellSupportLevel), L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_TIMEZONE));
    120   } else {
    121     DEBUG_CODE_BEGIN();
    122     //
    123     // we want to be able to test these so install them under a different name in debug mode...
    124     //
    125     ShellCommandRegisterCommandName(L"l2date",     ShellCommandRunDate    , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_DATE)   );
    126     ShellCommandRegisterCommandName(L"l2time",     ShellCommandRunTime    , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_TIME)   );
    127     ShellCommandRegisterCommandName(L"l2timezone", ShellCommandRunTimeZone, ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_TIMEZONE));
    128     DEBUG_CODE_END();
    129   }
    130 
    131   return (EFI_SUCCESS);
    132 }
    133 
    134 /**
    135   Destructor for the library.  free any resources.
    136 
    137   @param ImageHandle    The image handle of the process.
    138   @param SystemTable    The EFI System Table pointer.
    139 
    140   @retval EFI_SUCCESS   Always returned.
    141 **/
    142 EFI_STATUS
    143 EFIAPI
    144 ShellLevel2CommandsLibDestructor (
    145   IN EFI_HANDLE        ImageHandle,
    146   IN EFI_SYSTEM_TABLE  *SystemTable
    147   )
    148 {
    149   if (gShellLevel2HiiHandle != NULL) {
    150     HiiRemovePackages(gShellLevel2HiiHandle);
    151   }
    152   return (EFI_SUCCESS);
    153 }
    154 
    155 /**
    156   returns a fully qualified directory (contains a map drive at the begining)
    157   path from a unknown directory path.
    158 
    159   If Path is already fully qualified this will return a duplicat otherwise this
    160   will use get the current directory and use that to build the fully qualified
    161   version.
    162 
    163   if the return value is not NULL it must be caller freed.
    164 
    165   @param[in] Path         The unknown Path Value
    166 
    167   @retval NULL            A memory allocation failed
    168   @retval NULL            A fully qualified path could not be discovered.
    169   @retval other           An allocated pointer to a fuly qualified path.
    170 **/
    171 CHAR16*
    172 EFIAPI
    173 GetFullyQualifiedPath(
    174   IN CONST CHAR16* Path
    175   )
    176 {
    177   CHAR16        *PathToReturn;
    178   UINTN         Size;
    179   CONST CHAR16  *CurDir;
    180 
    181   PathToReturn  = NULL;
    182   Size          = 0;
    183 
    184   ASSERT((PathToReturn == NULL && Size == 0) || (PathToReturn != NULL));
    185   //
    186   // convert a local path to an absolute path
    187   //
    188   if (StrStr(Path, L":") == NULL) {
    189     CurDir = gEfiShellProtocol->GetCurDir(NULL);
    190     StrnCatGrow(&PathToReturn, &Size, CurDir, 0);
    191     StrnCatGrow(&PathToReturn, &Size, L"\\", 0);
    192     if (*Path == L'\\') {
    193       Path++;
    194     }
    195   }
    196   StrnCatGrow(&PathToReturn, &Size, Path, 0);
    197 
    198   PathCleanUpDirectories(PathToReturn);
    199 
    200   if (PathToReturn == NULL) {
    201     return NULL;
    202   }
    203 
    204   while (PathToReturn[StrLen(PathToReturn)-1] == L'*') {
    205     PathToReturn[StrLen(PathToReturn)-1] = CHAR_NULL;
    206   }
    207 
    208   return (PathToReturn);
    209 }
    210 
    211 /**
    212   Function to verify all intermediate directories in the path.
    213 
    214   @param[in] Path       The pointer to the path to fix.
    215 
    216   @retval EFI_SUCCESS   The operation was successful.
    217 **/
    218 EFI_STATUS
    219 EFIAPI
    220 VerifyIntermediateDirectories (
    221   IN CONST CHAR16 *Path
    222   )
    223 {
    224   EFI_STATUS      Status;
    225   CHAR16          *PathCopy;
    226   CHAR16          *TempSpot;
    227   SHELL_FILE_HANDLE          FileHandle;
    228 
    229   ASSERT(Path != NULL);
    230 
    231   Status      = EFI_SUCCESS;
    232   PathCopy    = NULL;
    233   PathCopy    = StrnCatGrow(&PathCopy, NULL, Path, 0);
    234   FileHandle  = NULL;
    235 
    236   if (PathCopy == NULL) {
    237     return (EFI_OUT_OF_RESOURCES);
    238   }
    239 
    240   for (TempSpot = &PathCopy[StrLen(PathCopy)-1] ; *TempSpot != CHAR_NULL && *TempSpot != L'\\' ; TempSpot = &PathCopy[StrLen(PathCopy)-1]){
    241     *TempSpot = CHAR_NULL;
    242   }
    243   if (*TempSpot == L'\\') {
    244     *TempSpot = CHAR_NULL;
    245   }
    246 
    247   if (PathCopy != NULL && *PathCopy != CHAR_NULL) {
    248     Status = VerifyIntermediateDirectories(PathCopy);
    249 
    250     if (PathCopy[StrLen(PathCopy)-1] != L':') {
    251       if (!EFI_ERROR(Status)) {
    252         Status = ShellOpenFileByName(PathCopy, &FileHandle, EFI_FILE_MODE_READ, 0);
    253         if (FileHandle != NULL) {
    254           ShellCloseFile(&FileHandle);
    255         }
    256       }
    257     }
    258   }
    259 
    260   SHELL_FREE_NON_NULL(PathCopy);
    261 
    262   return (Status);
    263 }
    264 
    265 /**
    266   Be lazy and borrow from baselib.
    267 
    268   @param[in] Char   The character to convert to upper case.
    269 
    270   @return Char as an upper case character.
    271 **/
    272 CHAR16
    273 EFIAPI
    274 InternalCharToUpper (
    275   IN CONST CHAR16                    Char
    276   );
    277 
    278 /**
    279   String comparison without regard to case for a limited number of characters.
    280 
    281   @param[in] Source   The first item to compare.
    282   @param[in] Target   The second item to compare.
    283   @param[in] Count    How many characters to compare.
    284 
    285   @retval NULL Source and Target are identical strings without regard to case.
    286   @return The location in Source where there is a difference.
    287 **/
    288 CONST CHAR16*
    289 EFIAPI
    290 StrniCmp(
    291   IN CONST CHAR16 *Source,
    292   IN CONST CHAR16 *Target,
    293   IN CONST UINTN  Count
    294   )
    295 {
    296   UINTN   LoopCount;
    297   CHAR16  Char1;
    298   CHAR16  Char2;
    299 
    300   ASSERT(Source != NULL);
    301   ASSERT(Target != NULL);
    302 
    303   for (LoopCount = 0 ; LoopCount < Count ; LoopCount++) {
    304     Char1 = InternalCharToUpper(Source[LoopCount]);
    305     Char2 = InternalCharToUpper(Target[LoopCount]);
    306     if (Char1 != Char2) {
    307       return (&Source[LoopCount]);
    308     }
    309   }
    310   return (NULL);
    311 }
    312 
    313 
    314 /**
    315   Cleans off all the quotes in the string.
    316 
    317   @param[in]     OriginalString   pointer to the string to be cleaned.
    318   @param[out]   CleanString      The new string with all quotes removed.
    319                                                   Memory allocated in the function and free
    320                                                   by caller.
    321 
    322   @retval EFI_SUCCESS   The operation was successful.
    323 **/
    324 EFI_STATUS
    325 EFIAPI
    326 ShellLevel2StripQuotes (
    327   IN  CONST CHAR16     *OriginalString,
    328   OUT CHAR16           **CleanString
    329   )
    330 {
    331   CHAR16            *Walker;
    332 
    333   if (OriginalString == NULL || CleanString == NULL) {
    334     return EFI_INVALID_PARAMETER;
    335   }
    336 
    337   *CleanString = AllocateCopyPool (StrSize (OriginalString), OriginalString);
    338   if (*CleanString == NULL) {
    339     return EFI_OUT_OF_RESOURCES;
    340   }
    341 
    342   for (Walker = *CleanString; Walker != NULL && *Walker != CHAR_NULL ; Walker++) {
    343     if (*Walker == L'\"') {
    344       CopyMem(Walker, Walker+1, StrSize(Walker) - sizeof(Walker[0]));
    345     }
    346   }
    347 
    348   return EFI_SUCCESS;
    349 }
    350 
    351 
    352