]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellLevel2CommandsLib/Cd.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / ShellPkg / Library / UefiShellLevel2CommandsLib / Cd.c
1 /** @file
2 Main file for attrib shell level 2 function.
3
4 (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
5 (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
6 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
7 Copyright (c) 2018, Dell Technologies. All rights reserved.<BR>
8 SPDX-License-Identifier: BSD-2-Clause-Patent
9
10 **/
11
12 #include "UefiShellLevel2CommandsLib.h"
13
14 /**
15 Function will replace drive identifier with CWD.
16
17 If FullPath begining with ':' is invalid path, then ASSERT.
18 If FullPath not include dirve identifier , then do nothing.
19 If FullPath likes "fs0:\xx" or "fs0:/xx" , then do nothing.
20 If FullPath likes "fs0:xxx" or "fs0:", the drive replaced by CWD.
21
22 @param[in, out] FullPath The pointer to the string containing the path.
23 @param[in] Cwd Current directory.
24
25 @retval EFI_SUCCESS Success.
26 @retval EFI_OUT_OF_SOURCES A memory allocation failed.
27 **/
28 EFI_STATUS
29 ReplaceDriveWithCwd (
30 IN OUT CHAR16 **FullPath,
31 IN CONST CHAR16 *Cwd
32 )
33 {
34 CHAR16 *Splitter;
35 CHAR16 *TempBuffer;
36 UINTN TotalSize;
37
38 Splitter = NULL;
39 TempBuffer = NULL;
40 TotalSize = 0;
41
42 if ((FullPath == NULL) || (*FullPath == NULL)) {
43 return EFI_SUCCESS;
44 }
45
46 Splitter = StrStr (*FullPath, L":");
47 ASSERT (Splitter != *FullPath);
48
49 if ((Splitter != NULL) && (*(Splitter + 1) != L'\\') && (*(Splitter + 1) != L'/')) {
50 TotalSize = StrSize (Cwd) + StrSize (Splitter + 1);
51 TempBuffer = AllocateZeroPool (TotalSize);
52 if (TempBuffer == NULL) {
53 return EFI_OUT_OF_RESOURCES;
54 }
55
56 StrCpyS (TempBuffer, TotalSize / sizeof (CHAR16), Cwd);
57 StrCatS (TempBuffer, TotalSize / sizeof (CHAR16), L"\\");
58 StrCatS (TempBuffer, TotalSize / sizeof (CHAR16), Splitter + 1);
59
60 FreePool (*FullPath);
61 *FullPath = TempBuffer;
62 }
63
64 return EFI_SUCCESS;
65 }
66
67 /**
68 function to determine if FullPath is under current filesystem.
69
70 @param[in] FullPath The target location to determine.
71 @param[in] Cwd Current directory.
72
73 @retval TRUE The FullPath is in the current filesystem.
74 @retval FALSE The FullPaht isn't in the current filesystem.
75 **/
76 BOOLEAN
77 IsCurrentFileSystem (
78 IN CONST CHAR16 *FullPath,
79 IN CONST CHAR16 *Cwd
80 )
81 {
82 CHAR16 *Splitter1;
83 CHAR16 *Splitter2;
84
85 Splitter1 = NULL;
86 Splitter2 = NULL;
87
88 ASSERT (FullPath != NULL);
89
90 Splitter1 = StrStr (FullPath, L":");
91 if (Splitter1 == NULL) {
92 return TRUE;
93 }
94
95 Splitter2 = StrStr (Cwd, L":");
96
97 if (((UINTN)Splitter1 - (UINTN)FullPath) != ((UINTN)Splitter2 - (UINTN)Cwd)) {
98 return FALSE;
99 } else {
100 if (StrniCmp (FullPath, Cwd, ((UINTN)Splitter1 - (UINTN)FullPath) / sizeof (CHAR16)) == 0) {
101 return TRUE;
102 } else {
103 return FALSE;
104 }
105 }
106 }
107
108 /**
109 Extract drive string and path string from FullPath.
110
111 The caller must be free Drive and Path.
112
113 @param[in] FullPath A path to be extracted.
114 @param[out] Drive Buffer to save drive identifier.
115 @param[out] Path Buffer to save path.
116
117 @retval EFI_SUCCESS Success.
118 @retval EFI_OUT_OF_RESOUCES A memory allocation failed.
119 **/
120 EFI_STATUS
121 ExtractDriveAndPath (
122 IN CONST CHAR16 *FullPath,
123 OUT CHAR16 **Drive,
124 OUT CHAR16 **Path
125 )
126 {
127 CHAR16 *Splitter;
128
129 ASSERT (FullPath != NULL);
130
131 Splitter = StrStr (FullPath, L":");
132
133 if (Splitter == NULL) {
134 *Drive = NULL;
135 *Path = AllocateCopyPool (StrSize (FullPath), FullPath);
136 if (*Path == NULL) {
137 return EFI_OUT_OF_RESOURCES;
138 }
139 } else {
140 if (*(Splitter + 1) == CHAR_NULL) {
141 *Drive = AllocateCopyPool (StrSize (FullPath), FullPath);
142 *Path = NULL;
143 if (*Drive == NULL) {
144 return EFI_OUT_OF_RESOURCES;
145 }
146 } else {
147 *Drive = AllocateCopyPool ((Splitter - FullPath + 2) * sizeof (CHAR16), FullPath);
148 if (*Drive == NULL) {
149 return EFI_OUT_OF_RESOURCES;
150 }
151
152 (*Drive)[Splitter - FullPath + 1] = CHAR_NULL;
153
154 *Path = AllocateCopyPool (StrSize (Splitter + 1), Splitter + 1);
155 if (*Path == NULL) {
156 FreePool (*Drive);
157 return EFI_OUT_OF_RESOURCES;
158 }
159 }
160 }
161
162 return EFI_SUCCESS;
163 }
164
165 /**
166 Function for 'cd' command.
167
168 @param[in] ImageHandle Handle to the Image (NULL if Internal).
169 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
170 **/
171 SHELL_STATUS
172 EFIAPI
173 ShellCommandRunCd (
174 IN EFI_HANDLE ImageHandle,
175 IN EFI_SYSTEM_TABLE *SystemTable
176 )
177 {
178 EFI_STATUS Status;
179 LIST_ENTRY *Package;
180 CONST CHAR16 *Cwd;
181 CHAR16 *Path;
182 CHAR16 *Drive;
183 CHAR16 *ProblemParam;
184 SHELL_STATUS ShellStatus;
185 CONST CHAR16 *Param1;
186 CHAR16 *Param1Copy;
187 CHAR16 *Walker;
188 CHAR16 *Splitter;
189 CHAR16 *TempBuffer;
190 UINTN TotalSize;
191
192 ProblemParam = NULL;
193 ShellStatus = SHELL_SUCCESS;
194 Cwd = NULL;
195 Path = NULL;
196 Drive = NULL;
197 Splitter = NULL;
198 TempBuffer = NULL;
199 TotalSize = 0;
200
201 Status = CommandInit ();
202 ASSERT_EFI_ERROR (Status);
203
204 //
205 // initialize the shell lib (we must be in non-auto-init...)
206 //
207 Status = ShellInitialize ();
208 ASSERT_EFI_ERROR (Status);
209
210 //
211 // parse the command line
212 //
213 Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);
214 if (EFI_ERROR (Status)) {
215 if ((Status == EFI_VOLUME_CORRUPTED) && (ProblemParam != NULL)) {
216 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"cd", ProblemParam);
217 FreePool (ProblemParam);
218 ShellStatus = SHELL_INVALID_PARAMETER;
219 } else {
220 ASSERT (FALSE);
221 }
222 }
223
224 //
225 // check for "-?"
226 //
227 if (ShellCommandLineGetFlag (Package, L"-?")) {
228 ASSERT (FALSE);
229 } else if (ShellCommandLineGetRawValue (Package, 2) != NULL) {
230 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"cd");
231 ShellStatus = SHELL_INVALID_PARAMETER;
232 } else {
233 //
234 // remember that param 0 is the command name
235 // If there are 0 value parameters, then print the current directory
236 // else If there are 2 value parameters, then print the error message
237 // else If there is 1 value paramerer , then change the directory
238 //
239 Cwd = ShellGetCurrentDir (NULL);
240 if (Cwd == NULL) {
241 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"cd");
242 ShellStatus = SHELL_NOT_FOUND;
243 } else {
244 Param1 = ShellCommandLineGetRawValue (Package, 1);
245 if (Param1 == NULL) {
246 //
247 // display the current directory
248 //
249 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_CD_PRINT), gShellLevel2HiiHandle, Cwd);
250 } else {
251 Param1Copy = CatSPrint (NULL, L"%s", Param1, NULL);
252 for (Walker = Param1Copy; Walker != NULL && *Walker != CHAR_NULL; Walker++) {
253 if (*Walker == L'\"') {
254 CopyMem (Walker, Walker + 1, StrSize (Walker) - sizeof (Walker[0]));
255 }
256 }
257
258 if ((Param1Copy != NULL) && IsCurrentFileSystem (Param1Copy, Cwd)) {
259 Status = ReplaceDriveWithCwd (&Param1Copy, Cwd);
260 } else {
261 //
262 // Can't use cd command to change filesystem.
263 //
264 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"cd");
265 Status = EFI_NOT_FOUND;
266 }
267
268 if (!EFI_ERROR (Status) && (Param1Copy != NULL)) {
269 Splitter = StrStr (Cwd, L":");
270 if (Param1Copy[0] == L'\\') {
271 //
272 // Absolute Path on current drive letter.
273 //
274 TotalSize = ((Splitter - Cwd + 1) * sizeof (CHAR16)) + StrSize (Param1Copy);
275 TempBuffer = AllocateZeroPool (TotalSize);
276 if (TempBuffer == NULL) {
277 Status = EFI_OUT_OF_RESOURCES;
278 } else {
279 StrnCpyS (TempBuffer, TotalSize / sizeof (CHAR16), Cwd, (Splitter - Cwd + 1));
280 StrCatS (TempBuffer, TotalSize / sizeof (CHAR16), Param1Copy);
281
282 FreePool (Param1Copy);
283 Param1Copy = TempBuffer;
284 TempBuffer = NULL;
285 }
286 } else {
287 if (StrStr (Param1Copy, L":") == NULL) {
288 TotalSize = StrSize (Cwd) + StrSize (Param1Copy);
289 TempBuffer = AllocateZeroPool (TotalSize);
290 if (TempBuffer == NULL) {
291 Status = EFI_OUT_OF_RESOURCES;
292 } else {
293 StrCpyS (TempBuffer, TotalSize / sizeof (CHAR16), Cwd);
294 StrCatS (TempBuffer, TotalSize / sizeof (CHAR16), L"\\");
295 StrCatS (TempBuffer, TotalSize / sizeof (CHAR16), Param1Copy);
296
297 FreePool (Param1Copy);
298 Param1Copy = TempBuffer;
299 TempBuffer = NULL;
300 }
301 }
302 }
303 }
304
305 if (!EFI_ERROR (Status)) {
306 Param1Copy = PathCleanUpDirectories (Param1Copy);
307 Status = ExtractDriveAndPath (Param1Copy, &Drive, &Path);
308 }
309
310 if (!EFI_ERROR (Status) && (Drive != NULL) && (Path != NULL)) {
311 if (EFI_ERROR (ShellIsDirectory (Param1Copy))) {
312 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR), gShellLevel2HiiHandle, L"cd", Param1Copy);
313 ShellStatus = SHELL_NOT_FOUND;
314 } else {
315 Status = gEfiShellProtocol->SetCurDir (Drive, Path + 1);
316 if (EFI_ERROR (Status)) {
317 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF), gShellLevel2HiiHandle, L"cd", Param1Copy);
318 ShellStatus = SHELL_NOT_FOUND;
319 }
320 }
321 }
322
323 if (Drive != NULL) {
324 FreePool (Drive);
325 }
326
327 if (Path != NULL) {
328 FreePool (Path);
329 }
330
331 FreePool (Param1Copy);
332 }
333 }
334 }
335
336 //
337 // free the command line package
338 //
339 ShellCommandLineFreeVarList (Package);
340
341 //
342 // return the status
343 //
344 return (ShellStatus);
345 }