From a405b86d274d32b92f69842bfb9a1ab143128f57 Mon Sep 17 00:00:00 2001 From: jcarsey Date: Tue, 14 Sep 2010 05:18:09 +0000 Subject: udk2010.up2.shell initial release. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10874 6f19259b-4bc3-4df7-8a09-765794883524 --- .../Library/UefiShellLevel2CommandsLib/Attrib.c | 271 +++++ ShellPkg/Library/UefiShellLevel2CommandsLib/Cd.c | 218 ++++ ShellPkg/Library/UefiShellLevel2CommandsLib/Cp.c | 599 +++++++++++ ShellPkg/Library/UefiShellLevel2CommandsLib/Load.c | 282 +++++ ShellPkg/Library/UefiShellLevel2CommandsLib/Ls.c | 564 ++++++++++ ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c | 1116 ++++++++++++++++++++ .../Library/UefiShellLevel2CommandsLib/MkDir.c | 128 +++ ShellPkg/Library/UefiShellLevel2CommandsLib/Mv.c | 478 +++++++++ .../Library/UefiShellLevel2CommandsLib/Parse.c | 190 ++++ .../Library/UefiShellLevel2CommandsLib/Reset.c | 131 +++ ShellPkg/Library/UefiShellLevel2CommandsLib/Rm.c | 296 ++++++ ShellPkg/Library/UefiShellLevel2CommandsLib/Set.c | 169 +++ .../Library/UefiShellLevel2CommandsLib/TimeDate.c | 772 ++++++++++++++ .../UefiShellLevel2CommandsLib.c | 329 ++++++ .../UefiShellLevel2CommandsLib.h | 297 ++++++ .../UefiShellLevel2CommandsLib.inf | 82 ++ .../UefiShellLevel2CommandsLib.uni | Bin 0 -> 105810 bytes 17 files changed, 5922 insertions(+) create mode 100644 ShellPkg/Library/UefiShellLevel2CommandsLib/Attrib.c create mode 100644 ShellPkg/Library/UefiShellLevel2CommandsLib/Cd.c create mode 100644 ShellPkg/Library/UefiShellLevel2CommandsLib/Cp.c create mode 100644 ShellPkg/Library/UefiShellLevel2CommandsLib/Load.c create mode 100644 ShellPkg/Library/UefiShellLevel2CommandsLib/Ls.c create mode 100644 ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c create mode 100644 ShellPkg/Library/UefiShellLevel2CommandsLib/MkDir.c create mode 100644 ShellPkg/Library/UefiShellLevel2CommandsLib/Mv.c create mode 100644 ShellPkg/Library/UefiShellLevel2CommandsLib/Parse.c create mode 100644 ShellPkg/Library/UefiShellLevel2CommandsLib/Reset.c create mode 100644 ShellPkg/Library/UefiShellLevel2CommandsLib/Rm.c create mode 100644 ShellPkg/Library/UefiShellLevel2CommandsLib/Set.c create mode 100644 ShellPkg/Library/UefiShellLevel2CommandsLib/TimeDate.c create mode 100644 ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.c create mode 100644 ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.h create mode 100644 ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf create mode 100644 ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.uni (limited to 'ShellPkg/Library/UefiShellLevel2CommandsLib') diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/Attrib.c b/ShellPkg/Library/UefiShellLevel2CommandsLib/Attrib.c new file mode 100644 index 0000000000..c891ca6afa --- /dev/null +++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/Attrib.c @@ -0,0 +1,271 @@ +/** @file + Main file for attrib shell level 2 function. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel2CommandsLib.h" + +STATIC CONST CHAR16 AllFiles[] = L"*"; + +STATIC CONST SHELL_PARAM_ITEM AttribParamList[] = { + {L"-a", TypeFlag}, + {L"+a", TypeFlag}, + {L"-s", TypeFlag}, + {L"+s", TypeFlag}, + {L"-h", TypeFlag}, + {L"+h", TypeFlag}, + {L"-r", TypeFlag}, + {L"+r", TypeFlag}, + {NULL, TypeMax} + }; + +/** + Function for 'attrib' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunAttrib ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + UINT64 FileAttributesToAdd; + UINT64 FileAttributesToRemove; + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + UINTN ParamNumberCount; + CONST CHAR16 *FileName; + EFI_SHELL_FILE_INFO *ListOfFiles; + EFI_SHELL_FILE_INFO *FileNode; + EFI_FILE_INFO *FileInfo; + + ListOfFiles = NULL; + ShellStatus = SHELL_SUCCESS; + ProblemParam = NULL; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (AttribParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + + // + // check for "-?" + // + if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } else { + FileAttributesToAdd = 0; + FileAttributesToRemove = 0; + + // + // apply or remove each flag + // + if (ShellCommandLineGetFlag(Package, L"+a")) { + FileAttributesToAdd |= EFI_FILE_ARCHIVE; + } + if (ShellCommandLineGetFlag(Package, L"-a")) { + FileAttributesToRemove |= EFI_FILE_ARCHIVE; + } + if (ShellCommandLineGetFlag(Package, L"+s")) { + FileAttributesToAdd |= EFI_FILE_SYSTEM; + } + if (ShellCommandLineGetFlag(Package, L"-s")) { + FileAttributesToRemove |= EFI_FILE_SYSTEM; + } + if (ShellCommandLineGetFlag(Package, L"+h")) { + FileAttributesToAdd |= EFI_FILE_HIDDEN; + } + if (ShellCommandLineGetFlag(Package, L"-h")) { + FileAttributesToRemove |= EFI_FILE_HIDDEN; + } + if (ShellCommandLineGetFlag(Package, L"+r")) { + FileAttributesToAdd |= EFI_FILE_READ_ONLY; + } + if (ShellCommandLineGetFlag(Package, L"-r")) { + FileAttributesToRemove |= EFI_FILE_READ_ONLY; + } + + if (FileAttributesToRemove == 0 && FileAttributesToAdd == 0) { + // + // Do display as we have no attributes to change + // + for ( ParamNumberCount = 1 + ; + ; ParamNumberCount++ + ){ + FileName = ShellCommandLineGetRawValue(Package, ParamNumberCount); + // if we dont have anything left, move on... + if (FileName == NULL && ParamNumberCount == 1) { + FileName = (CHAR16*)AllFiles; + } else if (FileName == NULL) { + break; + } + ASSERT(ListOfFiles == NULL); + Status = ShellOpenFileMetaArg((CHAR16*)FileName, EFI_FILE_MODE_READ, &ListOfFiles); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, ParamNumberCount)); + ShellStatus = SHELL_NOT_FOUND; + } else { + for (FileNode = (EFI_SHELL_FILE_INFO*)GetFirstNode(&ListOfFiles->Link) + ; !IsNull(&ListOfFiles->Link, &FileNode->Link) + ; FileNode = (EFI_SHELL_FILE_INFO*)GetNextNode(&ListOfFiles->Link, &FileNode->Link) + ){ + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_ATTRIB_OUTPUT_LINE), + gShellLevel2HiiHandle, + FileNode->Info->Attribute&EFI_FILE_DIRECTORY? L'D':L' ', + FileNode->Info->Attribute&EFI_FILE_ARCHIVE? L'A':L' ', + FileNode->Info->Attribute&EFI_FILE_SYSTEM? L'S':L' ', + FileNode->Info->Attribute&EFI_FILE_HIDDEN? L'H':L' ', + FileNode->Info->Attribute&EFI_FILE_READ_ONLY? L'R':L' ', + FileNode->FileName + ); + } + Status = ShellCloseFileMetaArg(&ListOfFiles); + ListOfFiles = NULL; + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_CLOSE_FAIL), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, ParamNumberCount)); + ShellStatus = SHELL_NOT_FOUND; + } + } // for loop for handling wildcard filenames + } // for loop for printing out the info + } else if ((FileAttributesToRemove & FileAttributesToAdd) != 0) { + // + // fail as we have conflcting params. + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CON), gShellLevel2HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // enumerate through all the files/directories and apply the attributes + // + for ( ParamNumberCount = 1 + ; + ; ParamNumberCount++ + ){ + FileName = ShellCommandLineGetRawValue(Package, ParamNumberCount); + // if we dont have anything left, move on... + if (FileName == NULL) { + // + // make sure we are not failing on the first one we do... if yes that's an error... + // + if (ParamNumberCount == 1) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } + break; + } + + // + // OpenFileByName / GetFileInfo / Change attributes / SetFileInfo / CloseFile / free memory + // for each file or directory on the line. + // + + // + // Open the file(s) + // + ASSERT(ListOfFiles == NULL); + Status = ShellOpenFileMetaArg((CHAR16*)FileName, EFI_FILE_MODE_READ, &ListOfFiles); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, ParamNumberCount)); + ShellStatus = SHELL_NOT_FOUND; + } else { + for (FileNode = (EFI_SHELL_FILE_INFO*)GetFirstNode(&ListOfFiles->Link) + ; !IsNull(&ListOfFiles->Link, &FileNode->Link) + ; FileNode = (EFI_SHELL_FILE_INFO*)GetNextNode(&ListOfFiles->Link, &FileNode->Link) + ){ + // + // skip the directory traversing stuff... + // + if (StrCmp(FileNode->FileName, L".") == 0 || StrCmp(FileNode->FileName, L"..") == 0) { + continue; + } + + FileInfo = gEfiShellProtocol->GetFileInfo(FileNode->Handle); + + // + // if we are removing Read-Only we need to do that alone + // + if ((FileAttributesToRemove & EFI_FILE_READ_ONLY) == EFI_FILE_READ_ONLY) { + FileInfo->Attribute &= ~EFI_FILE_READ_ONLY; + // + // SetFileInfo + // + Status = ShellSetFileInfo(FileNode->Handle, FileInfo); + if (EFI_ERROR(Status)) {; + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_AD), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, ParamNumberCount)); + ShellStatus = SHELL_ACCESS_DENIED; + } + } + + // + // change the attribute + // + FileInfo->Attribute &= ~FileAttributesToRemove; + FileInfo->Attribute |= FileAttributesToAdd; + + // + // SetFileInfo + // + Status = ShellSetFileInfo(FileNode->Handle, FileInfo); + if (EFI_ERROR(Status)) {; + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_AD), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, ParamNumberCount)); + ShellStatus = SHELL_ACCESS_DENIED; + } + + SHELL_FREE_NON_NULL(FileInfo); + } + Status = ShellCloseFileMetaArg(&ListOfFiles); + ListOfFiles = NULL; + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_CLOSE_FAIL), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, ParamNumberCount)); + ShellStatus = SHELL_NOT_FOUND; + } + } // for loop for handling wildcard filenames + } + } + } + } + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + + // + // return the status + // + return (ShellStatus); +} diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/Cd.c b/ShellPkg/Library/UefiShellLevel2CommandsLib/Cd.c new file mode 100644 index 0000000000..78403c2274 --- /dev/null +++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/Cd.c @@ -0,0 +1,218 @@ +/** @file + Main file for attrib shell level 2 function. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel2CommandsLib.h" + +/** + Function for 'cd' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunCd ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CONST CHAR16 *Directory; + CHAR16 *Path; + CHAR16 *Drive; + UINTN DriveSize; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + SHELL_FILE_HANDLE Handle; + CONST CHAR16 *Param1; + + ProblemParam = NULL; + ShellStatus = SHELL_SUCCESS; + Drive = NULL; + DriveSize = 0; + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } + + // + // check for "-?" + // + if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } else if (ShellCommandLineGetRawValue(Package, 2) != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // remember that param 0 is the command name + // If there are 0 value parameters, then print the current directory + // else If there are 2 value parameters, then print the error message + // else If there is 1 value paramerer , then change the directory + // + Param1 = ShellCommandLineGetRawValue(Package, 1); + if (Param1 == NULL) { + // + // display the current directory + // + Directory = ShellGetCurrentDir(NULL); + if (Directory != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_PRINT), gShellLevel2HiiHandle, Directory); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle); + ShellStatus = SHELL_NOT_FOUND; + } + } else { + if (StrCmp(Param1, L".") == 0) { + // + // nothing to do... change to current directory + // + } else if (StrCmp(Param1, L"..") == 0) { + // + // Change up one directory... + // + Directory = ShellGetCurrentDir(NULL); + if (Directory == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle); + ShellStatus = SHELL_NOT_FOUND; + } else { + Drive = GetFullyQualifiedPath(Directory); + ChopLastSlash(Drive); + } + if (ShellStatus == SHELL_SUCCESS && Drive != NULL) { + // + // change directory on current drive letter + // + Status = gEfiShellProtocol->SetCurDir(NULL, Drive); + if (Status == EFI_NOT_FOUND) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle); + ShellStatus = SHELL_NOT_FOUND; + } + } + } else if (StrCmp(Param1, L"\\") == 0) { + // + // Move to root of current drive + // + Directory = ShellGetCurrentDir(NULL); + if (Directory == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle); + ShellStatus = SHELL_NOT_FOUND; + } else { + Drive = GetFullyQualifiedPath(Directory); + while (ChopLastSlash(Drive)) ; + } + if (ShellStatus == SHELL_SUCCESS && Drive != NULL) { + // + // change directory on current drive letter + // + Status = gEfiShellProtocol->SetCurDir(NULL, Drive); + if (Status == EFI_NOT_FOUND) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle); + ShellStatus = SHELL_NOT_FOUND; + } + } + } else if (StrStr(Param1, L":") == NULL) { + if (ShellGetCurrentDir(NULL) == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle); + ShellStatus = SHELL_NOT_FOUND; + } else { + ASSERT((Drive == NULL && DriveSize == 0) || (Drive != NULL)); + Drive = StrnCatGrow(&Drive, &DriveSize, ShellGetCurrentDir(NULL), 0); + if (*Param1 == L'\\') { + while (ChopLastSlash(Drive)) ; + Drive = StrnCatGrow(&Drive, &DriveSize, Param1+1, 0); + } else { + Drive = StrnCatGrow(&Drive, &DriveSize, Param1, 0); + } + // + // Verify that this is a valid directory + // + Status = gEfiShellProtocol->OpenFileByName(Drive, &Handle, EFI_FILE_MODE_READ); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF), gShellLevel2HiiHandle, Drive); + ShellStatus = SHELL_NOT_FOUND; + } else if (EFI_ERROR(FileHandleIsDirectory(Handle))) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR), gShellLevel2HiiHandle, Drive); + ShellStatus = SHELL_NOT_FOUND; + } + if (ShellStatus == SHELL_SUCCESS && Drive != NULL) { + // + // change directory on current drive letter + // + Status = gEfiShellProtocol->SetCurDir(NULL, Drive); + if (Status == EFI_NOT_FOUND) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle); + ShellStatus = SHELL_NOT_FOUND; + } + } + if (Handle != NULL) { + gEfiShellProtocol->CloseFile(Handle); + DEBUG_CODE(Handle = NULL;); + } + } + } else { + // + // change directory on other drive letter + // + Drive = AllocateZeroPool(StrSize(Param1)); + Drive = StrCpy(Drive, Param1); + Path = StrStr(Drive, L":"); + *(++Path) = CHAR_NULL; + Status = gEfiShellProtocol->SetCurDir(Drive, ++Path); + + if (Status == EFI_NOT_FOUND) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle); + Status = SHELL_NOT_FOUND; + } else if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF), gShellLevel2HiiHandle, Param1); + Status = SHELL_NOT_FOUND; + } + } + } + } + + if (Drive != NULL) { + FreePool(Drive); + } + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + + // + // return the status + // + return (ShellStatus); +} + diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/Cp.c b/ShellPkg/Library/UefiShellLevel2CommandsLib/Cp.c new file mode 100644 index 0000000000..e35bf18824 --- /dev/null +++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/Cp.c @@ -0,0 +1,599 @@ +/** @file + Main file for cp shell level 2 function. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel2CommandsLib.h" + +// this is later in the file. +SHELL_STATUS +EFIAPI +ValidateAndCopyFiles( + IN CONST EFI_SHELL_FILE_INFO *FileList, + IN CONST CHAR16 *DestDir, + IN BOOLEAN SilentMode, + IN BOOLEAN RecursiveMode, + IN VOID **Resp + ); + +/** + Function to Copy one file to another location + + If the destination exists the user will be prompted and the result put into *resp + + @param[in] Source pointer to source file name + @param[in] Dest pointer to destination file name + @param[out] Resp pointer to response from question. Pass back on looped calling + @param[in] SilentMode whether to run in quiet mode or not + + @retval SHELL_SUCCESS The source file was copied to the destination +**/ +SHELL_STATUS +EFIAPI +CopySingleFile( + IN CONST CHAR16 *Source, + IN CONST CHAR16 *Dest, + OUT VOID **Resp, + IN BOOLEAN SilentMode + ) +{ + VOID *Response; + UINTN ReadSize; + SHELL_FILE_HANDLE SourceHandle; + SHELL_FILE_HANDLE DestHandle; + EFI_STATUS Status; + VOID *Buffer; + CHAR16 *TempName; + UINTN Size; + EFI_SHELL_FILE_INFO *List; + SHELL_STATUS ShellStatus; + + + ASSERT(Resp != NULL); + + SourceHandle = NULL; + DestHandle = NULL; + Response = *Resp; + List = NULL; + + ReadSize = PcdGet16(PcdShellFileOperationSize); + // Why bother copying a file to itself + if (StrCmp(Source, Dest) == 0) { + return (SHELL_SUCCESS); + } + + // + // Open destination file without create + // + Status = ShellOpenFileByName(Dest, &DestHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0); + + // + // close file + // + if (DestHandle != NULL) { + ShellCloseFile(&DestHandle); + DestHandle = NULL; + } + + // + // if the destination file existed check response and possibly prompt user + // + if (!EFI_ERROR(Status)) { + if (Response == NULL && !SilentMode) { + Status = ShellPromptForResponseHii(ShellPromptResponseTypeYesNoAllCancel, STRING_TOKEN (STR_CP_PROMPT), gShellLevel2HiiHandle, &Response); + } + // + // possibly return based on response + // + if (!SilentMode) { + switch (*(SHELL_PROMPT_RESPONSE*)Response) { + case ShellPromptResponseNo: + // + // return success here so we dont stop the process + // + return (SHELL_SUCCESS); + case ShellPromptResponseCancel: + *Resp = Response; + // + // indicate to stop everything + // + return (SHELL_ABORTED); + case ShellPromptResponseAll: + *Resp = Response; + case ShellPromptResponseYes: + break; + } + } + } + + if (ShellIsDirectory(Source) == EFI_SUCCESS) { + Status = ShellCreateDirectory(Dest, &DestHandle); + if (EFI_ERROR(Status)) { + return (SHELL_ACCESS_DENIED); + } + + // + // Now copy all the files under the directory... + // + TempName = NULL; + Size = 0; + StrnCatGrow(&TempName, &Size, Source, 0); + StrnCatGrow(&TempName, &Size, L"\\*", 0); + ShellOpenFileMetaArg((CHAR16*)TempName, EFI_FILE_MODE_READ, &List); + TempName = NULL; + StrnCatGrow(&TempName, &Size, Dest, 0); + StrnCatGrow(&TempName, &Size, L"\\", 0); + ShellStatus = ValidateAndCopyFiles(List, TempName, SilentMode, TRUE, Resp); + ShellCloseFileMetaArg(&List); + FreePool(TempName); + Size = 0; + } else { + // + // open file with create enabled + // + Status = ShellOpenFileByName(Dest, &DestHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0); + if (EFI_ERROR(Status)) { + return (SHELL_ACCESS_DENIED); + } + + // + // open source file + // + Status = ShellOpenFileByName(Source, &SourceHandle, EFI_FILE_MODE_READ, 0); + ASSERT_EFI_ERROR(Status); + + // + // copy data between files + // + Buffer = AllocateZeroPool(ReadSize); + ASSERT(Buffer != NULL); + while (ReadSize == PcdGet16(PcdShellFileOperationSize) && !EFI_ERROR(Status)) { + Status = ShellReadFile(SourceHandle, &ReadSize, Buffer); + ASSERT_EFI_ERROR(Status); + Status = ShellWriteFile(DestHandle, &ReadSize, Buffer); + } + } + + // + // close files + // + if (DestHandle != NULL) { + ShellCloseFile(&DestHandle); + DestHandle = NULL; + } + if (SourceHandle != NULL) { + ShellCloseFile(&SourceHandle); + SourceHandle = NULL; + } + + // + // return + // + return (SHELL_SUCCESS); +} + +/** + function to take a list of files to copy and a destination location and do + the verification and copying of those files to that location. This function + will report any errors to the user and halt. + + The key is to have this function called ONLY once. this allows for the parameter + verification to happen correctly. + + @param[in] FileList A LIST_ENTRY* based list of files to move + @param[in] DestDir the destination location + + @retval SHELL_SUCCESS the files were all moved. + @retval SHELL_INVALID_PARAMETER a parameter was invalid + @retval SHELL_SECURITY_VIOLATION a security violation ocurred + @retval SHELL_WRITE_PROTECTED the destination was write protected + @retval SHELL_OUT_OF_RESOURCES a memory allocation failed +**/ +SHELL_STATUS +EFIAPI +ValidateAndCopyFiles( + IN CONST EFI_SHELL_FILE_INFO *FileList, + IN CONST CHAR16 *DestDir, + IN BOOLEAN SilentMode, + IN BOOLEAN RecursiveMode, + IN VOID **Resp + ) +{ + CHAR16 *HiiOutput; + CHAR16 *HiiResultOk; + CONST EFI_SHELL_FILE_INFO *Node; + SHELL_STATUS ShellStatus; + CHAR16 *DestPath; + VOID *Response; + UINTN PathLen; + CONST CHAR16 *Cwd; + CONST CHAR16 *TempLocation; + UINTN NewSize; + + if (Resp == NULL) { + Response = NULL; + } else { + Response = *Resp; + } + + DestPath = NULL; + ShellStatus = SHELL_SUCCESS; + PathLen = 0; + Cwd = ShellGetCurrentDir(NULL); + + ASSERT(FileList != NULL); + ASSERT(DestDir != NULL); + + // + // If we are trying to copy multiple files... make sure we got a directory for the target... + // + if (EFI_ERROR(ShellIsDirectory(DestDir)) && FileList->Link.ForwardLink != FileList->Link.BackLink) { + // + // Error for destination not a directory + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR), gShellLevel2HiiHandle, DestDir); + return (SHELL_INVALID_PARAMETER); + } + for (Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&FileList->Link) + ; !IsNull(&FileList->Link, &Node->Link) + ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&FileList->Link, &Node->Link) + ){ + // + // skip the directory traversing stuff... + // + if (StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0) { + continue; + } + + NewSize = StrSize(DestDir); + NewSize += StrSize(Node->FileName); + NewSize += StrSize(Cwd); + if (NewSize > PathLen) { + PathLen = NewSize; + } + + // + // Make sure got -r if required + // + if (!RecursiveMode && !EFI_ERROR(ShellIsDirectory(Node->FullName))) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DIR_REQ), gShellLevel2HiiHandle); + return (SHELL_INVALID_PARAMETER); + } + + // + // make sure got dest as dir if needed + // + if (!EFI_ERROR(ShellIsDirectory(Node->FullName)) && EFI_ERROR(ShellIsDirectory(DestDir))) { + // + // Error for destination not a directory + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR), gShellLevel2HiiHandle, DestDir); + return (SHELL_INVALID_PARAMETER); + } + } + + HiiOutput = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_CP_OUTPUT), NULL); + HiiResultOk = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_GEN_RES_OK), NULL); + DestPath = AllocatePool(PathLen); + + // + // Go through the list of files to copy... + // + for (Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&FileList->Link) + ; !IsNull(&FileList->Link, &Node->Link) + ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&FileList->Link, &Node->Link) + ){ + if (ShellGetExecutionBreakFlag()) { + break; + } + ASSERT(Node->FileName != NULL); + ASSERT(Node->FullName != NULL); + + // + // skip the directory traversing stuff... + // + if (StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0) { + continue; + } + + if (FileList->Link.ForwardLink == FileList->Link.BackLink // 1 item + && EFI_ERROR(ShellIsDirectory(DestDir)) // not an existing directory + ) { + ASSERT(StrStr(DestDir, L":") == NULL); + // + // simple copy of a single file + // + StrCpy(DestPath, Cwd); + if (DestPath[StrLen(DestPath)-1] != L'\\' && DestDir[0] != L'\\') { + StrCat(DestPath, L"\\"); + } else if (DestPath[StrLen(DestPath)-1] == L'\\' && DestDir[0] == L'\\') { + ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL; + } + StrCat(DestPath, DestDir); + } else { + // + // we have multiple files or a directory in the DestDir + // + if (StrStr(DestDir, L":") == NULL) { + StrCpy(DestPath, Cwd); + if (DestPath[StrLen(DestPath)-1] != L'\\' && DestDir[0] != L'\\') { + StrCat(DestPath, L"\\"); + } else if (DestPath[StrLen(DestPath)-1] == L'\\' && DestDir[0] == L'\\') { + ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL; + } + StrCat(DestPath, DestDir); + if (DestDir[StrLen(DestDir)-1] != L'\\' && Node->FileName[0] != L'\\') { + StrCat(DestPath, L"\\"); + } else if (DestDir[StrLen(DestDir)-1] == L'\\' && Node->FileName[0] == L'\\') { + ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL; + } + StrCat(DestPath, Node->FileName); + + } else { + StrCpy(DestPath, DestDir); + if (DestDir[StrLen(DestDir)-1] != L'\\' && Node->FileName[0] != L'\\') { + StrCat(DestPath, L"\\"); + } else if (DestDir[StrLen(DestDir)-1] == L'\\' && Node->FileName[0] == L'\\') { + ((CHAR16*)DestDir)[StrLen(DestDir)-1] = CHAR_NULL; + } + StrCat(DestPath, Node->FileName); + } + } + + // + // Make sure the path exists + // + if (EFI_ERROR(VerifyIntermediateDirectories(DestPath))) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DIR_WNF), gShellLevel2HiiHandle); + ShellStatus = SHELL_DEVICE_ERROR; + break; + } + + if ( !EFI_ERROR(ShellIsDirectory(Node->FullName)) + && !EFI_ERROR(ShellIsDirectory(DestPath)) + && StrniCmp(Node->FullName, DestPath, StrLen(DestPath)) == NULL + ){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_SD_PARENT), gShellLevel2HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + break; + } + if (StringNoCaseCompare(&Node->FullName, &DestPath) == 0) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_SD_SAME), gShellLevel2HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + break; + } + + if ((TempLocation = StrniCmp(Node->FullName, DestPath, StrLen(Node->FullName))) == 0 + && (DestPath[StrLen(Node->FullName)] == CHAR_NULL || DestPath[StrLen(Node->FullName)] == L'\\') + ) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_SD_SAME), gShellLevel2HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + break; + } + + CleanPath(DestPath); + + ShellPrintEx(-1, -1, HiiOutput, Node->FullName, DestPath); + + // + // copy single file... + // + ShellStatus = CopySingleFile(Node->FullName, DestPath, &Response, SilentMode); + if (ShellStatus != SHELL_SUCCESS) { + break; + } + } + if (ShellStatus == SHELL_SUCCESS && Resp == NULL) { + ShellPrintEx(-1, -1, L"%s", HiiResultOk); + } + + SHELL_FREE_NON_NULL(DestPath); + SHELL_FREE_NON_NULL(HiiOutput); + SHELL_FREE_NON_NULL(HiiResultOk); + if (Resp != NULL) { + SHELL_FREE_NON_NULL(Response); + } + + return (ShellStatus); +} + +SHELL_STATUS +EFIAPI +ProcessValidateAndCopyFiles( + IN EFI_SHELL_FILE_INFO *FileList, + IN CONST CHAR16 *DestDir, + IN BOOLEAN SilentMode, + IN BOOLEAN RecursiveMode + ) +{ + SHELL_STATUS ShellStatus; + EFI_SHELL_FILE_INFO *List; + EFI_STATUS Status; + EFI_FILE_INFO *FileInfo; + + List = NULL; + + Status = ShellOpenFileMetaArg((CHAR16*)DestDir, EFI_FILE_MODE_READ, &List); + if (List != NULL && List->Link.ForwardLink != List->Link.BackLink) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_MARG_ERROR), gShellLevel2HiiHandle, DestDir); + ShellStatus = SHELL_INVALID_PARAMETER; + ShellCloseFileMetaArg(&List); + } else if (List != NULL) { + ASSERT(List != NULL); + ASSERT(((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink) != NULL); + ASSERT(((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink)->FullName != NULL); + FileInfo = NULL; + FileInfo = gEfiShellProtocol->GetFileInfo(((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink)->Handle); + ASSERT(FileInfo != NULL); + if ((FileInfo->Attribute & EFI_FILE_READ_ONLY) == 0) { + ShellStatus = ValidateAndCopyFiles(FileList, ((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink)->FullName, SilentMode, RecursiveMode, NULL); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DEST_ERROR), gShellLevel2HiiHandle); + ShellStatus = SHELL_ACCESS_DENIED; + } + SHELL_FREE_NON_NULL(FileInfo); + ShellCloseFileMetaArg(&List); + } else { + ShellStatus = ValidateAndCopyFiles(FileList, DestDir, SilentMode, RecursiveMode, NULL); + } + + return (ShellStatus); +} + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-r", TypeFlag}, + {L"-q", TypeFlag}, + {NULL, TypeMax} + }; + +/** + Function for 'cp' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunCp ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + UINTN ParamCount; + UINTN LoopCounter; + EFI_SHELL_FILE_INFO *FileList; + BOOLEAN SilentMode; + BOOLEAN RecursiveMode; + CONST CHAR16 *Cwd; + + ProblemParam = NULL; + ShellStatus = SHELL_SUCCESS; + ParamCount = 0; + FileList = NULL; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + // + // check for "-?" + // + if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } + + // + // Initialize SilentMode and RecursiveMode + // + if (gEfiShellProtocol->BatchIsActive()) { + SilentMode = TRUE; + } else { + SilentMode = ShellCommandLineGetFlag(Package, L"-q"); + } + RecursiveMode = ShellCommandLineGetFlag(Package, L"-r"); + + switch (ParamCount = ShellCommandLineGetCount(Package)) { + case 0: + case 1: + // + // we have insufficient parameters + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + break; + case 2: + // + // must have valid CWD for single parameter... + // + Cwd = ShellGetCurrentDir(NULL); + if (Cwd == NULL){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = ShellOpenFileMetaArg((CHAR16*)ShellCommandLineGetRawValue(Package, 1), EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList); + if (FileList == NULL || IsListEmpty(&FileList->Link) || EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, 1)); + ShellStatus = SHELL_NOT_FOUND; + } else { + ShellStatus = ProcessValidateAndCopyFiles(FileList, Cwd, SilentMode, RecursiveMode); + } + } + + break; + default: + // + // Make a big list of all the files... + // + for (ParamCount--, LoopCounter = 1 ; LoopCounter < ParamCount && ShellStatus == SHELL_SUCCESS ; LoopCounter++) { + if (ShellGetExecutionBreakFlag()) { + break; + } + Status = ShellOpenFileMetaArg((CHAR16*)ShellCommandLineGetRawValue(Package, LoopCounter), EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList); + if (EFI_ERROR(Status) || FileList == NULL || IsListEmpty(&FileList->Link)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, 1)); + ShellStatus = SHELL_NOT_FOUND; + } + } + // + // now copy them all... + // + if (FileList != NULL && !IsListEmpty(&FileList->Link)) { + ShellStatus = ProcessValidateAndCopyFiles(FileList, ShellCommandCleanPath((CHAR16*)ShellCommandLineGetRawValue(Package, ParamCount)), SilentMode, RecursiveMode); + Status = ShellCloseFileMetaArg(&FileList); + if (EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_FILE), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, 1), ShellStatus|MAX_BIT); + ShellStatus = SHELL_ACCESS_DENIED; + } + } + + break; + } // switch on parameter count + + if (FileList != NULL) { + ShellCloseFileMetaArg(&FileList); + } + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + } + + if (ShellGetExecutionBreakFlag()) { + return (SHELL_ABORTED); + } + + return (ShellStatus); +} + diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/Load.c b/ShellPkg/Library/UefiShellLevel2CommandsLib/Load.c new file mode 100644 index 0000000000..1e29ad62e1 --- /dev/null +++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/Load.c @@ -0,0 +1,282 @@ +/** @file + Main file for attrib shell level 2 function. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel2CommandsLib.h" + +// This function was from from the BdsLib implementation in +// IntelFrameworkModulePkg\Library\GenericBdsLib\BdsConnect.c +// function name: BdsLibConnectAllEfi +/** + This function will connect all current system handles recursively. The + connection will finish until every handle's child handle created if it have. + + @retval EFI_SUCCESS All handles and it's child handle have been + connected + @retval EFI_STATUS Return the status of gBS->LocateHandleBuffer(). + +**/ +EFI_STATUS +EFIAPI +ConnectAllEfi ( + VOID + ) +{ + EFI_STATUS Status; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN Index; + + Status = gBS->LocateHandleBuffer ( + AllHandles, + NULL, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE); + } + + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + } + + return EFI_SUCCESS; +} + +/** + function to load a .EFI driver into memory and possible connect the driver. + + if FileName is NULL then ASSERT. + + @param[in] FileName FileName of the driver to load + @param[in] Connect Whether to connect or not + + @retval EFI_SUCCESS the driver was loaded and if Connect was + true then connect was attempted. Connection may + have failed. + @retval EFI_OUT_OF_RESOURCES there was insufficient memory +**/ +EFI_STATUS +EFIAPI +LoadDriver( + IN CONST CHAR16 *FileName, + IN CONST BOOLEAN Connect + ) +{ + EFI_HANDLE LoadedDriverHandle; + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *Node; + EFI_DEVICE_PATH_PROTOCOL *FilePath; + EFI_LOADED_IMAGE_PROTOCOL *LoadedDriverImage; + + LoadedDriverImage = NULL; + FilePath = NULL; + Node = NULL; + LoadedDriverHandle = NULL; + Status = EFI_SUCCESS; + + ASSERT (FileName != NULL); + + // + // Fix local copies of the protocol pointers + // + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // Convert to DEVICE_PATH + // + FilePath = gEfiShellProtocol->GetDevicePathFromFilePath(FileName); + + if (FilePath == NULL) { + ASSERT(FALSE); + return (EFI_INVALID_PARAMETER); + } + + // + // Use LoadImage to get it into memory + // + Status = gBS->LoadImage( + FALSE, + gImageHandle, + FilePath, + NULL, + 0, + &LoadedDriverHandle); + + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOAD_NOT_IMAGE), gShellLevel2HiiHandle, FileName, Status); + } else { + // + // Make sure it is a driver image + // + Status = gBS->HandleProtocol (LoadedDriverHandle, &gEfiLoadedImageProtocolGuid, (VOID *) &LoadedDriverImage); + + ASSERT (LoadedDriverImage != NULL); + + if ( EFI_ERROR(Status) + || ( LoadedDriverImage->ImageCodeType != EfiBootServicesCode + && LoadedDriverImage->ImageCodeType != EfiRuntimeServicesCode) + ){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOAD_NOT_DRIVER), gShellLevel2HiiHandle, FileName); + + // + // Exit and unload the non-driver image + // + gBS->Exit(LoadedDriverHandle, EFI_INVALID_PARAMETER, 0, NULL); + Status = EFI_INVALID_PARAMETER; + } + } + + if (!EFI_ERROR(Status)) { + // + // Start the image + // + Status = gBS->StartImage(LoadedDriverHandle, NULL, NULL); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOAD_ERROR), gShellLevel2HiiHandle, FileName, Status); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOAD_LOADED), gShellLevel2HiiHandle, FileName, LoadedDriverImage->ImageBase, Status); + } + } + + if (!EFI_ERROR(Status) && Connect) { + // + // Connect it... + // + Status = ConnectAllEfi(); + } + + // + // clean up memory... + // + if (FilePath != NULL) { + FreePool(FilePath); + } + + return (Status); +} + +STATIC CONST SHELL_PARAM_ITEM LoadParamList[] = { + {L"-nc", TypeFlag}, + {NULL, TypeMax} + }; + +/** + Function for 'load' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunLoad ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + UINTN ParamCount; + EFI_SHELL_FILE_INFO *ListHead; + EFI_SHELL_FILE_INFO *Node; + + ListHead = NULL; + ProblemParam = NULL; + ShellStatus = SHELL_SUCCESS; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (LoadParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + // + // check for "-?" + // + if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } else if (ShellCommandLineGetRawValue(Package, 1) == NULL) { + // + // we didnt get a single file to load parameter + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + for ( ParamCount = 1 + ; ShellCommandLineGetRawValue(Package, ParamCount) != NULL + ; ParamCount++ + ){ + Status = ShellOpenFileMetaArg((CHAR16*)ShellCommandLineGetRawValue(Package, ParamCount), EFI_FILE_MODE_READ, &ListHead); + if (!EFI_ERROR(Status)) { + for ( Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&ListHead->Link) + ; !IsNull(&ListHead->Link, &Node->Link) + ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&ListHead->Link, &Node->Link) + ){ + // + // once we have an error preserve that value, but finish the loop. + // + if (EFI_ERROR(Status)) { + LoadDriver(Node->FullName, ShellCommandLineGetFlag(Package, L"-nc")); + } else { + Status = LoadDriver(Node->FullName, ShellCommandLineGetFlag(Package, L"-nc")); + } + } // for loop for multi-open + if (EFI_ERROR(Status)) { + ShellCloseFileMetaArg(&ListHead); + } else { + Status = ShellCloseFileMetaArg(&ListHead);; + } + } else { + // + // no files found. + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, (CHAR16*)ShellCommandLineGetRawValue(Package, ParamCount)); + ShellStatus = SHELL_NOT_FOUND; + } + } // for loop for params + } + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + } + + if (EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS) { + ShellStatus = SHELL_DEVICE_ERROR; + } + + return (ShellStatus); +} diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/Ls.c b/ShellPkg/Library/UefiShellLevel2CommandsLib/Ls.c new file mode 100644 index 0000000000..61d48977f1 --- /dev/null +++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/Ls.c @@ -0,0 +1,564 @@ +/** @file + Main file for ls shell level 2 function. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel2CommandsLib.h" +#include + +/** + print out the list of files and directories from the LS command + + @param[in] Rec TRUE to automatically recurse into each found directory + FALSE to only list the specified directory. + @param[in] Attribs List of required Attribute for display. + If 0 then all non-system and non-hidden files will be printed. + @param[in] Sfo TRUE to use Standard Format Output, FALSE otherwise + @param[in] Path String with starting path. + @param[in] First TRUE for the original and FALSE for any recursion spawned instances. + @param[in] Count The count of bits enabled in Attribs. + @param[in] TimeZone The current time zone offset. + + @retval SHELL_SUCCESS the printing was sucessful. +**/ +SHELL_STATUS +EFIAPI +PrintLsOutput( + IN CONST BOOLEAN Rec, + IN CONST UINT64 Attribs, + IN CONST BOOLEAN Sfo, + IN CONST CHAR16 *Path, + IN CONST BOOLEAN First, + IN CONST UINTN Count, + IN CONST INT16 TimeZone + ) +{ + EFI_STATUS Status; + EFI_SHELL_FILE_INFO *ListHead; + EFI_SHELL_FILE_INFO *Node; + SHELL_STATUS ShellStatus; + UINT64 FileCount; + UINT64 DirCount; + UINT64 FileSize; + CHAR16 *DirectoryName; + UINTN LongestPath; + EFI_FILE_SYSTEM_INFO *SysInfo; + UINTN SysInfoSize; + SHELL_FILE_HANDLE ShellFileHandle; + CHAR16 *CorrectedPath; + EFI_FILE_PROTOCOL *EfiFpHandle; + + FileCount = 0; + DirCount = 0; + FileSize = 0; + ListHead = NULL; + ShellStatus = SHELL_SUCCESS; + LongestPath = 0; + CorrectedPath = NULL; + + CorrectedPath = StrnCatGrow(&CorrectedPath, NULL, Path, 0); + ASSERT(CorrectedPath != NULL); + ShellCommandCleanPath(CorrectedPath); + + Status = ShellOpenFileMetaArg((CHAR16*)CorrectedPath, EFI_FILE_MODE_READ, &ListHead); + if (EFI_ERROR(Status)) { + return (SHELL_DEVICE_ERROR); + } + if (ListHead == NULL || IsListEmpty(&ListHead->Link)) { + // + // On the first one only we expect to find something... + // do we find the . and .. directories otherwise? + // + if (First) { + return (SHELL_NOT_FOUND); + } + return (SHELL_SUCCESS); + } + + if (Sfo && First) { + // + // Get the first valid handle (directories) + // + for ( Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&ListHead->Link) + ; !IsNull(&ListHead->Link, &Node->Link) && Node->Handle == NULL + ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&ListHead->Link, &Node->Link) + ); + + if (Node->Handle == NULL) { + DirectoryName = GetFullyQualifiedPath(((EFI_SHELL_FILE_INFO *)GetFirstNode(&ListHead->Link))->FullName); + + // + // We need to open something up to get system information + // + Status = gEfiShellProtocol->OpenFileByName( + DirectoryName, + &ShellFileHandle, + EFI_FILE_MODE_READ); + + ASSERT_EFI_ERROR(Status); + FreePool(DirectoryName); + + // + // Get the Volume Info from ShellFileHandle + // + SysInfo = NULL; + SysInfoSize = 0; + EfiFpHandle = ConvertShellHandleToEfiFileProtocol(ShellFileHandle); + Status = EfiFpHandle->GetInfo( + EfiFpHandle, + &gEfiFileSystemInfoGuid, + &SysInfoSize, + SysInfo); + + if (Status == EFI_BUFFER_TOO_SMALL) { + SysInfo = AllocateZeroPool(SysInfoSize); + Status = EfiFpHandle->GetInfo( + EfiFpHandle, + &gEfiFileSystemInfoGuid, + &SysInfoSize, + SysInfo); + } + + ASSERT_EFI_ERROR(Status); + + gEfiShellProtocol->CloseFile(ShellFileHandle); + } else { + // + // Get the Volume Info from Node->Handle + // + SysInfo = NULL; + SysInfoSize = 0; + EfiFpHandle = ConvertShellHandleToEfiFileProtocol(Node->Handle); + Status = EfiFpHandle->GetInfo( + EfiFpHandle, + &gEfiFileSystemInfoGuid, + &SysInfoSize, + SysInfo); + + if (Status == EFI_BUFFER_TOO_SMALL) { + SysInfo = AllocateZeroPool(SysInfoSize); + Status = EfiFpHandle->GetInfo( + EfiFpHandle, + &gEfiFileSystemInfoGuid, + &SysInfoSize, + SysInfo); + } + + ASSERT_EFI_ERROR(Status); + } + + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_GEN_SFO_HEADER), + gShellLevel2HiiHandle, + L"ls"); + // + // print VolumeInfo table + // + ASSERT(SysInfo != NULL); + ShellPrintHiiEx ( + 0, + gST->ConOut->Mode->CursorRow, + NULL, + STRING_TOKEN (STR_LS_SFO_VOLINFO), + gShellLevel2HiiHandle, + SysInfo->VolumeLabel, + SysInfo->VolumeSize, + SysInfo->ReadOnly?L"TRUE":L"FALSE", + SysInfo->FreeSpace, + SysInfo->BlockSize + ); + if (SysInfo != NULL) { + FreePool(SysInfo); + } + } + + if (!Sfo) { + // + // get directory name from path... + // + DirectoryName = GetFullyQualifiedPath(CorrectedPath); + + // + // print header + // + ShellPrintHiiEx ( + 0, + gST->ConOut->Mode->CursorRow, + NULL, + STRING_TOKEN (STR_LS_HEADER_LINE1), + gShellLevel2HiiHandle, + DirectoryName + ); + FreePool(DirectoryName); + } + for ( Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&ListHead->Link) + ; !IsNull(&ListHead->Link, &Node->Link) + ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&ListHead->Link, &Node->Link) + ){ + ASSERT(Node != NULL); + if (LongestPath < StrSize(Node->FullName)) { + LongestPath = StrSize(Node->FullName); + } + ASSERT(Node->Info != NULL); + ASSERT((Node->Info->Attribute & EFI_FILE_VALID_ATTR) == Node->Info->Attribute); + if (Attribs == 0) { + // + // NOT system & NOT hidden + // + if ( (Node->Info->Attribute & EFI_FILE_SYSTEM) + || (Node->Info->Attribute & EFI_FILE_HIDDEN) + ){ + continue; + } + } else if (Attribs != EFI_FILE_VALID_ATTR) { + if (Count == 1) { + // + // the bit must match + // + if ( (Node->Info->Attribute & Attribs) != Attribs) { + continue; + } + } else { + // + // exact match on all bits + // + if ( Node->Info->Attribute != Attribs) { + continue; + } + } + } + + if (Sfo) { + // + // Print the FileInfo Table + // + ShellPrintHiiEx ( + 0, + gST->ConOut->Mode->CursorRow, + NULL, + STRING_TOKEN (STR_LS_SFO_FILEINFO), + gShellLevel2HiiHandle, + Node->FullName, + Node->Info->FileSize, + Node->Info->PhysicalSize, + (Node->Info->Attribute & EFI_FILE_ARCHIVE) != 0?L"a":L"", + (Node->Info->Attribute & EFI_FILE_DIRECTORY) != 0?L"d":L"", + (Node->Info->Attribute & EFI_FILE_HIDDEN) != 0?L"h":L"", + (Node->Info->Attribute & EFI_FILE_READ_ONLY) != 0?L"r":L"", + (Node->Info->Attribute & EFI_FILE_SYSTEM) != 0?L"s":L"", + Node->Info->CreateTime.Hour, + Node->Info->CreateTime.Minute, + Node->Info->CreateTime.Second, + Node->Info->CreateTime.Day, + Node->Info->CreateTime.Month, + Node->Info->CreateTime.Year, + Node->Info->LastAccessTime.Hour, + Node->Info->LastAccessTime.Minute, + Node->Info->LastAccessTime.Second, + Node->Info->LastAccessTime.Day, + Node->Info->LastAccessTime.Month, + Node->Info->LastAccessTime.Year, + Node->Info->ModificationTime.Hour, + Node->Info->ModificationTime.Minute, + Node->Info->ModificationTime.Second, + Node->Info->ModificationTime.Day, + Node->Info->ModificationTime.Month, + Node->Info->ModificationTime.Year + ); + } else { + // + // print this one out... + // first print the universal start, next print the type specific name format, last print the CRLF + // + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_LS_LINE_START_ALL), + gShellLevel2HiiHandle, + &Node->Info->ModificationTime, + (Node->Info->Attribute & EFI_FILE_DIRECTORY) != 0?L"":L"", + (Node->Info->Attribute & EFI_FILE_READ_ONLY) != 0?L'r':L' ', + Node->Info->FileSize + ); + if (Node->Info->Attribute & EFI_FILE_DIRECTORY) { + DirCount++; + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_LS_LINE_END_DIR), + gShellLevel2HiiHandle, + Node->FileName + ); + } else { + FileCount++; + FileSize += Node->Info->FileSize; + if ( (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)L".nsh", (CHAR16*)&(Node->FileName[StrLen (Node->FileName) - 4])) == 0) + || (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)L".efi", (CHAR16*)&(Node->FileName[StrLen (Node->FileName) - 4])) == 0) + ){ + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_LS_LINE_END_EXE), + gShellLevel2HiiHandle, + Node->FileName + ); + } else { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_LS_LINE_END_FILE), + gShellLevel2HiiHandle, + Node->FileName + ); + } + } + } + } + + if (!Sfo) { + // + // print footer + // + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_LS_FOOTER_LINE), + gShellLevel2HiiHandle, + FileCount, + FileSize, + DirCount + ); + } + + if (Rec){ + DirectoryName = AllocatePool(LongestPath + 2*sizeof(CHAR16)); + for ( Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&ListHead->Link) + ; !IsNull(&ListHead->Link, &Node->Link) + ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&ListHead->Link, &Node->Link) + ){ + // + // recurse on any directory except the traversing ones... + // + if (((Node->Info->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY) + && StrCmp(Node->FileName, L".") != 0 + && StrCmp(Node->FileName, L"..") != 0 + ){ + StrCpy(DirectoryName, Node->FullName); + StrCat(DirectoryName, L"\\*"); + PrintLsOutput( + Rec, + Attribs, + Sfo, + DirectoryName, + FALSE, + Count, + TimeZone); + } + } + FreePool(DirectoryName); + } + + FreePool(CorrectedPath); + ShellCloseFileMetaArg(&ListHead); + FreePool(ListHead); + return (ShellStatus); +} + +STATIC CONST SHELL_PARAM_ITEM LsParamList[] = { + {L"-r", TypeFlag}, + {L"-a", TypeStart}, + {L"-sfo", TypeFlag}, + {NULL, TypeMax} + }; + +/** + Function for 'ls' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunLs ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + CONST CHAR16 *Attribs; + SHELL_STATUS ShellStatus; + UINT64 RequiredAttributes; + CONST CHAR16 *PathName; + CONST CHAR16 *CurDir; + UINTN Count; + CHAR16 *FullPath; + UINTN Size; + EFI_TIME theTime; + BOOLEAN SfoMode; + + Size = 0; + FullPath = NULL; + ProblemParam = NULL; + Attribs = NULL; + ShellStatus = SHELL_SUCCESS; + RequiredAttributes = 0; + PathName = NULL; + CurDir = NULL; + Count = 0; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + // + // Fix local copies of the protocol pointers + // + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (LsParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + // + // check for "-?" + // + if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } + + if (ShellCommandLineGetCount(Package) > 2) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // check for -a + // + if (ShellCommandLineGetFlag(Package, L"-a")) { + for ( Attribs = ShellCommandLineGetValue(Package, L"-a") + ; Attribs != NULL && *Attribs != CHAR_NULL && ShellStatus == SHELL_SUCCESS + ; Attribs++ + ){ + switch (*Attribs) { + case L'a': + case L'A': + RequiredAttributes |= EFI_FILE_ARCHIVE; + Count++; + continue; + case L's': + case L'S': + RequiredAttributes |= EFI_FILE_SYSTEM; + Count++; + continue; + case L'h': + case L'H': + RequiredAttributes |= EFI_FILE_HIDDEN; + Count++; + continue; + case L'r': + case L'R': + RequiredAttributes |= EFI_FILE_READ_ONLY; + Count++; + continue; + case L'd': + case L'D': + RequiredAttributes |= EFI_FILE_DIRECTORY; + Count++; + continue; + default: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ATTRIBUTE), gShellLevel2HiiHandle, ShellCommandLineGetValue(Package, L"-a")); + ShellStatus = SHELL_INVALID_PARAMETER; + break; + } // switch + } // for loop + // + // if nothing is specified all are specified + // + if (RequiredAttributes == 0) { + RequiredAttributes = EFI_FILE_VALID_ATTR; + } + } // if -a present + if (ShellStatus == SHELL_SUCCESS) { + PathName = ShellCommandLineGetRawValue(Package, 1); + if (PathName == NULL) { + CurDir = gEfiShellProtocol->GetCurDir(NULL); + if (CurDir == NULL) { + ShellStatus = SHELL_NOT_FOUND; + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle); + } + } + if (PathName != NULL) { + ASSERT((FullPath == NULL && Size == 0) || (FullPath != NULL)); + StrnCatGrow(&FullPath, &Size, PathName, 0); + if (ShellIsDirectory(PathName) == EFI_SUCCESS) { + StrnCatGrow(&FullPath, &Size, L"\\*", 0); + } + } else { + ASSERT(FullPath == NULL); + StrnCatGrow(&FullPath, NULL, L"*", 0); + } + Status = gRT->GetTime(&theTime, NULL); + ASSERT_EFI_ERROR(Status); + SfoMode = ShellCommandLineGetFlag(Package, L"-sfo"); + if (ShellStatus == SHELL_SUCCESS) { + ShellStatus = PrintLsOutput( + ShellCommandLineGetFlag(Package, L"-r"), + RequiredAttributes, + SfoMode, + FullPath, + TRUE, + Count, + (INT16)(theTime.TimeZone==2047?0:theTime.TimeZone) + ); + if (ShellStatus == SHELL_NOT_FOUND) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_FILES), gShellLevel2HiiHandle); + } else if (ShellStatus == SHELL_INVALID_PARAMETER) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle); + } else if (ShellStatus != SHELL_SUCCESS) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle); + } + } + } + } + } + + if (FullPath != NULL) { + FreePool(FullPath); + } + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + + return (ShellStatus); +} diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c b/ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c new file mode 100644 index 0000000000..5d6a200c19 --- /dev/null +++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c @@ -0,0 +1,1116 @@ +/** @file + Main file for map shell level 2 command. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel2CommandsLib.h" +#include +#include +#include +#include +#include + +BOOLEAN +EFIAPI +SearchList( + IN CONST CHAR16 *List, + IN CONST CHAR16 *MetaTarget, + OUT CHAR16 **FullName OPTIONAL, + IN CONST BOOLEAN Meta, + IN CONST BOOLEAN SkipTrailingNumbers, + IN CONST CHAR16 *Target + + ) +{ + CHAR16 *TempList; + CONST CHAR16 *ListWalker; + BOOLEAN Result; + CHAR16 *TempSpot; + + for (ListWalker = List , TempList = NULL + ; ListWalker != NULL && *ListWalker != CHAR_NULL + ; + ) { + TempList = StrnCatGrow(&TempList, NULL, ListWalker, 0); + ASSERT(TempList != NULL); + TempSpot = StrStr(TempList, Target); + if (TempSpot != NULL) { + *TempSpot = CHAR_NULL; + } + + while (SkipTrailingNumbers && (ShellIsDecimalDigitCharacter(TempList[StrLen(TempList)-1]) || TempList[StrLen(TempList)-1] == L':')) { + TempList[StrLen(TempList)-1] = CHAR_NULL; + } + + ListWalker = StrStr(ListWalker, Target); + while(ListWalker != NULL && *ListWalker == *Target) { + ListWalker++; + } + if (Meta) { + Result = gUnicodeCollation->MetaiMatch(gUnicodeCollation, (CHAR16*)TempList, (CHAR16*)MetaTarget); + } else { + Result = (BOOLEAN)(StrCmp(TempList, MetaTarget)==0); + } + if (Result) { + if (FullName != NULL) { + *FullName = TempList; + } else { + FreePool(TempList); + } + return (TRUE); + } + FreePool(TempList); + TempList = NULL; + } + + return (FALSE); +} + +EFI_STATUS +EFIAPI +UpdateMapping ( + VOID + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleList; + UINTN Count; + EFI_DEVICE_PATH_PROTOCOL **DevicePathList; + CHAR16 *NewDefaultName; + CHAR16 *NewConsistName; + EFI_DEVICE_PATH_PROTOCOL **ConsistMappingTable; + + HandleList = NULL; + Status = EFI_SUCCESS; + + // + // remove mappings that represent removed devices. + // + + // + // Find each handle with Simple File System + // + HandleList = GetHandleListByPotocol(&gEfiSimpleFileSystemProtocolGuid); + if (HandleList != NULL) { + // + // Do a count of the handles + // + for (Count = 0 ; HandleList[Count] != NULL ; Count++); + + // + // Get all Device Paths + // + DevicePathList = AllocatePool(sizeof(EFI_DEVICE_PATH_PROTOCOL*) * Count); + ASSERT(DevicePathList != NULL); + + for (Count = 0 ; HandleList[Count] != NULL ; Count++) { + DevicePathList[Count] = DevicePathFromHandle(HandleList[Count]); + } + + // + // Sort all DevicePaths + // + PerformQuickSort(DevicePathList, Count, sizeof(EFI_DEVICE_PATH_PROTOCOL*), DevicePathCompare); + + ShellCommandConsistMappingInitialize(&ConsistMappingTable); + + // + // Assign new Mappings to remainders + // + for (Count = 0 ; HandleList[Count] != NULL && !EFI_ERROR(Status); Count++) { + // + // Skip ones that already have + // + if (gEfiShellProtocol->GetMapFromDevicePath(&DevicePathList[Count]) != NULL) { + continue; + } + // + // Get default name + // + NewDefaultName = ShellCommandCreateNewMappingName(MappingTypeFileSystem); + ASSERT(NewDefaultName != NULL); + + // + // Call shell protocol SetMap function now... + // + Status = gEfiShellProtocol->SetMap(DevicePathList[Count], NewDefaultName); + + if (!EFI_ERROR(Status)) { + // + // Now do consistent name + // + NewConsistName = ShellCommandConsistMappingGenMappingName(DevicePathList[Count], ConsistMappingTable); + if (NewConsistName != NULL) { + Status = gEfiShellProtocol->SetMap(DevicePathList[Count], NewConsistName); + FreePool(NewConsistName); + } + } + + FreePool(NewDefaultName); + } + ShellCommandConsistMappingUnInitialize(ConsistMappingTable); + SHELL_FREE_NON_NULL(HandleList); + SHELL_FREE_NON_NULL(DevicePathList); + + HandleList = NULL; + } else { + Count = (UINTN)-1; + } + // + // Do it all over again for gEfiBlockIoProtocolGuid + // + + return (Status); +} + +CHAR16* +EFIAPI +GetDeviceMediaType ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + ACPI_HID_DEVICE_PATH *Acpi; + + // + // Parse the device path: + // Devicepath sub type mediatype + // MEDIA_HANRDDRIVE_DP -> Hard Disk + // MEDIA_CDROM_DP -> CD Rom + // Acpi.HID = 0X0604 -> Floppy + // + if (NULL == DevicePath) { + return HiiGetString(gShellLevel2HiiHandle, STRING_TOKEN(STR_MAP_MEDIA_UNKNOWN), NULL); + } + + for (;!IsDevicePathEndType (DevicePath) ;DevicePath = NextDevicePathNode (DevicePath)) { + if (DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) { + switch (DevicePathSubType (DevicePath)) { + case MEDIA_HARDDRIVE_DP: + return HiiGetString(gShellLevel2HiiHandle, STRING_TOKEN(STR_MAP_MEDIA_HARDDISK), NULL); + case MEDIA_CDROM_DP: + return HiiGetString(gShellLevel2HiiHandle, STRING_TOKEN(STR_MAP_MEDIA_CDROM), NULL); + } + } else if (DevicePathType (DevicePath) == ACPI_DEVICE_PATH) { + Acpi = (ACPI_HID_DEVICE_PATH *) DevicePath; + if (EISA_ID_TO_NUM (Acpi->HID) == 0x0604) { + return HiiGetString(gShellLevel2HiiHandle, STRING_TOKEN(STR_MAP_MEDIA_FLOPPY), NULL); + } + } + } + + return HiiGetString(gShellLevel2HiiHandle, STRING_TOKEN(STR_MAP_MEDIA_UNKNOWN), NULL); +} + +/** + Function to detemine if a handle has removable storage. + + @param[in] DevicePath DevicePath to test. + + @retval TRUE The handle has removable storage. + @retval FALSE The handle does not have removable storage. +**/ +BOOLEAN +EFIAPI +IsRemoveableDevice ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + if (NULL == DevicePath) { + return FALSE; + } + + while (!IsDevicePathEndType (DevicePath)) { + if (DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) { + switch (DevicePathSubType (DevicePath)) { + case MSG_USB_DP: + case MSG_SCSI_DP: + return TRUE; + default: + return FALSE; + } + } + DevicePath = NextDevicePathNode (DevicePath); + } + return FALSE; +} + +/** + Function to detemine if a something on the map list matches. + + @param[in] MapList The pointer to the list to test. + @param[in] Specific The pointer to a specific name to test for. + @param[in] TypeString The pointer to the list of types. + @param[in] Normal Always show normal mappings. + @param[in] Consist Always show consistent mappings. + + @retval TRUE The map should be displayed. + @retval FALSE The map should not be displayed. +**/ +BOOLEAN +EFIAPI +MappingListHasType( + IN CONST CHAR16 *MapList, + IN CONST CHAR16 *Specific, + IN CONST CHAR16 *TypeString, + IN CONST BOOLEAN Normal, + IN CONST BOOLEAN Consist + ) +{ + // + // specific has priority + // + if ( Specific != NULL + && SearchList(MapList, Specific, NULL, TRUE, FALSE, L";")) { + return (TRUE); + } + + if ( Consist + && (SearchList(MapList, L"HD*", NULL, TRUE, TRUE, L";") + ||SearchList(MapList, L"CD*", NULL, TRUE, TRUE, L";") + ||SearchList(MapList, L"F*", NULL, TRUE, TRUE, L";") + ||SearchList(MapList, L"FP*", NULL, TRUE, TRUE, L";"))){ + return (TRUE); + } + + if ( Normal + && (SearchList(MapList, L"FS", NULL, FALSE, TRUE, L";") + ||SearchList(MapList, L"BLK", NULL, FALSE, TRUE, L";"))){ + return (TRUE); + } + + if (TypeString != NULL && SearchList(MapList, TypeString, NULL, TRUE, TRUE, L";")) { + return (TRUE); + } + return (FALSE); +} + + +VOID +EFIAPI +PerformSingleMappingDisplay( + IN CONST BOOLEAN Verbose, + IN CONST BOOLEAN Consist, + IN CONST BOOLEAN Normal, + IN CONST CHAR16 *TypeString, + IN CONST BOOLEAN SFO, + IN CONST CHAR16 *Specific OPTIONAL, + IN CONST EFI_HANDLE Handle + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevPath; + EFI_DEVICE_PATH_PROTOCOL *DevPathCopy; + CONST CHAR16 *MapList; + CHAR16 *CurrentName; + CHAR16 *MediaType; + CHAR16 *DevPathString; + CHAR16 *TempSpot; + UINTN TempLen; + BOOLEAN Removable; + CONST CHAR16 *TempSpot2; + + DevPath = DevicePathFromHandle(Handle); + DevPathCopy = DevPath; + MapList = gEfiShellProtocol->GetMapFromDevicePath(&DevPathCopy); + if (MapList == NULL) { + return; + } + + if (!MappingListHasType(MapList, Specific, TypeString, Normal, Consist)){ + return; + } + + CurrentName = NULL; + CurrentName = StrnCatGrow(&CurrentName, 0, MapList, 0); + TempSpot = StrStr(CurrentName, L";"); + if (TempSpot != NULL) { + *TempSpot = CHAR_NULL; + } + DevPathString = gDevPathToText->ConvertDevicePathToText(DevPath, TRUE, FALSE); + if (!SFO) { + TempLen = StrLen(CurrentName); + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_MAP_ENTRY), + gShellLevel2HiiHandle, + CurrentName, + TempLen < StrLen(MapList)?MapList + TempLen+1:L"", + DevPathString + ); + if (Verbose) { + // + // also print handle, media type, removable (y/n), and current directory + // + MediaType = GetDeviceMediaType(DevPath); + if ((TypeString != NULL &&MediaType != NULL && StrStr(TypeString, MediaType) != NULL) || TypeString == NULL) { + Removable = IsRemoveableDevice(DevPath); + TempSpot2 = ShellGetCurrentDir(CurrentName); + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_MAP_ENTRY_VERBOSE), + gShellLevel2HiiHandle, + ConvertHandleToHandleIndex(Handle), + MediaType, + Removable?L"Yes":L"No", + TempSpot2 + ); + } + FreePool(MediaType); + } + } else { + TempLen = StrLen(CurrentName); + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_MAP_SFO_MAPPINGS), + gShellLevel2HiiHandle, + CurrentName, + DevPathString, + TempLen < StrLen(MapList)?MapList + TempLen+1:L"" + ); + } + FreePool(DevPathString); + FreePool(CurrentName); + return; +} + +EFI_STATUS +EFIAPI +PerformSingleMappingDelete( + IN CONST CHAR16 *Specific, + IN CONST EFI_HANDLE Handle + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevPath; + EFI_DEVICE_PATH_PROTOCOL *DevPathCopy; + CONST CHAR16 *MapList; + CHAR16 *CurrentName; + + DevPath = DevicePathFromHandle(Handle); + DevPathCopy = DevPath; + MapList = gEfiShellProtocol->GetMapFromDevicePath(&DevPathCopy); + CurrentName = NULL; + + if (MapList == NULL) { + return (EFI_NOT_FOUND); + } + // + // if there is a specific and its not on the list... + // + if (!SearchList(MapList, Specific, &CurrentName, TRUE, FALSE, L";")) { + return (EFI_NOT_FOUND); + } + return (gEfiShellProtocol->SetMap(NULL, CurrentName)); +} + +/** + Function to display mapping information to the user. + + if Specific is specified then Consist and Normal will be ignored since information will + be printed for the specific item only. + + @param[in] Verbose TRUE to display (extra) verbose information + @param[in] Consist TRUE to display consistent mappings + @param[in] Normal TRUE to display normal (not consist) mappings + @param[in] TypeString pointer to string of filter types + @param[in] SFO TRUE to display output in Standard Output Format + @param[in] Specific pointer to string for specific map to display + + @retval SHELL_SUCCESS the display was printed + @retval SHELL_INVALID_PARAMETER one of Consist or Normal must be TRUE if no Specific + +**/ +CONST CHAR16 Cd[] = L"cd*"; +CONST CHAR16 Hd[] = L"hd*"; +CONST CHAR16 Fp[] = L"fp*"; +CONST CHAR16 F[] = L"F*"; +SHELL_STATUS +EFIAPI +PerformMappingDisplay( + IN CONST BOOLEAN Verbose, + IN CONST BOOLEAN Consist, + IN CONST BOOLEAN Normal, + IN CONST CHAR16 *TypeString, + IN CONST BOOLEAN SFO, + IN CONST CHAR16 *Specific OPTIONAL, + IN CONST BOOLEAN Header + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN BufferSize; + UINTN LoopVar; + CHAR16 *Test; + + if (!Consist && !Normal && Specific == NULL && TypeString == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle); + return (SHELL_INVALID_PARAMETER); + } + + if (TypeString != NULL) { + Test = (CHAR16*)Cd; + if (StrnCmp(TypeString, Test, StrLen(Test)-1) != 0) { + Test = (CHAR16*)Hd; + if (StrnCmp(TypeString, Test, StrLen(Test)-1) != 0) { + Test = (CHAR16*)Fp; + if (StrnCmp(TypeString, Test, StrLen(Test)-1) != 0) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, TypeString); + return (SHELL_INVALID_PARAMETER); + } + } else if (Test == NULL) { + Test = (CHAR16*)F; + } + } + } else { + Test = NULL; + } + + if (Header) { + // + // Print the header + // + if (!SFO) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MAP_HEADER), gShellLevel2HiiHandle); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_SFO_HEADER), gShellLevel2HiiHandle, L"map"); + } + } + + BufferSize = 0; + HandleBuffer = NULL; + + // + // Look up all SimpleFileSystems in the platform + // + Status = gBS->LocateHandle( + ByProtocol, + &gEfiDevicePathProtocolGuid, + NULL, + &BufferSize, + HandleBuffer); + if (Status == EFI_BUFFER_TOO_SMALL) { + HandleBuffer = AllocatePool(BufferSize); + Status = gBS->LocateHandle( + ByProtocol, + &gEfiDevicePathProtocolGuid, + NULL, + &BufferSize, + HandleBuffer); + } + ASSERT_EFI_ERROR(Status); + ASSERT(HandleBuffer != NULL); + + // + // Get the map name(s) for each one. + // + for ( LoopVar = 0 + ; LoopVar < (BufferSize / sizeof(EFI_HANDLE)) + ; LoopVar ++ + ){ + PerformSingleMappingDisplay( + Verbose, + Consist, + Normal, + Test, + SFO, + Specific, + HandleBuffer[LoopVar]); + } + + // + // Look up all BlockIo in the platform + // + Status = gBS->LocateHandle( + ByProtocol, + &gEfiBlockIoProtocolGuid, + NULL, + &BufferSize, + HandleBuffer); + if (Status == EFI_BUFFER_TOO_SMALL) { + FreePool(HandleBuffer); + HandleBuffer = AllocatePool(BufferSize); + Status = gBS->LocateHandle( + ByProtocol, + &gEfiBlockIoProtocolGuid, + NULL, + &BufferSize, + HandleBuffer); + } + ASSERT_EFI_ERROR(Status); + + // + // Get the map name(s) for each one. + // + for ( LoopVar = 0 + ; LoopVar < BufferSize / sizeof(EFI_HANDLE) + ; LoopVar ++ + ){ + // + // Skip any that were already done... + // + if (gBS->OpenProtocol( + HandleBuffer[LoopVar], + &gEfiDevicePathProtocolGuid, + NULL, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL) == EFI_SUCCESS) { + continue; + } + PerformSingleMappingDisplay( + Verbose, + Consist, + Normal, + Test, + SFO, + Specific, + HandleBuffer[LoopVar]); + } + FreePool(HandleBuffer); + return (SHELL_SUCCESS); +} + +SHELL_STATUS +EFIAPI +PerformMappingDisplay2( + IN CONST BOOLEAN Verbose, + IN CONST BOOLEAN Consist, + IN CONST BOOLEAN Normal, + IN CONST CHAR16 *TypeString, + IN CONST BOOLEAN SFO, + IN CONST CHAR16 *Specific OPTIONAL + ) +{ + CONST CHAR16 *TypeWalker; + SHELL_STATUS ShellStatus; + CHAR16 *Comma; + + + if (TypeString == NULL) { + return (PerformMappingDisplay(Verbose, Consist, Normal, NULL, SFO, Specific, TRUE)); + } + ShellStatus = SHELL_SUCCESS; + for (TypeWalker = TypeString ; TypeWalker != NULL && *TypeWalker != CHAR_NULL ;) { + Comma = StrStr(TypeWalker, L","); + if (Comma == NULL) { + if (ShellStatus == SHELL_SUCCESS) { + ShellStatus = PerformMappingDisplay(Verbose, Consist, Normal, TypeWalker, SFO, Specific, (BOOLEAN)(TypeWalker == TypeString)); + } else { + PerformMappingDisplay(Verbose, Consist, Normal, TypeWalker, SFO, Specific, (BOOLEAN)(TypeWalker == TypeString)); + } + break; + } else { + *Comma = CHAR_NULL; + if (ShellStatus == SHELL_SUCCESS) { + ShellStatus = PerformMappingDisplay(Verbose, Consist, Normal, TypeWalker, SFO, Specific, (BOOLEAN)(TypeWalker == TypeString)); + } else { + PerformMappingDisplay(Verbose, Consist, Normal, TypeWalker, SFO, Specific, (BOOLEAN)(TypeWalker == TypeString)); + } + *Comma = L','; + TypeWalker = Comma + 1; + } + } + + return (ShellStatus); +} + +EFI_STATUS +EFIAPI +PerformMappingDelete( + IN CONST CHAR16 *Specific + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN BufferSize; + UINTN LoopVar; + BOOLEAN Deleted; + + if (Specific == NULL) { + return (EFI_INVALID_PARAMETER); + } + + BufferSize = 0; + HandleBuffer = NULL; + Deleted = FALSE; + + // + // Look up all SimpleFileSystems in the platform + // + Status = gBS->LocateHandle( + ByProtocol, + &gEfiDevicePathProtocolGuid, + NULL, + &BufferSize, + HandleBuffer); + if (Status == EFI_BUFFER_TOO_SMALL) { + HandleBuffer = AllocatePool(BufferSize); + Status = gBS->LocateHandle( + ByProtocol, + &gEfiDevicePathProtocolGuid, + NULL, + &BufferSize, + HandleBuffer); + } + ASSERT_EFI_ERROR(Status); + ASSERT(HandleBuffer != NULL); + + // + // Get the map name(s) for each one. + // + for ( LoopVar = 0 + ; LoopVar < BufferSize / sizeof(EFI_HANDLE) + ; LoopVar ++ + ){ + if (PerformSingleMappingDelete(Specific,HandleBuffer[LoopVar]) == SHELL_SUCCESS) { + Deleted = TRUE; + } + } + + // + // Look up all BlockIo in the platform + // + Status = gBS->LocateHandle( + ByProtocol, + &gEfiBlockIoProtocolGuid, + NULL, + &BufferSize, + HandleBuffer); + if (Status == EFI_BUFFER_TOO_SMALL) { + FreePool(HandleBuffer); + HandleBuffer = AllocatePool(BufferSize); + Status = gBS->LocateHandle( + ByProtocol, + &gEfiBlockIoProtocolGuid, + NULL, + &BufferSize, + HandleBuffer); + } + ASSERT_EFI_ERROR(Status); + + // + // Get the map name(s) for each one. + // + for ( LoopVar = 0 + ; LoopVar < BufferSize / sizeof(EFI_HANDLE) + ; LoopVar ++ + ){ + // + // Skip any that were already done... + // + if (gBS->OpenProtocol( + HandleBuffer[LoopVar], + &gEfiDevicePathProtocolGuid, + NULL, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL) == EFI_SUCCESS) { + continue; + } + if (PerformSingleMappingDelete(Specific,HandleBuffer[LoopVar]) == SHELL_SUCCESS) { + Deleted = TRUE; + } + } + FreePool(HandleBuffer); + if (!Deleted) { + return (EFI_NOT_FOUND); + } + return (EFI_SUCCESS); +} + +/** + function to add a mapping from mapping. + + This function will get the device path associated with the mapping and call SetMap. + + @param[in] Map The Map to add a mapping for + @param[in] SName The name of the new mapping + + @retval SHELL_SUCCESS the mapping was added + @retval SHELL_INVALID_PARAMETER the device path for Map could not be retrieved. + @return Shell version of a return value from EfiShellProtocol->SetMap + +**/ +SHELL_STATUS +EFIAPI +AddMappingFromMapping( + IN CONST CHAR16 *Map, + IN CONST CHAR16 *SName + ) +{ + CONST EFI_DEVICE_PATH_PROTOCOL *DevPath; + EFI_STATUS Status; + + if (StrStr(SName, L"*") != NULL + ||StrStr(SName, L"?") != NULL + ||StrStr(SName, L"[") != NULL + ||StrStr(SName, L"]") != NULL) { + return (SHELL_INVALID_PARAMETER); + } + + DevPath = gEfiShellProtocol->GetDevicePathFromMap(Map); + if (DevPath == NULL) { + return (SHELL_INVALID_PARAMETER); + } + + Status = gEfiShellProtocol->SetMap(DevPath, SName); + if (EFI_ERROR(Status)) { + return (SHELL_DEVICE_ERROR); + } + return (SHELL_SUCCESS); +} + +/** + function to determine if a string has only numbers and letters + + This is useful for such things as Map names which can only be letters and numbers + + @param[in] String pointer to the string to analyze + + @retval TRUE String has only numbers and letters + @retval FALSE String has at least one other character. +**/ +BOOLEAN +EFIAPI +IsNumberLetterOnly( + IN CONST CHAR16 *String + ) +{ + while(String != NULL && *String != CHAR_NULL) { + if (! ( *String >= L'a' && *String <= L'z' + || *String >= L'A' && *String <= L'Z' + || *String >= L'0' && *String <= L'9') + ){ + return (FALSE); + } + String++; + } + return (TRUE); +} + +/** + function to add a mapping from an EFI_HANDLE. + + This function will get the device path associated with the Handle and call SetMap. + + @param[in] Handle The handle to add a mapping for + @param[in] SName The name of the new mapping + + @retval SHELL_SUCCESS the mapping was added + @retval SHELL_INVALID_PARAMETER SName was not valid for a map name. + @return Shell version of a return value from either + gBS->OpenProtocol or EfiShellProtocol->SetMap + +**/ +SHELL_STATUS +EFIAPI +AddMappingFromHandle( + IN CONST EFI_HANDLE Handle, + IN CONST CHAR16 *SName + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevPath; + EFI_STATUS Status; + + if (!IsNumberLetterOnly(SName)) { + return (SHELL_INVALID_PARAMETER); + } + + Status = gBS->OpenProtocol( + Handle, + &gEfiDevicePathProtocolGuid, + (VOID**)&DevPath, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR(Status)) { + return (SHELL_DEVICE_ERROR); + } + Status = gEfiShellProtocol->SetMap(DevPath, SName); + if (EFI_ERROR(Status)) { + return (SHELL_DEVICE_ERROR); + } + return (SHELL_SUCCESS); +} + +STATIC CONST SHELL_PARAM_ITEM MapParamList[] = { + {L"-d", TypeValue}, + {L"-r", TypeFlag}, + {L"-v", TypeFlag}, + {L"-c", TypeFlag}, + {L"-f", TypeFlag}, + {L"-u", TypeFlag}, + {L"-t", TypeValue}, + {L"-sfo", TypeValue}, + {NULL, TypeMax} + }; + +/** + Function for 'map' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunMap ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + CONST CHAR16 *SName; + CONST CHAR16 *Mapping; + EFI_HANDLE MappingAsHandle; + CONST EFI_DEVICE_PATH_PROTOCOL *DevPath; + SHELL_STATUS ShellStatus; + BOOLEAN SfoMode; + BOOLEAN ConstMode; + BOOLEAN NormlMode; + CONST CHAR16 *Param1; + CONST CHAR16 *TypeString; + + ProblemParam = NULL; + Mapping = NULL; + SName = NULL; + DevPath = NULL; + ShellStatus = SHELL_SUCCESS; + MappingAsHandle = NULL; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (MapParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + // + // check for "-?" + // + SfoMode = ShellCommandLineGetFlag(Package, L"-sfo"); + ConstMode = ShellCommandLineGetFlag(Package, L"-c"); + NormlMode = ShellCommandLineGetFlag(Package, L"-f"); + if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } else if (ShellCommandLineGetRawValue(Package, 3) != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // Deleting a map name... + // + if (ShellCommandLineGetFlag(Package, L"-d")) { + if ( ShellCommandLineGetFlag(Package, L"-r") + || ShellCommandLineGetFlag(Package, L"-v") + || ConstMode + || NormlMode + || ShellCommandLineGetFlag(Package, L"-u") + || ShellCommandLineGetFlag(Package, L"-t") + ){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CON), gShellLevel2HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + SName = ShellCommandLineGetValue(Package, L"-d"); + if (SName != NULL) { + Status = PerformMappingDelete(SName); + if (EFI_ERROR(Status)) { + switch (Status) { + case EFI_ACCESS_DENIED: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellLevel2HiiHandle); + ShellStatus = SHELL_ACCESS_DENIED; + break; + case EFI_NOT_FOUND: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MAP_NF), gShellLevel2HiiHandle, SName); + ShellStatus = SHELL_INVALID_PARAMETER; + break; + default: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, Status); + ShellStatus = SHELL_UNSUPPORTED; + } + } + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + } else if ( ShellCommandLineGetFlag(Package, L"-r") +// || ShellCommandLineGetFlag(Package, L"-v") + || ConstMode + || NormlMode + || ShellCommandLineGetFlag(Package, L"-u") + || ShellCommandLineGetFlag(Package, L"-t") + ){ + if ( ShellCommandLineGetFlag(Package, L"-r")) { + // + // Do the reset + // + Status = ShellCommandCreateInitialMappingsAndPaths(); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, Status); + ShellStatus = SHELL_UNSUPPORTED; + } + } + if ( ShellStatus == SHELL_SUCCESS && ShellCommandLineGetFlag(Package, L"-u")) { + // + // Do the Update + // + Status = UpdateMapping(); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, Status); + ShellStatus = SHELL_UNSUPPORTED; + } + } + if (ShellStatus == SHELL_SUCCESS) { + Param1 = ShellCommandLineGetRawValue(Package, 1); + TypeString = ShellCommandLineGetValue(Package, L"-t"); + if (!ConstMode + &&!NormlMode + &&TypeString == NULL + ) { + // + // now do the display... + // + ShellStatus = PerformMappingDisplay( + ShellCommandLineGetFlag(Package, L"-v"), + TRUE, + TRUE, + NULL, + SfoMode, + Param1, + TRUE + ); + } else { + // + // now do the display... + // + ShellStatus = PerformMappingDisplay2( + ShellCommandLineGetFlag(Package, L"-v"), + ConstMode, + NormlMode, + TypeString, + SfoMode, + Param1 + ); + } + } + } else { + // + // adding or displaying (there were no flags) + // + SName = ShellCommandLineGetRawValue(Package, 1); + Mapping = ShellCommandLineGetRawValue(Package, 2); + if ( SName == NULL + && Mapping == NULL + ){ + // + // display only since no flags + // + ShellStatus = PerformMappingDisplay( + ShellCommandLineGetFlag(Package, L"-v"), + TRUE, + TRUE, + NULL, + SfoMode, + NULL, + TRUE + ); + } else if ( SName == NULL + || Mapping == NULL + ){ + // + // Display only the one specified + // + ShellStatus = PerformMappingDisplay( + FALSE, + FALSE, + FALSE, + NULL, + SfoMode, + SName, // note the variable here... + TRUE + ); + } else { + if (ShellIsHexOrDecimalNumber(Mapping, TRUE, FALSE)) { + MappingAsHandle = ConvertHandleIndexToHandle(StrHexToUintn(Mapping)); + } else { + MappingAsHandle = NULL; + } + if (MappingAsHandle == NULL && Mapping[StrLen(Mapping)-1] != L':') { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, Mapping); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + if (MappingAsHandle != NULL) { + ShellStatus = AddMappingFromHandle(MappingAsHandle, SName); + } else { + ShellStatus = AddMappingFromMapping(Mapping, SName); + } + if (ShellStatus != SHELL_SUCCESS) { + switch (ShellStatus) { + case SHELL_ACCESS_DENIED: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellLevel2HiiHandle); + break; + case SHELL_INVALID_PARAMETER: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle); + break; + default: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, ShellStatus|MAX_BIT); + } + } else { + // + // now do the display... + // + ShellStatus = PerformMappingDisplay( + FALSE, + FALSE, + FALSE, + NULL, + SfoMode, + SName, + TRUE + ); + } // we were sucessful so do an output + } // got a valid map target + } // got 2 variables + } // we are adding a mapping + } // got valid parameters + } + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + + return (ShellStatus); +} + diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/MkDir.c b/ShellPkg/Library/UefiShellLevel2CommandsLib/MkDir.c new file mode 100644 index 0000000000..421bd55d6f --- /dev/null +++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/MkDir.c @@ -0,0 +1,128 @@ +/** @file + Main file for attrib shell level 2 function. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel2CommandsLib.h" + +/** + Function for 'mkdir' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunMkDir ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + CONST CHAR16 *NewDirName; + UINTN DirCreateCount; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_FILE_HANDLE FileHandle; + SHELL_STATUS ShellStatus; + + ShellStatus = SHELL_SUCCESS; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + // + // check for "-?" + // + if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } + + // + // create a set of directories + // + if (ShellCommandLineGetRawValue(Package, 1) == NULL) { + // + // we didnt get a single parameter + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + for ( DirCreateCount = 1 + ; + ; DirCreateCount++ + ){ + // + // loop through each directory specified + // + + NewDirName = ShellCommandLineGetRawValue(Package, DirCreateCount); + if (NewDirName == NULL) { + break; + } + // + // check if that already exists... if yes fail + // + FileHandle = NULL; + Status = ShellOpenFileByName(NewDirName, + &FileHandle, + EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, + EFI_FILE_DIRECTORY + ); + if (!EFI_ERROR(Status)) { + ShellCloseFile(&FileHandle); + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MKDIR_ALREADY), gShellLevel2HiiHandle, NewDirName); + ShellStatus = SHELL_INVALID_PARAMETER; + break; + } else { + ASSERT(FileHandle == NULL); + // + // create the directory named NewDirName + // + Status = ShellCreateDirectory(NewDirName, &FileHandle); + if (FileHandle != NULL) { + gEfiShellProtocol->CloseFile(FileHandle); + } + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MKDIR_CREATEFAIL), gShellLevel2HiiHandle, NewDirName); + ShellStatus = SHELL_ACCESS_DENIED; + break; + } + } + } + } + } + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + + return (ShellStatus); +} + diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/Mv.c b/ShellPkg/Library/UefiShellLevel2CommandsLib/Mv.c new file mode 100644 index 0000000000..adb6f99759 --- /dev/null +++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/Mv.c @@ -0,0 +1,478 @@ +/** @file + Main file for mv shell level 2 function. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel2CommandsLib.h" + +/** + Function to validate that moving a specific file (FileName) to a specific + location (DestPath) is valid. + + This function will verify that the destination is not a subdirectory of + FullName, that the Current working Directory is not being moved, and that + the directory is not read only. + + if the move is invalid this function will report the error to StdOut. + + @param FullName [in] The name of the file to move. + @param Cwd [in] The current working directory + @param DestPath [in] The target location to move to + @param Attribute[in] The Attribute of the file + + @retval TRUE The move is valid + @retval FALSE The move is not +**/ +BOOLEAN +EFIAPI +IsValidMove( + IN CONST CHAR16 *FullName, + IN CONST CHAR16 *Cwd, + IN CONST CHAR16 *DestPath, + IN CONST UINT64 Attribute + ) +{ + CHAR16 *Test; + CHAR16 *Test1; + CHAR16 *TestWalker; + UINTN Result; + UINTN TempLen; + if (Cwd != NULL && StrCmp(FullName, Cwd) == 0) { + // + // Invalid move + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MV_INV_CWD), gShellLevel2HiiHandle); + return (FALSE); + } + Test = NULL; + Test = StrnCatGrow(&Test, NULL, DestPath, 0); + TestWalker = Test; + ASSERT(TestWalker != NULL); + while(*TestWalker == L'\\') { + TestWalker++; + } + while(TestWalker != NULL && TestWalker[StrLen(TestWalker)-1] == L'\\') { + TestWalker[StrLen(TestWalker)-1] = CHAR_NULL; + } + ASSERT(TestWalker != NULL); + ASSERT(FullName != NULL); + if (StrStr(FullName, TestWalker) != 0) { + TempLen = StrLen(FullName); + if (StrStr(FullName, TestWalker) != FullName // not the first items... (could below it) + && TempLen <= (StrLen(TestWalker) + 1) + && StrStr(FullName+StrLen(TestWalker) + 1, L"\\") == NULL) { + // + // Invalid move + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MV_INV_SUB), gShellLevel2HiiHandle); + FreePool(Test); + return (FALSE); + } + } + FreePool(Test); + if (StrStr(DestPath, FullName) != 0 && StrStr(DestPath, FullName) != DestPath) { + // + // Invalid move + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MV_INV_SUB), gShellLevel2HiiHandle); + return (FALSE); + } + if ((Attribute & EFI_FILE_READ_ONLY) != 0) { + // + // invalid to move read only + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MV_INV_RO), gShellLevel2HiiHandle); + return (FALSE); + } + Test = StrStr(FullName, L":"); + Test1 = StrStr(DestPath, L":"); + if (Test1 != NULL && Test != NULL) { + *Test = CHAR_NULL; + *Test1 = CHAR_NULL; + Result = StringNoCaseCompare(&FullName, &DestPath); + *Test = L':'; + *Test1 = L':'; + if (Result != 0) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MV_INV_FS), gShellLevel2HiiHandle); + return (FALSE); + } + } + return (TRUE); +} + +/** + Function to take a destination path that might contain wildcards and verify + that there is only a single possible target (IE we cant have wildcards that + have 2 possible destination). + + if the result is sucessful the caller must free *DestPathPointer. + + @param[in] DestDir The original path to the destination + @param[in,out] DestPathPointer a pointer to the callee allocated final path. + + @retval EFI_INVALID_PARAMETR the DestDir could not be resolved to a location + @retval EFI_INVALID_PARAMETR the DestDir could be resolved to more than 1 location + @retval EFI_SUCCESS the operation was sucessful +**/ +SHELL_STATUS +EFIAPI +GetDestinationLocation( + IN CONST CHAR16 *DestDir, + IN OUT CHAR16 **DestPathPointer, + IN CONST CHAR16 *Cwd + ) +{ + EFI_SHELL_FILE_INFO *DestList; + EFI_SHELL_FILE_INFO *Node; + EFI_STATUS Status; + CHAR16 *DestPath; + CHAR16 *TempLocation; + UINTN NewSize; + + DestList = NULL; + DestPath = NULL; + // + // get the destination path + // + Status = ShellOpenFileMetaArg((CHAR16*)DestDir, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE, &DestList); + if (DestList == NULL || IsListEmpty(&DestList->Link)) { + // + // Not existing... must be renaming + // + if ((TempLocation = StrStr(DestDir, L":")) == NULL) { + NewSize = StrSize(Cwd); + NewSize += StrSize(DestDir); + DestPath = AllocateZeroPool(NewSize); + StrCpy(DestPath, Cwd); + if (DestPath[StrLen(DestPath)-1] != L'\\' && DestDir[0] != L'\\') { + StrCat(DestPath, L"\\"); + } else if (DestPath[StrLen(DestPath)-1] == L'\\' && DestDir[0] == L'\\') { + ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL; + } + StrCat(DestPath, DestDir); + } else { + ASSERT(DestPath == NULL); + DestPath = StrnCatGrow(&DestPath, NULL, DestDir, 0); + } + } else { + Node = (EFI_SHELL_FILE_INFO*)GetFirstNode(&DestList->Link); + // + // Make sure there is only 1 node in the list. + // + if (!IsNodeAtEnd(&DestList->Link, &Node->Link)) { + ShellCloseFileMetaArg(&DestList); + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_MARG_ERROR), gShellLevel2HiiHandle, DestDir); + return (SHELL_INVALID_PARAMETER); + } + if (ShellIsDirectory(Node->FullName)==EFI_SUCCESS) { + DestPath = AllocateZeroPool(StrSize(Node->FullName)+sizeof(CHAR16)); + StrCpy(DestPath, Node->FullName); + StrCat(DestPath, L"\\"); + } else { + // + // cant move onto another file. + // + ShellCloseFileMetaArg(&DestList); + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_ERROR), gShellLevel2HiiHandle, DestDir); + return (SHELL_INVALID_PARAMETER); + } + } + + *DestPathPointer = DestPath; + ShellCloseFileMetaArg(&DestList); + + return (SHELL_SUCCESS); +} + +/** + function to take a list of files to move and a destination location and do + the verification and moving of those files to that location. This function + will report any errors to the user and continue to move the rest of the files. + + @param[in] FileList A LIST_ENTRY* based list of files to move + @param[in] DestDir the destination location + + @retval SHELL_SUCCESS the files were all moved. + @retval SHELL_INVALID_PARAMETER a parameter was invalid + @retval SHELL_SECURITY_VIOLATION a security violation ocurred + @retval SHELL_WRITE_PROTECTED the destination was write protected + @retval SHELL_OUT_OF_RESOURCES a memory allocation failed +**/ +SHELL_STATUS +EFIAPI +ValidateAndMoveFiles( + IN CONST EFI_SHELL_FILE_INFO *FileList, + IN CONST CHAR16 *DestDir + ) +{ + EFI_STATUS Status; + CHAR16 *HiiOutput; + CHAR16 *HiiResultOk; + CHAR16 *DestPath; + CONST CHAR16 *Cwd; + SHELL_STATUS ShellStatus; + CONST EFI_SHELL_FILE_INFO *Node; + EFI_FILE_INFO *NewFileInfo; + CHAR16 *TempLocation; + UINTN NewSize; + + ASSERT(FileList != NULL); + ASSERT(DestDir != NULL); + + DestPath = NULL; + Cwd = ShellGetCurrentDir(NULL); + + // + // Get and validate the destination location + // + ShellStatus = GetDestinationLocation(DestDir, &DestPath, Cwd); + if (ShellStatus != SHELL_SUCCESS) { + return (ShellStatus); + } + + HiiOutput = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_MV_OUTPUT), NULL); + HiiResultOk = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_GEN_RES_OK), NULL); + ASSERT (DestPath != NULL); + ASSERT (HiiResultOk != NULL); + ASSERT (HiiOutput != NULL); +// ASSERT (Cwd != NULL); + + // + // Go through the list of files and directories to move... + // + for (Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&FileList->Link) + ; !IsNull(&FileList->Link, &Node->Link) + ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&FileList->Link, &Node->Link) + ){ + if (ShellGetExecutionBreakFlag()) { + break; + } + ASSERT(Node->FileName != NULL); + ASSERT(Node->FullName != NULL); + + // + // skip the directory traversing stuff... + // + if (StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0) { + continue; + } + + // + // Validate that the move is valid + // + if (!IsValidMove(Node->FullName, Cwd, DestPath, Node->Info->Attribute)) { + ShellStatus = SHELL_INVALID_PARAMETER; + continue; + } + + // + // Chop off map info from "DestPath" + // + if ((TempLocation = StrStr(DestPath, L":")) != NULL) { + CopyMem(DestPath, TempLocation+1, StrSize(TempLocation+1)); + } + + // + // construct the new file info block + // + NewSize = StrSize(DestPath); + NewSize += StrSize(Node->FileName) + sizeof(EFI_FILE_INFO) + sizeof(CHAR16); + NewFileInfo = AllocateZeroPool(NewSize); + ASSERT(NewFileInfo != NULL); + CopyMem(NewFileInfo, Node->Info, sizeof(EFI_FILE_INFO)); + if (DestPath[0] != L'\\') { + StrCpy(NewFileInfo->FileName, L"\\"); + StrCat(NewFileInfo->FileName, DestPath); + } else { + StrCpy(NewFileInfo->FileName, DestPath); + } + if (NewFileInfo->FileName[StrLen(NewFileInfo->FileName)-1] == L'\\') { + if (Node->FileName[0] == L'\\') { + // + // Don't allow for double slashes. Eliminate one of them. + // + NewFileInfo->FileName[StrLen(NewFileInfo->FileName)-1] = CHAR_NULL; + } + StrCat(NewFileInfo->FileName, Node->FileName); + } + NewFileInfo->Size = sizeof(EFI_FILE_INFO) + StrSize(NewFileInfo->FileName); + + ShellPrintEx(-1, -1, HiiOutput, Node->FullName, NewFileInfo->FileName); + + // + // Perform the move operation + // + Status = ShellSetFileInfo(Node->Handle, NewFileInfo); + + // + // Free the info object we used... + // + ASSERT (NewFileInfo != NULL); + FreePool(NewFileInfo); + + // + // Check our result + // + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, Status); + // + // move failed + // + switch(Status){ + default: + ShellStatus = SHELL_INVALID_PARAMETER; + case EFI_SECURITY_VIOLATION: + ShellStatus = SHELL_SECURITY_VIOLATION; + case EFI_WRITE_PROTECTED: + ShellStatus = SHELL_WRITE_PROTECTED; + case EFI_OUT_OF_RESOURCES: + ShellStatus = SHELL_OUT_OF_RESOURCES; + case EFI_DEVICE_ERROR: + ShellStatus = SHELL_DEVICE_ERROR; + case EFI_ACCESS_DENIED: + ShellStatus = SHELL_ACCESS_DENIED; + } // switch + } else { + ShellPrintEx(-1, -1, L"%s", HiiResultOk); + } + } // for loop + + FreePool(DestPath); + FreePool(HiiOutput); + FreePool(HiiResultOk); + return (ShellStatus); +} + +SHELL_STATUS +EFIAPI +ShellCommandRunMv ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + UINTN ParamCount; + UINTN LoopCounter; + EFI_SHELL_FILE_INFO *FileList; + + ProblemParam = NULL; + ShellStatus = SHELL_SUCCESS; + ParamCount = 0; + FileList = NULL; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + // + // check for "-?" + // + if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } + + switch (ParamCount = ShellCommandLineGetCount(Package)) { + case 0: + case 1: + // + // we have insufficient parameters + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + break; + case 2: + // + // must have valid CWD for single parameter... + // + if (ShellGetCurrentDir(NULL) == NULL){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = ShellOpenFileMetaArg((CHAR16*)ShellCommandLineGetRawValue(Package, 1), EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList); + if (FileList == NULL || IsListEmpty(&FileList->Link) || EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, 1)); + ShellStatus = SHELL_NOT_FOUND; + } else { + // + // ValidateAndMoveFiles will report errors to the screen itself + // + ShellStatus = ValidateAndMoveFiles(FileList, ShellGetCurrentDir(NULL)); + } + } + + break; + default: + ///@todo make sure this works with error half way through and continues... + for (ParamCount--, LoopCounter = 1 ; LoopCounter < ParamCount && ShellStatus == SHELL_SUCCESS ; LoopCounter++) { + if (ShellGetExecutionBreakFlag()) { + break; + } + Status = ShellOpenFileMetaArg((CHAR16*)ShellCommandLineGetRawValue(Package, LoopCounter), EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList); + if (FileList == NULL || IsListEmpty(&FileList->Link) || EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, 1)); + ShellStatus = SHELL_NOT_FOUND; + } else { + // + // ValidateAndMoveFiles will report errors to the screen itself + // Only change ShellStatus if it's sucessful + // + if (ShellStatus == SHELL_SUCCESS) { + ShellStatus = ValidateAndMoveFiles(FileList, ShellCommandLineGetRawValue(Package, ParamCount)); + } else { + ValidateAndMoveFiles(FileList, ShellCommandLineGetRawValue(Package, ParamCount)); + } + } + if (FileList != NULL && !IsListEmpty(&FileList->Link)) { + Status = ShellCloseFileMetaArg(&FileList); + if (EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS) { + ShellStatus = SHELL_ACCESS_DENIED; + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_FILE), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, 1), ShellStatus|MAX_BIT); + } + } + } + break; + } // switch on parameter count + + if (FileList != NULL) { + ShellCloseFileMetaArg(&FileList); + } + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + } + + if (ShellGetExecutionBreakFlag()) { + return (SHELL_ABORTED); + } + + return (ShellStatus); +} diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/Parse.c b/ShellPkg/Library/UefiShellLevel2CommandsLib/Parse.c new file mode 100644 index 0000000000..927c8d9729 --- /dev/null +++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/Parse.c @@ -0,0 +1,190 @@ +/** @file + Main file for Parse shell level 2 function. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel2CommandsLib.h" + +SHELL_STATUS +EFIAPI +PerformParsing( + IN CONST CHAR16 *FileName, + IN CONST CHAR16 *TableName, + IN CONST UINTN ColumnIndex, + IN CONST UINTN TableNameInstance, + IN CONST UINTN ShellCommandInstance + ) +{ + SHELL_FILE_HANDLE FileHandle; + EFI_STATUS Status; + BOOLEAN Ascii; + UINTN LoopVariable; + UINTN ColumnLoop; + CHAR16 *TempLine; + CHAR16 *ColumnPointer; + SHELL_STATUS ShellStatus; + CHAR16 *TempSpot; + + ASSERT(FileName != NULL); + ASSERT(TableName != NULL); + + ShellStatus = SHELL_SUCCESS; + + Status = ShellOpenFileByName(FileName, &FileHandle, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel2HiiHandle, FileName); + ShellStatus = SHELL_NOT_FOUND; + } else { + for (LoopVariable = 0 ; LoopVariable < ShellCommandInstance && !ShellFileHandleEof(FileHandle);) { + TempLine = ShellFileHandleReturnLine(FileHandle, &Ascii); + if (TempLine == NULL) { + break; + } + if (StrStr(TempLine, L"ShellCommand, \"") == TempLine) { + LoopVariable++; + } + SHELL_FREE_NON_NULL(TempLine); + } + if (LoopVariable == ShellCommandInstance) { + LoopVariable = 0; + while(1) { + TempLine = ShellFileHandleReturnLine(FileHandle, &Ascii); + if ( TempLine == NULL + || *TempLine == CHAR_NULL + || StrStr(TempLine, L"ShellCommand, \"") == TempLine + ){ + SHELL_FREE_NON_NULL(TempLine); + break; + } + if (StrStr(TempLine, TableName) == TempLine) { + LoopVariable++; + } + if ( LoopVariable == TableNameInstance + || (TableNameInstance == (UINTN)-1 && StrStr(TempLine, TableName) == TempLine) + ){ + for (ColumnLoop = 1, ColumnPointer = TempLine; ColumnLoop < ColumnIndex && ColumnPointer != NULL && *ColumnPointer != CHAR_NULL; ColumnLoop++) { + ColumnPointer = StrStr(ColumnPointer, L","); + if (ColumnPointer != NULL && *ColumnPointer != CHAR_NULL){ + ColumnPointer++; + } + } + if (ColumnLoop == ColumnIndex) { + ASSERT(ColumnPointer != NULL); + TempSpot = StrStr(ColumnPointer, L","); + if (TempSpot != NULL) { + *TempSpot = CHAR_NULL; + } + while (ColumnPointer != NULL && *ColumnPointer != CHAR_NULL && ColumnPointer[0] == L' '){ + ColumnPointer++; + } + if (ColumnPointer != NULL && *ColumnPointer != CHAR_NULL && ColumnPointer[0] == L'\"'){ + ColumnPointer++; + } + if (ColumnPointer != NULL && *ColumnPointer != CHAR_NULL && ColumnPointer[StrLen(ColumnPointer)-1] == L'\"'){ + ColumnPointer[StrLen(ColumnPointer)-1] = CHAR_NULL; + } + + ShellPrintEx(-1, -1, L"%s\r\n", ColumnPointer); + } + } + SHELL_FREE_NON_NULL(TempLine); + } + } + } + return (ShellStatus); +} + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-i", TypeValue}, + {L"-s", TypeValue}, + {NULL, TypeMax} + }; + +/** + Function for 'parse' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunParse ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + CONST CHAR16 *FileName; + CONST CHAR16 *TableName; + CONST CHAR16 *ColumnString; + SHELL_STATUS ShellStatus; + UINTN ShellCommandInstance; + UINTN TableNameInstance; + + ShellStatus = SHELL_SUCCESS; + ProblemParam = NULL; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + if (ShellCommandLineGetCount(Package) < 4) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetCount(Package) > 4) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + FileName = ShellCommandLineGetRawValue(Package, 1); + TableName = ShellCommandLineGetRawValue(Package, 2); + ColumnString = ShellCommandLineGetRawValue(Package, 3); + + if (ShellCommandLineGetValue(Package, L"-i") == NULL) { + TableNameInstance = (UINTN)-1; + } else { + TableNameInstance = ShellStrToUintn(ShellCommandLineGetValue(Package, L"-i")); + } + if (ShellCommandLineGetValue(Package, L"-s") == NULL) { + ShellCommandInstance = 1; + } else { + ShellCommandInstance = ShellStrToUintn(ShellCommandLineGetValue(Package, L"-s")); + } + + ShellStatus = PerformParsing(FileName, TableName, ShellStrToUintn(ColumnString), TableNameInstance, ShellCommandInstance); + } + } + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + + return (ShellStatus); +} + diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/Reset.c b/ShellPkg/Library/UefiShellLevel2CommandsLib/Reset.c new file mode 100644 index 0000000000..d0eea8d033 --- /dev/null +++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/Reset.c @@ -0,0 +1,131 @@ +/** @file + Main file for attrib shell level 2 function. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel2CommandsLib.h" + +STATIC CONST SHELL_PARAM_ITEM ResetParamList[] = { + {L"-w", TypeValue}, + {L"-s", TypeValue}, + {L"-c", TypeValue}, + {NULL, TypeMax} + }; + +/** + Function for 'reset' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunReset ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CONST CHAR16 *String; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + + ShellStatus = SHELL_SUCCESS; + ProblemParam = NULL; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (ResetParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam); + FreePool(ProblemParam); + return (SHELL_INVALID_PARAMETER); + } else { + ASSERT(FALSE); + } + } else { + // + // check for "-?" + // + if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } else if (ShellCommandLineGetRawValue(Package, 1) != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // check for cold reset flag, then shutdown reset flag, then warm (default) reset flag + // + if (ShellCommandLineGetFlag(Package, L"-c")) { + if (ShellCommandLineGetFlag(Package, L"-s") || ShellCommandLineGetFlag(Package, L"-w")) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + String = ShellCommandLineGetValue(Package, L"-c"); + if (String != NULL) { + gRT->ResetSystem(EfiResetCold, EFI_SUCCESS, StrSize(String), (VOID*)String); + } else { + gRT->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL); + } + } + } else if (ShellCommandLineGetFlag(Package, L"-s")) { + if (ShellCommandLineGetFlag(Package, L"-w")) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + String = ShellCommandLineGetValue(Package, L"-s"); + DEBUG_CODE(ShellPrintEx(-1,-1,L"Reset with %s (%d bytes)", String, String!=NULL?StrSize(String):0);); + if (String != NULL) { + gRT->ResetSystem(EfiResetShutdown, EFI_SUCCESS, StrSize(String), (VOID*)String); + } else { + gRT->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL); + } + } + } else { + // + // this is default so dont worry about flag... + // + String = ShellCommandLineGetValue(Package, L"-w"); + if (String != NULL) { + gRT->ResetSystem(EfiResetWarm, EFI_SUCCESS, StrSize(String), (VOID*)String); + } else { + gRT->ResetSystem(EfiResetWarm, EFI_SUCCESS, 0, NULL); + } + } + } + } + + // + // we should never get here... so the free and return are for formality more than use + // as the ResetSystem function should not return... + // + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + + // + // return the status + // + return (ShellStatus); +} + diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/Rm.c b/ShellPkg/Library/UefiShellLevel2CommandsLib/Rm.c new file mode 100644 index 0000000000..bde710faf0 --- /dev/null +++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/Rm.c @@ -0,0 +1,296 @@ +/** @file + Main file for attrib shell level 2 function. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel2CommandsLib.h" + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-q", TypeFlag}, + {NULL, TypeMax} + }; + +BOOLEAN +EFIAPI +IsDirectoryEmpty ( + IN EFI_HANDLE FileHandle + ) +{ + EFI_STATUS Status; + EFI_FILE_INFO *FileInfo; + BOOLEAN NoFile; + BOOLEAN RetVal; + + RetVal = TRUE; + NoFile = FALSE; + + for (Status = FileHandleFindFirstFile(FileHandle, &FileInfo) + ; !NoFile + ; Status = FileHandleFindNextFile(FileHandle, FileInfo, &NoFile) + ){ + if (StrStr(FileInfo->FileName, L".") != FileInfo->FileName + &&StrStr(FileInfo->FileName, L"..") != FileInfo->FileName) { + RetVal = FALSE; + } + } + return (RetVal); +} + +SHELL_STATUS +EFIAPI +CascadeDelete( + IN EFI_SHELL_FILE_INFO *Node, + IN CONST BOOLEAN Quiet + ) +{ + SHELL_STATUS ShellStatus; + EFI_SHELL_FILE_INFO *List; + EFI_SHELL_FILE_INFO *Node2; + EFI_STATUS Status; + SHELL_PROMPT_RESPONSE *Resp; + + Resp = NULL; + ShellStatus = SHELL_SUCCESS; + List = NULL; + Status = EFI_SUCCESS; + + if ((Node->Info->Attribute & EFI_FILE_READ_ONLY) == EFI_FILE_READ_ONLY) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_RM_LOG_DETELE_RO), gShellLevel2HiiHandle, Node->FullName); + return (SHELL_ACCESS_DENIED); + } + + if ((Node->Info->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY) { + if (!IsDirectoryEmpty(Node->Handle)) { + if (!Quiet) { + Status = ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_RM_LOG_DELETE_CONF), gShellLevel2HiiHandle, Node->FullName); + Status = ShellPromptForResponse(ShellPromptResponseTypeYesNo, NULL, (VOID**)&Resp); + ASSERT_EFI_ERROR(Status); + ASSERT(Resp != NULL); + if (EFI_ERROR(Status) || *Resp != ShellPromptResponseYes) { + SHELL_FREE_NON_NULL(Resp); + return (SHELL_ABORTED); + } + SHELL_FREE_NON_NULL(Resp); + } + // + // empty out the directory + // + Status = gEfiShellProtocol->FindFilesInDir(Node->Handle, &List); + if (EFI_ERROR(Status)) { + if (List!=NULL) { + gEfiShellProtocol->FreeFileList(&List); + } + return (SHELL_DEVICE_ERROR); + } + for (Node2 = (EFI_SHELL_FILE_INFO *)GetFirstNode(&List->Link) + ; !IsNull(&List->Link, &Node2->Link) + ; Node2 = (EFI_SHELL_FILE_INFO *)GetNextNode(&List->Link, &Node2->Link) + ){ + // + // skip the directory traversing stuff... + // + if (StrCmp(Node2->FileName, L".") == 0 || StrCmp(Node2->FileName, L"..") == 0) { + continue; + } + Node2->Status = gEfiShellProtocol->OpenFileByName (Node2->FullName, &Node2->Handle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE); + ShellStatus = CascadeDelete(Node2, Quiet); + if (ShellStatus != SHELL_SUCCESS) { + if (List!=NULL) { + gEfiShellProtocol->FreeFileList(&List); + } + return (ShellStatus); + } + } + if (List!=NULL) { + gEfiShellProtocol->FreeFileList(&List); + } + } + } + + if (!(StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0)) { + // + // now delete the current node... + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_RM_LOG_DELETE), gShellLevel2HiiHandle, Node->FullName); + Status = gEfiShellProtocol->DeleteFile(Node->Handle); + Node->Handle = NULL; + } + + // + // We cant allow for the warning here! + // + if (Status != EFI_SUCCESS){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_RM_LOG_DELETE_ERR), gShellLevel2HiiHandle, Status); + return (SHELL_ACCESS_DENIED); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_RM_LOG_DELETE_COMP), gShellLevel2HiiHandle); + return (SHELL_SUCCESS); + } +} + +BOOLEAN +EFIAPI +IsValidDeleteTarget( + IN CONST EFI_SHELL_FILE_INFO *List, + IN CONST EFI_SHELL_FILE_INFO *Node, + IN CONST LIST_ENTRY *Package + ) +{ + CONST CHAR16 *TempLocation; + CHAR16 *Temp2; + UINTN Size; + + TempLocation = StrStr(Node->FullName, L":"); + if (StrLen(TempLocation) == 2) { + // + // Deleting the root directory is invalid. + // + return (FALSE); + } + TempLocation = ShellGetCurrentDir(NULL); + Size = 0; + Temp2 = NULL; + StrnCatGrow(&Temp2, &Size, TempLocation, 0); + if (StrStr(Temp2, Node->FullName) != NULL) { + FreePool(Temp2); + return (FALSE); + } + FreePool(Temp2); + + return (TRUE); +} + +/** + Function for 'rm' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunRm ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + CONST CHAR16 *Param; + SHELL_STATUS ShellStatus; + UINTN ParamCount; + EFI_SHELL_FILE_INFO *FileList; + EFI_SHELL_FILE_INFO *Node; + + ProblemParam = NULL; + ShellStatus = SHELL_SUCCESS; + ParamCount = 0; + FileList = NULL; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + // + // check for "-?" + // + if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } + if (ShellCommandLineGetRawValue(Package, 1) == NULL) { + // + // we insufficient parameters + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // get a list with each file specified by parameters + // if parameter is a directory then add all the files below it to the list + // + for ( ParamCount = 1, Param = ShellCommandLineGetRawValue(Package, ParamCount) + ; Param != NULL + ; ParamCount++, Param = ShellCommandLineGetRawValue(Package, ParamCount) + ){ + Status = ShellOpenFileMetaArg((CHAR16*)Param, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList); + if (EFI_ERROR(Status) || FileList == NULL || IsListEmpty(&FileList->Link)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, (CHAR16*)Param); + ShellStatus = SHELL_NOT_FOUND; + break; + } + } + + if (ShellStatus == SHELL_SUCCESS){ + // + // loop through the list and make sure we are not aborting... + // + for ( Node = (EFI_SHELL_FILE_INFO*)GetFirstNode(&FileList->Link) + ; !IsNull(&FileList->Link, &Node->Link) && !ShellGetExecutionBreakFlag() + ; Node = (EFI_SHELL_FILE_INFO*)GetNextNode(&FileList->Link, &Node->Link) + ){ + // + // skip the directory traversing stuff... + // + if (StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0) { + continue; + } + + // + // do the deleting of nodes + // + if (EFI_ERROR(Node->Status)){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_RM_LOG_DELETE_ERR2), gShellLevel2HiiHandle, Node->Status); + ShellStatus = SHELL_ACCESS_DENIED; + break; + } + if (!IsValidDeleteTarget(FileList, Node, Package)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_RM_LOG_DELETE_ERR3), gShellLevel2HiiHandle, Node->FullName); + ShellStatus = SHELL_INVALID_PARAMETER; + break; + } + + ShellStatus = CascadeDelete(Node, ShellCommandLineGetFlag(Package, L"-q")); + } + } + // + // Free the fileList + // + if (FileList != NULL) { + Status = ShellCloseFileMetaArg(&FileList); + } + FileList = NULL; + } + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + } + + return (ShellStatus); +} + diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/Set.c b/ShellPkg/Library/UefiShellLevel2CommandsLib/Set.c new file mode 100644 index 0000000000..a3452f0b62 --- /dev/null +++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/Set.c @@ -0,0 +1,169 @@ +/** @file + Main file for attrib shell level 2 function. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel2CommandsLib.h" + +/** + Print out each environment variable registered with the Shell 2.0 GUID. + + If you spawn a pre 2.0 shell from the Shell 2.0 the environment variable may not carry through. + + @retval STATUS_SUCCESS the printout was sucessful + @return any return code from GetNextVariableName except EFI_NOT_FOUND +**/ +SHELL_STATUS +EFIAPI +PrintAllShellEnvVars( + VOID + ) +{ + CONST CHAR16 *Value; + CONST CHAR16 *ConstEnvNameList; + + ConstEnvNameList = gEfiShellProtocol->GetEnv(NULL); + if (ConstEnvNameList == NULL) { + return (SHELL_SUCCESS); + } + while (*ConstEnvNameList != CHAR_NULL){ + Value = gEfiShellProtocol->GetEnv(ConstEnvNameList); + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SET_DISP), gShellLevel2HiiHandle, ConstEnvNameList, Value); + ConstEnvNameList += StrLen(ConstEnvNameList)+1; + } + + return (SHELL_SUCCESS); +} + +STATIC CONST SHELL_PARAM_ITEM SetParamList[] = { + {L"-d", TypeValue}, + {L"-v", TypeFlag}, + {NULL, TypeMax} + }; + +/** + Function for 'set' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunSet ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CONST CHAR16 *KeyName; + CONST CHAR16 *Value; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + + ProblemParam = NULL; + ShellStatus = SHELL_SUCCESS; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + // + // Make sure globals are good... + // + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (SetParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam); + FreePool(ProblemParam); + return (SHELL_INVALID_PARAMETER); + } else { + ASSERT(FALSE); + } + } else { + // + // check for "-?" + // + if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } else if (ShellCommandLineGetRawValue(Package, 3) != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetRawValue(Package, 1) != NULL && ShellCommandLineGetFlag(Package, L"-d")) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetFlag(Package, L"-d")) { + // + // delete a environment variable + // + KeyName = ShellCommandLineGetValue(Package, L"-d"); + if (KeyName == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellLevel2HiiHandle, L"-d"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = ShellSetEnvironmentVariable(KeyName, L"", ShellCommandLineGetFlag(Package, L"-v")); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SET_ND), gShellLevel2HiiHandle, KeyName, Status); + ShellStatus = SHELL_DEVICE_ERROR; + } + } + } else if (ShellCommandLineGetRawValue(Package, 1) == NULL) { + // + // print out all current environment variables + // + return(PrintAllShellEnvVars()); + } else { + // + // we are either printing one or assigning one + // + KeyName = ShellCommandLineGetRawValue(Package, 1); + Value = ShellCommandLineGetRawValue(Package, 2); + if (KeyName != NULL && Value != NULL) { + // + // assigning one + // + Status = ShellSetEnvironmentVariable(KeyName, Value, ShellCommandLineGetFlag(Package, L"-v")); + } else { + if (KeyName != NULL) { + // + // print out value for this one only. + // + Value = ShellGetEnvironmentVariable(KeyName); + if (Value == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SET_NF), gShellLevel2HiiHandle, KeyName); + ShellStatus = SHELL_SUCCESS; + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SET_DISP), gShellLevel2HiiHandle, KeyName, Value); + ShellStatus = SHELL_SUCCESS; + } + } else { + ASSERT(FALSE); + } + } + } + } + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + + return (ShellStatus); +} diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/TimeDate.c b/ShellPkg/Library/UefiShellLevel2CommandsLib/TimeDate.c new file mode 100644 index 0000000000..c8de9cf066 --- /dev/null +++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/TimeDate.c @@ -0,0 +1,772 @@ +/** @file + Main file for time, timezone, and date shell level 2 and shell level 3 functions. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel2CommandsLib.h" + +INT16 +EFIAPI +AbsVal( + INT16 v + ) +{ + if (v>0) { + return (v); + } + return ((INT16)(-v)); +} + +BOOLEAN +EFIAPI +InternalIsTimeLikeString ( + IN CONST CHAR16 *String, + IN CONST CHAR16 Char, + IN CONST UINTN Min, + IN CONST UINTN Max, + IN CONST BOOLEAN MinusOk + ) +{ + UINTN Count; + Count = 0; + + if (MinusOk) { + // + // A single minus is ok. + // + if (*String == L'-') { + String++; + } + } + + // + // the first char must be numeric. + // + if (!ShellIsDecimalDigitCharacter(*String)) { + return (FALSE); + } + // + // loop through the characters and use the lib function + // + for ( ; String != NULL && *String != CHAR_NULL ; String++){ + if (*String == Char) { + Count++; + if (Count > Max) { + return (FALSE); + } + continue; + } + if (!ShellIsDecimalDigitCharacter(*String)) { + return (FALSE); + } + } + if (Count < Min) { + return (FALSE); + } + return (TRUE); +} + +SHELL_STATUS +EFIAPI +CheckAndSetDate ( + IN CONST CHAR16 *DateString + ) +{ + EFI_TIME TheTime; + EFI_STATUS Status; + CONST CHAR16 *Walker; + + if (!InternalIsTimeLikeString(DateString, L'/', 2, 2, FALSE)) { + return (SHELL_INVALID_PARAMETER); + } + + Status = gRT->GetTime(&TheTime, NULL); + ASSERT_EFI_ERROR(Status); + + Walker = DateString; + + TheTime.Month = 0xFF; + TheTime.Day = 0xFF; + TheTime.Year = 0xFFFF; + + TheTime.Month = (UINT8)StrDecimalToUintn (Walker); + Walker = StrStr(Walker, L"/"); + if (Walker != NULL && *Walker == L'/') { + Walker = Walker + 1; + } + if (Walker != NULL && Walker[0] != CHAR_NULL) { + TheTime.Day = (UINT8)StrDecimalToUintn (Walker); + Walker = StrStr(Walker, L"/"); + if (Walker != NULL && *Walker == L'/') { + Walker = Walker + 1; + } + if (Walker != NULL && Walker[0] != CHAR_NULL) { + TheTime.Year = (UINT16)StrDecimalToUintn (Walker); + } + } + + if (TheTime.Year < 100) { + if (TheTime.Year >= 98) { + TheTime.Year = (UINT16)(1900 + TheTime.Year); + } else { + TheTime.Year = (UINT16)(2000 + TheTime.Year); + } + } + + Status = gRT->SetTime(&TheTime); + + if (!EFI_ERROR(Status)){ + return (SHELL_SUCCESS); + } + return (SHELL_INVALID_PARAMETER); +} + +/** + Function for 'date' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunDate ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + EFI_TIME TheTime; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + + ShellStatus = SHELL_SUCCESS; + ProblemParam = NULL; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (SfoParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + // + // check for "-?" + // + if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } else if (ShellCommandLineGetRawValue(Package, 2) != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // If there are 0 value parameters, then print the current date + // else If there are any value paramerers, then print error + // + if (ShellCommandLineGetRawValue(Package, 1) == NULL) { + // + // get the current date + // + Status = gRT->GetTime(&TheTime, NULL); + ASSERT_EFI_ERROR(Status); + + // + // ShellPrintEx the date in SFO or regular format + // + if (ShellCommandLineGetFlag(Package, L"-sfo")) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DATE_SFO_FORMAT), gShellLevel2HiiHandle, TheTime.Month, TheTime.Day, TheTime.Year); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DATE_FORMAT), gShellLevel2HiiHandle, TheTime.Month, TheTime.Day, TheTime.Year); + } + } else { + if (PcdGet8(PcdShellSupportLevel) == 2) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // perform level 3 operation here. + // + ShellStatus = CheckAndSetDate(ShellCommandLineGetRawValue(Package, 1)); + if (ShellStatus != SHELL_SUCCESS) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, 1)); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + } + } + } + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + + // + // return the status + // + return (ShellStatus); +} + +// +// Note "-tz" is invalid for this (non-interactive) version of 'time'. +// +STATIC CONST SHELL_PARAM_ITEM TimeParamList2[] = { + {L"-d", TypeValue}, + {NULL, TypeMax} + }; + +STATIC CONST SHELL_PARAM_ITEM TimeParamList3[] = { + {L"-d", TypeValue}, + {L"-tz", TypeValue}, + {NULL, TypeMax} + }; + +SHELL_STATUS +EFIAPI +CheckAndSetTime ( + IN CONST CHAR16 *TimeString, + IN CONST INT16 Tz, + IN CONST UINT8 Daylight + ) +{ + EFI_TIME TheTime; + EFI_STATUS Status; + CONST CHAR16 *Walker; + + if (TimeString != NULL && !InternalIsTimeLikeString(TimeString, L':', 1, 2, FALSE)) { + return (SHELL_INVALID_PARAMETER); + } + + Status = gRT->GetTime(&TheTime, NULL); + ASSERT_EFI_ERROR(Status); + + if (TimeString != NULL) { + Walker = TimeString; + TheTime.Hour = 0xFF; + TheTime.Minute = 0xFF; + + TheTime.Hour = (UINT8)StrDecimalToUintn (Walker); + Walker = StrStr(Walker, L":"); + if (Walker != NULL && *Walker == L':') { + Walker = Walker + 1; + } + if (Walker != NULL && Walker[0] != CHAR_NULL) { + TheTime.Minute = (UINT8)StrDecimalToUintn (Walker); + Walker = StrStr(Walker, L":"); + if (Walker != NULL && *Walker == L':') { + Walker = Walker + 1; + } + if (Walker != NULL && Walker[0] != CHAR_NULL) { + TheTime.Second = (UINT8)StrDecimalToUintn (Walker); + } + } + } + + if ((Tz >= -1440 && Tz <= 1440)||(Tz == 2047)) { + TheTime.TimeZone = Tz; + } + if (Daylight <= 3 && Daylight != 2) { + TheTime.Daylight = Daylight; + } + Status = gRT->SetTime(&TheTime); + + if (!EFI_ERROR(Status)){ + return (SHELL_SUCCESS); + } + + return (SHELL_INVALID_PARAMETER); +} + +/** + Function for 'time' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunTime ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *Message; + EFI_TIME TheTime; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + INT16 Tz; + UINT8 Daylight; + CONST CHAR16 *TempLocation; + UINTN TzMinutes; + + ShellStatus = SHELL_SUCCESS; + ProblemParam = NULL; + + // + // Initialize variables + // + Message = NULL; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + if (PcdGet8(PcdShellSupportLevel) == 2) { + Status = ShellCommandLineParseEx (TimeParamList2, &Package, &ProblemParam, TRUE, TRUE); + } else { + ASSERT(PcdGet8(PcdShellSupportLevel) == 3); + Status = ShellCommandLineParseEx (TimeParamList3, &Package, &ProblemParam, TRUE, TRUE); + } + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + // + // check for "-?" + // + Status = gRT->GetTime(&TheTime, NULL); + ASSERT_EFI_ERROR(Status); + if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } else if (ShellCommandLineGetRawValue(Package, 2) != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // If there are no parameters, then print the current time + // + if (ShellCommandLineGetRawValue(Package, 1) == NULL + && !ShellCommandLineGetFlag(Package, L"-d") + && !ShellCommandLineGetFlag(Package, L"-tz")) { + // + // ShellPrintEx the current time + // + if (TheTime.TimeZone == 2047) { + TzMinutes = 0; + } else { + TzMinutes = AbsVal(TheTime.TimeZone) % 60; + } + + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_TIME_FORMAT), + gShellLevel2HiiHandle, + TheTime.Hour, + TheTime.Minute, + TheTime.Second, + TheTime.TimeZone==2047?L" ":(TheTime.TimeZone > 0?L"-":L"+"), + TheTime.TimeZone==2047?0:AbsVal(TheTime.TimeZone) / 60, + TzMinutes + ); + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_CRLF), gShellLevel2HiiHandle); + } else if (ShellCommandLineGetFlag(Package, L"-d") && ShellCommandLineGetValue(Package, L"-d") == NULL) { + if (TheTime.TimeZone == 2047) { + TzMinutes = 0; + } else { + TzMinutes = AbsVal(TheTime.TimeZone) % 60; + } + + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_TIME_FORMAT), + gShellLevel2HiiHandle, + TheTime.Hour, + TheTime.Minute, + TheTime.Second, + TheTime.TimeZone==2047?L" ":(TheTime.TimeZone > 0?L"-":L"+"), + TheTime.TimeZone==2047?0:AbsVal(TheTime.TimeZone) / 60, + TzMinutes + ); + switch (TheTime.Daylight) { + case 0: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TIME_DSTNA), gShellLevel2HiiHandle); + break; + case EFI_TIME_ADJUST_DAYLIGHT: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TIME_DSTST), gShellLevel2HiiHandle); + break; + case EFI_TIME_IN_DAYLIGHT: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TIME_DSTDT), gShellLevel2HiiHandle); + break; + default: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_ERROR), gShellLevel2HiiHandle, L"gRT->GetTime", L"TheTime.Daylight", TheTime.Daylight); + } + } else { + if (PcdGet8(PcdShellSupportLevel) == 2) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // perform level 3 operation here. + // + if ((TempLocation = ShellCommandLineGetValue(Package, L"-tz")) != NULL) { + if (TempLocation[0] == L'-') { + Tz = (INT16)(0 - StrDecimalToUintn(++TempLocation)); + } else { + Tz = (INT16)StrDecimalToUintn(TempLocation); + } + if (!(Tz >= -1440 && Tz <= 1440) && Tz != 2047) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"-d"); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } else { + // + // intentionally out of bounds value will prevent changing it... + // + Tz = 1441; + } + TempLocation = ShellCommandLineGetValue(Package, L"-d"); + if (TempLocation != NULL) { + Daylight = (UINT8)StrDecimalToUintn(TempLocation); + if (Daylight != 0 && Daylight != 1 && Daylight != 3) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"-d"); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } else { + // + // invalid = will not use + // + Daylight = 0xFF; + } + if (ShellStatus == SHELL_SUCCESS) { + ShellStatus = CheckAndSetTime(ShellCommandLineGetRawValue(Package, 1), Tz, Daylight); + if (ShellStatus != SHELL_SUCCESS) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, 1)); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + } + } + } + } + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + + // + // return the status + // + return (ShellStatus); +} + +typedef struct { + INT16 TimeZone; + EFI_STRING_ID StringId; +} TIME_ZONE_ITEM; + +STATIC CONST SHELL_PARAM_ITEM TimeZoneParamList2[] = { + {L"-l", TypeFlag}, + {L"-f", TypeFlag}, + {NULL, TypeMax} + }; +STATIC CONST SHELL_PARAM_ITEM TimeZoneParamList3[] = { + {L"-l", TypeFlag}, + {L"-f", TypeFlag}, + {L"-s", TypeValue}, + {NULL, TypeMax} + }; + + STATIC CONST TIME_ZONE_ITEM TimeZoneList[] = { + {720, STRING_TOKEN (STR_TIMEZONE_M12)}, + {660, STRING_TOKEN (STR_TIMEZONE_M11)}, + {600, STRING_TOKEN (STR_TIMEZONE_M10)}, + {540, STRING_TOKEN (STR_TIMEZONE_M9)}, + {480, STRING_TOKEN (STR_TIMEZONE_M8)}, + {420, STRING_TOKEN (STR_TIMEZONE_M7)}, + {360, STRING_TOKEN (STR_TIMEZONE_M6)}, + {300, STRING_TOKEN (STR_TIMEZONE_M5)}, + {270, STRING_TOKEN (STR_TIMEZONE_M430)}, + {240, STRING_TOKEN (STR_TIMEZONE_M4)}, + {210, STRING_TOKEN (STR_TIMEZONE_M330)}, + {180, STRING_TOKEN (STR_TIMEZONE_M3)}, + {120, STRING_TOKEN (STR_TIMEZONE_M2)}, + {60 , STRING_TOKEN (STR_TIMEZONE_M1)}, + {0 , STRING_TOKEN (STR_TIMEZONE_0)}, + {-60 , STRING_TOKEN (STR_TIMEZONE_P1)}, + {-120 , STRING_TOKEN (STR_TIMEZONE_P2)}, + {-180 , STRING_TOKEN (STR_TIMEZONE_P3)}, + {-210 , STRING_TOKEN (STR_TIMEZONE_P330)}, + {-240 , STRING_TOKEN (STR_TIMEZONE_P4)}, + {-270 , STRING_TOKEN (STR_TIMEZONE_P430)}, + {-300 , STRING_TOKEN (STR_TIMEZONE_P5)}, + {-330 , STRING_TOKEN (STR_TIMEZONE_P530)}, + {-345 , STRING_TOKEN (STR_TIMEZONE_P545)}, + {-360 , STRING_TOKEN (STR_TIMEZONE_P6)}, + {-390 , STRING_TOKEN (STR_TIMEZONE_P630)}, + {-420 , STRING_TOKEN (STR_TIMEZONE_P7)}, + {-480 , STRING_TOKEN (STR_TIMEZONE_P8)}, + {-540 , STRING_TOKEN (STR_TIMEZONE_P9)}, + {-570 , STRING_TOKEN (STR_TIMEZONE_P930)}, + {-600 , STRING_TOKEN (STR_TIMEZONE_P10)}, + {-660 , STRING_TOKEN (STR_TIMEZONE_P11)}, + {-720 , STRING_TOKEN (STR_TIMEZONE_P12)}, + {-780 , STRING_TOKEN (STR_TIMEZONE_P13)}, + {-840 , STRING_TOKEN (STR_TIMEZONE_P14)} + }; + +SHELL_STATUS +EFIAPI +CheckAndSetTimeZone ( + IN CONST CHAR16 *TimeZoneString + ) +{ + EFI_TIME TheTime; + EFI_STATUS Status; + CONST CHAR16 *Walker; + UINTN LoopVar; + + if (TimeZoneString == NULL) { + return (SHELL_INVALID_PARAMETER); + } + + if (TimeZoneString != NULL && !InternalIsTimeLikeString(TimeZoneString, L':', 1, 1, TRUE)) { + return (SHELL_INVALID_PARAMETER); + } + + Status = gRT->GetTime(&TheTime, NULL); + ASSERT_EFI_ERROR(Status); + + Walker = TimeZoneString; + if (*Walker == L'-') { + TheTime.TimeZone = (INT16)((StrDecimalToUintn (++Walker)) * 60); + } else { + TheTime.TimeZone = (INT16)((StrDecimalToUintn (Walker)) * -60); + } + Walker = StrStr(Walker, L":"); + if (Walker != NULL && *Walker == L':') { + Walker = Walker + 1; + } + if (Walker != NULL && Walker[0] != CHAR_NULL) { + if (TheTime.TimeZone < 0) { + TheTime.TimeZone = (INT16)(TheTime.TimeZone - (UINT8)StrDecimalToUintn (Walker)); + } else { + TheTime.TimeZone = (INT16)(TheTime.TimeZone + (UINT8)StrDecimalToUintn (Walker)); + } + } + + Status = EFI_INVALID_PARAMETER; + + for ( LoopVar = 0 + ; LoopVar < sizeof(TimeZoneList) / sizeof(TimeZoneList[0]) + ; LoopVar++ + ){ + if (TheTime.TimeZone == TimeZoneList[LoopVar].TimeZone) { + Status = gRT->SetTime(&TheTime); + break; + } + } + + if (!EFI_ERROR(Status)){ + return (SHELL_SUCCESS); + } + return (SHELL_INVALID_PARAMETER); +} + + +/** + Function for 'timezone' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunTimeZone ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + // + // non interactive + // + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + UINT8 LoopVar; + EFI_TIME TheTime; + BOOLEAN Found; + UINTN TzMinutes; + + ShellStatus = SHELL_SUCCESS; + ProblemParam = NULL; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + if (PcdGet8(PcdShellSupportLevel) == 2) { + Status = ShellCommandLineParse (TimeZoneParamList2, &Package, &ProblemParam, FALSE); + } else { + ASSERT(PcdGet8(PcdShellSupportLevel) == 3); + Status = ShellCommandLineParseEx (TimeZoneParamList3, &Package, &ProblemParam, FALSE, TRUE); + } + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + // + // check for "-?" + // + if (ShellCommandLineGetCount(Package) > 1) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } else if (ShellCommandLineGetFlag(Package, L"-s")) { + if ((ShellCommandLineGetFlag(Package, L"-l")) || (ShellCommandLineGetFlag(Package, L"-f"))) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"-l or -f"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(PcdGet8(PcdShellSupportLevel) == 3); + if (ShellCommandLineGetValue(Package, L"-s") == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellLevel2HiiHandle, L"-s"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // Set the time zone + // + ShellStatus = CheckAndSetTimeZone(ShellCommandLineGetValue(Package, L"-s")); + if (ShellStatus != SHELL_SUCCESS) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ShellCommandLineGetValue(Package, L"-s")); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + } + } else if (ShellCommandLineGetFlag(Package, L"-l")) { + // + // Print a list of all time zones + // + for ( LoopVar = 0 + ; LoopVar < sizeof(TimeZoneList) / sizeof(TimeZoneList[0]) + ; LoopVar++ + ){ + ShellPrintHiiEx (-1, -1, NULL, TimeZoneList[LoopVar].StringId, gShellLevel2HiiHandle); + } + } else { + // + // Get Current Time Zone Info + // + Status = gRT->GetTime(&TheTime, NULL); + ASSERT_EFI_ERROR(Status); + + if (TheTime.TimeZone != 2047) { + Found = FALSE; + for ( LoopVar = 0 + ; LoopVar < sizeof(TimeZoneList) / sizeof(TimeZoneList[0]) + ; LoopVar++ + ){ + if (TheTime.TimeZone == TimeZoneList[LoopVar].TimeZone) { + if (ShellCommandLineGetFlag(Package, L"-f")) { + // + // Print all info about current time zone + // + ShellPrintHiiEx (-1, -1, NULL, TimeZoneList[LoopVar].StringId, gShellLevel2HiiHandle); + } else { + // + // Print basic info only + // + if (TheTime.TimeZone == 2047) { + TzMinutes = 0; + } else { + TzMinutes = AbsVal(TheTime.TimeZone) % 60; + } + + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN(STR_TIMEZONE_SIMPLE), + gShellLevel2HiiHandle, + TheTime.TimeZone==2047?0:(TheTime.TimeZone > 0?L"-":L"+"), + TheTime.TimeZone==2047?0:AbsVal(TheTime.TimeZone) / 60, + TzMinutes); + } + Found = TRUE; + break; + } + } + if (!Found) { + // + // Print basic info only + // + if (TheTime.TimeZone == 2047) { + TzMinutes = 0; + } else { + TzMinutes = AbsVal(TheTime.TimeZone) % 60; + } + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN(STR_TIMEZONE_SIMPLE), + gShellLevel2HiiHandle, + TheTime.TimeZone==2047?0:(TheTime.TimeZone > 0?L"-":L"+"), + TheTime.TimeZone==2047?0:AbsVal(TheTime.TimeZone) / 60, + TzMinutes); + if (ShellCommandLineGetFlag(Package, L"-f")) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN(STR_TIMEZONE_NI), gShellLevel2HiiHandle); + } + } + } else { + // + // TimeZone was 2047 (unknown) from GetTime() + // + } + } + } + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + + return (ShellStatus); +} diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.c b/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.c new file mode 100644 index 0000000000..7fe5a1102c --- /dev/null +++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.c @@ -0,0 +1,329 @@ +/** @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* + + * functions are non-interactive only + + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +#include "UefiShellLevel2CommandsLib.h" + +CONST CHAR16 mFileName[] = L"ShellCommands"; +EFI_HANDLE gShellLevel2HiiHandle = NULL; +CONST EFI_GUID gShellLevel2HiiGuid = \ + { \ + 0xf95a7ccc, 0x4c55, 0x4426, { 0xa7, 0xb4, 0xdc, 0x89, 0x61, 0x95, 0xb, 0xae } \ + }; + +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_UNSUPPORTED); + } + + 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"", TRUE, 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) ); + + // + // support for permenant (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\\"); + // + // 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); +} + +/** + Function to clean up paths. Removes the following items: + single periods in the path (no need for the current directory tag) + double periods in the path and removes a single parent directory. + + This will be done inline and the resultant string may be be 'too big'. + + @param[in] PathToReturn The pointer to the string containing the path. + + @return PathToReturn is always returned. +**/ +CHAR16* +EFIAPI +CleanPath( + IN CHAR16 *PathToReturn + ) +{ + CHAR16 *TempString; + UINTN TempSize; + if (PathToReturn==NULL) { + return(NULL); + } + // + // Fix up the directory name + // + while ((TempString = StrStr(PathToReturn, L"\\..\\")) != NULL) { + *TempString = CHAR_NULL; + TempString += 4; + ChopLastSlash(PathToReturn); + TempSize = StrSize(TempString); + CopyMem(PathToReturn+StrLen(PathToReturn), TempString, TempSize); + } + if ((TempString = StrStr(PathToReturn, L"\\..")) != NULL && *(TempString + 3) == CHAR_NULL) { + *TempString = CHAR_NULL; + ChopLastSlash(PathToReturn); + } + while ((TempString = StrStr(PathToReturn, L"\\.\\")) != NULL) { + *TempString = CHAR_NULL; + TempString += 2; + TempSize = StrSize(TempString); + CopyMem(PathToReturn+StrLen(PathToReturn), TempString, TempSize); + } + if ((TempString = StrStr(PathToReturn, L"\\.")) != NULL && *(TempString + 2) == CHAR_NULL) { + *TempString = CHAR_NULL; + } + return (PathToReturn); +} + +/** + 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 pointer to a fuly qualified path. +**/ +CHAR16* +EFIAPI +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); + if (*Path == L'\\') { + Path++; + } + } + StrnCatGrow(&PathToReturn, &Size, Path, 0); + + CleanPath(PathToReturn); + + 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 +EFIAPI +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; + + 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); +} + +// be lazy and borrow from baselib. +CHAR16 +EFIAPI +InternalCharToUpper ( + IN CONST CHAR16 Char + ); + +CONST CHAR16* +EFIAPI +StrniCmp( + IN CONST CHAR16 *Source, + IN CONST CHAR16 *Target, + IN CONST UINTN Count + ) +{ + UINTN LoopCount; + CHAR16 Char1; + CHAR16 Char2; + + ASSERT(Source != NULL); + ASSERT(Target != NULL); + + for (LoopCount = 0 ; LoopCount < Count ; LoopCount++) { + Char1 = InternalCharToUpper(Source[LoopCount]); + Char2 = InternalCharToUpper(Target[LoopCount]); + if (Char1 != Char2) { + return (&Source[LoopCount]); + } + } + return (NULL); +} + diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.h b/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.h new file mode 100644 index 0000000000..c04acccf05 --- /dev/null +++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.h @@ -0,0 +1,297 @@ +/** @file + Main file for NULL named library for level 2 shell command functions. + + these functions are: + attrib, cd, cp, date*, time*, rm, reset, + load, ls, map, mkdir, mv, parse, set, timezone* + + + * functions are non-interactive only + + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern CONST CHAR16 mFileName[]; +extern EFI_HANDLE gShellLevel2HiiHandle; +extern CONST EFI_GUID gShellLevel2HiiGuid; + +/** + Function for 'attrib' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunAttrib ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'date' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunDate ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'time' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunTime ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'load' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunLoad ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'ls' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunLs ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'map' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunMap ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'reset' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunReset ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'timezone' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunTimeZone ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'set' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunSet ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'mkdir' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunMkDir ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'cd' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunCd ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'cp' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunCp ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'parse' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunParse ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'rm' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunRm ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'mv' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunMv ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + 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 pointer to a fuly qualified path. +**/ +CHAR16* +EFIAPI +GetFullyQualifiedPath( + IN CONST CHAR16* Path + ); + +/** + 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 +EFIAPI +VerifyIntermediateDirectories ( + IN CONST CHAR16 *Path + ); + +/** + CaseInsensitive length limited string comparison. + + @param[in] Source Pointer to first string. + @param[in] Target Pointer to second string. + @param[in] Count Number of characters to compare. + + @retval 0 The strings are the same. + @return non-zero if the strings are different. +**/ +CONST CHAR16* +EFIAPI +StrniCmp( + IN CONST CHAR16 *Source, + IN CONST CHAR16 *Target, + IN CONST UINTN Count + ); diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf b/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf new file mode 100644 index 0000000000..9280ad5cbd --- /dev/null +++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf @@ -0,0 +1,82 @@ +## @file +# Provides shell level 2 functions +# +# Copyright (c) 2009, Intel Corporation.All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = UefiShellLevel2CommandsLib + FILE_GUID = CBF3931C-A2DF-40e5-B77E-CCA9555E9755 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = NULL|UEFI_APPLICATION UEFI_DRIVER + CONSTRUCTOR = ShellLevel2CommandsLibConstructor + DESTRUCTOR = ShellLevel2CommandsLibDestructor + +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources.common] + UefiShellLevel2CommandsLib.c + UefiShellLevel2CommandsLib.h + UefiShellLevel2CommandsLib.uni + TimeDate.c + Load.c + Ls.c + Map.c + Reset.c + Set.c + MkDir.c + Cd.c + Cp.c + Parse.c + Rm.c + Mv.c + Attrib.c + +[Packages] + MdePkg/MdePkg.dec + ShellPkg/ShellPkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + MemoryAllocationLib + BaseLib + BaseMemoryLib + DebugLib + ShellCommandLib + ShellLib + UefiLib + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + PcdLib + HiiLib + HandleParsingLib + +[Protocols] + gEfiUnicodeCollation2ProtocolGuid # ALWAYS_CONSUMED + gEfiShellProtocolGuid # ALWAYS_CONSUMED + gEfiShellParametersProtocolGuid # ALWAYS_CONSUMED + gEfiDevicePathProtocolGuid # ALWAYS_CONSUMED + gEfiLoadedImageProtocolGuid # ALWAYS_CONSUMED + gEfiSimpleFileSystemProtocolGuid # ALWAYS_CONSUMED + gEfiDevicePathToTextProtocolGuid # ALWAYS_CONSUMED + +[Pcd.common] + gEfiShellPkgTokenSpaceGuid.PcdShellSupportLevel # ALWAYS_CONSUMED + gEfiShellPkgTokenSpaceGuid.PcdShellFileOperationSize # ALWAYS_CONSUMED + +[Guids] + gEfiFileSystemInfoGuid + gEfiFileInfoGuid diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.uni b/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.uni new file mode 100644 index 0000000000..27b1053354 Binary files /dev/null and b/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.uni differ -- cgit v1.2.3