| /** @file | |
| Main file for NULL named library for level 2 shell command functions. | |
| these functions are: | |
| attrib, | |
| cd, | |
| cp, | |
| date*, | |
| time*, | |
| load, | |
| ls, | |
| map, | |
| mkdir, | |
| mv, | |
| parse, | |
| rm, | |
| reset, | |
| set, | |
| timezone*, | |
| vol | |
| * functions are non-interactive only | |
| Copyright (c) 2014 Hewlett-Packard Development Company, L.P. | |
| Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR> | |
| SPDX-License-Identifier: BSD-2-Clause-Patent | |
| **/ | |
| #include "UefiShellLevel2CommandsLib.h" | |
| CONST CHAR16 mFileName[] = L"ShellCommands"; | |
| EFI_HII_HANDLE gShellLevel2HiiHandle = NULL; | |
| /** | |
| Get the filename to get help text from if not using HII. | |
| @retval The filename. | |
| **/ | |
| CONST CHAR16 * | |
| EFIAPI | |
| ShellCommandGetManFileNameLevel2 ( | |
| VOID | |
| ) | |
| { | |
| return (mFileName); | |
| } | |
| /** | |
| Constructor for the Shell Level 2 Commands library. | |
| Install the handlers for level 2 UEFI Shell 2.0 commands. | |
| @param ImageHandle the image handle of the process | |
| @param SystemTable the EFI System Table pointer | |
| @retval EFI_SUCCESS the shell command handlers were installed sucessfully | |
| @retval EFI_UNSUPPORTED the shell level required was not found. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| ShellLevel2CommandsLibConstructor ( | |
| IN EFI_HANDLE ImageHandle, | |
| IN EFI_SYSTEM_TABLE *SystemTable | |
| ) | |
| { | |
| // | |
| // if shell level is less than 2 do nothing | |
| // | |
| if (PcdGet8 (PcdShellSupportLevel) < 2) { | |
| return (EFI_SUCCESS); | |
| } | |
| gShellLevel2HiiHandle = HiiAddPackages (&gShellLevel2HiiGuid, gImageHandle, UefiShellLevel2CommandsLibStrings, NULL); | |
| if (gShellLevel2HiiHandle == NULL) { | |
| return (EFI_DEVICE_ERROR); | |
| } | |
| // | |
| // install our shell command handlers that are always installed | |
| // | |
| ShellCommandRegisterCommandName (L"attrib", ShellCommandRunAttrib, ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN (STR_GET_HELP_ATTRIB)); | |
| ShellCommandRegisterCommandName (L"cd", ShellCommandRunCd, ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN (STR_GET_HELP_CD)); | |
| ShellCommandRegisterCommandName (L"cp", ShellCommandRunCp, ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN (STR_GET_HELP_CP)); | |
| ShellCommandRegisterCommandName (L"load", ShellCommandRunLoad, ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN (STR_GET_HELP_LOAD)); | |
| ShellCommandRegisterCommandName (L"map", ShellCommandRunMap, ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN (STR_GET_HELP_MAP)); | |
| ShellCommandRegisterCommandName (L"mkdir", ShellCommandRunMkDir, ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN (STR_GET_HELP_MKDIR)); | |
| ShellCommandRegisterCommandName (L"mv", ShellCommandRunMv, ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN (STR_GET_HELP_MV)); | |
| ShellCommandRegisterCommandName (L"parse", ShellCommandRunParse, ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN (STR_GET_HELP_PARSE)); | |
| ShellCommandRegisterCommandName (L"reset", ShellCommandRunReset, ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN (STR_GET_HELP_RESET)); | |
| ShellCommandRegisterCommandName (L"set", ShellCommandRunSet, ShellCommandGetManFileNameLevel2, 2, L"", FALSE, gShellLevel2HiiHandle, STRING_TOKEN (STR_GET_HELP_SET)); | |
| ShellCommandRegisterCommandName (L"ls", ShellCommandRunLs, ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN (STR_GET_HELP_LS)); | |
| ShellCommandRegisterCommandName (L"rm", ShellCommandRunRm, ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN (STR_GET_HELP_RM)); | |
| ShellCommandRegisterCommandName (L"vol", ShellCommandRunVol, ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN (STR_GET_HELP_VOL)); | |
| // | |
| // support for permanent (built in) aliases | |
| // | |
| ShellCommandRegisterAlias (L"rm", L"del"); | |
| ShellCommandRegisterAlias (L"ls", L"dir"); | |
| ShellCommandRegisterAlias (L"cp", L"copy"); | |
| ShellCommandRegisterAlias (L"mkdir", L"md"); | |
| ShellCommandRegisterAlias (L"cd ..", L"cd.."); | |
| ShellCommandRegisterAlias (L"cd \\", L"cd\\"); | |
| ShellCommandRegisterAlias (L"mv", L"ren"); | |
| ShellCommandRegisterAlias (L"mv", L"move"); | |
| ShellCommandRegisterAlias (L"map", L"mount"); | |
| // | |
| // These are installed in level 2 or 3... | |
| // | |
| if ((PcdGet8 (PcdShellSupportLevel) == 2) || (PcdGet8 (PcdShellSupportLevel) == 3)) { | |
| ShellCommandRegisterCommandName (L"date", ShellCommandRunDate, ShellCommandGetManFileNameLevel2, PcdGet8 (PcdShellSupportLevel), L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN (STR_GET_HELP_DATE)); | |
| ShellCommandRegisterCommandName (L"time", ShellCommandRunTime, ShellCommandGetManFileNameLevel2, PcdGet8 (PcdShellSupportLevel), L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN (STR_GET_HELP_TIME)); | |
| ShellCommandRegisterCommandName (L"timezone", ShellCommandRunTimeZone, ShellCommandGetManFileNameLevel2, PcdGet8 (PcdShellSupportLevel), L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN (STR_GET_HELP_TIMEZONE)); | |
| } else { | |
| DEBUG_CODE_BEGIN (); | |
| // | |
| // we want to be able to test these so install them under a different name in debug mode... | |
| // | |
| ShellCommandRegisterCommandName (L"l2date", ShellCommandRunDate, ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN (STR_GET_HELP_DATE)); | |
| ShellCommandRegisterCommandName (L"l2time", ShellCommandRunTime, ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN (STR_GET_HELP_TIME)); | |
| ShellCommandRegisterCommandName (L"l2timezone", ShellCommandRunTimeZone, ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN (STR_GET_HELP_TIMEZONE)); | |
| DEBUG_CODE_END (); | |
| } | |
| return (EFI_SUCCESS); | |
| } | |
| /** | |
| Destructor for the library. free any resources. | |
| @param ImageHandle The image handle of the process. | |
| @param SystemTable The EFI System Table pointer. | |
| @retval EFI_SUCCESS Always returned. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| ShellLevel2CommandsLibDestructor ( | |
| IN EFI_HANDLE ImageHandle, | |
| IN EFI_SYSTEM_TABLE *SystemTable | |
| ) | |
| { | |
| if (gShellLevel2HiiHandle != NULL) { | |
| HiiRemovePackages (gShellLevel2HiiHandle); | |
| } | |
| return (EFI_SUCCESS); | |
| } | |
| /** | |
| returns a fully qualified directory (contains a map drive at the begining) | |
| path from a unknown directory path. | |
| If Path is already fully qualified this will return a duplicat otherwise this | |
| will use get the current directory and use that to build the fully qualified | |
| version. | |
| if the return value is not NULL it must be caller freed. | |
| @param[in] Path The unknown Path Value | |
| @retval NULL A memory allocation failed | |
| @retval NULL A fully qualified path could not be discovered. | |
| @retval other An allocated pointer to a fuly qualified path. | |
| **/ | |
| CHAR16 * | |
| GetFullyQualifiedPath ( | |
| IN CONST CHAR16 *Path | |
| ) | |
| { | |
| CHAR16 *PathToReturn; | |
| UINTN Size; | |
| CONST CHAR16 *CurDir; | |
| PathToReturn = NULL; | |
| Size = 0; | |
| ASSERT ((PathToReturn == NULL && Size == 0) || (PathToReturn != NULL)); | |
| // | |
| // convert a local path to an absolute path | |
| // | |
| if (StrStr (Path, L":") == NULL) { | |
| CurDir = gEfiShellProtocol->GetCurDir (NULL); | |
| StrnCatGrow (&PathToReturn, &Size, CurDir, 0); | |
| StrnCatGrow (&PathToReturn, &Size, L"\\", 0); | |
| if (*Path == L'\\') { | |
| Path++; | |
| } | |
| } | |
| StrnCatGrow (&PathToReturn, &Size, Path, 0); | |
| PathCleanUpDirectories (PathToReturn); | |
| if (PathToReturn == NULL) { | |
| return NULL; | |
| } | |
| while (PathToReturn[StrLen (PathToReturn)-1] == L'*') { | |
| PathToReturn[StrLen (PathToReturn)-1] = CHAR_NULL; | |
| } | |
| return (PathToReturn); | |
| } | |
| /** | |
| Function to verify all intermediate directories in the path. | |
| @param[in] Path The pointer to the path to fix. | |
| @retval EFI_SUCCESS The operation was successful. | |
| **/ | |
| EFI_STATUS | |
| VerifyIntermediateDirectories ( | |
| IN CONST CHAR16 *Path | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| CHAR16 *PathCopy; | |
| CHAR16 *TempSpot; | |
| SHELL_FILE_HANDLE FileHandle; | |
| ASSERT (Path != NULL); | |
| Status = EFI_SUCCESS; | |
| PathCopy = NULL; | |
| PathCopy = StrnCatGrow (&PathCopy, NULL, Path, 0); | |
| FileHandle = NULL; | |
| if (PathCopy == NULL) { | |
| return (EFI_OUT_OF_RESOURCES); | |
| } | |
| for (TempSpot = &PathCopy[StrLen (PathCopy)-1]; *TempSpot != CHAR_NULL && *TempSpot != L'\\'; TempSpot = &PathCopy[StrLen (PathCopy)-1]) { | |
| *TempSpot = CHAR_NULL; | |
| } | |
| if (*TempSpot == L'\\') { | |
| *TempSpot = CHAR_NULL; | |
| } | |
| if ((PathCopy != NULL) && (*PathCopy != CHAR_NULL)) { | |
| Status = VerifyIntermediateDirectories (PathCopy); | |
| if (PathCopy[StrLen (PathCopy)-1] != L':') { | |
| if (!EFI_ERROR (Status)) { | |
| Status = ShellOpenFileByName (PathCopy, &FileHandle, EFI_FILE_MODE_READ, 0); | |
| if (FileHandle != NULL) { | |
| ShellCloseFile (&FileHandle); | |
| } | |
| } | |
| } | |
| } | |
| SHELL_FREE_NON_NULL (PathCopy); | |
| return (Status); | |
| } | |
| /** | |
| String comparison without regard to case for a limited number of characters. | |
| @param[in] Source The first item to compare. | |
| @param[in] Target The second item to compare. | |
| @param[in] Count How many characters to compare. | |
| @retval 0 Source and Target are identical strings without regard to case. | |
| @retval !=0 Source is not identical to Target. | |
| **/ | |
| INTN | |
| StrniCmp ( | |
| IN CONST CHAR16 *Source, | |
| IN CONST CHAR16 *Target, | |
| IN CONST UINTN Count | |
| ) | |
| { | |
| CHAR16 *SourceCopy; | |
| CHAR16 *TargetCopy; | |
| UINTN SourceLength; | |
| UINTN TargetLength; | |
| INTN Result; | |
| if (Count == 0) { | |
| return 0; | |
| } | |
| SourceLength = StrLen (Source); | |
| TargetLength = StrLen (Target); | |
| SourceLength = MIN (SourceLength, Count); | |
| TargetLength = MIN (TargetLength, Count); | |
| SourceCopy = AllocateCopyPool ((SourceLength + 1) * sizeof (CHAR16), Source); | |
| if (SourceCopy == NULL) { | |
| return -1; | |
| } | |
| TargetCopy = AllocateCopyPool ((TargetLength + 1) * sizeof (CHAR16), Target); | |
| if (TargetCopy == NULL) { | |
| FreePool (SourceCopy); | |
| return -1; | |
| } | |
| SourceCopy[SourceLength] = L'\0'; | |
| TargetCopy[TargetLength] = L'\0'; | |
| Result = gUnicodeCollation->StriColl (gUnicodeCollation, SourceCopy, TargetCopy); | |
| FreePool (SourceCopy); | |
| FreePool (TargetCopy); | |
| return Result; | |
| } | |
| /** | |
| Cleans off all the quotes in the string. | |
| @param[in] OriginalString pointer to the string to be cleaned. | |
| @param[out] CleanString The new string with all quotes removed. | |
| Memory allocated in the function and free | |
| by caller. | |
| @retval EFI_SUCCESS The operation was successful. | |
| **/ | |
| EFI_STATUS | |
| ShellLevel2StripQuotes ( | |
| IN CONST CHAR16 *OriginalString, | |
| OUT CHAR16 **CleanString | |
| ) | |
| { | |
| CHAR16 *Walker; | |
| if ((OriginalString == NULL) || (CleanString == NULL)) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| *CleanString = AllocateCopyPool (StrSize (OriginalString), OriginalString); | |
| if (*CleanString == NULL) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| for (Walker = *CleanString; Walker != NULL && *Walker != CHAR_NULL; Walker++) { | |
| if (*Walker == L'\"') { | |
| CopyMem (Walker, Walker+1, StrSize (Walker) - sizeof (Walker[0])); | |
| } | |
| } | |
| return EFI_SUCCESS; | |
| } |