Home | History | Annotate | Download | only in UefiShellLevel1CommandsLib
      1 /** @file
      2   Main file for NULL named library for level 1 shell command functions.
      3 
      4   (C) Copyright 2013 Hewlett-Packard Development Company, L.P.<BR>
      5   Copyright (c) 2009 - 2011, 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 "UefiShellLevel1CommandsLib.h"
     17 
     18 STATIC CONST CHAR16 mFileName[] = L"ShellCommands";
     19 EFI_HANDLE gShellLevel1HiiHandle = NULL;
     20 
     21 /**
     22   Return the help text filename.  Only used if no HII information found.
     23 
     24   @retval the filename.
     25 **/
     26 CONST CHAR16*
     27 EFIAPI
     28 ShellCommandGetManFileNameLevel1 (
     29   VOID
     30   )
     31 {
     32   return (mFileName);
     33 }
     34 
     35 /**
     36   Constructor for the Shell Level 1 Commands library.
     37 
     38   Install the handlers for level 1 UEFI Shell 2.0 commands.
     39 
     40   @param ImageHandle    the image handle of the process
     41   @param SystemTable    the EFI System Table pointer
     42 
     43   @retval EFI_SUCCESS        the shell command handlers were installed sucessfully
     44   @retval EFI_UNSUPPORTED    the shell level required was not found.
     45 **/
     46 EFI_STATUS
     47 EFIAPI
     48 ShellLevel1CommandsLibConstructor (
     49   IN EFI_HANDLE        ImageHandle,
     50   IN EFI_SYSTEM_TABLE  *SystemTable
     51   )
     52 {
     53   //
     54   // if shell level is less than 2 do nothing
     55   //
     56   if (PcdGet8(PcdShellSupportLevel) < 1) {
     57     return (EFI_SUCCESS);
     58   }
     59 
     60   gShellLevel1HiiHandle = HiiAddPackages (&gShellLevel1HiiGuid, gImageHandle, UefiShellLevel1CommandsLibStrings, NULL);
     61   if (gShellLevel1HiiHandle == NULL) {
     62     return (EFI_DEVICE_ERROR);
     63   }
     64 
     65   //
     66   // install our shell command handlers that are always installed
     67   //
     68   ShellCommandRegisterCommandName(L"stall",  ShellCommandRunStall   , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_STALL) ));
     69   ShellCommandRegisterCommandName(L"for",    ShellCommandRunFor     , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_FOR)   ));
     70   ShellCommandRegisterCommandName(L"goto",   ShellCommandRunGoto    , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_GOTO)  ));
     71   ShellCommandRegisterCommandName(L"if",     ShellCommandRunIf      , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_IF)    ));
     72   ShellCommandRegisterCommandName(L"shift",  ShellCommandRunShift   , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_SHIFT) ));
     73   ShellCommandRegisterCommandName(L"exit",   ShellCommandRunExit    , ShellCommandGetManFileNameLevel1, 1, L"", TRUE , gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_EXIT)  ));
     74   ShellCommandRegisterCommandName(L"else",   ShellCommandRunElse    , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_ELSE)  ));
     75   ShellCommandRegisterCommandName(L"endif",  ShellCommandRunEndIf   , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_ENDIF) ));
     76   ShellCommandRegisterCommandName(L"endfor", ShellCommandRunEndFor  , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_ENDFOR)));
     77 
     78   return (EFI_SUCCESS);
     79 }
     80 
     81 /**
     82   Destructor for the library.  free any resources.
     83 
     84   @param ImageHandle            The image handle of the process.
     85   @param SystemTable            The EFI System Table pointer.
     86 **/
     87 EFI_STATUS
     88 EFIAPI
     89 ShellLevel1CommandsLibDestructor (
     90   IN EFI_HANDLE        ImageHandle,
     91   IN EFI_SYSTEM_TABLE  *SystemTable
     92   )
     93 {
     94   if (gShellLevel1HiiHandle != NULL) {
     95     HiiRemovePackages(gShellLevel1HiiHandle);
     96   }
     97   return (EFI_SUCCESS);
     98 }
     99 
    100 /**
    101   Test a node to see if meets the criterion.
    102 
    103   It functions so that count starts at 1 and it increases or decreases when it
    104   hits the specified tags.  when it hits zero the location has been found.
    105 
    106   DecrementerTag and IncrementerTag are used to get around for/endfor and
    107   similar paired types where the entire middle should be ignored.
    108 
    109   If label is used it will be used instead of the count.
    110 
    111   @param[in] Function          The function to use to enumerate through the
    112                                list.  Normally GetNextNode or GetPreviousNode.
    113   @param[in] DecrementerTag    The tag to decrement the count at.
    114   @param[in] IncrementerTag    The tag to increment the count at.
    115   @param[in] Label             A label to look for.
    116   @param[in, out] ScriptFile   The pointer to the current script file structure.
    117   @param[in] MovePast          TRUE makes function return 1 past the found
    118                                location.
    119   @param[in] FindOnly          TRUE to not change the ScriptFile.
    120   @param[in] CommandNode       The pointer to the Node to test.
    121   @param[in, out] TargetCount  The pointer to the current count.
    122 **/
    123 BOOLEAN
    124 EFIAPI
    125 TestNodeForMove (
    126   IN CONST LIST_MANIP_FUNC      Function,
    127   IN CONST CHAR16               *DecrementerTag,
    128   IN CONST CHAR16               *IncrementerTag,
    129   IN CONST CHAR16               *Label OPTIONAL,
    130   IN OUT SCRIPT_FILE            *ScriptFile,
    131   IN CONST BOOLEAN              MovePast,
    132   IN CONST BOOLEAN              FindOnly,
    133   IN CONST SCRIPT_COMMAND_LIST  *CommandNode,
    134   IN OUT UINTN                  *TargetCount
    135   )
    136 {
    137   BOOLEAN             Found;
    138   CHAR16              *CommandName;
    139   CHAR16              *CommandNameWalker;
    140   CHAR16              *TempLocation;
    141 
    142   Found = FALSE;
    143 
    144   //
    145   // get just the first part of the command line...
    146   //
    147   CommandName   = NULL;
    148   CommandName   = StrnCatGrow(&CommandName, NULL, CommandNode->Cl, 0);
    149   if (CommandName == NULL) {
    150     return (FALSE);
    151   }
    152 
    153   CommandNameWalker = CommandName;
    154 
    155   //
    156   // Skip leading spaces and tabs.
    157   //
    158   while ((CommandNameWalker[0] == L' ') || (CommandNameWalker[0] == L'\t')) {
    159     CommandNameWalker++;
    160   }
    161   TempLocation  = StrStr(CommandNameWalker, L" ");
    162 
    163   if (TempLocation != NULL) {
    164     *TempLocation = CHAR_NULL;
    165   }
    166 
    167   //
    168   // did we find a nested item ?
    169   //
    170   if (gUnicodeCollation->StriColl(
    171       gUnicodeCollation,
    172       (CHAR16*)CommandNameWalker,
    173       (CHAR16*)IncrementerTag) == 0) {
    174     (*TargetCount)++;
    175   } else if (gUnicodeCollation->StriColl(
    176       gUnicodeCollation,
    177       (CHAR16*)CommandNameWalker,
    178       (CHAR16*)DecrementerTag) == 0) {
    179     if (*TargetCount > 0) {
    180       (*TargetCount)--;
    181     }
    182   }
    183 
    184   //
    185   // did we find the matching one...
    186   //
    187   if (Label == NULL) {
    188     if (*TargetCount == 0) {
    189       Found = TRUE;
    190       if (!FindOnly) {
    191         if (MovePast) {
    192           ScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)(*Function)(&ScriptFile->CommandList, &CommandNode->Link);
    193         } else {
    194           ScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)CommandNode;
    195         }
    196       }
    197     }
    198   } else {
    199     if (gUnicodeCollation->StriColl(
    200       gUnicodeCollation,
    201       (CHAR16*)CommandNameWalker,
    202       (CHAR16*)Label) == 0
    203       && (*TargetCount) == 0) {
    204       Found = TRUE;
    205       if (!FindOnly) {
    206         //
    207         // we found the target label without loops
    208         //
    209         if (MovePast) {
    210           ScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)(*Function)(&ScriptFile->CommandList, &CommandNode->Link);
    211         } else {
    212           ScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)CommandNode;
    213         }
    214       }
    215     }
    216   }
    217 
    218   //
    219   // Free the memory for this loop...
    220   //
    221   FreePool(CommandName);
    222   return (Found);
    223 }
    224 
    225 /**
    226   Move the script pointer from 1 tag (line) to another.
    227 
    228   It functions so that count starts at 1 and it increases or decreases when it
    229   hits the specified tags.  when it hits zero the location has been found.
    230 
    231   DecrementerTag and IncrementerTag are used to get around for/endfor and
    232   similar paired types where the entire middle should be ignored.
    233 
    234   If label is used it will be used instead of the count.
    235 
    236   @param[in] Function          The function to use to enumerate through the
    237                                list.  Normally GetNextNode or GetPreviousNode.
    238   @param[in] DecrementerTag    The tag to decrement the count at.
    239   @param[in] IncrementerTag    The tag to increment the count at.
    240   @param[in] Label             A label to look for.
    241   @param[in, out] ScriptFile   The pointer to the current script file structure.
    242   @param[in] MovePast          TRUE makes function return 1 past the found
    243                                location.
    244   @param[in] FindOnly          TRUE to not change the ScriptFile.
    245   @param[in] WrapAroundScript  TRUE to wrap end-to-begining or vise versa in
    246                                searching.
    247 **/
    248 BOOLEAN
    249 EFIAPI
    250 MoveToTag (
    251   IN CONST LIST_MANIP_FUNC      Function,
    252   IN CONST CHAR16               *DecrementerTag,
    253   IN CONST CHAR16               *IncrementerTag,
    254   IN CONST CHAR16               *Label OPTIONAL,
    255   IN OUT SCRIPT_FILE            *ScriptFile,
    256   IN CONST BOOLEAN              MovePast,
    257   IN CONST BOOLEAN              FindOnly,
    258   IN CONST BOOLEAN              WrapAroundScript
    259   )
    260 {
    261   SCRIPT_COMMAND_LIST *CommandNode;
    262   BOOLEAN             Found;
    263   UINTN               TargetCount;
    264 
    265   if (Label == NULL) {
    266     TargetCount       = 1;
    267   } else {
    268     TargetCount       = 0;
    269   }
    270 
    271   if (ScriptFile == NULL) {
    272     return FALSE;
    273   }
    274 
    275   for (CommandNode = (SCRIPT_COMMAND_LIST *)(*Function)(&ScriptFile->CommandList, &ScriptFile->CurrentCommand->Link), Found = FALSE
    276     ;  !IsNull(&ScriptFile->CommandList, &CommandNode->Link)&& !Found
    277     ;  CommandNode = (SCRIPT_COMMAND_LIST *)(*Function)(&ScriptFile->CommandList, &CommandNode->Link)
    278    ){
    279     Found = TestNodeForMove(
    280       Function,
    281       DecrementerTag,
    282       IncrementerTag,
    283       Label,
    284       ScriptFile,
    285       MovePast,
    286       FindOnly,
    287       CommandNode,
    288       &TargetCount);
    289   }
    290 
    291   if (WrapAroundScript && !Found) {
    292     for (CommandNode = (SCRIPT_COMMAND_LIST *)GetFirstNode(&ScriptFile->CommandList), Found = FALSE
    293       ;  CommandNode != ScriptFile->CurrentCommand && !Found
    294       ;  CommandNode = (SCRIPT_COMMAND_LIST *)(*Function)(&ScriptFile->CommandList, &CommandNode->Link)
    295      ){
    296       Found = TestNodeForMove(
    297         Function,
    298         DecrementerTag,
    299         IncrementerTag,
    300         Label,
    301         ScriptFile,
    302         MovePast,
    303         FindOnly,
    304         CommandNode,
    305         &TargetCount);
    306     }
    307   }
    308   return (Found);
    309 }
    310 
    311