/** @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.
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; }