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