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