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