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