1 /** @file
2   Main file for Alias shell level 3 function.
3 
4   (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
5   Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved. <BR>
6   SPDX-License-Identifier: BSD-2-Clause-Patent
7 
8 **/
9 
10 #include "UefiShellLevel3CommandsLib.h"
11 
12 #include <Library/ShellLib.h>
13 
14 /**
15   Print out single alias registered with the Shell.
16 
17   @param[in]  Alias             Points to the NULL-terminated shell alias.
18                                 If this parameter is NULL, then all
19                                 aliases will be returned in ReturnedData.
20   @retval     SHELL_SUCCESS     the printout was sucessful
21 **/
22 SHELL_STATUS
PrintSingleShellAlias(IN CONST CHAR16 * Alias)23 PrintSingleShellAlias(
24   IN  CONST CHAR16 *Alias
25   )
26 {
27   CONST CHAR16        *ConstAliasVal;
28   SHELL_STATUS        ShellStatus;
29   BOOLEAN             Volatile;
30 
31   ShellStatus = SHELL_SUCCESS;
32   ConstAliasVal = gEfiShellProtocol->GetAlias (Alias, &Volatile);
33   if (ConstAliasVal == NULL) {
34     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel3HiiHandle, L"alias", Alias);
35     ShellStatus = SHELL_INVALID_PARAMETER;
36   } else {
37     if (ShellCommandIsOnAliasList (Alias)) {
38       Volatile = FALSE;
39     }
40     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_ALIAS_OUTPUT), gShellLevel3HiiHandle, !Volatile ? L' ' : L'*', Alias, ConstAliasVal);
41   }
42   return ShellStatus;
43 }
44 
45 /**
46   Print out each alias registered with the Shell.
47 
48   @retval STATUS_SUCCESS  the printout was sucessful
49   @return any return code from GetNextVariableName except EFI_NOT_FOUND
50 **/
51 SHELL_STATUS
PrintAllShellAlias(VOID)52 PrintAllShellAlias(
53   VOID
54   )
55 {
56   CONST CHAR16      *ConstAllAliasList;
57   CHAR16            *Alias;
58   CHAR16            *Walker;
59 
60   ConstAllAliasList = gEfiShellProtocol->GetAlias(NULL, NULL);
61   if (ConstAllAliasList == NULL) {
62     return (SHELL_SUCCESS);
63   }
64   Alias = AllocateZeroPool(StrSize(ConstAllAliasList));
65   if (Alias == NULL) {
66     return (SHELL_OUT_OF_RESOURCES);
67   }
68   Walker = (CHAR16*)ConstAllAliasList;
69 
70   do {
71     CopyMem(Alias, Walker, StrSize(Walker));
72     Walker = StrStr(Alias, L";");
73     if (Walker != NULL) {
74       Walker[0] = CHAR_NULL;
75       Walker = Walker + 1;
76     }
77     PrintSingleShellAlias(Alias);
78   } while (Walker != NULL && Walker[0] != CHAR_NULL);
79 
80   FreePool(Alias);
81 
82   return (SHELL_SUCCESS);
83 }
84 
85 /**
86   Changes a shell command alias.
87 
88   This function creates an alias for a shell command or if Alias is NULL it will delete an existing alias.
89 
90 
91   @param[in] Command            Points to the NULL-terminated shell command or existing alias.
92   @param[in] Alias              Points to the NULL-terminated alias for the shell command. If this is NULL, and
93                                 Command refers to an alias, that alias will be deleted.
94   @param[in] Replace            If TRUE and the alias already exists, then the existing alias will be replaced. If
95                                 FALSE and the alias already exists, then the existing alias is unchanged and
96                                 EFI_ACCESS_DENIED is returned.
97   @param[in] Volatile           if TRUE the Alias being set will be stored in a volatile fashion.  if FALSE the
98                                 Alias being set will be stored in a non-volatile fashion.
99 
100   @retval SHELL_SUCCESS        Alias created or deleted successfully.
101   @retval SHELL_NOT_FOUND       the Alias intended to be deleted was not found
102   @retval SHELL_ACCESS_DENIED   The alias is a built-in alias or already existed and Replace was set to
103                                 FALSE.
104   @retval SHELL_DEVICE_ERROR    Command is null or the empty string.
105 **/
106 SHELL_STATUS
ShellLevel3CommandsLibSetAlias(IN CONST CHAR16 * Command,IN CONST CHAR16 * Alias,IN BOOLEAN Replace,IN BOOLEAN Volatile)107 ShellLevel3CommandsLibSetAlias(
108   IN CONST CHAR16 *Command,
109   IN CONST CHAR16 *Alias,
110   IN BOOLEAN Replace,
111   IN BOOLEAN Volatile
112   )
113 {
114   SHELL_STATUS        ShellStatus;
115   EFI_STATUS          Status;
116 
117   ShellStatus = SHELL_SUCCESS;
118   Status = gEfiShellProtocol->SetAlias (Command, Alias, Replace, Volatile);
119   if (EFI_ERROR(Status)) {
120     if (Status == EFI_ACCESS_DENIED) {
121       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellLevel3HiiHandle, L"alias");
122       ShellStatus = SHELL_ACCESS_DENIED;
123     } else if (Status == EFI_NOT_FOUND) {
124       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_NOT_FOUND), gShellLevel3HiiHandle, L"alias", Command);
125       ShellStatus = SHELL_NOT_FOUND;
126     } else {
127       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel3HiiHandle, L"alias", Status);
128       ShellStatus = SHELL_DEVICE_ERROR;
129     }
130   }
131   return ShellStatus;
132 }
133 
134 STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
135   {L"-v", TypeFlag},
136   {L"-d", TypeValue},
137   {NULL, TypeMax}
138   };
139 
140 /**
141   Function for 'alias' command.
142 
143   @param[in] ImageHandle  Handle to the Image (NULL if Internal).
144   @param[in] SystemTable  Pointer to the System Table (NULL if Internal).
145 **/
146 SHELL_STATUS
147 EFIAPI
ShellCommandRunAlias(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)148 ShellCommandRunAlias (
149   IN EFI_HANDLE        ImageHandle,
150   IN EFI_SYSTEM_TABLE  *SystemTable
151   )
152 {
153   EFI_STATUS          Status;
154   LIST_ENTRY          *Package;
155   CHAR16              *ProblemParam;
156   SHELL_STATUS        ShellStatus;
157   CONST CHAR16        *Param1;
158   CONST CHAR16        *Param2;
159   CONST CHAR16        *ParamStrD;
160   CHAR16              *CleanParam2;
161   BOOLEAN             DeleteFlag;
162   BOOLEAN             VolatileFlag;
163 
164   ProblemParam        = NULL;
165   ShellStatus         = SHELL_SUCCESS;
166   CleanParam2         = NULL;
167 
168   //
169   // initialize the shell lib (we must be in non-auto-init...)
170   //
171   Status = ShellInitialize();
172   ASSERT_EFI_ERROR(Status);
173 
174   Status = CommandInit();
175   ASSERT_EFI_ERROR(Status);
176 
177   //
178   // parse the command line
179   //
180   Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
181   if (EFI_ERROR(Status)) {
182     if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
183       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, L"alias", ProblemParam);
184       FreePool(ProblemParam);
185       ShellStatus = SHELL_INVALID_PARAMETER;
186     } else {
187       ASSERT(FALSE);
188     }
189   } else {
190     Param1 = ShellCommandLineGetRawValue(Package, 1);
191     Param2 = ShellCommandLineGetRawValue(Package, 2);
192 
193     DeleteFlag   = ShellCommandLineGetFlag (Package, L"-d");
194     VolatileFlag = ShellCommandLineGetFlag (Package, L"-v");
195 
196     if (Param2 != NULL) {
197       CleanParam2 = AllocateCopyPool (StrSize(Param2), Param2);
198       if (CleanParam2 == NULL) {
199         ShellCommandLineFreeVarList (Package);
200         return SHELL_OUT_OF_RESOURCES;
201       }
202 
203       if (CleanParam2[0] == L'\"' && CleanParam2[StrLen(CleanParam2)-1] == L'\"') {
204         CleanParam2[StrLen(CleanParam2)-1] = L'\0';
205         CopyMem (CleanParam2, CleanParam2 + 1, StrSize(CleanParam2) - sizeof(CleanParam2[0]));
206       }
207     }
208 
209     if (!DeleteFlag && !VolatileFlag) {
210       switch (ShellCommandLineGetCount (Package)) {
211         case 1:
212           //
213           // "alias"
214           //
215           ShellStatus = PrintAllShellAlias ();
216           break;
217         case 2:
218           //
219           // "alias Param1"
220           //
221           ShellStatus = PrintSingleShellAlias (Param1);
222           break;
223         case 3:
224           //
225           // "alias Param1 CleanParam2"
226           //
227           ShellStatus = ShellLevel3CommandsLibSetAlias (CleanParam2, Param1, FALSE, VolatileFlag);
228           break;
229         default:
230           ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel3HiiHandle, L"alias");
231           ShellStatus = SHELL_INVALID_PARAMETER;
232       }
233     } else if (DeleteFlag) {
234       if (VolatileFlag || ShellCommandLineGetCount (Package) > 1) {
235         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel3HiiHandle, L"alias");
236         ShellStatus = SHELL_INVALID_PARAMETER;
237       } else {
238         ParamStrD = ShellCommandLineGetValue (Package, L"-d");
239         if (ParamStrD == NULL) {
240           ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel3HiiHandle, L"alias");
241           ShellStatus = SHELL_INVALID_PARAMETER;
242         } else {
243           //
244           // Delete an alias: "alias -d ParamStrD"
245           //
246           ShellStatus = ShellLevel3CommandsLibSetAlias (ParamStrD, NULL, TRUE, FALSE);
247         }
248       }
249     } else {
250       //
251       // Set volatile alias.
252       //
253       ASSERT (VolatileFlag);
254       ASSERT (!DeleteFlag);
255       switch (ShellCommandLineGetCount (Package)) {
256         case 1:
257         case 2:
258           ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel3HiiHandle, L"alias");
259           ShellStatus = SHELL_INVALID_PARAMETER;
260           break;
261         case 3:
262           //
263           // "alias -v Param1 CleanParam2"
264           //
265           ShellStatus = ShellLevel3CommandsLibSetAlias (CleanParam2, Param1, FALSE, VolatileFlag);
266           break;
267         default:
268           ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel3HiiHandle, L"alias");
269           ShellStatus = SHELL_INVALID_PARAMETER;
270       }
271     }
272     //
273     // free the command line package
274     //
275     ShellCommandLineFreeVarList (Package);
276   }
277 
278   SHELL_FREE_NON_NULL (CleanParam2);
279   return (ShellStatus);
280 }
281