blob: ae643996aa72d9a4e4cefffae176668a04502585 [file] [log] [blame]
/** @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 successfully
@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 beginning)
path from a unknown directory path.
If Path is already fully qualified this will return a duplicate 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 fully 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;
}