From 878342a9d5543bd15129f38a4330aa4dd6c71739 Mon Sep 17 00:00:00 2001 From: Guo Mang Date: Thu, 27 Apr 2017 11:20:30 +0800 Subject: ShellPkg: Move to new location Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Guo Mang --- .../Library/UefiShellLevel2CommandsLib/Attrib.c | 277 +++++ .../Library/UefiShellLevel2CommandsLib/Cd.c | 351 ++++++ .../Library/UefiShellLevel2CommandsLib/Cp.c | 779 ++++++++++++ .../Library/UefiShellLevel2CommandsLib/Load.c | 279 +++++ .../Library/UefiShellLevel2CommandsLib/Ls.c | 758 ++++++++++++ .../Library/UefiShellLevel2CommandsLib/Map.c | 1244 ++++++++++++++++++++ .../Library/UefiShellLevel2CommandsLib/MkDir.c | 129 ++ .../Library/UefiShellLevel2CommandsLib/Mv.c | 863 ++++++++++++++ .../Library/UefiShellLevel2CommandsLib/Parse.c | 456 +++++++ .../Library/UefiShellLevel2CommandsLib/Reset.c | 170 +++ .../Library/UefiShellLevel2CommandsLib/Rm.c | 379 ++++++ .../Library/UefiShellLevel2CommandsLib/Set.c | 174 +++ .../Library/UefiShellLevel2CommandsLib/TimeDate.c | 972 +++++++++++++++ .../UefiShellLevel2CommandsLib.c | 346 ++++++ .../UefiShellLevel2CommandsLib.h | 368 ++++++ .../UefiShellLevel2CommandsLib.inf | 84 ++ .../UefiShellLevel2CommandsLib.uni | 1088 +++++++++++++++++ .../Library/UefiShellLevel2CommandsLib/Vol.c | 313 +++++ 18 files changed, 9030 insertions(+) create mode 100644 Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Attrib.c create mode 100644 Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Cd.c create mode 100644 Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Cp.c create mode 100644 Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Load.c create mode 100644 Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Ls.c create mode 100644 Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c create mode 100644 Core/ShellPkg/Library/UefiShellLevel2CommandsLib/MkDir.c create mode 100644 Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Mv.c create mode 100644 Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Parse.c create mode 100644 Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Reset.c create mode 100644 Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Rm.c create mode 100644 Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Set.c create mode 100644 Core/ShellPkg/Library/UefiShellLevel2CommandsLib/TimeDate.c create mode 100644 Core/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.c create mode 100644 Core/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.h create mode 100644 Core/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf create mode 100644 Core/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.uni create mode 100644 Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Vol.c (limited to 'Core/ShellPkg/Library/UefiShellLevel2CommandsLib') diff --git a/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Attrib.c b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Attrib.c new file mode 100644 index 0000000000..30d643431f --- /dev/null +++ b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Attrib.c @@ -0,0 +1,277 @@ +/** @file + Main file for attrib shell level 2 function. + + (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
+ 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, L"attrib", 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, L"attrib", 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 + ); + + if (ShellGetExecutionBreakFlag()) { + ShellStatus = SHELL_ABORTED; + break; + } + } + Status = ShellCloseFileMetaArg(&ListOfFiles); + ListOfFiles = NULL; + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_CLOSE_FAIL), gShellLevel2HiiHandle, L"attrib", 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, L"attrib"); + 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, L"attrib"); + 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, L"attrib", 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, L"attrib", 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, L"attrib", 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, L"attrib", 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/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Cd.c b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Cd.c new file mode 100644 index 0000000000..9ae81763f7 --- /dev/null +++ b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Cd.c @@ -0,0 +1,351 @@ +/** @file + Main file for attrib shell level 2 function. + + (C) Copyright 2016 Hewlett Packard Enterprise Development LP
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
+ Copyright (c) 2009 - 2017, 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 will replace drive identifier with CWD. + + If FullPath begining with ':' is invalid path, then ASSERT. + If FullPath not include dirve identifier , then do nothing. + If FullPath likes "fs0:\xx" or "fs0:/xx" , then do nothing. + If FullPath likes "fs0:xxx" or "fs0:", the drive replaced by CWD. + + @param[in, out] FullPath The pointer to the string containing the path. + @param[in] Cwd Current directory. + + @retval EFI_SUCCESS Success. + @retval EFI_OUT_OF_SOURCES A memory allocation failed. +**/ +EFI_STATUS +ReplaceDriveWithCwd ( + IN OUT CHAR16 **FullPath, + IN CONST CHAR16 *Cwd + ) +{ + CHAR16 *Splitter; + CHAR16 *TempBuffer; + UINTN TotalSize; + + Splitter = NULL; + TempBuffer = NULL; + TotalSize = 0; + + if (FullPath == NULL || *FullPath == NULL) { + return EFI_SUCCESS; + } + + Splitter = StrStr (*FullPath, L":"); + ASSERT(Splitter != *FullPath); + + if (Splitter != NULL && *(Splitter + 1) != L'\\' && *(Splitter + 1) != L'/') { + TotalSize = StrSize (Cwd) + StrSize (Splitter + 1); + TempBuffer = AllocateZeroPool (TotalSize); + if (TempBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + StrCpyS (TempBuffer, TotalSize / sizeof(CHAR16), Cwd); + StrCatS (TempBuffer, TotalSize / sizeof(CHAR16), L"\\"); + StrCatS (TempBuffer, TotalSize / sizeof(CHAR16), Splitter + 1); + + FreePool(*FullPath); + *FullPath = TempBuffer; + } + + return EFI_SUCCESS; +} + +/** + function to determine if FullPath is under current filesystem. + + @param[in] FullPath The target location to determine. + @param[in] Cwd Current directory. + + @retval TRUE The FullPath is in the current filesystem. + @retval FALSE The FullPaht isn't in the current filesystem. +**/ +BOOLEAN +IsCurrentFileSystem ( + IN CONST CHAR16 *FullPath, + IN CONST CHAR16 *Cwd + ) +{ + CHAR16 *Splitter1; + CHAR16 *Splitter2; + + Splitter1 = NULL; + Splitter2 = NULL; + + ASSERT(FullPath != NULL); + + Splitter1 = StrStr (FullPath, L":"); + if (Splitter1 == NULL) { + return TRUE; + } + + Splitter2 = StrStr (Cwd, L":"); + + if (((UINTN) Splitter1 - (UINTN) FullPath) != ((UINTN) Splitter2 - (UINTN) Cwd)) { + return FALSE; + } else { + if (StrniCmp (FullPath, Cwd, ((UINTN) Splitter1 - (UINTN) FullPath) / sizeof (CHAR16)) == NULL) { + return TRUE; + } else { + return FALSE; + } + } +} + +/** + Extract drive string and path string from FullPath. + + The caller must be free Drive and Path. + + @param[in] FullPath A path to be extracted. + @param[out] Drive Buffer to save drive identifier. + @param[out] Path Buffer to save path. + + @retval EFI_SUCCESS Success. + @retval EFI_OUT_OF_RESOUCES A memory allocation failed. +**/ +EFI_STATUS +ExtractDriveAndPath ( + IN CONST CHAR16 *FullPath, + OUT CHAR16 **Drive, + OUT CHAR16 **Path + ) +{ + CHAR16 *Splitter; + + ASSERT (FullPath != NULL); + + Splitter = StrStr (FullPath, L":"); + + if (Splitter == NULL) { + *Drive = NULL; + *Path = AllocateCopyPool (StrSize (FullPath), FullPath); + if (*Path == NULL) { + return EFI_OUT_OF_RESOURCES; + } + } else { + if (*(Splitter + 1) == CHAR_NULL) { + *Drive = AllocateCopyPool (StrSize (FullPath), FullPath); + *Path = NULL; + if (*Drive == NULL) { + return EFI_OUT_OF_RESOURCES; + } + } else { + *Drive = AllocateCopyPool ((Splitter - FullPath + 2) * sizeof(CHAR16), FullPath); + if (*Drive == NULL) { + return EFI_OUT_OF_RESOURCES; + } + (*Drive)[Splitter - FullPath + 1] = CHAR_NULL; + + *Path = AllocateCopyPool (StrSize (Splitter + 1), Splitter + 1); + if (*Path == NULL) { + FreePool (*Drive); + return EFI_OUT_OF_RESOURCES; + } + } + } + + return EFI_SUCCESS; +} + +/** + 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 *Cwd; + CHAR16 *Path; + CHAR16 *Drive; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + CONST CHAR16 *Param1; + CHAR16 *Param1Copy; + CHAR16 *Walker; + CHAR16 *Splitter; + CHAR16 *TempBuffer; + UINTN TotalSize; + + ProblemParam = NULL; + ShellStatus = SHELL_SUCCESS; + Cwd = NULL; + Path = NULL; + Drive = NULL; + Splitter = NULL; + TempBuffer = NULL; + TotalSize = 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, L"cd", 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, L"cd"); + 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 + // + Cwd = ShellGetCurrentDir (NULL); + if (Cwd == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN(STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"cd"); + ShellStatus = SHELL_NOT_FOUND; + } else { + Param1 = ShellCommandLineGetRawValue (Package, 1); + if (Param1 == NULL) { + // + // display the current directory + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN(STR_CD_PRINT), gShellLevel2HiiHandle, Cwd); + } else { + Param1Copy = CatSPrint (NULL, L"%s", Param1, NULL); + for (Walker = Param1Copy; Walker != NULL && *Walker != CHAR_NULL; Walker++) { + if (*Walker == L'\"') { + CopyMem (Walker, Walker + 1, StrSize(Walker) - sizeof(Walker[0])); + } + } + + if (Param1Copy != NULL && IsCurrentFileSystem (Param1Copy, Cwd)) { + Status = ReplaceDriveWithCwd (&Param1Copy,Cwd); + if (!EFI_ERROR (Status)) { + Param1Copy = PathCleanUpDirectories (Param1Copy); + } + } else { + // + // Can't use cd command to change filesystem. + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"cd"); + Status = EFI_NOT_FOUND; + } + + if (!EFI_ERROR(Status) && Param1Copy != NULL) { + Splitter = StrStr (Cwd, L":"); + if (Param1Copy[0] == L'\\') { + // + // Absolute Path on current drive letter. + // + TotalSize = ((Splitter - Cwd + 1) * sizeof(CHAR16)) + StrSize(Param1Copy); + TempBuffer = AllocateZeroPool (TotalSize); + if (TempBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } else { + StrnCpyS (TempBuffer, TotalSize / sizeof(CHAR16), Cwd, (Splitter - Cwd + 1)); + StrCatS (TempBuffer, TotalSize / sizeof(CHAR16), Param1Copy); + + FreePool (Param1Copy); + Param1Copy = TempBuffer; + TempBuffer = NULL; + } + } else { + if (StrStr (Param1Copy,L":") == NULL) { + TotalSize = StrSize (Cwd) + StrSize (Param1Copy); + TempBuffer = AllocateZeroPool (TotalSize); + if (TempBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } else { + StrCpyS (TempBuffer, TotalSize / sizeof (CHAR16), Cwd); + StrCatS (TempBuffer, TotalSize / sizeof (CHAR16), L"\\"); + StrCatS (TempBuffer, TotalSize / sizeof (CHAR16), Param1Copy); + + FreePool (Param1Copy); + Param1Copy = PathCleanUpDirectories (TempBuffer); + } + } + } + } + + if (!EFI_ERROR(Status)) { + Status = ExtractDriveAndPath (Param1Copy, &Drive, &Path); + } + + if (!EFI_ERROR (Status) && Drive != NULL && Path != NULL) { + if (EFI_ERROR(ShellIsDirectory (Param1Copy))) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN(STR_GEN_NOT_DIR), gShellLevel2HiiHandle, L"cd", Param1Copy); + ShellStatus = SHELL_NOT_FOUND; + } else { + Status = gEfiShellProtocol->SetCurDir (Drive, Path + 1); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN(STR_GEN_DIR_NF), gShellLevel2HiiHandle, L"cd", Param1Copy); + ShellStatus = SHELL_NOT_FOUND; + } + } + } + + if (Drive != NULL) { + FreePool (Drive); + } + + if (Path != NULL) { + FreePool (Path); + } + + FreePool (Param1Copy); + } + } + } + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + + // + // return the status + // + return (ShellStatus); +} + diff --git a/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Cp.c b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Cp.c new file mode 100644 index 0000000000..b8f6d310f6 --- /dev/null +++ b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Cp.c @@ -0,0 +1,779 @@ +/** @file + Main file for cp shell level 2 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
+ Copyright (c) 2009 - 2016, 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 + +/** + 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. + + @param[in] FileList A LIST_ENTRY* based list of files to move. + @param[in] DestDir The destination location. + @param[in] SilentMode TRUE to eliminate screen output. + @param[in] RecursiveMode TRUE to copy directories. + @param[in] Resp The response to the overwrite query (if always). + + @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 +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 + @param[in] CmdName Source command name requesting single file copy + + @retval SHELL_SUCCESS The source file was copied to the destination +**/ +SHELL_STATUS +CopySingleFile( + IN CONST CHAR16 *Source, + IN CONST CHAR16 *Dest, + OUT VOID **Resp, + IN BOOLEAN SilentMode, + IN CONST CHAR16 *CmdName + ) +{ + 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; + UINT64 SourceFileSize; + UINT64 DestFileSize; + EFI_FILE_PROTOCOL *DestVolumeFP; + EFI_FILE_SYSTEM_INFO *DestVolumeInfo; + UINTN DestVolumeInfoSize; + + ASSERT(Resp != NULL); + + SourceHandle = NULL; + DestHandle = NULL; + Response = *Resp; + List = NULL; + DestVolumeInfo = NULL; + ShellStatus = SHELL_SUCCESS; + + ReadSize = PcdGet32(PcdShellFileOperationSize); + // Why bother copying a file to itself + if (StrCmp(Source, Dest) == 0) { + return (SHELL_SUCCESS); + } + + // + // if the destination file existed check response and possibly prompt user + // + if (ShellFileExists(Dest) == EFI_SUCCESS) { + if (Response == NULL && !SilentMode) { + Status = ShellPromptForResponseHii(ShellPromptResponseTypeYesNoAllCancel, STRING_TOKEN (STR_GEN_DEST_EXIST_OVR), 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; + default: + return SHELL_ABORTED; + } + } + } + + if (ShellIsDirectory(Source) == EFI_SUCCESS) { + Status = ShellCreateDirectory(Dest, &DestHandle); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DEST_DIR_FAIL), gShellLevel2HiiHandle, CmdName, Dest); + 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); + if (TempName != NULL) { + ShellOpenFileMetaArg((CHAR16*)TempName, EFI_FILE_MODE_READ, &List); + *TempName = CHAR_NULL; + StrnCatGrow(&TempName, &Size, Dest, 0); + StrnCatGrow(&TempName, &Size, L"\\", 0); + ShellStatus = ValidateAndCopyFiles(List, TempName, SilentMode, TRUE, Resp); + ShellCloseFileMetaArg(&List); + SHELL_FREE_NON_NULL(TempName); + Size = 0; + } + } else { + Status = ShellDeleteFileByName(Dest); + + // + // 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)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DEST_OPEN_FAIL), gShellLevel2HiiHandle, CmdName, Dest); + return (SHELL_ACCESS_DENIED); + } + + // + // open source file + // + Status = ShellOpenFileByName (Source, &SourceHandle, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_CP_SRC_OPEN_FAIL), gShellLevel2HiiHandle, CmdName, Source); + return (SHELL_ACCESS_DENIED); + } + + // + //get file size of source file and freespace available on destination volume + // + ShellGetFileSize(SourceHandle, &SourceFileSize); + ShellGetFileSize(DestHandle, &DestFileSize); + + // + //if the destination file already exists then it will be replaced, meaning the sourcefile effectively needs less storage space + // + if(DestFileSize < SourceFileSize){ + SourceFileSize -= DestFileSize; + } else { + SourceFileSize = 0; + } + + // + //get the system volume info to check the free space + // + DestVolumeFP = ConvertShellHandleToEfiFileProtocol(DestHandle); + DestVolumeInfo = NULL; + DestVolumeInfoSize = 0; + Status = DestVolumeFP->GetInfo( + DestVolumeFP, + &gEfiFileSystemInfoGuid, + &DestVolumeInfoSize, + DestVolumeInfo + ); + + if (Status == EFI_BUFFER_TOO_SMALL) { + DestVolumeInfo = AllocateZeroPool(DestVolumeInfoSize); + Status = DestVolumeFP->GetInfo( + DestVolumeFP, + &gEfiFileSystemInfoGuid, + &DestVolumeInfoSize, + DestVolumeInfo + ); + } + + // + //check if enough space available on destination drive to complete copy + // + if (DestVolumeInfo!= NULL && (DestVolumeInfo->FreeSpace < SourceFileSize)) { + // + //not enough space on destination directory to copy file + // + SHELL_FREE_NON_NULL(DestVolumeInfo); + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_CPY_FAIL), gShellLevel2HiiHandle, CmdName); + return(SHELL_VOLUME_FULL); + } else { + // + // copy data between files + // + Buffer = AllocateZeroPool(ReadSize); + if (Buffer == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellLevel2HiiHandle, CmdName); + return SHELL_OUT_OF_RESOURCES; + } + while (ReadSize == PcdGet32(PcdShellFileOperationSize) && !EFI_ERROR(Status)) { + Status = ShellReadFile(SourceHandle, &ReadSize, Buffer); + if (!EFI_ERROR(Status)) { + Status = ShellWriteFile(DestHandle, &ReadSize, Buffer); + if (EFI_ERROR(Status)) { + ShellStatus = (SHELL_STATUS) (Status & (~MAX_BIT)); + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_CPY_WRITE_ERROR), gShellLevel2HiiHandle, CmdName, Dest); + break; + } + } else { + ShellStatus = (SHELL_STATUS) (Status & (~MAX_BIT)); + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_CPY_READ_ERROR), gShellLevel2HiiHandle, CmdName, Source); + break; + } + } + } + SHELL_FREE_NON_NULL(DestVolumeInfo); + } + + // + // close files + // + if (DestHandle != NULL) { + ShellCloseFile(&DestHandle); + DestHandle = NULL; + } + if (SourceHandle != NULL) { + ShellCloseFile(&SourceHandle); + SourceHandle = NULL; + } + + // + // return + // + return ShellStatus; +} + +/** + 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. + @param[in] SilentMode TRUE to eliminate screen output. + @param[in] RecursiveMode TRUE to copy directories. + @param[in] Resp The response to the overwrite query (if always). + + @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 +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; + EFI_STATUS Status; + CHAR16 *DestPath; + VOID *Response; + UINTN PathSize; + CONST CHAR16 *Cwd; + UINTN NewSize; + CHAR16 *CleanFilePathStr; + + if (Resp == NULL) { + Response = NULL; + } else { + Response = *Resp; + } + + DestPath = NULL; + ShellStatus = SHELL_SUCCESS; + PathSize = 0; + Cwd = ShellGetCurrentDir(NULL); + CleanFilePathStr = NULL; + + ASSERT(FileList != NULL); + ASSERT(DestDir != NULL); + + + Status = ShellLevel2StripQuotes (DestDir, &CleanFilePathStr); + if (EFI_ERROR (Status)) { + if (Status == EFI_OUT_OF_RESOURCES) { + return SHELL_OUT_OF_RESOURCES; + } else { + return SHELL_INVALID_PARAMETER; + } + } + + ASSERT (CleanFilePathStr != NULL); + + // + // If we are trying to copy multiple files... make sure we got a directory for the target... + // + if (EFI_ERROR(ShellIsDirectory(CleanFilePathStr)) && FileList->Link.ForwardLink != FileList->Link.BackLink) { + // + // Error for destination not a directory + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR), gShellLevel2HiiHandle, L"cp", CleanFilePathStr); + FreePool (CleanFilePathStr); + 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(CleanFilePathStr); + NewSize += StrSize(Node->FullName); + NewSize += (Cwd == NULL)? 0 : (StrSize(Cwd) + sizeof(CHAR16)); + if (NewSize > PathSize) { + PathSize = 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, L"cp"); + FreePool (CleanFilePathStr); + return (SHELL_INVALID_PARAMETER); + } + + // + // make sure got dest as dir if needed + // + if (!EFI_ERROR(ShellIsDirectory(Node->FullName)) && EFI_ERROR(ShellIsDirectory(CleanFilePathStr))) { + // + // Error for destination not a directory + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR), gShellLevel2HiiHandle, L"cp", CleanFilePathStr); + FreePool (CleanFilePathStr); + return (SHELL_INVALID_PARAMETER); + } + } + + HiiOutput = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_CP_OUTPUT), NULL); + HiiResultOk = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_GEN_RES_OK), NULL); + DestPath = AllocateZeroPool(PathSize); + + if (DestPath == NULL || HiiOutput == NULL || HiiResultOk == NULL) { + SHELL_FREE_NON_NULL(DestPath); + SHELL_FREE_NON_NULL(HiiOutput); + SHELL_FREE_NON_NULL(HiiResultOk); + FreePool (CleanFilePathStr); + return (SHELL_OUT_OF_RESOURCES); + } + + // + // 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(CleanFilePathStr)) // not an existing directory + ) { + if (StrStr(CleanFilePathStr, L":") == NULL) { + // + // simple copy of a single file + // + if (Cwd != NULL) { + StrCpyS(DestPath, PathSize / sizeof(CHAR16), Cwd); + StrCatS(DestPath, PathSize / sizeof(CHAR16), L"\\"); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF), gShellLevel2HiiHandle, L"cp", CleanFilePathStr); + FreePool (CleanFilePathStr); + return (SHELL_INVALID_PARAMETER); + } + if (DestPath[StrLen(DestPath)-1] != L'\\' && CleanFilePathStr[0] != L'\\') { + StrCatS(DestPath, PathSize / sizeof(CHAR16), L"\\"); + } else if (DestPath[StrLen(DestPath)-1] == L'\\' && CleanFilePathStr[0] == L'\\') { + ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL; + } + StrCatS(DestPath, PathSize/sizeof(CHAR16), CleanFilePathStr); + } else { + StrCpyS(DestPath, PathSize/sizeof(CHAR16), CleanFilePathStr); + } + } else { + // + // we have multiple files or a directory in the DestDir + // + + // + // Check for leading slash + // + if (CleanFilePathStr[0] == L'\\') { + // + // Copy to the root of CWD + // + if (Cwd != NULL) { + StrCpyS(DestPath, PathSize/sizeof(CHAR16), Cwd); + StrCatS(DestPath, PathSize/sizeof(CHAR16), L"\\"); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF), gShellLevel2HiiHandle, L"cp", CleanFilePathStr); + FreePool(CleanFilePathStr); + return (SHELL_INVALID_PARAMETER); + } + while (PathRemoveLastItem(DestPath)); + StrCatS(DestPath, PathSize/sizeof(CHAR16), CleanFilePathStr+1); + StrCatS(DestPath, PathSize/sizeof(CHAR16), Node->FileName); + } else if (StrStr(CleanFilePathStr, L":") == NULL) { + if (Cwd != NULL) { + StrCpyS(DestPath, PathSize/sizeof(CHAR16), Cwd); + StrCatS(DestPath, PathSize/sizeof(CHAR16), L"\\"); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF), gShellLevel2HiiHandle, L"cp", CleanFilePathStr); + FreePool(CleanFilePathStr); + return (SHELL_INVALID_PARAMETER); + } + if (DestPath[StrLen(DestPath)-1] != L'\\' && CleanFilePathStr[0] != L'\\') { + StrCatS(DestPath, PathSize/sizeof(CHAR16), L"\\"); + } else if (DestPath[StrLen(DestPath)-1] == L'\\' && CleanFilePathStr[0] == L'\\') { + ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL; + } + StrCatS(DestPath, PathSize/sizeof(CHAR16), CleanFilePathStr); + if (CleanFilePathStr[StrLen(CleanFilePathStr)-1] != L'\\' && Node->FileName[0] != L'\\') { + StrCatS(DestPath, PathSize/sizeof(CHAR16), L"\\"); + } else if (CleanFilePathStr[StrLen(CleanFilePathStr)-1] == L'\\' && Node->FileName[0] == L'\\') { + ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL; + } + StrCatS(DestPath, PathSize/sizeof(CHAR16), Node->FileName); + + } else { + StrCpyS(DestPath, PathSize/sizeof(CHAR16), CleanFilePathStr); + if (CleanFilePathStr[StrLen(CleanFilePathStr)-1] != L'\\' && Node->FileName[0] != L'\\') { + StrCatS(DestPath, PathSize/sizeof(CHAR16), L"\\"); + } else if (CleanFilePathStr[StrLen(CleanFilePathStr)-1] == L'\\' && Node->FileName[0] == L'\\') { + ((CHAR16*)CleanFilePathStr)[StrLen(CleanFilePathStr)-1] = CHAR_NULL; + } + StrCatS(DestPath, PathSize/sizeof(CHAR16), Node->FileName); + } + } + + // + // Make sure the path exists + // + if (EFI_ERROR(VerifyIntermediateDirectories(DestPath))) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DIR_WNF), gShellLevel2HiiHandle, L"cp", DestPath); + 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, L"cp"); + ShellStatus = SHELL_INVALID_PARAMETER; + break; + } + if (StringNoCaseCompare(&Node->FullName, &DestPath) == 0) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_SD_SAME), gShellLevel2HiiHandle, L"cp"); + ShellStatus = SHELL_INVALID_PARAMETER; + break; + } + + if ((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, L"cp"); + ShellStatus = SHELL_INVALID_PARAMETER; + break; + } + + PathCleanUpDirectories(DestPath); + + if (!SilentMode) { + ShellPrintEx(-1, -1, HiiOutput, Node->FullName, DestPath); + } + + // + // copy single file... + // + ShellStatus = CopySingleFile(Node->FullName, DestPath, &Response, SilentMode, L"cp"); + 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); + SHELL_FREE_NON_NULL(CleanFilePathStr); + if (Resp == NULL) { + SHELL_FREE_NON_NULL(Response); + } + + return (ShellStatus); + +} + +/** + Validate and if successful copy all the files from the list into + destination directory. + + @param[in] FileList The list of files to copy. + @param[in] DestDir The directory to copy files to. + @param[in] SilentMode TRUE to eliminate screen output. + @param[in] RecursiveMode TRUE to copy directories. + + @retval SHELL_INVALID_PARAMETER A parameter was invalid. + @retval SHELL_SUCCESS The operation was successful. +**/ +SHELL_STATUS +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_FILE_INFO *FileInfo; + CHAR16 *FullName; + + List = NULL; + FullName = NULL; + FileInfo = NULL; + + 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, L"cp", DestDir); + ShellStatus = SHELL_INVALID_PARAMETER; + ShellCloseFileMetaArg(&List); + } else if (List != NULL) { + ASSERT(((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink) != NULL); + ASSERT(((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink)->FullName != NULL); + FileInfo = gEfiShellProtocol->GetFileInfo(((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink)->Handle); + ASSERT(FileInfo != NULL); + StrnCatGrow(&FullName, NULL, ((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink)->FullName, 0); + ShellCloseFileMetaArg(&List); + if ((FileInfo->Attribute & EFI_FILE_READ_ONLY) == 0) { + ShellStatus = ValidateAndCopyFiles(FileList, FullName, SilentMode, RecursiveMode, NULL); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DEST_ERROR), gShellLevel2HiiHandle, L"cp"); + ShellStatus = SHELL_ACCESS_DENIED; + } + } else { + ShellCloseFileMetaArg(&List); + ShellStatus = ValidateAndCopyFiles(FileList, DestDir, SilentMode, RecursiveMode, NULL); + } + + SHELL_FREE_NON_NULL(FileInfo); + SHELL_FREE_NON_NULL(FullName); + 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; + CHAR16 *FullCwd; + + 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, L"cp", 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, L"cp"); + 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, L"cp"); + 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, L"cp", ShellCommandLineGetRawValue(Package, 1)); + ShellStatus = SHELL_NOT_FOUND; + } else { + FullCwd = AllocateZeroPool(StrSize(Cwd) + sizeof(CHAR16)); + if (FullCwd == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellLevel2HiiHandle, L"cp"); + ShellStatus = SHELL_OUT_OF_RESOURCES; + } else { + StrCpyS (FullCwd, StrSize (Cwd) / sizeof (CHAR16) + 1, Cwd); + ShellStatus = ProcessValidateAndCopyFiles (FileList, FullCwd, SilentMode, RecursiveMode); + FreePool (FullCwd); + } + } + } + + 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, L"cp", ShellCommandLineGetRawValue(Package, LoopCounter)); + ShellStatus = SHELL_NOT_FOUND; + } + } + if (ShellStatus != SHELL_SUCCESS) { + Status = ShellCloseFileMetaArg(&FileList); + } else { + // + // now copy them all... + // + if (FileList != NULL && !IsListEmpty(&FileList->Link)) { + ShellStatus = ProcessValidateAndCopyFiles(FileList, PathCleanUpDirectories((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, L"cp", ShellCommandLineGetRawValue(Package, ParamCount), 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/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Load.c b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Load.c new file mode 100644 index 0000000000..322d510eac --- /dev/null +++ b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Load.c @@ -0,0 +1,279 @@ +/** @file + Main file for attrib shell level 2 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
+ Copyright (c) 2009 - 2011, 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 +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 +LoadDriver( + IN CONST CHAR16 *FileName, + IN CONST BOOLEAN Connect + ) +{ + EFI_HANDLE LoadedDriverHandle; + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *FilePath; + EFI_LOADED_IMAGE_PROTOCOL *LoadedDriverImage; + + LoadedDriverImage = NULL; + FilePath = 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, L"load", 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, L"load"); + 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, (BOOLEAN)(ShellCommandLineGetFlag(Package, L"-nc")==FALSE)); + } else { + Status = LoadDriver(Node->FullName, (BOOLEAN)(ShellCommandLineGetFlag(Package, L"-nc")==FALSE)); + } + } // 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, L"load", (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/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Ls.c b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Ls.c new file mode 100644 index 0000000000..52ae18f19b --- /dev/null +++ b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Ls.c @@ -0,0 +1,758 @@ +/** @file + Main file for ls shell level 2 function. + + (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.
+ Copyright (c) 2009 - 2016, 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 standard format output volume entry. + + @param[in] TheList a list of files from the volume. +**/ +EFI_STATUS +PrintSfoVolumeInfoTableEntry( + IN CONST EFI_SHELL_FILE_INFO *TheList + ) +{ + EFI_STATUS Status; + EFI_SHELL_FILE_INFO *Node; + CHAR16 *DirectoryName; + EFI_FILE_SYSTEM_INFO *SysInfo; + UINTN SysInfoSize; + SHELL_FILE_HANDLE ShellFileHandle; + EFI_FILE_PROTOCOL *EfiFpHandle; + + // + // Get the first valid handle (directories) + // + for ( Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&TheList->Link) + ; !IsNull(&TheList->Link, &Node->Link) && Node->Handle == NULL + ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&TheList->Link, &Node->Link) + ); + + if (Node->Handle == NULL) { + DirectoryName = GetFullyQualifiedPath(((EFI_SHELL_FILE_INFO *)GetFirstNode(&TheList->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 + ); + + SHELL_FREE_NON_NULL(SysInfo); + + return (Status); +} + +/** + print out the info on a single file. + + @param[in] Sfo TRUE if in SFO, false otherwise. + @param[in] TheNode the EFI_SHELL_FILE_INFO node to print out information on. + @param[in] Files incremented if a file is printed. + @param[in] Size incremented by file size. + @param[in] Dirs incremented if a directory is printed. + +**/ +VOID +PrintFileInformation( + IN CONST BOOLEAN Sfo, + IN CONST EFI_SHELL_FILE_INFO *TheNode, + IN UINT64 *Files, + IN UINT64 *Size, + IN UINT64 *Dirs + ) +{ + ASSERT(Files != NULL); + ASSERT(Size != NULL); + ASSERT(Dirs != NULL); + ASSERT(TheNode != NULL); + + if (Sfo) { + // + // Print the FileInfo Table + // + ShellPrintHiiEx ( + 0, + gST->ConOut->Mode->CursorRow, + NULL, + STRING_TOKEN (STR_LS_SFO_FILEINFO), + gShellLevel2HiiHandle, + TheNode->FullName, + TheNode->Info->FileSize, + TheNode->Info->PhysicalSize, + (TheNode->Info->Attribute & EFI_FILE_ARCHIVE) != 0?L"a":L"", + (TheNode->Info->Attribute & EFI_FILE_DIRECTORY) != 0?L"d":L"", + (TheNode->Info->Attribute & EFI_FILE_HIDDEN) != 0?L"h":L"", + (TheNode->Info->Attribute & EFI_FILE_READ_ONLY) != 0?L"r":L"", + (TheNode->Info->Attribute & EFI_FILE_SYSTEM) != 0?L"s":L"", + TheNode->Info->CreateTime.Hour, + TheNode->Info->CreateTime.Minute, + TheNode->Info->CreateTime.Second, + TheNode->Info->CreateTime.Day, + TheNode->Info->CreateTime.Month, + TheNode->Info->CreateTime.Year, + TheNode->Info->LastAccessTime.Hour, + TheNode->Info->LastAccessTime.Minute, + TheNode->Info->LastAccessTime.Second, + TheNode->Info->LastAccessTime.Day, + TheNode->Info->LastAccessTime.Month, + TheNode->Info->LastAccessTime.Year, + TheNode->Info->ModificationTime.Hour, + TheNode->Info->ModificationTime.Minute, + TheNode->Info->ModificationTime.Second, + TheNode->Info->ModificationTime.Day, + TheNode->Info->ModificationTime.Month, + TheNode->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, + &TheNode->Info->ModificationTime, + (TheNode->Info->Attribute & EFI_FILE_DIRECTORY) != 0?L"":L"", + (TheNode->Info->Attribute & EFI_FILE_READ_ONLY) != 0?L'r':L' ', + TheNode->Info->FileSize + ); + if (TheNode->Info->Attribute & EFI_FILE_DIRECTORY) { + (*Dirs)++; + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_LS_LINE_END_DIR), + gShellLevel2HiiHandle, + TheNode->FileName + ); + } else { + (*Files)++; + (*Size) += TheNode->Info->FileSize; + if ( (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)L".nsh", (CHAR16*)&(TheNode->FileName[StrLen (TheNode->FileName) - 4])) == 0) + || (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)L".efi", (CHAR16*)&(TheNode->FileName[StrLen (TheNode->FileName) - 4])) == 0) + ){ + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_LS_LINE_END_EXE), + gShellLevel2HiiHandle, + TheNode->FileName + ); + } else { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_LS_LINE_END_FILE), + gShellLevel2HiiHandle, + TheNode->FileName + ); + } + } + } +} + +/** + print out the header when not using standard format output. + + @param[in] Path String with starting path. +**/ +VOID +PrintNonSfoHeader( + IN CONST CHAR16 *Path + ) +{ + CHAR16 *DirectoryName; + + // + // get directory name from path... + // + DirectoryName = GetFullyQualifiedPath(Path); + + if (DirectoryName != NULL) { + // + // print header + // + ShellPrintHiiEx ( + 0, + gST->ConOut->Mode->CursorRow, + NULL, + STRING_TOKEN (STR_LS_HEADER_LINE1), + gShellLevel2HiiHandle, + DirectoryName + ); + + SHELL_FREE_NON_NULL(DirectoryName); + } +} + +/** + print out the footer when not using standard format output. + + @param[in] Files The number of files. + @param[in] Size The size of files in bytes. + @param[in] Dirs The number of directories. +**/ +VOID +PrintNonSfoFooter( + IN UINT64 Files, + IN UINT64 Size, + IN UINT64 Dirs + ) +{ + // + // print footer + // + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_LS_FOOTER_LINE), + gShellLevel2HiiHandle, + Files, + Size, + Dirs + ); +} + +/** + 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] RootPath String with starting path to search in. + @param[in] SearchString String with search string. + @param[in] Found Set to TRUE, if anyone were found. + @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 +PrintLsOutput( + IN CONST BOOLEAN Rec, + IN CONST UINT64 Attribs, + IN CONST BOOLEAN Sfo, + IN CONST CHAR16 *RootPath, + IN CONST CHAR16 *SearchString, + IN BOOLEAN *Found, + 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; + UINTN LongestPath; + CHAR16 *CorrectedPath; + BOOLEAN FoundOne; + BOOLEAN HeaderPrinted; + + HeaderPrinted = FALSE; + FileCount = 0; + DirCount = 0; + FileSize = 0; + ListHead = NULL; + ShellStatus = SHELL_SUCCESS; + LongestPath = 0; + CorrectedPath = NULL; + + if (Found != NULL) { + FoundOne = *Found; + } else { + FoundOne = FALSE; + } + + CorrectedPath = StrnCatGrow(&CorrectedPath, &LongestPath, RootPath, 0); + if (CorrectedPath == NULL) { + return SHELL_OUT_OF_RESOURCES; + } + if (CorrectedPath[StrLen(CorrectedPath)-1] != L'\\' + &&CorrectedPath[StrLen(CorrectedPath)-1] != L'/') { + CorrectedPath = StrnCatGrow(&CorrectedPath, &LongestPath, L"\\", 0); + } + CorrectedPath = StrnCatGrow(&CorrectedPath, &LongestPath, SearchString, 0); + if (CorrectedPath == NULL) { + return (SHELL_OUT_OF_RESOURCES); + } + + PathCleanUpDirectories(CorrectedPath); + + Status = ShellOpenFileMetaArg((CHAR16*)CorrectedPath, EFI_FILE_MODE_READ, &ListHead); + if (!EFI_ERROR(Status)) { + if (ListHead == NULL || IsListEmpty(&ListHead->Link)) { + SHELL_FREE_NON_NULL(CorrectedPath); + return (SHELL_SUCCESS); + } + + if (Sfo && Found == NULL) { + PrintSfoVolumeInfoTableEntry(ListHead); + } + + for ( Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&ListHead->Link), LongestPath = 0 + ; !IsNull(&ListHead->Link, &Node->Link) + ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&ListHead->Link, &Node->Link) + ){ + if (ShellGetExecutionBreakFlag ()) { + ShellStatus = SHELL_ABORTED; + break; + } + 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) || + (Count == 5)) { + // + // Only matches the bits which "Attribs" contains, not + // all files/directories with any of the bits. + // Count == 5 is used to tell the difference between a user + // specifying all bits (EX: -arhsda) and just specifying + // -a (means display all files with any attribute). + // + if ( (Node->Info->Attribute & Attribs) != Attribs) { + continue; + } + } + + if (!Sfo && !HeaderPrinted) { + PathRemoveLastItem (CorrectedPath); + PrintNonSfoHeader(CorrectedPath); + } + PrintFileInformation(Sfo, Node, &FileCount, &FileSize, &DirCount); + FoundOne = TRUE; + HeaderPrinted = TRUE; + } + + if (!Sfo && ShellStatus != SHELL_ABORTED) { + PrintNonSfoFooter(FileCount, FileSize, DirCount); + } + } + + if (Rec && ShellStatus != SHELL_ABORTED) { + // + // Re-Open all the files under the starting path for directories that didnt necessarily match our file filter + // + ShellCloseFileMetaArg(&ListHead); + CorrectedPath[0] = CHAR_NULL; + CorrectedPath = StrnCatGrow(&CorrectedPath, &LongestPath, RootPath, 0); + if (CorrectedPath == NULL) { + return SHELL_OUT_OF_RESOURCES; + } + if (CorrectedPath[StrLen(CorrectedPath)-1] != L'\\' + &&CorrectedPath[StrLen(CorrectedPath)-1] != L'/') { + CorrectedPath = StrnCatGrow(&CorrectedPath, &LongestPath, L"\\", 0); + } + CorrectedPath = StrnCatGrow(&CorrectedPath, &LongestPath, L"*", 0); + Status = ShellOpenFileMetaArg((CHAR16*)CorrectedPath, EFI_FILE_MODE_READ, &ListHead); + + if (!EFI_ERROR(Status)) { + for ( Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&ListHead->Link) + ; !IsNull(&ListHead->Link, &Node->Link) && ShellStatus == SHELL_SUCCESS + ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&ListHead->Link, &Node->Link) + ){ + if (ShellGetExecutionBreakFlag ()) { + ShellStatus = SHELL_ABORTED; + break; + } + + // + // 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 + ){ + ShellStatus = PrintLsOutput( + Rec, + Attribs, + Sfo, + Node->FullName, + SearchString, + &FoundOne, + Count, + TimeZone); + + // + // Since it's running recursively, we have to break immediately when returned SHELL_ABORTED + // + if (ShellStatus == SHELL_ABORTED) { + break; + } + } + } + } + } + + SHELL_FREE_NON_NULL(CorrectedPath); + ShellCloseFileMetaArg(&ListHead); + + if (Found == NULL && !FoundOne) { + return (SHELL_NOT_FOUND); + } + + if (Found != NULL) { + *Found = FoundOne; + } + + 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; + CHAR16 *SearchString; + + Size = 0; + FullPath = NULL; + ProblemParam = NULL; + Attribs = NULL; + ShellStatus = SHELL_SUCCESS; + RequiredAttributes = 0; + PathName = NULL; + SearchString = 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, L"ls", 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, L"ls"); + 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, L"ls", 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) { + // + // Nothing specified... must start from current directory + // + CurDir = gEfiShellProtocol->GetCurDir(NULL); + if (CurDir == NULL) { + ShellStatus = SHELL_NOT_FOUND; + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"ls"); + } + // + // Copy to the 2 strings for starting path and file search string + // + ASSERT(SearchString == NULL); + ASSERT(FullPath == NULL); + StrnCatGrow(&SearchString, NULL, L"*", 0); + StrnCatGrow(&FullPath, NULL, CurDir, 0); + Size = FullPath != NULL? StrSize(FullPath) : 0; + StrnCatGrow(&FullPath, &Size, L"\\", 0); + } else { + if (StrStr(PathName, L":") == NULL && gEfiShellProtocol->GetCurDir(NULL) == NULL) { + // + // If we got something and it doesnt have a fully qualified path, then we needed to have a CWD. + // + ShellStatus = SHELL_NOT_FOUND; + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"ls"); + } else { + // + // We got a valid fully qualified path or we have a CWD + // + ASSERT((FullPath == NULL && Size == 0) || (FullPath != NULL)); + if (StrStr(PathName, L":") == NULL) { + StrnCatGrow(&FullPath, &Size, gEfiShellProtocol->GetCurDir(NULL), 0); + if (FullPath == NULL) { + ShellCommandLineFreeVarList (Package); + return SHELL_OUT_OF_RESOURCES; + } + Size = FullPath != NULL? StrSize(FullPath) : 0; + StrnCatGrow(&FullPath, &Size, L"\\", 0); + } + StrnCatGrow(&FullPath, &Size, PathName, 0); + if (FullPath == NULL) { + ShellCommandLineFreeVarList (Package); + return SHELL_OUT_OF_RESOURCES; + } + + if (ShellIsDirectory(PathName) == EFI_SUCCESS) { + // + // is listing ends with a directory, then we list all files in that directory + // + StrnCatGrow(&SearchString, NULL, L"*", 0); + } else { + // + // must split off the search part that applies to files from the end of the directory part + // + StrnCatGrow(&SearchString, NULL, FullPath, 0); + if (SearchString == NULL) { + FreePool (FullPath); + ShellCommandLineFreeVarList (Package); + return SHELL_OUT_OF_RESOURCES; + } + PathRemoveLastItem (FullPath); + CopyMem (SearchString, SearchString + StrLen (FullPath), StrSize (SearchString + StrLen (FullPath))); + } + } + } + Status = gRT->GetTime(&TheTime, NULL); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_WARN), gShellLevel2HiiHandle, L"ls", L"gRT->GetTime", Status); + TheTime.TimeZone = EFI_UNSPECIFIED_TIMEZONE; + } + + if (ShellStatus == SHELL_SUCCESS) { + ShellStatus = PrintLsOutput( + ShellCommandLineGetFlag(Package, L"-r"), + RequiredAttributes, + ShellCommandLineGetFlag(Package, L"-sfo"), + FullPath, + SearchString, + NULL, + Count, + TheTime.TimeZone + ); + if (ShellStatus == SHELL_NOT_FOUND) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LS_FILE_NOT_FOUND), gShellLevel2HiiHandle, L"ls", FullPath); + } else if (ShellStatus == SHELL_INVALID_PARAMETER) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"ls", FullPath); + } else if (ShellStatus == SHELL_ABORTED) { + // + // Ignore aborting. + // + } else if (ShellStatus != SHELL_SUCCESS) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"ls", FullPath); + } + } + } + } + } + + // + // Free memory allocated + // + SHELL_FREE_NON_NULL(SearchString); + SHELL_FREE_NON_NULL(FullPath); + ShellCommandLineFreeVarList (Package); + + return (ShellStatus); +} diff --git a/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c new file mode 100644 index 0000000000..20eb528fa3 --- /dev/null +++ b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c @@ -0,0 +1,1244 @@ +/** @file + Main file for map shell level 2 command. + + Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.
+ (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP
+ + 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 + +/** + 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, + @param[in] Len Number of characters to analyze. + + @retval TRUE String has only numbers and letters + @retval FALSE String has at least one other character. +**/ +BOOLEAN +IsNumberLetterOnly( + IN CONST CHAR16 *String, + IN CONST UINTN Len + ) +{ + UINTN Count; + for (Count = 0 ; Count < Len && String != NULL && *String != CHAR_NULL ; String++,Count++) { + if (! ((*String >= L'a' && *String <= L'z') || + (*String >= L'A' && *String <= L'Z') || + (*String >= L'0' && *String <= L'9')) + ){ + return (FALSE); + } + } + return (TRUE); +} + +/** + Do a search in the Target delimited list. + + @param[in] List The list to seatch in. + @param[in] MetaTarget The item to search for. MetaMatching supported. + @param[out] FullName Optional pointer to an allocated buffer containing + the match. + @param[in] Meta TRUE to use MetaMatching. + @param[in] SkipTrailingNumbers TRUE to allow for numbers after the MetaTarget. + @param[in] Target The single character that delimits list + items (";" normally). +**/ +BOOLEAN +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); +} + +/** + Determine what type of device is represented and return it's string. The + string is in allocated memory and must be callee freed. The HII is is listed below. + The actual string cannot be determined. + + @param[in] DevicePath The device to analyze. + + @retval STR_MAP_MEDIA_UNKNOWN The media type is unknown. + @retval STR_MAP_MEDIA_HARDDISK The media is a hard drive. + @retval STR_MAP_MEDIA_CDROM The media is a CD ROM. + @retval STR_MAP_MEDIA_FLOPPY The media is a floppy drive. +**/ +CHAR16* +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 +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 +MappingListHasType( + IN CONST CHAR16 *MapList, + IN CONST CHAR16 *Specific, + IN CONST CHAR16 *TypeString, + IN CONST BOOLEAN Normal, + IN CONST BOOLEAN Consist + ) +{ + CHAR16 *NewSpecific; + RETURN_STATUS Status; + + // + // specific has priority + // + if (Specific != NULL) { + NewSpecific = AllocateCopyPool(StrSize(Specific) + sizeof(CHAR16), Specific); + if (NewSpecific == NULL){ + return FALSE; + } + if (NewSpecific[StrLen(NewSpecific)-1] != L':') { + Status = StrnCatS(NewSpecific, (StrSize(Specific) + sizeof(CHAR16))/sizeof(CHAR16), L":", StrLen(L":")); + if (EFI_ERROR (Status)) { + FreePool(NewSpecific); + return FALSE; + } + } + + if (SearchList(MapList, NewSpecific, NULL, TRUE, FALSE, L";")) { + FreePool(NewSpecific); + return (TRUE); + } + FreePool(NewSpecific); + } + if ( Consist + && Specific == NULL + && (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 + && Specific == NULL + && (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); +} + + +/** + Display a single map line for device Handle if conditions are met. + + @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. + @param[in] Handle The handle to display from. + + @retval EFI_SUCCESS The mapping was displayed. +**/ +EFI_STATUS +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; + CHAR16 *Alias; + UINTN TempLen; + BOOLEAN Removable; + CONST CHAR16 *TempSpot2; + + Alias = NULL; + TempSpot2 = NULL; + CurrentName = NULL; + DevPath = DevicePathFromHandle(Handle); + DevPathCopy = DevPath; + MapList = gEfiShellProtocol->GetMapFromDevicePath(&DevPathCopy); + if (MapList == NULL) { + return EFI_NOT_FOUND; + } + + if (!MappingListHasType(MapList, Specific, TypeString, Normal, Consist)){ + return EFI_NOT_FOUND; + } + + if (Normal || !Consist) { + // + // need the Normal here since people can use both on command line. otherwise unused. + // + + // + // Allocate a name + // + CurrentName = NULL; + CurrentName = StrnCatGrow(&CurrentName, 0, MapList, 0); + if (CurrentName == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + + // + // Chop off the other names that become "Alias(s)" + // leaving just the normal name + // + TempSpot = StrStr(CurrentName, L";"); + if (TempSpot != NULL) { + *TempSpot = CHAR_NULL; + } + } else { + CurrentName = NULL; + + // + // Skip the first name. This is the standard name. + // + TempSpot = StrStr(MapList, L";"); + if (TempSpot != NULL) { + TempSpot++; + } + SearchList(TempSpot, L"HD*", &CurrentName, TRUE, FALSE, L";"); + if (CurrentName == NULL) { + SearchList(TempSpot, L"CD*", &CurrentName, TRUE, FALSE, L";"); + } + if (CurrentName == NULL) { + SearchList(TempSpot, L"FP*", &CurrentName, TRUE, FALSE, L";"); + } + if (CurrentName == NULL) { + SearchList(TempSpot, L"F*", &CurrentName, TRUE, FALSE, L";"); + } + if (CurrentName == NULL) { + // + // We didnt find anything, so just the first one in the list... + // + CurrentName = StrnCatGrow(&CurrentName, 0, MapList, 0); + if (CurrentName == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + TempSpot = StrStr(CurrentName, L";"); + if (TempSpot != NULL) { + *TempSpot = CHAR_NULL; + } + } else { + Alias = StrnCatGrow(&Alias, 0, MapList, 0); + if (Alias == NULL) { + return EFI_OUT_OF_RESOURCES; + } + TempSpot = StrStr(Alias, CurrentName); + if (TempSpot != NULL) { + TempSpot2 = StrStr(TempSpot, L";"); + if (TempSpot2 != NULL) { + TempSpot2++; // Move past ";" from CurrentName + CopyMem(TempSpot, TempSpot2, StrSize(TempSpot2)); + } else { + *TempSpot = CHAR_NULL; + } + } + if (Alias[StrLen(Alias)-1] == L';') { + Alias[StrLen(Alias)-1] = CHAR_NULL; + } + } + } + DevPathString = ConvertDevicePathToText(DevPath, TRUE, FALSE); + TempLen = StrLen(CurrentName); + if (!SFO) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_MAP_ENTRY), + gShellLevel2HiiHandle, + CurrentName, + Alias!=NULL?Alias:(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 + ); + } + SHELL_FREE_NON_NULL(MediaType); + } + } else { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_MAP_SFO_MAPPINGS), + gShellLevel2HiiHandle, + CurrentName, + DevPathString, + Consist?L"":(TempLen < StrLen(MapList)?MapList + TempLen+1:L"") + ); + } + SHELL_FREE_NON_NULL(DevPathString); + SHELL_FREE_NON_NULL(CurrentName); + SHELL_FREE_NON_NULL(Alias); + return EFI_SUCCESS; +} + +/** + Delete Specific from the list of maps for device Handle. + + @param[in] Specific The name to delete. + @param[in] Handle The device to look on. + + @retval EFI_SUCCESS The delete was successful. + @retval EFI_NOT_FOUND Name was not a map on Handle. +**/ +EFI_STATUS +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)); +} + +CONST CHAR16 Cd[] = L"cd*"; +CONST CHAR16 Hd[] = L"hd*"; +CONST CHAR16 Fp[] = L"fp*"; +CONST CHAR16 AnyF[] = L"F*"; +/** + 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. + @param[in] Header TRUE to print the header block. + + @retval SHELL_SUCCESS The display was printed. + @retval SHELL_INVALID_PARAMETER One of Consist or Normal must be TRUE if no Specific. + +**/ +SHELL_STATUS +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; + BOOLEAN Found; + + if (!Consist && !Normal && Specific == NULL && TypeString == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle, L"map"); + 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_PARAM_INV), gShellLevel2HiiHandle, L"map", TypeString); + return (SHELL_INVALID_PARAMETER); + } + } else if (Test == NULL) { + Test = (CHAR16*)AnyF; + } + } + } 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, + &gEfiSimpleFileSystemProtocolGuid, + NULL, + &BufferSize, + HandleBuffer); + if (Status == EFI_BUFFER_TOO_SMALL) { + HandleBuffer = AllocateZeroPool(BufferSize); + if (HandleBuffer == NULL) { + return (SHELL_OUT_OF_RESOURCES); + } + Status = gBS->LocateHandle( + ByProtocol, + &gEfiSimpleFileSystemProtocolGuid, + NULL, + &BufferSize, + HandleBuffer); + } + + // + // Get the map name(s) for each one. + // + for ( LoopVar = 0, Found = FALSE + ; LoopVar < (BufferSize / sizeof(EFI_HANDLE)) && HandleBuffer != NULL + ; LoopVar ++ + ){ + Status = PerformSingleMappingDisplay( + Verbose, + Consist, + Normal, + Test, + SFO, + Specific, + HandleBuffer[LoopVar]); + if (!EFI_ERROR(Status)) { + Found = TRUE; + } + } + + // + // Look up all BlockIo in the platform + // + Status = gBS->LocateHandle( + ByProtocol, + &gEfiBlockIoProtocolGuid, + NULL, + &BufferSize, + HandleBuffer); + if (Status == EFI_BUFFER_TOO_SMALL) { + SHELL_FREE_NON_NULL(HandleBuffer); + HandleBuffer = AllocateZeroPool(BufferSize); + if (HandleBuffer == NULL) { + return (SHELL_OUT_OF_RESOURCES); + } + Status = gBS->LocateHandle( + ByProtocol, + &gEfiBlockIoProtocolGuid, + NULL, + &BufferSize, + HandleBuffer); + } + if (!EFI_ERROR(Status) && HandleBuffer != NULL) { + // + // 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], + &gEfiSimpleFileSystemProtocolGuid, + NULL, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL) == EFI_SUCCESS) { + continue; + } + Status = PerformSingleMappingDisplay( + Verbose, + Consist, + Normal, + Test, + SFO, + Specific, + HandleBuffer[LoopVar]); + if (!EFI_ERROR(Status)) { + Found = TRUE; + } + } + FreePool(HandleBuffer); + } + if (!Found) { + if (Specific != NULL) { + ShellPrintHiiEx(gST->ConOut->Mode->CursorColumn, gST->ConOut->Mode->CursorRow-1, NULL, STRING_TOKEN (STR_MAP_NF), gShellLevel2HiiHandle, L"map", Specific); + } else { + ShellPrintHiiEx(gST->ConOut->Mode->CursorColumn, gST->ConOut->Mode->CursorRow-1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"map"); + } + } + return (SHELL_SUCCESS); +} + +/** + Perform a mapping display and parse for multiple types in the TypeString. + + @param[in] Verbose TRUE to use verbose output. + @param[in] Consist TRUE to display consistent names. + @param[in] Normal TRUE to display normal names. + @param[in] TypeString An optional comma-delimited list of types. + @param[in] SFO TRUE to display in SFO format. See Spec. + @param[in] Specific An optional specific map name to display alone. + + @retval SHELL_INVALID_PARAMETER A parameter was invalid. + @retval SHELL_SUCCESS The display was successful. + @sa PerformMappingDisplay +**/ +SHELL_STATUS +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); +} + +/** + Delete a specific map. + + @param[in] Specific The pointer to the name of the map to delete. + + @retval EFI_INVALID_PARAMETER Specific was NULL. + @retval EFI_SUCCESS The operation was successful. + @retval EFI_NOT_FOUND Specific could not be found. +**/ +EFI_STATUS +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 = AllocateZeroPool(BufferSize); + if (HandleBuffer == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + Status = gBS->LocateHandle( + ByProtocol, + &gEfiDevicePathProtocolGuid, + NULL, + &BufferSize, + HandleBuffer); + } + if (EFI_ERROR(Status)) { + SHELL_FREE_NON_NULL(HandleBuffer); + return (Status); + } + + if (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 = AllocateZeroPool(BufferSize); + if (HandleBuffer == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + Status = gBS->LocateHandle( + ByProtocol, + &gEfiBlockIoProtocolGuid, + NULL, + &BufferSize, + HandleBuffer); + } + if (EFI_ERROR(Status)) { + SHELL_FREE_NON_NULL(HandleBuffer); + return (Status); + } + + if (HandleBuffer != NULL) { + // + // 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; + } + } + } + SHELL_FREE_NON_NULL(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 +AddMappingFromMapping( + IN CONST CHAR16 *Map, + IN CONST CHAR16 *SName + ) +{ + CONST EFI_DEVICE_PATH_PROTOCOL *DevPath; + EFI_STATUS Status; + CHAR16 *NewSName; + RETURN_STATUS StrRetStatus; + + NewSName = AllocateCopyPool(StrSize(SName) + sizeof(CHAR16), SName); + if (NewSName == NULL) { + return (SHELL_OUT_OF_RESOURCES); + } + if (NewSName[StrLen(NewSName)-1] != L':') { + StrRetStatus = StrnCatS(NewSName, (StrSize(SName) + sizeof(CHAR16))/sizeof(CHAR16), L":", StrLen(L":")); + if (EFI_ERROR(StrRetStatus)) { + FreePool(NewSName); + return ((SHELL_STATUS) (StrRetStatus & (~MAX_BIT))); + } + } + + if (!IsNumberLetterOnly(NewSName, StrLen(NewSName)-1)) { + FreePool(NewSName); + return (SHELL_INVALID_PARAMETER); + } + + DevPath = gEfiShellProtocol->GetDevicePathFromMap(Map); + if (DevPath == NULL) { + FreePool(NewSName); + return (SHELL_INVALID_PARAMETER); + } + + Status = gEfiShellProtocol->SetMap(DevPath, NewSName); + FreePool(NewSName); + if (EFI_ERROR(Status)) { + return (SHELL_DEVICE_ERROR); + } + return (SHELL_SUCCESS); +} + +/** + 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 +AddMappingFromHandle( + IN CONST EFI_HANDLE Handle, + IN CONST CHAR16 *SName + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevPath; + EFI_STATUS Status; + CHAR16 *NewSName; + RETURN_STATUS StrRetStatus; + + NewSName = AllocateCopyPool(StrSize(SName) + sizeof(CHAR16), SName); + if (NewSName == NULL) { + return (SHELL_OUT_OF_RESOURCES); + } + if (NewSName[StrLen(NewSName)-1] != L':') { + StrRetStatus = StrnCatS(NewSName, (StrSize(SName) + sizeof(CHAR16))/sizeof(CHAR16), L":", StrLen(L":")); + if (EFI_ERROR(StrRetStatus)) { + FreePool(NewSName); + return ((SHELL_STATUS) (StrRetStatus & (~MAX_BIT))); + } + } + + if (!IsNumberLetterOnly(NewSName, StrLen(NewSName)-1)) { + FreePool(NewSName); + return (SHELL_INVALID_PARAMETER); + } + + Status = gBS->OpenProtocol( + Handle, + &gEfiDevicePathProtocolGuid, + (VOID**)&DevPath, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR(Status)) { + FreePool(NewSName); + return (SHELL_DEVICE_ERROR); + } + Status = gEfiShellProtocol->SetMap(DevPath, NewSName); + FreePool(NewSName); + 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 MapAsHandle; + SHELL_STATUS ShellStatus; + BOOLEAN SfoMode; + BOOLEAN ConstMode; + BOOLEAN NormlMode; + CONST CHAR16 *Param1; + CONST CHAR16 *TypeString; + UINTN TempStringLength; + + ProblemParam = NULL; + Mapping = NULL; + SName = NULL; + ShellStatus = SHELL_SUCCESS; + MapAsHandle = 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, L"map", 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, L"map"); + 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, L"map"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + SName = ShellCommandLineGetValue(Package, L"-d"); + if (SName != NULL) { + Status = PerformMappingDelete(SName); + if (EFI_ERROR(Status)) { + if (Status == EFI_ACCESS_DENIED) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellLevel2HiiHandle, L"map"); + ShellStatus = SHELL_ACCESS_DENIED; + } else if (Status == EFI_NOT_FOUND) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MAP_NF), gShellLevel2HiiHandle, L"map", SName); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, L"map", Status); + ShellStatus = SHELL_UNSUPPORTED; + } + } + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle, L"map"); + 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, L"map", Status); + ShellStatus = SHELL_UNSUPPORTED; + } + } + if ( ShellStatus == SHELL_SUCCESS && ShellCommandLineGetFlag(Package, L"-u")) { + // + // Do the Update + // + Status = ShellCommandUpdateMapping (); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, L"map", 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)) { + MapAsHandle = ConvertHandleIndexToHandle(ShellStrToUintn(Mapping)); + } else { + MapAsHandle = NULL; + } + if (MapAsHandle == NULL && Mapping[StrLen(Mapping)-1] != L':') { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"map", Mapping); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + TempStringLength = StrLen(SName); + if (!IsNumberLetterOnly(SName, TempStringLength-(SName[TempStringLength-1]==L':'?1:0))) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"map", SName); + ShellStatus = SHELL_INVALID_PARAMETER; + } + + if (ShellStatus == SHELL_SUCCESS) { + if (MapAsHandle != NULL) { + ShellStatus = AddMappingFromHandle(MapAsHandle, 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, L"map"); + break; + case SHELL_INVALID_PARAMETER: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"map", Mapping); + break; + case SHELL_DEVICE_ERROR: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MAP_NOF), gShellLevel2HiiHandle, L"map", Mapping); + break; + default: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, L"map", 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/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/MkDir.c b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/MkDir.c new file mode 100644 index 0000000000..4aade13aac --- /dev/null +++ b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/MkDir.c @@ -0,0 +1,129 @@ +/** @file + Main file for attrib shell level 2 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
+ 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, L"mkdir", 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, L"mkdir"); + 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/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Mv.c b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Mv.c new file mode 100644 index 0000000000..71e43367c6 --- /dev/null +++ b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Mv.c @@ -0,0 +1,863 @@ +/** @file + Main file for mv shell level 2 function. + + (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.
+ Copyright (c) 2009 - 2016, 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 determine if a move is between file systems. + + @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 + + @retval TRUE The move is across file system. + @retval FALSE The move is within a file system. +**/ +BOOLEAN +IsBetweenFileSystem( + IN CONST CHAR16 *FullName, + IN CONST CHAR16 *Cwd, + IN CONST CHAR16 *DestPath + ) +{ + CHAR16 *Test; + CHAR16 *Test1; + UINTN Result; + + Test = StrStr(FullName, L":"); + if (Test == NULL && Cwd != NULL) { + Test = StrStr(Cwd, L":"); + } + Test1 = StrStr(DestPath, L":"); + if (Test1 == NULL && Cwd != NULL) { + Test1 = StrStr(Cwd, L":"); + } + if (Test1 != NULL && Test != NULL) { + *Test = CHAR_NULL; + *Test1 = CHAR_NULL; + Result = StringNoCaseCompare(&FullName, &DestPath); + *Test = L':'; + *Test1 = L':'; + if (Result != 0) { + return (TRUE); + } + } + return (FALSE); +} + +/** + function to determine if SrcPath is valid to mv. + + if SrcPath equal CWD then it's invalid. + if SrcPath is the parent path of CWD then it's invalid. + is SrcPath is NULL return FALSE. + + if CwdPath is NULL then ASSERT() + + @param SrcPath [in] The source path. + @param CwdPath [in] The current working directory. + + @retval TRUE The source path is valid. + @retval FALSE The source path is invalid. +**/ +BOOLEAN +IsSoucePathValid( + IN CONST CHAR16* SrcPath, + IN CONST CHAR16* CwdPath + ) +{ + CHAR16* SrcPathBuffer; + CHAR16* CwdPathBuffer; + BOOLEAN Ret; + + ASSERT (CwdPath != NULL); + if (SrcPath == NULL) { + return FALSE; + } + + Ret = TRUE; + + SrcPathBuffer = AllocateCopyPool (StrSize (SrcPath), SrcPath); + if (SrcPathBuffer == NULL) { + return FALSE; + } + + CwdPathBuffer = AllocateCopyPool (StrSize (CwdPath), CwdPath); + if (CwdPathBuffer == NULL) { + FreePool(SrcPathBuffer); + return FALSE; + } + + gUnicodeCollation->StrUpr (gUnicodeCollation, SrcPathBuffer); + gUnicodeCollation->StrUpr (gUnicodeCollation, CwdPathBuffer); + + if (SrcPathBuffer[StrLen (SrcPathBuffer) -1 ] == L'\\') { + SrcPathBuffer[StrLen (SrcPathBuffer) - 1] = CHAR_NULL; + } + + if (CwdPathBuffer[StrLen (CwdPathBuffer) - 1] == L'\\') { + CwdPathBuffer[StrLen (CwdPathBuffer) - 1] = CHAR_NULL; + } + + if (StrCmp (CwdPathBuffer, SrcPathBuffer) == 0 || + ((StrStr (CwdPathBuffer, SrcPathBuffer) == CwdPathBuffer) && + (CwdPathBuffer[StrLen (SrcPathBuffer)] == L'\\')) + ) { + Ret = FALSE; + } + + FreePool (SrcPathBuffer); + FreePool (CwdPathBuffer); + + return Ret; +} + +/** + 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 SourcePath [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 + @param DestAttr [in] The Attribute of the destination + @param FileStatus [in] The Status of the file when opened + + @retval TRUE The move is valid + @retval FALSE The move is not +**/ +BOOLEAN +IsValidMove( + IN CONST CHAR16 *SourcePath, + IN CONST CHAR16 *Cwd, + IN CONST CHAR16 *DestPath, + IN CONST UINT64 Attribute, + IN CONST UINT64 DestAttr, + IN CONST EFI_STATUS FileStatus + ) +{ + CHAR16 *DestPathCopy; + CHAR16 *DestPathWalker; + + if ((Cwd != NULL) && ((Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY)) { + if (!IsSoucePathValid (SourcePath, Cwd)) { + // + // Invalid move + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_MV_INV_CWD), gShellLevel2HiiHandle); + return FALSE; + } + } + + // + // invalid to move read only or move to a read only destination + // + if (((Attribute & EFI_FILE_READ_ONLY) != 0) + || (FileStatus == EFI_WRITE_PROTECTED) + || ((DestAttr & EFI_FILE_READ_ONLY) != 0) + ) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MV_INV_RO), gShellLevel2HiiHandle, SourcePath); + return (FALSE); + } + + DestPathCopy = AllocateCopyPool(StrSize(DestPath), DestPath); + if (DestPathCopy == NULL) { + return (FALSE); + } + + for (DestPathWalker = DestPathCopy; *DestPathWalker == L'\\'; DestPathWalker++) ; + + while(DestPathWalker != NULL && DestPathWalker[StrLen(DestPathWalker)-1] == L'\\') { + DestPathWalker[StrLen(DestPathWalker)-1] = CHAR_NULL; + } + + ASSERT(DestPathWalker != NULL); + ASSERT(SourcePath != NULL); + + // + // If they're the same, or if source is "above" dest on file path tree + // + if ( StringNoCaseCompare (&DestPathWalker, &SourcePath) == 0 || + ((StrStr(DestPathWalker, SourcePath) == DestPathWalker) && + (DestPathWalker[StrLen(SourcePath)] == '\\') + ) + ) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MV_INV_SUB), gShellLevel2HiiHandle); + FreePool(DestPathCopy); + return (FALSE); + } + FreePool(DestPathCopy); + + 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] DestParameter The original path to the destination. + @param[in, out] DestPathPointer A pointer to the callee allocated final path. + @param[in] Cwd A pointer to the current working directory. + @param[in] SingleSource TRUE to have only one source file. + @param[in, out] DestAttr A pointer to the destination information attribute. + + @retval SHELL_INVALID_PARAMETER The DestParameter could not be resolved to a location. + @retval SHELL_INVALID_PARAMETER The DestParameter could be resolved to more than 1 location. + @retval SHELL_INVALID_PARAMETER Cwd is required and is NULL. + @retval SHELL_SUCCESS The operation was sucessful. +**/ +SHELL_STATUS +GetDestinationLocation( + IN CONST CHAR16 *DestParameter, + IN OUT CHAR16 **DestPathPointer, + IN CONST CHAR16 *Cwd, + IN CONST BOOLEAN SingleSource, + IN OUT UINT64 *DestAttr + ) +{ + EFI_SHELL_FILE_INFO *DestList; + EFI_SHELL_FILE_INFO *Node; + CHAR16 *DestPath; + UINTN NewSize; + UINTN CurrentSize; + + DestList = NULL; + DestPath = NULL; + + ASSERT(DestAttr != NULL); + + if (StrStr(DestParameter, L"\\") == DestParameter) { + if (Cwd == NULL) { + return SHELL_INVALID_PARAMETER; + } + DestPath = AllocateZeroPool(StrSize(Cwd)); + if (DestPath == NULL) { + return (SHELL_OUT_OF_RESOURCES); + } + StrCpyS(DestPath, StrSize(Cwd) / sizeof(CHAR16), Cwd); + while (PathRemoveLastItem(DestPath)) ; + + // + // Append DestParameter beyond '\' which may be present + // + CurrentSize = StrSize(DestPath); + StrnCatGrow(&DestPath, &CurrentSize, &DestParameter[1], 0); + + *DestPathPointer = DestPath; + return (SHELL_SUCCESS); + } + // + // get the destination path + // + ShellOpenFileMetaArg((CHAR16*)DestParameter, 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 (StrStr(DestParameter, L":") == NULL) { + if (Cwd == NULL) { + ShellCloseFileMetaArg(&DestList); + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle); + return (SHELL_INVALID_PARAMETER); + } + NewSize = StrSize(Cwd); + NewSize += StrSize(DestParameter); + DestPath = AllocateZeroPool(NewSize); + if (DestPath == NULL) { + ShellCloseFileMetaArg(&DestList); + return (SHELL_OUT_OF_RESOURCES); + } + StrCpyS(DestPath, NewSize / sizeof(CHAR16), Cwd); + if (DestPath[StrLen(DestPath)-1] != L'\\' && DestParameter[0] != L'\\') { + StrCatS(DestPath, NewSize / sizeof(CHAR16), L"\\"); + } else if (DestPath[StrLen(DestPath)-1] == L'\\' && DestParameter[0] == L'\\') { + ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL; + } + StrCatS(DestPath, NewSize / sizeof(CHAR16), DestParameter); + } else { + ASSERT(DestPath == NULL); + DestPath = StrnCatGrow(&DestPath, NULL, DestParameter, 0); + if (DestPath == NULL) { + ShellCloseFileMetaArg(&DestList); + return (SHELL_OUT_OF_RESOURCES); + } + } + } else { + Node = (EFI_SHELL_FILE_INFO*)GetFirstNode(&DestList->Link); + *DestAttr = Node->Info->Attribute; + // + // 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, L"mv", DestParameter); + return (SHELL_INVALID_PARAMETER); + } + + // + // If we are a directory or a single file, then one node is fine. + // + if (ShellIsDirectory(Node->FullName)==EFI_SUCCESS || SingleSource) { + DestPath = AllocateZeroPool(StrSize(Node->FullName)+sizeof(CHAR16)); + if (DestPath == NULL) { + ShellCloseFileMetaArg(&DestList); + return (SHELL_OUT_OF_RESOURCES); + } + StrCpyS(DestPath, (StrSize(Node->FullName)+sizeof(CHAR16)) / sizeof(CHAR16), Node->FullName); + StrCatS(DestPath, (StrSize(Node->FullName)+sizeof(CHAR16)) / sizeof(CHAR16), L"\\"); + } else { + // + // cant move multiple files onto a single file. + // + ShellCloseFileMetaArg(&DestList); + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_ERROR), gShellLevel2HiiHandle, L"mv", DestParameter); + return (SHELL_INVALID_PARAMETER); + } + } + + *DestPathPointer = DestPath; + ShellCloseFileMetaArg(&DestList); + + return (SHELL_SUCCESS); +} + +/** + Function to do a move across file systems. + + @param[in] Node A pointer to the file to be removed. + @param[in] DestPath A pointer to the destination file path. + @param[out] Resp A pointer to response from question. Pass back on looped calling + + @retval SHELL_SUCCESS The source file was moved to the destination. +**/ +EFI_STATUS +MoveBetweenFileSystems( + IN EFI_SHELL_FILE_INFO *Node, + IN CONST CHAR16 *DestPath, + OUT VOID **Resp + ) +{ + SHELL_STATUS ShellStatus; + + // + // First we copy the file + // + ShellStatus = CopySingleFile (Node->FullName, DestPath, Resp, TRUE, L"mv"); + + // + // Check our result + // + if (ShellStatus == SHELL_SUCCESS) { + // + // The copy was successful. delete the source file. + // + CascadeDelete(Node, TRUE); + Node->Handle = NULL; + } else if (ShellStatus == SHELL_ABORTED) { + return EFI_ABORTED; + } else if (ShellStatus == SHELL_ACCESS_DENIED) { + return EFI_ACCESS_DENIED; + } else if (ShellStatus == SHELL_VOLUME_FULL) { + return EFI_VOLUME_FULL; + } else { + return EFI_UNSUPPORTED; + } + + return (EFI_SUCCESS); +} + +/** + Function to take the destination path and target file name to generate the full destination path. + + @param[in] DestPath A pointer to the destination file path string. + @param[out] FullDestPath A pointer to the full destination path string. + @param[in] FileName Name string of the targe file. + + @retval SHELL_SUCCESS the files were all moved. + @retval SHELL_INVALID_PARAMETER a parameter was invalid + @retval SHELL_OUT_OF_RESOURCES a memory allocation failed +**/ +EFI_STATUS +CreateFullDestPath( + IN CONST CHAR16 **DestPath, + OUT CHAR16 **FullDestPath, + IN CONST CHAR16 *FileName + ) +{ + UINTN Size; + if (FullDestPath == NULL || FileName == NULL || DestPath == NULL || *DestPath == NULL){ + return (EFI_INVALID_PARAMETER); + } + + Size = StrSize(*DestPath) + StrSize(FileName); + + *FullDestPath = AllocateZeroPool(Size); + if (*FullDestPath == NULL){ + return (EFI_OUT_OF_RESOURCES); + } + + StrCpyS(*FullDestPath, Size / sizeof(CHAR16), *DestPath); + if ((*FullDestPath)[StrLen(*FullDestPath)-1] != L'\\' && FileName[0] != L'\\') { + StrCatS(*FullDestPath, Size / sizeof(CHAR16), L"\\"); + } + StrCatS(*FullDestPath, Size / sizeof(CHAR16), FileName); + + return (EFI_SUCCESS); +} + +/** + Function to do a move within a file system. + + @param[in] Node A pointer to the file to be removed. + @param[in] DestPath A pointer to the destination file path. + @param[out] Resp A pointer to response from question. Pass back on looped calling. + + @retval SHELL_SUCCESS The source file was moved to the destination. + @retval SHELL_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +MoveWithinFileSystems( + IN EFI_SHELL_FILE_INFO *Node, + IN CHAR16 *DestPath, + OUT VOID **Resp + ) +{ + EFI_FILE_INFO *NewFileInfo; + CHAR16 *TempLocation; + UINTN NewSize; + UINTN Length; + EFI_STATUS Status; + + // + // 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) + SIZE_OF_EFI_FILE_INFO + sizeof(CHAR16); + NewFileInfo = AllocateZeroPool(NewSize); + if (NewFileInfo == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_MEM), gShellLevel2HiiHandle); + Status = EFI_OUT_OF_RESOURCES; + } else { + CopyMem(NewFileInfo, Node->Info, SIZE_OF_EFI_FILE_INFO); + if (DestPath[0] != L'\\') { + StrCpyS(NewFileInfo->FileName, (NewSize - SIZE_OF_EFI_FILE_INFO) / sizeof(CHAR16), L"\\"); + StrCatS(NewFileInfo->FileName, (NewSize - SIZE_OF_EFI_FILE_INFO) / sizeof(CHAR16), DestPath); + } else { + StrCpyS(NewFileInfo->FileName, (NewSize - SIZE_OF_EFI_FILE_INFO) / sizeof(CHAR16), DestPath); + } + Length = StrLen(NewFileInfo->FileName); + if (Length > 0) { + Length--; + } + if (NewFileInfo->FileName[Length] == L'\\') { + if (Node->FileName[0] == L'\\') { + // + // Don't allow for double slashes. Eliminate one of them. + // + NewFileInfo->FileName[Length] = CHAR_NULL; + } + StrCatS(NewFileInfo->FileName, (NewSize - SIZE_OF_EFI_FILE_INFO) / sizeof(CHAR16), Node->FileName); + } + NewFileInfo->Size = SIZE_OF_EFI_FILE_INFO + StrSize(NewFileInfo->FileName); + + // + // Perform the move operation + // + Status = ShellSetFileInfo(Node->Handle, NewFileInfo); + + // + // Free the info object we used... + // + FreePool(NewFileInfo); + } + + return (Status); +} +/** + 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[out] Resp pointer to response from question. Pass back on looped calling + @param[in] DestParameter the originally specified 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 +ValidateAndMoveFiles( + IN EFI_SHELL_FILE_INFO *FileList, + OUT VOID **Resp, + IN CONST CHAR16 *DestParameter + ) +{ + EFI_STATUS Status; + CHAR16 *HiiOutput; + CHAR16 *HiiResultOk; + CHAR16 *DestPath; + CHAR16 *FullDestPath; + CONST CHAR16 *Cwd; + CHAR16 *FullCwd; + SHELL_STATUS ShellStatus; + EFI_SHELL_FILE_INFO *Node; + VOID *Response; + UINT64 Attr; + CHAR16 *CleanFilePathStr; + + ASSERT(FileList != NULL); + ASSERT(DestParameter != NULL); + + DestPath = NULL; + FullDestPath = NULL; + Cwd = ShellGetCurrentDir(NULL); + Response = *Resp; + Attr = 0; + CleanFilePathStr = NULL; + FullCwd = NULL; + + if (Cwd != NULL) { + FullCwd = AllocateZeroPool(StrSize(Cwd) + sizeof(CHAR16)); + if (FullCwd == NULL) { + return SHELL_OUT_OF_RESOURCES; + } else { + StrCpyS(FullCwd, StrSize(Cwd)/sizeof(CHAR16)+1, Cwd); + StrCatS(FullCwd, StrSize(Cwd)/sizeof(CHAR16)+1, L"\\"); + } + } + + Status = ShellLevel2StripQuotes (DestParameter, &CleanFilePathStr); + if (EFI_ERROR (Status)) { + SHELL_FREE_NON_NULL(FullCwd); + if (Status == EFI_OUT_OF_RESOURCES) { + return SHELL_OUT_OF_RESOURCES; + } else { + return SHELL_INVALID_PARAMETER; + } + } + + ASSERT (CleanFilePathStr != NULL); + + // + // Get and validate the destination location + // + ShellStatus = GetDestinationLocation(CleanFilePathStr, &DestPath, FullCwd, (BOOLEAN)(FileList->Link.ForwardLink == FileList->Link.BackLink), &Attr); + FreePool (CleanFilePathStr); + + if (ShellStatus != SHELL_SUCCESS) { + SHELL_FREE_NON_NULL (FullCwd); + return (ShellStatus); + } + DestPath = PathCleanUpDirectories(DestPath); + if (DestPath == NULL) { + FreePool (FullCwd); + return (SHELL_OUT_OF_RESOURCES); + } + + HiiOutput = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_MV_OUTPUT), NULL); + HiiResultOk = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_GEN_RES_OK), NULL); + if (HiiOutput == NULL || HiiResultOk == NULL) { + SHELL_FREE_NON_NULL(DestPath); + SHELL_FREE_NON_NULL(HiiOutput); + SHELL_FREE_NON_NULL(HiiResultOk); + SHELL_FREE_NON_NULL(FullCwd); + return (SHELL_OUT_OF_RESOURCES); + } + + // + // 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; + } + + // + // These should never be NULL + // + ASSERT(Node->FileName != NULL); + ASSERT(Node->FullName != NULL); + ASSERT(Node->Info != NULL); + + // + // skip the directory traversing stuff... + // + if (StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0) { + continue; + } + + SHELL_FREE_NON_NULL(FullDestPath); + FullDestPath = NULL; + if (ShellIsDirectory(DestPath)==EFI_SUCCESS) { + CreateFullDestPath((CONST CHAR16 **)&DestPath, &FullDestPath, Node->FileName); + } + + // + // Validate that the move is valid + // + if (!IsValidMove(Node->FullName, FullCwd, FullDestPath!=NULL? FullDestPath:DestPath, Node->Info->Attribute, Attr, Node->Status)) { + ShellStatus = SHELL_INVALID_PARAMETER; + continue; + } + + ShellPrintEx(-1, -1, HiiOutput, Node->FullName, FullDestPath!=NULL? FullDestPath:DestPath); + + // + // See if destination exists + // + if (!EFI_ERROR(ShellFileExists(FullDestPath!=NULL? FullDestPath:DestPath))) { + if (Response == NULL) { + ShellPromptForResponseHii(ShellPromptResponseTypeYesNoAllCancel, STRING_TOKEN (STR_GEN_DEST_EXIST_OVR), gShellLevel2HiiHandle, &Response); + } + switch (*(SHELL_PROMPT_RESPONSE*)Response) { + case ShellPromptResponseNo: + FreePool(Response); + Response = NULL; + continue; + case ShellPromptResponseCancel: + *Resp = Response; + // + // indicate to stop everything + // + SHELL_FREE_NON_NULL(FullCwd); + return (SHELL_ABORTED); + case ShellPromptResponseAll: + *Resp = Response; + break; + case ShellPromptResponseYes: + FreePool(Response); + Response = NULL; + break; + default: + FreePool(Response); + SHELL_FREE_NON_NULL(FullCwd); + return SHELL_ABORTED; + } + Status = ShellDeleteFileByName(FullDestPath!=NULL? FullDestPath:DestPath); + } + + if (IsBetweenFileSystem(Node->FullName, FullCwd, DestPath)) { + while (FullDestPath == NULL && DestPath != NULL && DestPath[0] != CHAR_NULL && DestPath[StrLen(DestPath) - 1] == L'\\') { + DestPath[StrLen(DestPath) - 1] = CHAR_NULL; + } + Status = MoveBetweenFileSystems(Node, FullDestPath!=NULL? FullDestPath:DestPath, &Response); + } else { + Status = MoveWithinFileSystems(Node, DestPath, &Response); + // + // Display error status + // + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, L"mv", Status); + } + } + + // + // Check our result + // + if (EFI_ERROR(Status)) { + ShellStatus = SHELL_INVALID_PARAMETER; + if (Status == EFI_SECURITY_VIOLATION) { + ShellStatus = SHELL_SECURITY_VIOLATION; + } else if (Status == EFI_WRITE_PROTECTED) { + ShellStatus = SHELL_WRITE_PROTECTED; + } else if (Status == EFI_OUT_OF_RESOURCES) { + ShellStatus = SHELL_OUT_OF_RESOURCES; + } else if (Status == EFI_DEVICE_ERROR) { + ShellStatus = SHELL_DEVICE_ERROR; + } else if (Status == EFI_ACCESS_DENIED) { + ShellStatus = SHELL_ACCESS_DENIED; + } + } else { + ShellPrintEx(-1, -1, L"%s", HiiResultOk); + } + + } // main for loop + + SHELL_FREE_NON_NULL(FullDestPath); + SHELL_FREE_NON_NULL(DestPath); + SHELL_FREE_NON_NULL(HiiOutput); + SHELL_FREE_NON_NULL(HiiResultOk); + SHELL_FREE_NON_NULL(FullCwd); + return (ShellStatus); +} + +/** + 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 + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + CHAR16 *Cwd; + UINTN CwdSize; + SHELL_STATUS ShellStatus; + UINTN ParamCount; + UINTN LoopCounter; + EFI_SHELL_FILE_INFO *FileList; + VOID *Response; + + ProblemParam = NULL; + ShellStatus = SHELL_SUCCESS; + ParamCount = 0; + FileList = NULL; + Response = 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, L"mv", 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, L"mv"); + 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, L"mv"); + 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, L"mv", ShellCommandLineGetRawValue(Package, 1)); + ShellStatus = SHELL_NOT_FOUND; + } else { + // + // ValidateAndMoveFiles will report errors to the screen itself + // + CwdSize = StrSize(ShellGetCurrentDir(NULL)) + sizeof(CHAR16); + Cwd = AllocateZeroPool(CwdSize); + if (Cwd == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellLevel2HiiHandle, L"mv"); + ShellStatus = SHELL_OUT_OF_RESOURCES; + } else { + StrCpyS (Cwd, CwdSize / sizeof (CHAR16), ShellGetCurrentDir (NULL)); + StrCatS (Cwd, CwdSize / sizeof (CHAR16), L"\\"); + ShellStatus = ValidateAndMoveFiles (FileList, &Response, Cwd); + FreePool (Cwd); + } + } + } + + break; + default: + ///@todo make sure this works with error half way through and continues... + for (ParamCount--, LoopCounter = 1 ; LoopCounter < ParamCount ; 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, L"mv", ShellCommandLineGetRawValue(Package, LoopCounter)); + 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, &Response, ShellCommandLineGetRawValue(Package, ParamCount)); + } else { + ValidateAndMoveFiles(FileList, &Response, 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, L"mv", ShellCommandLineGetRawValue(Package, 1), ShellStatus|MAX_BIT); + } + } + } + break; + } // switch on parameter count + + if (FileList != NULL) { + ShellCloseFileMetaArg(&FileList); + } + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + } + + SHELL_FREE_NON_NULL(Response); + + if (ShellGetExecutionBreakFlag()) { + return (SHELL_ABORTED); + } + + return (ShellStatus); +} diff --git a/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Parse.c b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Parse.c new file mode 100644 index 0000000000..4b1973a505 --- /dev/null +++ b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Parse.c @@ -0,0 +1,456 @@ +/** @file + Main file for Parse shell level 2 function. + + (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.
+ Copyright (c) 2009 - 2012, 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" + +/** + Check if data is coming from StdIn output. + + @param[in] None + + @retval TRUE StdIn stream data available to parse + @retval FALSE StdIn stream data is not available to parse. +**/ +BOOLEAN +IsStdInDataAvailable ( + VOID + ) +{ + SHELL_FILE_HANDLE FileHandle; + EFI_STATUS Status; + CHAR16 CharBuffer; + UINTN CharSize; + UINT64 OriginalFilePosition; + + Status = EFI_SUCCESS; + FileHandle = NULL; + OriginalFilePosition = 0; + + if (ShellOpenFileByName (L">i", &FileHandle, EFI_FILE_MODE_READ, 0) == EFI_SUCCESS) { + CharSize = sizeof(CHAR16); + gEfiShellProtocol->GetFilePosition (FileHandle, &OriginalFilePosition); + Status = gEfiShellProtocol->ReadFile (FileHandle, &CharSize, &CharBuffer); + if (EFI_ERROR (Status) || (CharSize != sizeof(CHAR16))) { + return FALSE; + } + gEfiShellProtocol->SetFilePosition(FileHandle, OriginalFilePosition); + } + + if (FileHandle == NULL) { + return FALSE; + } else { + return TRUE; + } +} + +/** + Function to read a single line (up to but not including the \n) using StdIn data from a SHELL_FILE_HANDLE. + + If the position upon start is 0, then the Ascii Boolean will be set. This should be + maintained and not changed for all operations with the same file. + + @param[in] Handle SHELL_FILE_HANDLE to read from. + @param[in, out] Buffer The pointer to buffer to read into. + @param[in, out] Size The pointer to number of bytes in Buffer. + @param[in] Truncate If the buffer is large enough, this has no effect. + If the buffer is is too small and Truncate is TRUE, + the line will be truncated. + If the buffer is is too small and Truncate is FALSE, + then no read will occur. + + @retval EFI_SUCCESS The operation was successful. The line is stored in + Buffer. + @retval EFI_INVALID_PARAMETER Handle was NULL. + @retval EFI_INVALID_PARAMETER Size was NULL. + @retval EFI_BUFFER_TOO_SMALL Size was not large enough to store the line. + Size was updated to the minimum space required. +**/ +EFI_STATUS +ShellFileHandleReadStdInLine( + IN SHELL_FILE_HANDLE Handle, + IN OUT CHAR16 *Buffer, + IN OUT UINTN *Size, + IN BOOLEAN Truncate + ) +{ + EFI_STATUS Status; + CHAR16 CharBuffer; + UINTN CharSize; + UINTN CountSoFar; + UINT64 OriginalFilePosition; + + + if (Handle == NULL + ||Size == NULL + ){ + return (EFI_INVALID_PARAMETER); + } + if (Buffer == NULL) { + ASSERT(*Size == 0); + } else { + *Buffer = CHAR_NULL; + } + gEfiShellProtocol->GetFilePosition (Handle, &OriginalFilePosition); + + for (CountSoFar = 0;;CountSoFar++){ + CharBuffer = 0; + CharSize = sizeof(CHAR16); + Status = gEfiShellProtocol->ReadFile (Handle, &CharSize, &CharBuffer); + if ( EFI_ERROR(Status) + || CharSize == 0 + || (CharBuffer == L'\n') + ){ + break; + } + // + // if we have space save it... + // + if ((CountSoFar+1)*sizeof(CHAR16) < *Size){ + ASSERT(Buffer != NULL); + ((CHAR16*)Buffer)[CountSoFar] = CharBuffer; + ((CHAR16*)Buffer)[CountSoFar+1] = CHAR_NULL; + } + } + + // + // if we ran out of space tell when... + // + if ((CountSoFar+1)*sizeof(CHAR16) > *Size){ + *Size = (CountSoFar+1)*sizeof(CHAR16); + if (!Truncate) { + gEfiShellProtocol->SetFilePosition(Handle, OriginalFilePosition); + } else { + DEBUG((DEBUG_WARN, "The line was truncated in ShellFileHandleReadLine")); + } + return (EFI_BUFFER_TOO_SMALL); + } + while(Buffer[StrLen(Buffer)-1] == L'\r') { + Buffer[StrLen(Buffer)-1] = CHAR_NULL; + } + + return (Status); +} + + +/** + Function to read a single line using StdIn from a SHELL_FILE_HANDLE. The \n is not included in the returned + buffer. The returned buffer must be callee freed. + + If the position upon start is 0, then the Ascii Boolean will be set. This should be + maintained and not changed for all operations with the same file. + + @param[in] Handle SHELL_FILE_HANDLE to read from. + + @return The line of text from the file. + @retval NULL There was not enough memory available. + + @sa ShellFileHandleReadLine +**/ +CHAR16* +ParseReturnStdInLine ( + IN SHELL_FILE_HANDLE Handle + ) +{ + CHAR16 *RetVal; + UINTN Size; + EFI_STATUS Status; + + Size = 0; + RetVal = NULL; + + Status = ShellFileHandleReadStdInLine (Handle, RetVal, &Size, FALSE); + if (Status == EFI_BUFFER_TOO_SMALL) { + RetVal = AllocateZeroPool(Size); + if (RetVal == NULL) { + return (NULL); + } + Status = ShellFileHandleReadStdInLine (Handle, RetVal, &Size, FALSE); + + } + if (EFI_ERROR(Status) && (RetVal != NULL)) { + FreePool(RetVal); + RetVal = NULL; + } + return (RetVal); +} + +/** + Handle stings for SFO Output with escape character ^ in a string + 1. Quotation marks in the string must be escaped by using a ^ character (i.e. ^"). + 2. The ^ character may be inserted using ^^. + + @param[in] String The Unicode NULL-terminated string. + + @retval NewString The new string handled for SFO. +**/ +EFI_STRING +HandleStringWithEscapeCharForParse ( + IN CHAR16 *String + ) +{ + EFI_STRING NewStr; + EFI_STRING StrWalker; + EFI_STRING ReturnStr; + + if (String == NULL) { + return NULL; + } + + // + // start to parse the input string. + // + NewStr = AllocateZeroPool (StrSize (String)); + if (NewStr == NULL) { + return NULL; + } + ReturnStr = NewStr; + StrWalker = String; + while (*StrWalker != CHAR_NULL) { + if (*StrWalker == L'^' && (*(StrWalker + 1) == L'^' || *(StrWalker + 1) == L'"')) { + *NewStr = *(StrWalker + 1); + StrWalker++; + } else { + *NewStr = *StrWalker; + } + StrWalker++; + NewStr++; + } + + return ReturnStr; +} + + +/** + Do the actual parsing of the file. the file should be SFO output from a + shell command or a similar format. + + @param[in] FileName The filename to open. + @param[in] TableName The name of the table to find. + @param[in] ColumnIndex The column number to get. + @param[in] TableNameInstance Which instance of the table to get (row). + @param[in] ShellCommandInstance Which instance of the command to get. + @param[in] StreamingUnicode Indicates Input file is StdIn Unicode streaming data or not + + @retval SHELL_NOT_FOUND The requested instance was not found. + @retval SHELL_SUCCESS The operation was successful. +**/ +SHELL_STATUS +PerformParsing( + IN CONST CHAR16 *FileName, + IN CONST CHAR16 *TableName, + IN CONST UINTN ColumnIndex, + IN CONST UINTN TableNameInstance, + IN CONST UINTN ShellCommandInstance, + IN BOOLEAN StreamingUnicode + ) +{ + SHELL_FILE_HANDLE FileHandle; + EFI_STATUS Status; + BOOLEAN Ascii; + UINTN LoopVariable; + UINTN ColumnLoop; + CHAR16 *TempLine; + CHAR16 *ColumnPointer; + SHELL_STATUS ShellStatus; + CHAR16 *TempSpot; + CHAR16 *SfoString; + + 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, L"parse", FileName); + ShellStatus = SHELL_NOT_FOUND; + } else if (!EFI_ERROR (FileHandleIsDirectory (FileHandle))) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_FILE), gShellLevel2HiiHandle, L"parse", FileName); + ShellStatus = SHELL_NOT_FOUND; + } else { + for (LoopVariable = 0 ; LoopVariable < ShellCommandInstance && !ShellFileHandleEof(FileHandle);) { + if (StreamingUnicode) { + TempLine = ParseReturnStdInLine (FileHandle); + } else { + TempLine = ShellFileHandleReturnLine (FileHandle, &Ascii); + } + + if ((TempLine == NULL) || (*TempLine == CHAR_NULL && StreamingUnicode)) { + break; + } + + // + // Search for "ShellCommand," in the file to start the SFO table + // for a given ShellCommand. The UEFI Shell spec does not specify + // a space after the comma. + // + if (StrStr (TempLine, L"ShellCommand,") == TempLine) { + LoopVariable++; + } + SHELL_FREE_NON_NULL(TempLine); + } + if (LoopVariable == ShellCommandInstance) { + LoopVariable = 0; + while(1) { + if (StreamingUnicode) { + TempLine = ParseReturnStdInLine (FileHandle); + } else { + 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)) { + 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) { + if (ColumnPointer == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellLevel2HiiHandle, L"parse", L"Column Index"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + 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; + } + SfoString = HandleStringWithEscapeCharForParse (ColumnPointer); + if (SfoString != NULL) { + ShellPrintEx (-1, -1, L"%s\r\n", SfoString); + SHELL_FREE_NON_NULL (SfoString); + } + } + } + } + } + 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; + BOOLEAN StreamingUnicode; + + ShellStatus = SHELL_SUCCESS; + ProblemParam = NULL; + StreamingUnicode = FALSE; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParseEx (ParamList, &Package, &ProblemParam, TRUE, FALSE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"parse", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + StreamingUnicode = IsStdInDataAvailable (); + if ((!StreamingUnicode && (ShellCommandLineGetCount(Package) < 4)) || + (ShellCommandLineGetCount(Package) < 3)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle, L"parse"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if ((StreamingUnicode && (ShellCommandLineGetCount(Package) > 3)) || + (ShellCommandLineGetCount(Package) > 4)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"parse"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + if (StreamingUnicode) { + FileName = L">i"; + TableName = ShellCommandLineGetRawValue(Package, 1); + ColumnString = ShellCommandLineGetRawValue(Package, 2); + } 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, StreamingUnicode); + } + } + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + + return (ShellStatus); +} + diff --git a/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Reset.c b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Reset.c new file mode 100644 index 0000000000..40ad8d9c4e --- /dev/null +++ b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Reset.c @@ -0,0 +1,170 @@ +/** @file + Main file for attrib shell level 2 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
+ Copyright (c) 2009 - 2016, 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}, + {L"-fwui", TypeFlag }, + {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; + UINT64 OsIndications; + UINT32 Attr; + UINTN DataSize; + + 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, L"reset", 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, L"reset"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + + if (ShellCommandLineGetFlag (Package, L"-fwui")) { + + DataSize = sizeof (OsIndications); + Status = gRT->GetVariable ( + EFI_OS_INDICATIONS_SUPPORT_VARIABLE_NAME, &gEfiGlobalVariableGuid, + &Attr, &DataSize, &OsIndications + ); + if (!EFI_ERROR (Status)) { + if ((OsIndications & EFI_OS_INDICATIONS_BOOT_TO_FW_UI) != 0) { + DataSize = sizeof (OsIndications); + Status = gRT->GetVariable ( + EFI_OS_INDICATIONS_VARIABLE_NAME, &gEfiGlobalVariableGuid, + &Attr, &DataSize, &OsIndications + ); + if (!EFI_ERROR (Status)) { + OsIndications |= EFI_OS_INDICATIONS_BOOT_TO_FW_UI; + } else { + OsIndications = EFI_OS_INDICATIONS_BOOT_TO_FW_UI; + } + Status = gRT->SetVariable ( + EFI_OS_INDICATIONS_VARIABLE_NAME, &gEfiGlobalVariableGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + sizeof (OsIndications), &OsIndications + ); + } + } + if (EFI_ERROR (Status)) { + ShellStatus = SHELL_UNSUPPORTED; + goto Error; + } + } + + // + // check for warm reset flag, then shutdown reset flag, then cold (default) reset flag + // + if (ShellCommandLineGetFlag(Package, L"-w")) { + if (ShellCommandLineGetFlag(Package, L"-s") || ShellCommandLineGetFlag(Package, L"-c")) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"reset"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + 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); + } + } + } else if (ShellCommandLineGetFlag(Package, L"-s")) { + if (ShellCommandLineGetFlag(Package, L"-c")) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"reset"); + 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"-c"); + if (String != NULL) { + gRT->ResetSystem(EfiResetCold, EFI_SUCCESS, StrSize(String), (VOID*)String); + } else { + gRT->ResetSystem(EfiResetCold, 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... + // + +Error: + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + + // + // return the status + // + return (ShellStatus); +} + diff --git a/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Rm.c b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Rm.c new file mode 100644 index 0000000000..618610d0f3 --- /dev/null +++ b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Rm.c @@ -0,0 +1,379 @@ +/** @file + Main file for attrib shell level 2 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
+ Copyright (c) 2009 - 2015, 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} + }; + +/** + Determine if a directory has no files in it. + + @param[in] FileHandle The EFI_HANDLE to the directory. + + @retval TRUE The directory has no files (or directories). + @retval FALSE The directory has at least 1 file or directory in it. +**/ +BOOLEAN +IsDirectoryEmpty ( + IN EFI_HANDLE FileHandle + ) +{ + EFI_FILE_INFO *FileInfo; + BOOLEAN NoFile; + BOOLEAN RetVal; + + RetVal = TRUE; + NoFile = FALSE; + FileInfo = NULL; + + for (FileHandleFindFirstFile(FileHandle, &FileInfo) + ; !NoFile + ; FileHandleFindNextFile(FileHandle, FileInfo, &NoFile) + ){ + if (StrStr(FileInfo->FileName, L".") != FileInfo->FileName + &&StrStr(FileInfo->FileName, L"..") != FileInfo->FileName) { + RetVal = FALSE; + } + } + return (RetVal); +} + +/** + Delete a node and all nodes under it (including sub directories). + + @param[in] Node The node to start deleting with. + @param[in] Quiet TRUE to print no messages. + + @retval SHELL_SUCCESS The operation was successful. + @retval SHELL_ACCESS_DENIED A file was read only. + @retval SHELL_ABORTED The abort message was received. + @retval SHELL_DEVICE_ERROR A device error occured reading this Node. +**/ +SHELL_STATUS +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; + CHAR16 *TempName; + UINTN NewSize; + + 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, L"rm", 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(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); + if (EFI_ERROR(Node2->Status) && StrStr(Node2->FileName, L":") == NULL) { + // + // Update the node filename to have full path with file system identifier + // + NewSize = StrSize(Node->FullName) + StrSize(Node2->FullName); + TempName = AllocateZeroPool(NewSize); + if (TempName == NULL) { + ShellStatus = SHELL_OUT_OF_RESOURCES; + } else { + StrCpyS(TempName, NewSize/sizeof(CHAR16), Node->FullName); + TempName[StrStr(TempName, L":")+1-TempName] = CHAR_NULL; + StrCatS(TempName, NewSize/sizeof(CHAR16), Node2->FullName); + FreePool((VOID*)Node2->FullName); + Node2->FullName = TempName; + + // + // Now try again to open the file + // + Node2->Status = gEfiShellProtocol->OpenFileByName (Node2->FullName, &Node2->Handle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE); + } + } + if (!EFI_ERROR(Node2->Status)) { + ShellStatus = CascadeDelete(Node2, Quiet); + } else if (ShellStatus == SHELL_SUCCESS) { + ShellStatus = (SHELL_STATUS)(Node2->Status&(~0x80000000)); + } + 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... + // + if (!Quiet) { + 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! (Dont use EFI_ERROR Macro). + // + if (Status != EFI_SUCCESS){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_RM_LOG_DELETE_ERR), gShellLevel2HiiHandle, Status); + return (SHELL_ACCESS_DENIED); + } else { + if (!Quiet) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_RM_LOG_DELETE_COMP), gShellLevel2HiiHandle); + } + return (SHELL_SUCCESS); + } +} + +/** + Determines if a Node is a valid delete target. Will prevent deleting the root directory. + + @param[in] List RESERVED. Not used. + @param[in] Node The node to analyze. + @param[in] Package RESERVED. Not used. +**/ +BOOLEAN +IsValidDeleteTarget( + IN CONST EFI_SHELL_FILE_INFO *List, + IN CONST EFI_SHELL_FILE_INFO *Node, + IN CONST LIST_ENTRY *Package + ) +{ + CONST CHAR16 *TempLocation; + BOOLEAN RetVal; + CHAR16 *SearchString; + CHAR16 *Pattern; + UINTN Size; + + if (Node == NULL || Node->FullName == NULL) { + return (FALSE); + } + + TempLocation = StrStr(Node->FullName, L":"); + if (StrLen(TempLocation) <= 2) { + // + // Deleting the root directory is invalid. + // + return (FALSE); + } + + TempLocation = ShellGetCurrentDir(NULL); + if (TempLocation == NULL) { + // + // No working directory is specified so whatever is left is ok. + // + return (TRUE); + } + + Pattern = NULL; + SearchString = NULL; + Size = 0; + Pattern = StrnCatGrow(&Pattern, &Size, TempLocation , 0); + Pattern = StrnCatGrow(&Pattern, &Size, L"\\" , 0); + Size = 0; + SearchString = StrnCatGrow(&SearchString, &Size, Node->FullName, 0); + if (!EFI_ERROR(ShellIsDirectory(SearchString))) { + SearchString = StrnCatGrow(&SearchString, &Size, L"\\", 0); + SearchString = StrnCatGrow(&SearchString, &Size, L"*", 0); + } + + if (Pattern == NULL || SearchString == NULL) { + RetVal = FALSE; + } else { + RetVal = TRUE; + if (gUnicodeCollation->MetaiMatch(gUnicodeCollation, Pattern, SearchString)) { + RetVal = FALSE; + } + } + + SHELL_FREE_NON_NULL(Pattern ); + SHELL_FREE_NON_NULL(SearchString); + + return (RetVal); +} + +/** + 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, L"rm", 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, L"rm"); + 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, L"rm", (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/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Set.c b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Set.c new file mode 100644 index 0000000000..7ca19427d5 --- /dev/null +++ b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Set.c @@ -0,0 +1,174 @@ +/** @file + Main file for attrib shell level 2 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
+ Copyright (c) 2009 - 2015, 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 +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, L"set", 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, L"set"); + 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, L"set"); + 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"set", 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, L"set", KeyName); + 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")); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SET_ERROR_SET), gShellLevel2HiiHandle, L"set", KeyName); + ShellStatus = (SHELL_STATUS) (Status & (~MAX_BIT)); + } + + } 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, L"set", 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/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/TimeDate.c b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/TimeDate.c new file mode 100644 index 0000000000..5383cffe87 --- /dev/null +++ b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/TimeDate.c @@ -0,0 +1,972 @@ +/** @file + Main file for time, timezone, and date shell level 2 and shell level 3 functions. + + (C) Copyright 2012-2015 Hewlett-Packard Development Company, L.P.
+ Copyright (c) 2009 - 2014, 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" + +/** + Determine if String is a valid representation for a time or date. + + @param[in] String The pointer to the string to test. + @param[in] Char The delimeter character. + @param[in] Min The minimum value allowed. + @param[in] Max The maximum value allowed. + @param[in] MinusOk Whether negative numbers are permitted. + + @retval TRUE String is a valid representation. + @retval FALSE String is invalid. +**/ +BOOLEAN +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); +} + +/** + Verify that the DateString is valid and if so set that as the current + date. + + @param[in] DateString The pointer to a string representation of the date. + + @retval SHELL_INVALID_PARAMETER DateString was NULL. + @retval SHELL_INVALID_PARAMETER DateString was mis-formatted. + @retval SHELL_SUCCESS The operation was successful. +**/ +SHELL_STATUS +CheckAndSetDate ( + IN CONST CHAR16 *DateString + ) +{ + EFI_TIME TheTime; + EFI_STATUS Status; + CHAR16 *DateStringCopy; + CHAR16 *Walker; + CHAR16 *Walker1; + + if (!InternalIsTimeLikeString(DateString, L'/', 2, 2, FALSE)) { + return (SHELL_INVALID_PARAMETER); + } + + Status = gRT->GetTime(&TheTime, NULL); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_WARN), gShellLevel2HiiHandle, L"date", L"gRT->GetTime", Status); + return (SHELL_DEVICE_ERROR); + } + + DateStringCopy = NULL; + DateStringCopy = StrnCatGrow(&DateStringCopy, NULL, DateString, 0); + if (DateStringCopy == NULL) { + return (SHELL_OUT_OF_RESOURCES); + } + Walker = DateStringCopy; + + TheTime.Month = 0xFF; + TheTime.Day = 0xFF; + TheTime.Year = 0xFFFF; + + Walker1 = StrStr(Walker, L"/"); + if (Walker1 != NULL && *Walker1 == L'/') { + *Walker1 = CHAR_NULL; + } + + TheTime.Month = (UINT8)ShellStrToUintn (Walker); + if (Walker1 != NULL) { + Walker = Walker1 + 1; + } + Walker1 = Walker!=NULL?StrStr(Walker, L"/"):NULL; + if (Walker1 != NULL && *Walker1 == L'/') { + *Walker1 = CHAR_NULL; + } + if (Walker != NULL && Walker[0] != CHAR_NULL) { + TheTime.Day = (UINT8)ShellStrToUintn (Walker); + if (Walker1 != NULL) { + Walker = Walker1 + 1; + } + Walker1 = Walker!=NULL?StrStr(Walker, L"/"):NULL; + if (Walker1 != NULL && *Walker1 == L'/') { + *Walker1 = CHAR_NULL; + } + if (Walker != NULL && Walker[0] != CHAR_NULL) { + TheTime.Year = (UINT16)ShellStrToUintn (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; + CONST CHAR16 *Param1; + + 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, L"date", 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, L"date"); + 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); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_WARN), gShellLevel2HiiHandle, L"date", L"gRT->GetTime", Status); + return (SHELL_DEVICE_ERROR); + } + + // + // ShellPrintEx the date in SFO or regular format + // + if (ShellCommandLineGetFlag(Package, L"-sfo")) { + // + // Match UEFI Shell spec: + // ShellCommand,"date" + // Date,"DD","MM","YYYY" + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_SFO_HEADER), gShellLevel2HiiHandle, L"date"); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DATE_SFO_FORMAT), gShellLevel2HiiHandle, TheTime.Day, TheTime.Month, 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, L"date"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // perform level 3 operation here. + // + Param1 = ShellCommandLineGetRawValue(Package, 1); + if (Param1 == NULL) { + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ShellStatus = CheckAndSetDate(Param1); + } + if (ShellStatus != SHELL_SUCCESS) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"date", Param1); + 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} + }; + +/** + Verify that the TimeString is valid and if so set that as the current + time. + + @param[in] TimeString The pointer to a string representation of the time. + @param[in] Tz The value to set for TimeZone. + @param[in] Daylight The value to set for Daylight. + + @retval SHELL_INVALID_PARAMETER TimeString was NULL. + @retval SHELL_INVALID_PARAMETER TimeString was mis-formatted. + @retval SHELL_SUCCESS The operation was successful. +**/ +SHELL_STATUS +CheckAndSetTime ( + IN CONST CHAR16 *TimeString, + IN CONST INT16 Tz, + IN CONST UINT8 Daylight + ) +{ + EFI_TIME TheTime; + EFI_STATUS Status; + CHAR16 *TimeStringCopy; + CHAR16 *Walker1; + CHAR16 *Walker2; + + if (TimeString != NULL && !InternalIsTimeLikeString(TimeString, L':', 1, 2, FALSE)) { + return (SHELL_INVALID_PARAMETER); + } + if (Daylight != 0xFF &&((Daylight & (EFI_TIME_IN_DAYLIGHT|EFI_TIME_ADJUST_DAYLIGHT)) != Daylight)) { + return (SHELL_INVALID_PARAMETER); + } + + Status = gRT->GetTime(&TheTime, NULL); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_WARN), gShellLevel2HiiHandle, L"time", L"gRT->GetTime", Status); + return (SHELL_DEVICE_ERROR); + } + + if (TimeString != NULL) { + TimeStringCopy = NULL; + TimeStringCopy = StrnCatGrow(&TimeStringCopy, NULL, TimeString, 0); + Walker1 = TimeStringCopy; + TheTime.Hour = 0xFF; + TheTime.Minute = 0xFF; + + Walker2 = Walker1!=NULL?StrStr(Walker1, L":"):NULL; + if (Walker2 != NULL && *Walker2 == L':') { + *Walker2 = CHAR_NULL; + } + TheTime.Hour = (UINT8)ShellStrToUintn (Walker1); + if (Walker2 != NULL) { + Walker1 = Walker2 + 1; + } + Walker2 = Walker1!=NULL?StrStr(Walker1, L":"):NULL; + if (Walker2 != NULL && *Walker2 == L':') { + *Walker2 = CHAR_NULL; + TheTime.Second = (UINT8)0; + } + else if (Walker2 == NULL) { + TheTime.Second = (UINT8)0; + } + if (Walker1 != NULL && Walker1[0] != CHAR_NULL) { + TheTime.Minute = (UINT8)ShellStrToUintn (Walker1); + if (Walker2 != NULL) { + Walker1 = Walker2 + 1; + if (Walker1 != NULL && Walker1[0] != CHAR_NULL) { + TheTime.Second = (UINT8)ShellStrToUintn (Walker1); + } + } + } + SHELL_FREE_NON_NULL(TimeStringCopy); + } + + + if (Tz >= -1440 && Tz <= 1440) { + // + // EFI_TIME TimeZone is stored to meet the following calculation (see UEFI Spec): + // Localtime = UTC - TimeZone + // This means the sign must be changed for the user provided Tz. + // EX: User wants to set TimeZone to Pacific Standard Time, so runs + // time -tz -480 # set to UTC-08:00 + // To meet the calculation, the sign must be changed. + // + TheTime.TimeZone = -Tz; + } else if (Tz == EFI_UNSPECIFIED_TIMEZONE) { + TheTime.TimeZone = Tz; + } + + if (Daylight != 0xFF) { + 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; + EFI_TIME TheTime; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + INT16 Tz; + UINT8 Daylight; + CONST CHAR16 *TempLocation; + UINTN TzMinutes; + + // + // Initialize variables + // + 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 = 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, L"time", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + // + // check for "-?" + // + Status = gRT->GetTime(&TheTime, NULL); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_WARN), gShellLevel2HiiHandle, L"time", L"gRT->GetTime", Status); + return (SHELL_DEVICE_ERROR); + } + + if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } else if (ShellCommandLineGetRawValue(Package, 2) != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"time"); + 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 == EFI_UNSPECIFIED_TIMEZONE) { + TzMinutes = 0; + } else { + TzMinutes = (ABS(TheTime.TimeZone)) % 60; + } + + if (TheTime.TimeZone != EFI_UNSPECIFIED_TIMEZONE) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_TIME_FORMAT), + gShellLevel2HiiHandle, + TheTime.Hour, + TheTime.Minute, + TheTime.Second, + (TheTime.TimeZone > 0?L"-":L"+"), + ((ABS(TheTime.TimeZone)) / 60), + TzMinutes + ); + } else { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_TIME_FORMAT_LOCAL), + gShellLevel2HiiHandle, + TheTime.Hour, + TheTime.Minute, + TheTime.Second + ); + } + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_CRLF), gShellLevel2HiiHandle); + } else if (ShellCommandLineGetFlag(Package, L"-d") && ShellCommandLineGetValue(Package, L"-d") == NULL) { + if (TheTime.TimeZone == EFI_UNSPECIFIED_TIMEZONE) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_TIME_FORMAT_LOCAL), + gShellLevel2HiiHandle, + TheTime.Hour, + TheTime.Minute, + TheTime.Second + ); + } else { + TzMinutes = (ABS(TheTime.TimeZone)) % 60; + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_TIME_FORMAT), + gShellLevel2HiiHandle, + TheTime.Hour, + TheTime.Minute, + TheTime.Second, + (TheTime.TimeZone > 0?L"-":L"+"), + ((ABS(TheTime.TimeZone)) / 60), + TzMinutes + ); + } + switch (TheTime.Daylight) { + case 0: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TIME_DST0), gShellLevel2HiiHandle); + break; + case EFI_TIME_ADJUST_DAYLIGHT: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TIME_DST1), gShellLevel2HiiHandle); + break; + case EFI_TIME_IN_DAYLIGHT: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TIME_DST2), gShellLevel2HiiHandle); + break; + case EFI_TIME_IN_DAYLIGHT|EFI_TIME_ADJUST_DAYLIGHT: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TIME_DST3), gShellLevel2HiiHandle); + break; + default: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_ERROR), gShellLevel2HiiHandle, L"time", L"gRT->GetTime", L"TheTime.Daylight", TheTime.Daylight); + } + } else { + if (PcdGet8(PcdShellSupportLevel) == 2) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"time"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // perform level 3 operation here. + // + if ((TempLocation = ShellCommandLineGetValue(Package, L"-tz")) != NULL) { + if (StrniCmp (TempLocation, L"_local", StrLen (TempLocation)) == NULL) { + Tz = EFI_UNSPECIFIED_TIMEZONE; + } else if (TempLocation[0] == L'-') { + + Tz = (INT16) ShellStrToUintn (++TempLocation); + // + // When the argument of "time [-tz tz]" is not numeric, ShellStrToUintn() returns "-1". + // Here we can detect the argument error by checking the return of ShellStrToUintn(). + // + if (Tz == -1) { + Tz = 1441; //make it to be out of bounds value + } else { + Tz *= (-1); //sign convert + } + } else { + if (TempLocation[0] == L'+') { + Tz = (INT16)ShellStrToUintn (++TempLocation); + } else { + Tz = (INT16)ShellStrToUintn (TempLocation); + } + // + // Detect the return of ShellStrToUintn() to make sure the argument is valid. + // + if (Tz == -1) { + Tz = 1441; //make it to be out of bounds value + } + } + if (!(Tz >= -1440 && Tz <= 1440) && Tz != EFI_UNSPECIFIED_TIMEZONE) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellLevel2HiiHandle, L"time", TempLocation, L"-tz"); + 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)ShellStrToUintn(TempLocation); + // + // The argument of "time [-d dl]" is unsigned, if the first character is '-', + // the argument is incorrect. That's because ShellStrToUintn() will skip past + // any '-' sign and convert what's next, forgetting the sign is here. + // + if (TempLocation[0] == '-') { + Daylight = 0xff; //make it invalid = will not use + } + if (Daylight != 0 && Daylight != 1 && Daylight != 3) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellLevel2HiiHandle, L"time", TempLocation, 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_PARAM_INV), gShellLevel2HiiHandle, L"time", 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", TypeTimeValue}, + {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)}, + {EFI_UNSPECIFIED_TIMEZONE, STRING_TOKEN (STR_TIMEZONE_LOCAL)} +}; + +/** + Verify that the TimeZoneString is valid and if so set that as the current + timezone. + + @param[in] TimeZoneString The pointer to a string representation of the timezone. + + @retval SHELL_INVALID_PARAMETER TimeZoneString was NULL. + @retval SHELL_INVALID_PARAMETER TimeZoneString was mis-formatted. + @retval SHELL_SUCCESS The operation was successful. +**/ +SHELL_STATUS +CheckAndSetTimeZone ( + IN CONST CHAR16 *TimeZoneString + ) +{ + EFI_TIME TheTime; + EFI_STATUS Status; + CHAR16 *TimeZoneCopy; + CHAR16 *Walker; + CHAR16 *Walker2; + UINTN LoopVar; + + if (TimeZoneString == NULL) { + return (SHELL_INVALID_PARAMETER); + } + + if (StrniCmp (TimeZoneString, L"_local", StrLen (TimeZoneString)) == NULL) { + Status = gRT->GetTime (&TheTime, NULL); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_WARN), gShellLevel2HiiHandle, L"gRT->GetTime", Status); + return (SHELL_DEVICE_ERROR); + } + + TheTime.TimeZone = EFI_UNSPECIFIED_TIMEZONE; + Status = gRT->SetTime (&TheTime); + if (!EFI_ERROR(Status)){ + return (SHELL_SUCCESS); + } + return (SHELL_INVALID_PARAMETER); + } + if (TimeZoneString != NULL && !InternalIsTimeLikeString(TimeZoneString, L':', 1, 1, TRUE)) { + return (SHELL_INVALID_PARAMETER); + } + + Status = gRT->GetTime(&TheTime, NULL); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_WARN), gShellLevel2HiiHandle, L"timezone", L"gRT->GetTime", Status); + return (SHELL_DEVICE_ERROR); + } + + TimeZoneCopy = NULL; + TimeZoneCopy = StrnCatGrow(&TimeZoneCopy, NULL, TimeZoneString, 0); + if (TimeZoneCopy == NULL) { + return (SHELL_OUT_OF_RESOURCES); + } + Walker = TimeZoneCopy; + Walker2 = StrStr(Walker, L":"); + if (Walker2 != NULL && *Walker2 == L':') { + *Walker2 = CHAR_NULL; + } + if (*Walker == L'-') { + TheTime.TimeZone = (INT16)((ShellStrToUintn (++Walker)) * 60); + } else { + TheTime.TimeZone = (INT16)((INT16)(ShellStrToUintn (Walker)) * -60); + } + if (Walker2 != NULL) { + Walker = Walker2 + 1; + } + if (Walker != NULL && Walker[0] != CHAR_NULL) { + if (TheTime.TimeZone < 0) { + TheTime.TimeZone = (INT16)(TheTime.TimeZone - (UINT8)ShellStrToUintn (Walker)); + } else { + TheTime.TimeZone = (INT16)(TheTime.TimeZone + (UINT8)ShellStrToUintn (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; + } + } + + FreePool(TimeZoneCopy); + + 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, TRUE); + } else { + ASSERT(PcdGet8(PcdShellSupportLevel) == 3); + Status = ShellCommandLineParseEx (TimeZoneParamList3, &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, L"timezone", 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, L"timezone"); + 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_PARAM_INV), gShellLevel2HiiHandle, L"timezone", 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"timezone", 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_PARAM_INV), gShellLevel2HiiHandle, L"timezone", 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); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_WARN), gShellLevel2HiiHandle, L"timezone", L"gRT->GetTime", Status); + return (SHELL_DEVICE_ERROR); + } + + if (TheTime.TimeZone != EFI_UNSPECIFIED_TIMEZONE) { + 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 + // + TzMinutes = (ABS(TheTime.TimeZone)) % 60; + + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN(STR_TIMEZONE_SIMPLE), + gShellLevel2HiiHandle, + (TheTime.TimeZone > 0?L"-":L"+"), + (ABS(TheTime.TimeZone)) / 60, + TzMinutes); + } + Found = TRUE; + break; + } + } + if (!Found) { + // + // Print basic info only + // + TzMinutes = (ABS(TheTime.TimeZone)) % 60; + + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN(STR_TIMEZONE_SIMPLE), + gShellLevel2HiiHandle, + (TheTime.TimeZone > 0?L"-":L"+"), + (ABS(TheTime.TimeZone)) / 60, + TzMinutes); + + if (ShellCommandLineGetFlag(Package, L"-f")) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN(STR_TIMEZONE_NI), gShellLevel2HiiHandle); + } + } + } else { + // + // TimeZone was EFI_UNSPECIFIED_TIMEZONE (local) from GetTime() + // + if (ShellCommandLineGetFlag (Package, L"-f")) { + for ( LoopVar = 0 + ; LoopVar < ARRAY_SIZE (TimeZoneList) + ; LoopVar++ + ){ + if (TheTime.TimeZone == TimeZoneList[LoopVar].TimeZone) { + // + // Print all info about current time zone + // + ShellPrintHiiEx (-1, -1, NULL, TimeZoneList[LoopVar].StringId, gShellLevel2HiiHandle); + break; + } + } + } else { + // + // Print basic info only + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_TIMEZONE_SIMPLE_LOCAL), gShellLevel2HiiHandle); + } + } + } + } + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + + return (ShellStatus); +} diff --git a/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.c b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.c new file mode 100644 index 0000000000..7948e53cfc --- /dev/null +++ b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.c @@ -0,0 +1,346 @@ +/** @file + Main file for NULL named library for level 2 shell command functions. + + these functions are: + attrib, + cd, + cp, + date*, + time*, + load, + ls, + map, + mkdir, + mv, + parse, + rm, + reset, + set, + timezone*, + vol + + * functions are non-interactive only + + Copyright (c) 2014 Hewlett-Packard Development Company, L.P. + Copyright (c) 2009 - 2015, 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; + +/** + Get the filename to get help text from if not using HII. + + @retval The filename. +**/ +CONST CHAR16* +EFIAPI +ShellCommandGetManFileNameLevel2 ( + VOID + ) +{ + return (mFileName); +} + +/** + Constructor for the Shell Level 2 Commands library. + + Install the handlers for level 2 UEFI Shell 2.0 commands. + + @param ImageHandle the image handle of the process + @param SystemTable the EFI System Table pointer + + @retval EFI_SUCCESS the shell command handlers were installed sucessfully + @retval EFI_UNSUPPORTED the shell level required was not found. +**/ +EFI_STATUS +EFIAPI +ShellLevel2CommandsLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + // + // if shell level is less than 2 do nothing + // + if (PcdGet8(PcdShellSupportLevel) < 2) { + return (EFI_SUCCESS); + } + + gShellLevel2HiiHandle = HiiAddPackages (&gShellLevel2HiiGuid, gImageHandle, UefiShellLevel2CommandsLibStrings, NULL); + if (gShellLevel2HiiHandle == NULL) { + return (EFI_DEVICE_ERROR); + } + + // + // install our shell command handlers that are always installed + // + ShellCommandRegisterCommandName(L"attrib", ShellCommandRunAttrib , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_ATTRIB) ); + ShellCommandRegisterCommandName(L"cd", ShellCommandRunCd , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_CD) ); + ShellCommandRegisterCommandName(L"cp", ShellCommandRunCp , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_CP) ); + ShellCommandRegisterCommandName(L"load", ShellCommandRunLoad , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_LOAD) ); + ShellCommandRegisterCommandName(L"map", ShellCommandRunMap , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_MAP) ); + ShellCommandRegisterCommandName(L"mkdir", ShellCommandRunMkDir , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_MKDIR) ); + ShellCommandRegisterCommandName(L"mv", ShellCommandRunMv , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_MV) ); + ShellCommandRegisterCommandName(L"parse", ShellCommandRunParse , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_PARSE) ); + ShellCommandRegisterCommandName(L"reset", ShellCommandRunReset , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_RESET) ); + ShellCommandRegisterCommandName(L"set", ShellCommandRunSet , ShellCommandGetManFileNameLevel2, 2, L"",FALSE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_SET) ); + ShellCommandRegisterCommandName(L"ls", ShellCommandRunLs , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_LS) ); + ShellCommandRegisterCommandName(L"rm", ShellCommandRunRm , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_RM) ); + ShellCommandRegisterCommandName(L"vol", ShellCommandRunVol , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_VOL) ); + + // + // support for permanent (built in) aliases + // + ShellCommandRegisterAlias(L"rm", L"del"); + ShellCommandRegisterAlias(L"ls", L"dir"); + ShellCommandRegisterAlias(L"cp", L"copy"); + ShellCommandRegisterAlias(L"mkdir", L"md"); + ShellCommandRegisterAlias(L"cd ..", L"cd.."); + ShellCommandRegisterAlias(L"cd \\", L"cd\\"); + ShellCommandRegisterAlias(L"mv", L"ren"); + ShellCommandRegisterAlias(L"mv", L"move"); + ShellCommandRegisterAlias(L"map", L"mount"); + // + // These are installed in level 2 or 3... + // + if (PcdGet8(PcdShellSupportLevel) == 2 || PcdGet8(PcdShellSupportLevel) == 3) { + ShellCommandRegisterCommandName(L"date", ShellCommandRunDate , ShellCommandGetManFileNameLevel2, PcdGet8(PcdShellSupportLevel), L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_DATE) ); + ShellCommandRegisterCommandName(L"time", ShellCommandRunTime , ShellCommandGetManFileNameLevel2, PcdGet8(PcdShellSupportLevel), L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_TIME) ); + ShellCommandRegisterCommandName(L"timezone", ShellCommandRunTimeZone, ShellCommandGetManFileNameLevel2, PcdGet8(PcdShellSupportLevel), L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_TIMEZONE)); + } else { + DEBUG_CODE_BEGIN(); + // + // we want to be able to test these so install them under a different name in debug mode... + // + ShellCommandRegisterCommandName(L"l2date", ShellCommandRunDate , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_DATE) ); + ShellCommandRegisterCommandName(L"l2time", ShellCommandRunTime , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_TIME) ); + ShellCommandRegisterCommandName(L"l2timezone", ShellCommandRunTimeZone, ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_TIMEZONE)); + DEBUG_CODE_END(); + } + + return (EFI_SUCCESS); +} + +/** + Destructor for the library. free any resources. + + @param ImageHandle The image handle of the process. + @param SystemTable The EFI System Table pointer. + + @retval EFI_SUCCESS Always returned. +**/ +EFI_STATUS +EFIAPI +ShellLevel2CommandsLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + if (gShellLevel2HiiHandle != NULL) { + HiiRemovePackages(gShellLevel2HiiHandle); + } + return (EFI_SUCCESS); +} + +/** + returns a fully qualified directory (contains a map drive at the begining) + path from a unknown directory path. + + If Path is already fully qualified this will return a duplicat otherwise this + will use get the current directory and use that to build the fully qualified + version. + + if the return value is not NULL it must be caller freed. + + @param[in] Path The unknown Path Value + + @retval NULL A memory allocation failed + @retval NULL A fully qualified path could not be discovered. + @retval other An allocated pointer to a fuly qualified path. +**/ +CHAR16* +GetFullyQualifiedPath( + IN CONST CHAR16* Path + ) +{ + CHAR16 *PathToReturn; + UINTN Size; + CONST CHAR16 *CurDir; + + PathToReturn = NULL; + Size = 0; + + ASSERT((PathToReturn == NULL && Size == 0) || (PathToReturn != NULL)); + // + // convert a local path to an absolute path + // + if (StrStr(Path, L":") == NULL) { + CurDir = gEfiShellProtocol->GetCurDir(NULL); + StrnCatGrow(&PathToReturn, &Size, CurDir, 0); + StrnCatGrow(&PathToReturn, &Size, L"\\", 0); + if (*Path == L'\\') { + Path++; + } + } + StrnCatGrow(&PathToReturn, &Size, Path, 0); + + PathCleanUpDirectories(PathToReturn); + + if (PathToReturn == NULL) { + return NULL; + } + + while (PathToReturn[StrLen(PathToReturn)-1] == L'*') { + PathToReturn[StrLen(PathToReturn)-1] = CHAR_NULL; + } + + return (PathToReturn); +} + +/** + Function to verify all intermediate directories in the path. + + @param[in] Path The pointer to the path to fix. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +VerifyIntermediateDirectories ( + IN CONST CHAR16 *Path + ) +{ + EFI_STATUS Status; + CHAR16 *PathCopy; + CHAR16 *TempSpot; + SHELL_FILE_HANDLE FileHandle; + + ASSERT(Path != NULL); + + Status = EFI_SUCCESS; + PathCopy = NULL; + PathCopy = StrnCatGrow(&PathCopy, NULL, Path, 0); + FileHandle = NULL; + + if (PathCopy == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + + for (TempSpot = &PathCopy[StrLen(PathCopy)-1] ; *TempSpot != CHAR_NULL && *TempSpot != L'\\' ; TempSpot = &PathCopy[StrLen(PathCopy)-1]){ + *TempSpot = CHAR_NULL; + } + if (*TempSpot == L'\\') { + *TempSpot = CHAR_NULL; + } + + if (PathCopy != NULL && *PathCopy != CHAR_NULL) { + Status = VerifyIntermediateDirectories(PathCopy); + + if (PathCopy[StrLen(PathCopy)-1] != L':') { + if (!EFI_ERROR(Status)) { + Status = ShellOpenFileByName(PathCopy, &FileHandle, EFI_FILE_MODE_READ, 0); + if (FileHandle != NULL) { + ShellCloseFile(&FileHandle); + } + } + } + } + + SHELL_FREE_NON_NULL(PathCopy); + + return (Status); +} + +/** + Be lazy and borrow from baselib. + + @param[in] Char The character to convert to upper case. + + @return Char as an upper case character. +**/ +CHAR16 +InternalCharToUpper ( + IN CONST CHAR16 Char + ); + +/** + String comparison without regard to case for a limited number of characters. + + @param[in] Source The first item to compare. + @param[in] Target The second item to compare. + @param[in] Count How many characters to compare. + + @retval NULL Source and Target are identical strings without regard to case. + @return The location in Source where there is a difference. +**/ +CONST CHAR16* +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); +} + + +/** + Cleans off all the quotes in the string. + + @param[in] OriginalString pointer to the string to be cleaned. + @param[out] CleanString The new string with all quotes removed. + Memory allocated in the function and free + by caller. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ShellLevel2StripQuotes ( + IN CONST CHAR16 *OriginalString, + OUT CHAR16 **CleanString + ) +{ + CHAR16 *Walker; + + if (OriginalString == NULL || CleanString == NULL) { + return EFI_INVALID_PARAMETER; + } + + *CleanString = AllocateCopyPool (StrSize (OriginalString), OriginalString); + if (*CleanString == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + for (Walker = *CleanString; Walker != NULL && *Walker != CHAR_NULL ; Walker++) { + if (*Walker == L'\"') { + CopyMem(Walker, Walker+1, StrSize(Walker) - sizeof(Walker[0])); + } + } + + return EFI_SUCCESS; +} + + diff --git a/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.h b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.h new file mode 100644 index 0000000000..857487fd80 --- /dev/null +++ b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.h @@ -0,0 +1,368 @@ +/** @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 - 2016, 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. + +**/ + +#ifndef _UEFI_SHELL_LEVEL2_COMMANDS_LIB_H_ +#define _UEFI_SHELL_LEVEL2_COMMANDS_LIB_H_ + +#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; + +/** + 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* +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 +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* +StrniCmp( + IN CONST CHAR16 *Source, + IN CONST CHAR16 *Target, + IN CONST UINTN Count + ); + +/** + Cleans off all the quotes in the string. + + @param[in] OriginalString pointer to the string to be cleaned. + @param[out] CleanString The new string with all quotes removed. + Memory allocated in the function and free + by caller. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ShellLevel2StripQuotes ( + IN CONST CHAR16 *OriginalString, + OUT CHAR16 **CleanString + ); + +/** + Function for 'Vol' 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 +ShellCommandRunVol ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + 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 + @param[in] CmdName Source command name requesting single file copy + + @retval SHELL_SUCCESS The source file was copied to the destination +**/ +SHELL_STATUS +CopySingleFile( + IN CONST CHAR16 *Source, + IN CONST CHAR16 *Dest, + OUT VOID **Resp, + IN BOOLEAN SilentMode, + IN CONST CHAR16 *CmdName + ); + +/** + Delete a node and all nodes under it (including sub directories). + + @param[in] Node The node to start deleting with. + @param[in] Quiet TRUE to print no messages. + + @retval SHELL_SUCCESS The operation was successful. + @retval SHELL_ACCESS_DENIED A file was read only. + @retval SHELL_ABORTED The abort message was received. + @retval SHELL_DEVICE_ERROR A device error occured reading this Node. +**/ +SHELL_STATUS +CascadeDelete( + IN EFI_SHELL_FILE_INFO *Node, + IN CONST BOOLEAN Quiet + ); + +#endif + diff --git a/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf new file mode 100644 index 0000000000..16faad2d2d --- /dev/null +++ b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf @@ -0,0 +1,84 @@ +## @file +# Provides shell level 2 functions +# +# Copyright (c) 2009 - 2015, 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_APPLICATION + 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 + Vol.c + +[Packages] + MdePkg/MdePkg.dec + ShellPkg/ShellPkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + MemoryAllocationLib + BaseLib + BaseMemoryLib + DebugLib + ShellCommandLib + ShellLib + UefiLib + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + PcdLib + HiiLib + HandleParsingLib + DevicePathLib + +[Protocols] + gEfiUnicodeCollation2ProtocolGuid ## CONSUMES + gEfiShellProtocolGuid ## CONSUMES + gEfiShellParametersProtocolGuid ## CONSUMES + gEfiDevicePathProtocolGuid ## CONSUMES + gEfiLoadedImageProtocolGuid ## CONSUMES + gEfiSimpleFileSystemProtocolGuid ## SOMETIMES_CONSUMES + +[Pcd.common] + gEfiShellPkgTokenSpaceGuid.PcdShellSupportLevel ## CONSUMES + gEfiShellPkgTokenSpaceGuid.PcdShellFileOperationSize ## CONSUMES + +[Guids] + gEfiFileSystemInfoGuid ## SOMETIMES_CONSUMES ## GUID + gEfiFileInfoGuid ## UNDEFINED + gShellLevel2HiiGuid ## SOMETIMES_CONSUMES ## HII diff --git a/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.uni b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.uni new file mode 100644 index 0000000000..60f48f4633 --- /dev/null +++ b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.uni @@ -0,0 +1,1088 @@ +// /** +// +// (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.
+// Copyright (c) 2009 - 2015, 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. +// +// Module Name: +// +// UefiShellLevel2CommandsLib.uni +// +// Abstract: +// +// String definitions for UEFI Shell 2.0 level 2 commands +// +// +// **/ + +/=# + +#langdef en-US "english" + +#string STR_GEN_NO_MEM #language en-US "%H%s%N: Memory is not available.\r\n" +#string STR_GEN_TOO_MANY #language en-US "%H%s%N: Too many arguments.\r\n" +#string STR_GEN_TOO_FEW #language en-US "%H%s%N: Too few arguments.\r\n" +#string STR_GEN_PARAM_INV #language en-US "%H%s%N: Invalid argument - '%H%s%N'\r\n" +#string STR_GEN_PROBLEM #language en-US "%H%s%N: Unknown flag - '%H%s%N'\r\n" +#string STR_GEN_PROBLEM_VAL #language en-US "%H%s%N: Bad value - '%H%s%N' for flag - '%H%s%N'\r\n" +#string STR_GEN_ATTRIBUTE #language en-US "%H%s%N: Invalid argument - '%H-a%s%N'\r\n" +#string STR_GEN_NO_VALUE #language en-US "%H%s%N: Missing argument for flag - '%H%s%N'\r\n" +#string STR_GEN_ERR_AD #language en-US "%H%s%N: Access denied.\r\n" +#string STR_GEN_ERR_FILE #language en-US "%H%s%N: File '%H%s%N' error - %r\r\n" +#string STR_GEN_ERR_UK #language en-US "%H%s%N: Status: %r\r\n" +#string STR_GEN_PARAM_CON #language en-US "%H%s%N: Parameters conflict.\r\n" +#string STR_GEN_PARAM_CONFLICT #language en-US "%H%s%N: Flags conflict with - '%H%s%N' and '%H%s%N'\r\n" +#string STR_GEN_FILE_OPEN_FAIL #language en-US "%H%s%N: Cannot open file - '%H%s%N'\r\n" +#string STR_GEN_FILE_CLOSE_FAIL #language en-US "%H%s%N: Cannot close file - '%H%s%N'\r\n" +#string STR_GEN_FILE_AD #language en-US "%H%s%N: File access error - '%H%s%N'\r\n" +#string STR_GEN_FILE_NF #language en-US "%H%s%N: File not found - '%H%s%N'\r\n" +#string STR_GEN_CRLF #language en-US "\r\n" +#string STR_GEN_NO_CWD #language en-US "%H%s%N: Current directory not specified.\r\n" +#string STR_GEN_NO_FILES #language en-US "%H%s%N: No matching files were found.\r\n" +#string STR_GEN_DIR_NF #language en-US "%H%s%N: Directory not found - '%H%s%N'\r\n" +#string STR_GEN_RES_OK #language en-US "- [ok]\r\n" +#string STR_GEN_NOT_DIR #language en-US "%H%s%N: '%H%s%N' is not a directory.\r\n" +#string STR_GEN_NOT_FILE #language en-US "%H%s%N: '%H%s%N' is not a file.\r\n" +#string STR_GEN_SFO_HEADER #language en-US "ShellCommand,"%s"\r\n" +#string STR_GEN_MARG_ERROR #language en-US "%H%s%N: The destination '%H%s%N' is ambiguous.\r\n" +#string STR_GEN_FILE_ERROR #language en-US "%H%s%N: The destination is an existing file '%H%s%N'.\r\n" +#string STR_GEN_UEFI_FUNC_ERROR #language en-US "%H%s%N: UEFI function '%H%s%N' returned an incorrect value for: %s (%x).\r\n" +#string STR_GEN_UEFI_FUNC_WARN #language en-US "%H%s%N: UEFI function '%H%s%N' returned: %r\r\n" +#string STR_GEN_DEST_EXIST_OVR #language en-US "Destination file already exists. Overwrite? %BY%Nes, %BN%No, %BA%Nll, %BC%Nancel " +#string STR_GEN_CPY_FAIL #language en-US "%H%s%N: Copy failure: insufficient capacity on destination media.\r\n" +#string STR_GEN_CPY_READ_ERROR #language en-US "%H%s%N: reading '%B%s%N': IO Error \r\n" +#string STR_GEN_CPY_WRITE_ERROR #language en-US "%H%s%N: writing '%B%s%N': IO Error \r\n" +#string STR_GEN_OUT_MEM #language en-US "%H%s%N: Memory allocation was not successful.\r\n" + +#string STR_SET_DISP #language en-US "%V%8s %N= %H%s%N\r\n" +#string STR_SET_NF #language en-US "%H%s%N: Environment Variable '%H%s%N' not defined.\r\n" +#string STR_SET_ND #language en-US "%H%s%N: Environment Variable '%H%s%N' could not be deleted.\r\n" +#string STR_SET_ERROR_SET #language en-US "%H%s%N: Unable to set %H%s%N\r\n" + +#string STR_CD_PRINT #language en-US "%s\r\n" +#string STR_CD_NF #language en-US "%H%s%N: No mapping found.\r\n" + +#string STR_MAP_NF #language en-US "%H%s%N: Cannot find mapped device - '%H%s%N'\r\n" +#string STR_MAP_NOF #language en-US "%H%s%N: No mappable target found - '%H%s%N'\r\n" +#string STR_MAP_SFO_MAPPINGS #language en-US "Mappings,"%s","%s","%s"\r\n" +#string STR_MAP_HEADER #language en-US "%EMapping table%N\r\n" +#string STR_MAP_ENTRY #language en-US "%E%10s%N %HAlias(s):%N%s\r\n %s\r\n" +#string STR_MAP_ENTRY_VERBOSE #language en-US " Handle: [%H%02x%N]\r\n" + " Media Type: %s\r\n" + " Removable: %s\r\n" + " Current Dir: %s\r\n" + +#string STR_ATTRIB_OUTPUT_LINE #language en-US "Attrib: %1c%1c%1c%1c%1c %s\r\n" + +#string STR_MAP_MEDIA_FLOPPY #language en-US "Floppy" +#string STR_MAP_MEDIA_UNKNOWN #language en-US "Unknown" +#string STR_MAP_MEDIA_HARDDISK #language en-US "HardDisk" +#string STR_MAP_MEDIA_CDROM #language en-US "CD-Rom" + +#string STR_MKDIR_ALREADY #language en-US "Directory '%B%s%N' already exists.\r\n" +#string STR_MKDIR_CREATEFAIL #language en-US "Directory '%B%s%N' unable to create.\r\n" + +#string STR_DATE_FORMAT #language en-US "%02d/%02d/%04d\r\n" +#string STR_DATE_SFO_FORMAT #language en-US "Date,"%02d","%02d","%04d"\r\n" + +#string STR_TIME_FORMAT #language en-US "%02d:%02d:%02d (UTC%1s%02d:%02d)" +#string STR_TIME_FORMAT_LOCAL #language en-US "%02d:%02d:%02d (LOCAL)" +#string STR_TIME_DST0 #language en-US " DST: Not Affected\r\n" +#string STR_TIME_DST1 #language en-US " DST: Affected\r\n" +#string STR_TIME_DST2 #language en-US " DST: Adjusted\r\n" +#string STR_TIME_DST3 #language en-US " DST: Affected and Adjusted\r\n" + +#string STR_TIMEZONE_M12 #language en-US "UTC-12:00, International Date Line West\r\n" +#string STR_TIMEZONE_M11 #language en-US "UTC-11:00, Midway Island, Samoa\r\n" +#string STR_TIMEZONE_M10 #language en-US "UTC-10:00, Hawaii\r\n" +#string STR_TIMEZONE_M9 #language en-US "UTC-09:00, Alaska\r\n" +#string STR_TIMEZONE_M8 #language en-US "UTC-08:00, Pacific Time(US & Canada), Tijuana, Portland\r\n" +#string STR_TIMEZONE_M7 #language en-US "UTC-07:00, Arizona, Chihuahua, La Paz, Mazatlan, Mountain Time (US & Canada)\r\n" +#string STR_TIMEZONE_M6 #language en-US "UTC-06:00, Central America, Central Time(US & Canada)\r\n" +#string STR_TIMEZONE_M5 #language en-US "UTC-05:00, Bogota, Lima, Quito, Eastern Time(US & Canada)\r\n" +#string STR_TIMEZONE_M430 #language en-US "UTC-04:30, Caracas\r\n" +#string STR_TIMEZONE_M4 #language en-US "UTC-04:00, Atlantic Time(Canada), Caracas, Santiago\r\n" +#string STR_TIMEZONE_M330 #language en-US "UTC-03:30, Newfoundland\r\n" +#string STR_TIMEZONE_M3 #language en-US "UTC-03:00, Brasilia, Buenos Aires, Georgetown, Greenland\r\n" +#string STR_TIMEZONE_M2 #language en-US "UTC-02:00, Mid-Atlantic\r\n" +#string STR_TIMEZONE_M1 #language en-US "UTC-01:00, Azores, Cape Verde Is.\r\n" +#string STR_TIMEZONE_0 #language en-US "UTC , Greenwich Mean Time, Casablanca, Monrovia, Dublin, London\r\n" +#string STR_TIMEZONE_P1 #language en-US "UTC+01:00, Amsterdam, Berlin, Bern, Rome, Paris, West Central Africa\r\n" +#string STR_TIMEZONE_P2 #language en-US "UTC+02:00, Athens, Istanbul, Bucharest, Cairo, Jerusalem\r\n" +#string STR_TIMEZONE_P3 #language en-US "UTC+03:00, Baghdad, Kuwait, Riyadh, Moscow, Nairobi\r\n" +#string STR_TIMEZONE_P330 #language en-US "UTC+03:30, Tehran\r\n" +#string STR_TIMEZONE_P4 #language en-US "UTC+04:00, Abu Dhabi, Muscat, Baku, Tbilisi, Yerevan\r\n" +#string STR_TIMEZONE_P430 #language en-US "UTC+04:30, Kabul\r\n" +#string STR_TIMEZONE_P5 #language en-US "UTC+05:00, Ekaterinburg, Islamabad, Karachi, Tashkent\r\n" +#string STR_TIMEZONE_P530 #language en-US "UTC+05:30, Chennai, Kolkata, Mumbai, New Delhi\r\n" +#string STR_TIMEZONE_P545 #language en-US "UTC+05:45, Kathmandu\r\n" +#string STR_TIMEZONE_P6 #language en-US "UTC+06:00, Almaty, Novosibirsk, Astana, Dhaka, Sri Jayawardenepura\r\n" +#string STR_TIMEZONE_P630 #language en-US "UTC+06:30, Rangoon\r\n" +#string STR_TIMEZONE_P7 #language en-US "UTC+07:00, Bangkok, Hanio, Jakarta, Krasnoyarsk\r\n" +#string STR_TIMEZONE_P8 #language en-US "UTC+08:00, Beijing, Chongqing, Hong Kong, Urumqi, Taipei, Perth\r\n" +#string STR_TIMEZONE_P9 #language en-US "UTC+09:00, Osaka, Sapporo, Tokyo, Seoul, Yakutsk\r\n" +#string STR_TIMEZONE_P930 #language en-US "UTC+09:30, Adelaide, Darwin\r\n" +#string STR_TIMEZONE_P10 #language en-US "UTC+10:00, Canberra, Melbourne, Sydney, Guam, Hobart, Vladivostok\r\n" +#string STR_TIMEZONE_P11 #language en-US "UTC+11:00, Magadan, Solomon Is., New Caledonia\r\n" +#string STR_TIMEZONE_P12 #language en-US "UTC+12:00, Auckland, Wellington, Fiji, Kamchatka, Marshall Is.\r\n" +#string STR_TIMEZONE_P13 #language en-US "UTC+13:00, Nuku'alofa\r\n" +#string STR_TIMEZONE_P14 #language en-US "UTC+14:00, Line Islands\r\n" +#string STR_TIMEZONE_LOCAL #language en-US "LOCAL , Local Time\r\n" +#string STR_TIMEZONE_SIMPLE #language en-US "UTC%1s%02d:%02d\r\n" +#string STR_TIMEZONE_SIMPLE_LOCAL #language en-US "LOCAL\r\n" +#string STR_TIMEZONE_NI #language en-US "No additional information known." + +#string STR_LOAD_NOT_IMAGE #language en-US "Image '%s' is not an image.\r\n" +#string STR_LOAD_NOT_DRIVER #language en-US "Image '%s' is not a driver.\r\n" +#string STR_LOAD_LOADED #language en-US "Image '%s' loaded at %x - %r\r\n" +#string STR_LOAD_ERROR #language en-US "Image '%s' error in StartImage: %r\r\n" + +#string STR_LS_LINE_START_ALL #language en-US "%t %5s %1c % ,L11d " +#string STR_LS_LINE_END_FILE #language en-US "%s\r\n" +#string STR_LS_LINE_END_EXE #language en-US "%V%s%N\r\n" +#string STR_LS_LINE_END_DIR #language en-US "%B%s%N\r\n" +#string STR_LS_FOOTER_LINE #language en-US "% ,L11d File(s) % ,L11d bytes\r\n% ,L11d Dir(s)\r\n" +#string STR_LS_HEADER_LINE1 #language en-US "Directory of: %H%s%N\r\n" +#string STR_LS_FILE_NOT_FOUND #language en-US "%H%s%N: File Not Found - '%H%s%N'\r\n" +#string STR_LS_SFO_VOLINFO #language en-US "VolumeInfo,"%s","%Ld","%5s","%Ld","%Ld"\r\n" +#string STR_LS_SFO_FILEINFO #language en-US "FileInfo,"%s","%Ld","%Ld","%s%s%s%s%s","%02d:%02d:%02d","%02d.%02d.%04d","%02d:%02d:%02d","%02d.%02d.%04d","%02d:%02d:%02d","%02d.%02d.%04d"\r\n" + +#string STR_VOL_VOLINFO #language en-US "Volume %s (%s)\r\n" + "%Ld bytes total disk space\r\n" + "%Ld bytes available on disk\r\n" + "%d bytes in each allocation unit\r\n" + +#string STR_RM_LOG_DELETE_CONF #language en-US "Remove Subtree '%B%s%N' [y/n]?" +#string STR_RM_LOG_DELETE #language en-US "Deleting '%B%s%N'\r\n" +#string STR_RM_LOG_DELETE_ERR #language en-US "Delete error: %r\r\n" +#string STR_RM_LOG_DELETE_ERR2 #language en-US "Delete error. Couldn't open file: %r\r\n" +#string STR_RM_LOG_DELETE_ERR3 #language en-US "Delete error. Invalid target '%B%s%N'\r\n" +#string STR_RM_LOG_DELETE_COMP #language en-US "Delete successful.\r\n" +#string STR_RM_LOG_DETELE_RO #language en-US "%H%s%N: '%H%s%N' is read-only\r\n" + +#string STR_MV_OUTPUT #language en-US "Moving %s -> %s\r\n" +#string STR_MV_INV_SUB #language en-US "Cannot move a directory into itself or its subdirectory.\r\n" +#string STR_MV_INV_RO #language en-US "Cannot move to or from a read-only file or directory '%B%s%N'\r\n" +#string STR_MV_INV_CWD #language en-US "Cannot move current working directory or its subdirectory.\r\n" + +#string STR_CP_OUTPUT #language en-US "Copying %s -> %s\r\n" +#string STR_CP_ERROR #language en-US "%H%s%N: Could not copy - '%H%s%N'\r\n" +#string STR_CP_DIR_REQ #language en-US "%H%s%N: Copying a directory requires -r.\r\n" +#string STR_CP_DIR_WNF #language en-US "%H%s%N: The specified path does not exist - '%H%s%N'\r\n" +#string STR_CP_SD_SAME #language en-US "%H%s%N: The source and destination are the same.\r\n" +#string STR_CP_SD_PARENT #language en-US "%H%s%N: The destination is a parent of the source.\r\n" +#string STR_CP_DEST_ERROR #language en-US "%H%s%N: The destination is read-only.\r\n" +#string STR_CP_DEST_OPEN_FAIL #language en-US "%H%s%N: The destination file '%B%s%N' failed to open with create.\r\n" +#string STR_CP_DEST_DIR_FAIL #language en-US "%H%s%N: The destination directory '%B%s%N' could not be created.\r\n" +#string STR_CP_SRC_OPEN_FAIL #language en-US "%H%s%N: The source file '%B%s%N' failed to open with read.\r\n" + +#string STR_GET_HELP_ATTRIB #language en-US "" +".TH attrib 0 "Displays or modifies the attributes of files or directories."\r\n" +".SH NAME\r\n" +"Displays or modifies the attributes of files or directories.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"ATTRIB [+a|-a] [+s|-s] [+h|-h] [+r|-r] [file...] [directory...]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" +a|-a - Sets or clears the 'archive' attribute.\r\n" +" +s|-s - Sets or clears the 'system' attribute.\r\n" +" +h|-h - Sets or clears the 'hidden' attribute.\r\n" +" +r|-r - Sets or clears the 'read-only' attribute.\r\n" +" file - Specifies the file name (wild cards are permitted).\r\n" +" directory - Specifies the directory name (wildcards are permitted).\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. Four attribute types are supported in the UEFI file system:\r\n" +" - Archive [A]\r\n" +" - System [S]\r\n" +" - Hidden [H]\r\n" +" - Read only [R]\r\n" +" 2. If a file (in general meaning) is a directory, then it is also shown\r\n" +" to have the attribute [D].\r\n" +" 3. If any file in the file list that is specified \r\n" +" does not exist, attrib will continue processing the remaining files\r\n" +" while reporting the error.\r\n" +" 4. If no attributes parameters are specified, the current attributes of\r\n" +" the specified files or directories are displayed.\r\n" +" 5. If no files or directories are specified, the command applies to\r\n" +" all files and sub-directories within the current directory.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To display the attributes of a directory:\r\n" +" fs0:\> attrib fs0:\ \r\n" +" \r\n" +" * To display the attributes of all files and sub-directories in the current\r\n" +" directory:\r\n" +" fs0:\> attrib *\r\n" +" \r\n" +" * To add the system attribute to all files with extension '.efi':\r\n" +" fs0:\> attrib +s *.efi\r\n" +" \r\n" +" * To remove the read-only attribute from all files with extension '.inf':\r\n" +" fs0:\> attrib -r *.inf\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_NOT_FOUND The requested file was not found.\r\n" +" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_WRITE_PROTECTED The media that the action was to take place on is\r\n" +" write-protected.\r\n" + +#string STR_GET_HELP_CD #language en-US "" +".TH cd 0 "Displays or changes the current directory."\r\n" +".SH NAME\r\n" +"Displays or changes the current directory.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"CD [path]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" path - Specifies the relative or absolute directory path.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command changes the current working directory that is used by the\r\n" +" UEFI Shell environment. If a file system mapping is specified, then the\r\n" +" current working directory is changed for that device. Otherwise, the\r\n" +" current working directory is changed for the current device.\r\n" +" 2. If path is not present, then the current working directory (including\r\n" +" file system mapping) is displayed to standard out.\r\n" +" 3. The table below describes the conventions that are used to refer to the\r\n" +" directory, its parent, and the root directory in the UEFI Shell\r\n" +" environment.\r\n" +" Convention Description\r\n" +" '.' Refers to the current directory.\r\n" +" '..' Refers to the directory's parent.\r\n" +" '\\\' Refers to the root of the current file system.\r\n" +" 4. The current working directory is maintained in the environment\r\n" +" variable %cwd%.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To change the current file system to the mapped fs0 file system:\r\n" +" Shell> fs0:\r\n" +" \r\n" +" * To change the current directory to subdirectory 'efi':\r\n" +" fs0:\> cd efi\r\n" +" \r\n" +" * To change the current directory to the parent directory (fs0:\):\r\n" +" fs0:\efi\> cd ..\r\n" +" \r\n" +" * To change the current directory to 'fs0:\efi\Tools':\r\n" +" fs0:\> cd efi\Tools\r\n" +" \r\n" +" * To change the current directory to the root of the current fs (fs0):\r\n" +" fs0:\efi\Tools\> cd \ \r\n" +" \r\n" +" * To move between volumes and maintain the current path, and then copy\r\n" +" all of files in fs0:\efi\Tools into the fs1:\Tmp directory:\r\n" +" fs0:\> cd \efi\Tools\r\n" +" fs0:\efi\Tools\> fs1:\r\n" +" fs1:\> cd Tmp\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" + +#string STR_GET_HELP_CP #language en-US "" +".TH cp 0 "Copies files or directories."\r\n" +".SH NAME\r\n" +"Copies one or more files or directories to another location.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"CP [-r] [-q] src [src...] [dst]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -r - Makes a recursive copy.\r\n" +" -q - Makes a quiet copy (without a prompt).\r\n" +" src - Specifies a source file/directory name (wildcards are permitted).\r\n" +" dst - Specifies a destination file/directory name (wildcards are not permitted). \r\n" +" If more than one directory is specified, the last directory is\r\n" +" assumed to be the destination.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. '-r' must be specified if src is a directory. If '-r' is specified,\r\n" +" the source directory is recursively copied to the destination.\r\n" +" 'src' itself is copied.\r\n" +" 2. If a destination is not specified, the current working directory is\r\n" +" assumed to be the destination.\r\n" +" 3. 'CP -r src1 src2 dst' copies all files and subdirectories in 'src1' and\r\n" +" 'src2' to the destination 'dst'. 'src1' and 'src2' themselves are also\r\n" +" copied. The 'dst' parameter is interpreted as a directory.\r\n" +" 4. Copying a directory or file to itself is not allowed.\r\n" +" 5. If an error occurs, this command exits immediately and the remaining files or\r\n" +" directories are not copied.\r\n" +" 6. When 'cp' is executed with a script file, it always performs quiet\r\n" +" copying, regardless of whether the '-q' option is specified.\r\n" +" 7. If you are copying multiple files, the destination must be an existing\r\n" +" directory.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To display the contents of the current directory:\r\n" +" fs0:\> ls\r\n" +" \r\n" +" * To copy a file in the same directory and change the file name:\r\n" +" fs0:\> cp temp.txt readme.txt\r\n" +" \r\n" +" * To copy multiple files to another directory:\r\n" +" fs0:\> cp temp.txt isaBus.efi \Test\r\n" +" \r\n" +" * To copy multiple directories recursively to another directory:\r\n" +" fs0:\> cp -r test1 test2 boot \Test\r\n" +" \r\n" +" * To see the results of the above operations:\r\n" +" fs0:\> ls \Test\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly \r\n" +" formatted or its value was out of bounds.\r\n" +" SHELL_OUT_OF_RESOURCES There was insufficient space to save the \r\n" +" requested file at the destination.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security \r\n" +" violation.\r\n" +" SHELL_WRITE_PROTECTED An attempt was made to create a file on media that\r\n" +" was write-protected.\r\n" + +#string STR_GET_HELP_MAP #language en-US "" +".TH map 0 "Displays or defines file system mappings"\r\n" +".SH NAME\r\n" +"Displays or defines file system mappings.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"MAP [-d ]\r\n" +"MAP [[-r][-v][-c][-f][-u][-t ][sname]]\r\n" +"MAP [sname handle | mapping]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -d - Deletes a file system mapping.\r\n" +" -r - Resets file system mappings to default values.\r\n" +" -u - Adds file system mappings for newly-installed devices and\r\n" +" removes mappings for uninstalled devices. This does not change\r\n" +" the mappings of existing devices and preserves user-defined mappings.\r\n" +" -v - Displays verbose information about all file system mappings.\r\n" +" -c - Displays the consistent mappings.\r\n" +" -f - Displays the normal mappings (not the consistent mappings).\r\n" +" -t - Displays the device mappings, filtered according to the device type.\r\n" +" Supported types are:\r\n" +" fp - Floppy\r\n" +" hd - Hard Disk\r\n" +" cd - CD-ROM\r\n" +" Types can be combined by putting a comma between two types. Spaces\r\n" +" are not allowed between types.\r\n" +" -sfo - Displays information in Standard-Format Output.\r\n" +" sname - Specifies a mapping name.\r\n" +" handle - Specifies the number of a handle. Use the same value that is\r\n" +" displayed by the 'dh' command.\r\n" +" mapping - Specifies a new mapping name to assign to a device.\r\n" +" This value must end with a ':'.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command creates a mapping between a user-defined name and a device.\r\n" +" The most common use of this command is to create a mapped name for\r\n" +" devices that support a file system protocol. After these mappings are\r\n" +" created, the names can be used with all the file manipulation commands.\r\n" +" 2. The UEFI Shell environment creates default mappings for all of the\r\n" +" devices that support a recognized file system.\r\n" +" 3. This command can be used to create additional mappings, or \r\n" +" when used with the -d option, to delete an existing mapping. If it is\r\n" +" used without any parameters, all of the current mappings are listed.\r\n" +" If the -v option is used, the mappings are shown with additional\r\n" +" information about each device.\r\n" +" 4. The -r option is used to reset all the default mappings in a system,\r\n" +" which is useful if the system configuration has changed since the\r\n" +" last boot.\r\n" +" 5. The -u option adds mappings for newly-installed devices and removes\r\n" +" mappings for uninstalled devices without changing the mappings of\r\n" +" existing devices. User-defined mappings are also preserved. A mapping\r\n" +" history is saved, which preserves the original mapping name for\r\n" +" a device with a specific device path. The current directory is also\r\n" +" preserved if the current device is not changed.\r\n" +" 6. Each device in the system has a consistent mapping. If the hardware\r\n" +" configuration has not changed, the device's consistent mappings do not\r\n" +" change. If two or more machines have the same hardware configurations,\r\n" +" the device's consistent mapping remains the same. Use the -c option to\r\n" +" list all the consistent mappings in the system.\r\n" +" 7. The mapping value must consist of digits and characters. Other\r\n" +" characters are illegal.\r\n" +" 8. This command support wildcards. You can use the wildcards to delete\r\n" +" or show the mapping. However, when you assign the mapping, wildcards\r\n" +" are forbidden.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To display verbose mapping table information:\r\n" +" Shell> map -v\r\n" +" \r\n" +" * To assign a different name to fs0:\r\n" +" Shell> map floppy fs0:\r\n" +" \r\n" +" * To operate with the mapped name:\r\n" +" Shell> floppy:\r\n" +" \r\n" +" * To delete a mapped name:\r\n" +" Shell> map -d floppy:\r\n" +" \r\n" +" * To display all the mapped names starting with 'f': \r\n" +" Shell> map f* \r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" + +#string STR_GET_HELP_MKDIR #language en-US "" +".TH mkdir 0 "Creates directories."\r\n" +".SH NAME\r\n" +"Creates one or more new directories.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"MKDIR dir [dir...]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" dir - Specifies the name of a directory or directories to create. (Wildcards are not\r\n" +" allowed) \r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. The parent directory must already exist.\r\n" +" 2. If the directory already exists, mkdir will abort.\r\n" +" 3. Specifying additional directory parameters dependent on previous\r\n" +" directory parameters is not allowed:\r\n" +" For example, mkdir new new\Test is not allowed.\r\n" +" 4. Redirecting output to a file that exists under the directory specified\r\n" +" by this command is not allowed.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To create a new directory:\r\n" +" fs0:\> mkdir rafter\r\n" +" \r\n" +" * To create multiple directories:\r\n" +" fs0:\> mkdir temp1 temp2\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly \r\n" +" formatted or its value was out of bounds.\r\n" +" SHELL_OUT_OF_RESOURCES There was insufficient space on the destination \r\n" +" to create the requested directory.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security \r\n" +" violation.\r\n" +" SHELL_WRITE_PROTECTED An attempt was made to create a directory when the\r\n" +" target media was write-protected.\r\n" + +#string STR_GET_HELP_MV #language en-US "" +".TH mv 0 "Moves files."\r\n" +".SH NAME\r\n" +"Moves one or more files to a destination within or between file systems.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"MV src [src...] [dst]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" src - Specifies a source file/directory name (wildcards are permitted).\r\n" +" dst - Specifies a destination file/directory name (wildcards are permitted).\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command moves one or more files to a destination within or between\r\n" +" file systems.\r\n" +" 2. If the destination is an existing directory, the sources are moved\r\n" +" into that directory. You cannot move the sources to a non-existing\r\n" +" directory.\r\n" +" 3. If a destination is not specified, the current directory is assumed to be\r\n" +" the destination. If there is more than one argument on the command line,\r\n" +" the last one is assumed to be the destination.\r\n" +" 4. Attempting to move a read-only file/directory results in an error.\r\n" +" Moving a directory that contains read-only files is allowed.\r\n" +" 5. You cannot move a directory into itself or its subdirectories.\r\n" +" 6. You cannot move a directory if the current working directory is itself or\r\n" +" its subdirectories.\r\n" +" 7. If an error occurs, the remaining files or directories are still be\r\n" +" moved.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To rename a file:\r\n" +" fs0:\> mv IsaBus.efi Bus.efi\r\n" +" \r\n" +" * To move a directory to the current directory:\r\n" +" fs0:\> mkdir Test1\Temp\r\n" +" fs0:\> mv Test1\Temp\r\n" +" \r\n" +" * To rename a directory:\r\n" +" fs0:\> mv efi efi1.1\r\n" +" \r\n" +" * To move multiple directories at a time:\r\n" +" fs0:\> mv Test1 Test2 Test\r\n" +" \r\n" +" * To attempt moving a read-only directory, which results in a failure:\r\n" +" fs0:\Test> attrib +r Temp1\r\n" +" DA R fs0:\Test\Temp1\r\n" +" fs0:\Test> mv Temp1 Temp2\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" +" SHELL_NOT_FOUND The source file was not able to be found.\r\n" +" SHELL_OUT_OF_RESOURCES There was insufficient free space to move the\r\n" +" requested file to its destination.\r\n" +" SHELL_WRITE_PROTECTED An attempt was made to create a file on media that\r\n" +" was write-protected.\r\n" + +#string STR_GET_HELP_PARSE #language en-US "" +".TH parse 0 "Parses standard format output files."\r\n" +".SH NAME\r\n" +"Retrieves a value from a standard format output file.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"PARSE filename tablename column [-i ] [-s ]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" filename - Specifies a source file name.\r\n" +" tablename - Specifies the name of the table to be parsed.\r\n" +" column - Specifies the one-based column index to use to determine which value\r\n" +" from a particular record to parse.\r\n" +" -i - Specifies an instance number to use to start parsing the ShellCommand table,\r\n" +" and then the specified tablename. If not specified, all instances are returned.\r\n" +" -s - Specifies an instance number to use to start parsing the ShellCommand\r\n" +" table. If not present, then 1 is assumed.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command enables you to parse data from a file that has been output\r\n" +" using the -sfo parameter.\r\n" +" 2. Since the standard formatted output has a well known means of parsing,\r\n" +" this command is intended to provide an easy way of enabling\r\n" +" scripts to consume retrieved data from such constructed output files, and\r\n" +" use it in the logic of scripts written for the UEFI shell.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * The following data is contained in a temporary file (temp.txt):\r\n" +" ShellCommand,"ls"\r\n" +" VolumeInfo,"MikesVolume","400000000","FALSE","32000000","16000000"\r\n" +" FileInfo,"FS0:\efi\\boot\winloader.efi","45670","45900","arsh","08:30:12","01.08.2013","00:00:00","01.08.2013","08:30:12","01.08.2013"\r\n" +" FileInfo,"FS0:\efi\\boot\mikesfile.txt","1250","1280","a","08:30:12","01.08.2013","00:00:00","01.08.2013","08:30:12","01.08.2013"\r\n" +" FileInfo,"FS0:\efi\\boot\\readme.txt","795","900","a","08:30:12","01.08.2013","00:00:00","01.08.2013","08:30:12","01.08.2013"\r\n" +" \r\n" +" * To display VolumeInfo column 2 in temp.txt:\r\n" +" fs0:\> parse temp.txt VolumeInfo 2\r\n" +" MikesVolume\r\n" +" \r\n" +" * To display FileInfo column 3 in temp.txt, starting with instance 3:\r\n" +" fs0:\> parse temp.txt FileInfo 3 -i 3\r\n" +" 795\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" +" SHELL_NOT_FOUND The source file was not able to be found.\r\n" + +#string STR_GET_HELP_RESET #language en-US "" +".TH reset 0 "Reset the system."\r\n" +".SH NAME\r\n" +"Resets the system.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"RESET [-w [string]]\r\n" +"RESET [-s [string]]\r\n" +"RESET [-c [string]]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -s - Performs a shutdown.\r\n" +" -w - Performs a warm boot.\r\n" +" -c - Performs a cold boot.\r\n" +" string - Describes a reason for the reset.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command resets the system.\r\n" +" 2. The default is to perform a cold reset unless the -w parameter is\r\n" +" specified.\r\n" +" 3. If a reset string is specified, it is passed into the Reset() \r\n" +" function, and the system records the reason for the system reset.\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_INVALID_PARAMETER One of the passed in parameters was incorrectly \r\n" +" formatted or its value was out of bounds.\r\n" + +#string STR_GET_HELP_RM #language en-US "" +".TH rm 0 "Deletes one or more files or directories."\r\n" +".SH NAME\r\n" +"Deletes one or more files or directories.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"RM [-q] file/directory [file/directory ...]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -q - Specifies quiet mode. Does not prompt for a confirmation.\r\n" +" file - Specifies a file name (wildcards are permitted).\r\n" +" directory - Specifies a directory name (wildcards are permitted).\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command deletes one or more files or directories.\r\n" +" 2. If the target is a directory, it deletes the directory, including all\r\n" +" its subdirectories.\r\n" +" 3. Redirecting a file whose parent directory (or the file\r\n" +" itself) is being deleted is not allowed.\r\n" +" 4. Removing a read-only file/directory results in a failure.\r\n" +" 5. Removing a directory containing read-only file(s) results in\r\n" +" a failure. If an error occurs, the command exits immediately and stops\r\n" +" removing files/directories.\r\n" +" 6. You cannot remove a directory when the current directory is itself or its\r\n" +" subdirectory. If a file contains wildcards, you are not prompted for\r\n" +" confirmation.\r\n" +" 7. The root directory cannot be removed.\r\n" +" 8. The current directory or its ancestor directories cannot be removed.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To remove multiple directories at a time:\r\n" +" fs0:\> rm Test\Temp1 Temp2\r\n" +" \r\n" +" * To remove multiple directories with wildcards:\r\n" +" fs0:\> rm Test\Temp*\r\n" +" \r\n" +" * To attempt removing a directory that contains a read-only file,\r\n" +" which results in a failure:\r\n" +" fs0:\> attrib +r Test\Temp1\readme.txt\r\n" +" A R fs0:\Test\Temp1\readme.txt\r\n" +" fs0:\> rm Test\Temp1\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_NOT_FOUND The source file was not able to be found.\r\n" +" SHELL_WRITE_PROTECTED The target was write protected.\r\n" + +#string STR_GET_HELP_SET #language en-US "" +".TH set 0 "Displays or modifies UEFI Shell environment variables."\r\n" +".SH NAME\r\n" +"Displays or modifies UEFI Shell environment variables.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"SET [-v] [sname [value]]\r\n" +"SET [-d ]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -d - Deletes the environment variable.\r\n" +" -v - Displays or modifies a volatile variable.\r\n" +" sname - Specifies an environment variable name.\r\n" +" value - Specifies an environment variable value.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command is used to maintain the UEFI Shell environment variables.\r\n" +" This command can do the following:\r\n" +" - Display environment variables.\r\n" +" - Create new environment variables.\r\n" +" - Change the value of existing environment variables.\r\n" +" - Delete environment variables.\r\n" +" 2. This command sets an environment variable to a specified \r\n" +" value. You can use it to create a new environment\r\n" +" variable or to modify an existing environment variable.\r\n" +" 3. If used without any parameters, all the environment variables\r\n" +" are displayed.\r\n" +" 4. If used with the -d option, the environment variable that\r\n" +" is specified by sname is deleted.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To add an environment variable:\r\n" +" Shell> set DiagnosticPath fs0:\efi\diag;fs1:\efi\diag\r\n" +" \r\n" +" * To display environment variables:\r\n" +" Shell> set\r\n" +" \r\n" +" * To delete an environment variable:\r\n" +" Shell> set -d diagnosticpath\r\n" +" \r\n" +" * To change an environment variable:\r\n" +" fs0:\> set src efi\r\n" +" fs0:\> set src efi1.1\r\n" +" \r\n" +" * To append an environment variable:\r\n" +" Shell> set path %path%;fs0:\efi\Tools;fs0:\efi\boot;fs0:\\r\n" +" \r\n" +" * To set a volatile variable that will disappear at the next boot:\r\n" +" Shell> set -v EFI_SOURCE c:\project\EFI1.1\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_OUT_OF_RESOURCES A request to set a variable in a non-volatile \r\n" +" fashion could not be completed. The resulting \r\n" +" non-volatile request has been converted into a \r\n" +" volatile request.\r\n" + +#string STR_GET_HELP_DATE #language en-US "" +".TH date 0 "Displays and sets the current date for the system."\r\n" +".SH NAME\r\n" +"Displays and sets the current date for the system.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"DATE [mm/dd/[yy]yy][-sfo]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -sfo - Displays information in Standard-Format Output.\r\n" +" mm - Specifies the month of the date to be set. (1-12)\r\n" +" dd - Specifies the day of the date to be set (1-31)\r\n" +" yy/yyyy - Specifies the year of the date to be set. If only two digits,\r\n" +" then enter 9x = 199x. Otherwise enter 20xx.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command displays and/or sets the current date for the system.\r\n" +" If no parameters are used, it shows the current date. If a valid month,\r\n" +" day, and year are specified, the system's date is updated.\r\n" +" The following rules apply:\r\n" +" - Except for numeric characters and /, all other characters in the\r\n" +" argument are invalid.\r\n" +" - The Shell reports an error if the number is in the wrong\r\n" +" month/date/year range.\r\n" +" - A space before or after the numeric character is not allowed. Inserting\r\n" +" a space into the number is invalid.\r\n" +" - Repeated zeros are allowed before the number. For example:\r\n" +" Shell > date 0000008/000004/000097\r\n" +" Shell > date\r\n" +" 08/04/2097\r\n" +" Shell >\r\n" +" - The year range must be greater than or equal to 1998.\r\n" +" - Two numeric characters indicate the year. Numbers below 98 are\r\n" +" regarded as 20xx, and numbers equal to or above 98 are regarded as\r\n" +" 19xx. 00 means 2000. For example:\r\n" +" Shell > date 8/4/97\r\n" +" Shell > date\r\n" +" 08/04/2097\r\n" +" Shell >\r\n" +" Shell > date 8/4/98\r\n" +" Shell > date\r\n" +" 08/04/1998\r\n" +" Shell >\r\n" +" 2. The range of valid years is from 1998-2099.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To display the current date in the system:\r\n" +" fs0:\> date\r\n" +" \r\n" +" * To set the date with long year format:\r\n" +" fs0:\> date 01/01/2050\r\n" +" \r\n" +" * To set the date with short year format:\r\n" +" fs0:\> date 06/18/01\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_DEVICE_ERROR There was a hardware error preventing the\r\n" +" completion of this command.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" + +#string STR_GET_HELP_TIME #language en-US "" +".TH time 0 "Displays or sets the time for the system."\r\n" +".SH NAME\r\n" +"Displays or sets the current time for the system.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"TIME [hh:mm[:ss]] [-tz tz] [-d dl]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -d - Sets or displays a daylight savings time value.\r\n" +" -tz - Specifies a time zone adjustment, measured in minutes offset from UTC. Valid values\r\n" +" are between -1440 and 1440 or 2047. If not present or set to 2047,\r\n" +" time is interpreted as local time.\r\n" +" hh - Specifies a new hour (0-23) (required).\r\n" +" mm - Specifies a new minute (0-59) (required).\r\n" +" ss - Specifies a new second (0-59). If not specified, zero is used.\r\n" +" dl - Specifies a daylight saving time value to set.\r\n" +" 0 : Time is not affected.\r\n" +" 1 : Time is affected, and has not been adjusted for daylight\r\n" +" savings.\r\n" +" 3 : Time is affected, and has been adjusted for daylight savings.\r\n" +" All other values are invalid. If no value follows -d, the\r\n" +" current daylight savings time is displayed.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command displays or sets the current time for the system.\r\n" +" If no parameters are used, it shows the current time. If valid hours, \r\n" +" minutes, and seconds are provided, the system time is\r\n" +" updated. Note the following rules:\r\n" +" - Except for numeric characters and the : character, all other\r\n" +" characters in the argument are invalid.\r\n" +" - The Shell reports an error if the number is in the wrong \r\n" +" hour/minute/second range.\r\n" +" - Spaces before or after the numeric character and spaces inserted into\r\n" +" the number are not allowed.\r\n" +" - Repeated zeros are allowed before the number. For example:\r\n" +" Shell> time 00000017:000004:0000\r\n" +" Shell> time\r\n" +" 17:04:00 (UTC+08:00)\r\n" +" 2. The seconds parameter is optional. If none is specified, it is\r\n" +" set to zero.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To display current system time:\r\n" +" fs0:\> time\r\n" +" \r\n" +" * To set the system time:\r\n" +" fs0:\> time 9:51:30\r\n" +" \r\n" +" * To display the system time, including daylight savings time:\r\n" +" fs0:\> time -d\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_DEVICE_ERROR There was a hardware error preventing the\r\n" +" completion of this command\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" + +#string STR_GET_HELP_TIMEZONE #language en-US "" +".TH timezone 0 "Displays or sets time zone information."\r\n" +".SH NAME\r\n" +"Displays or sets time zone information.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"TIMEZONE [-s hh:mm | -l] [-b] [-f]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -s - Sets the time zone associated with hh:mm offset from UTC.\r\n" +" -l - Displays a list of all time zones.\r\n" +" -b - Displays one screen at a time.\r\n" +" -f - Displays full information for the specified time zone.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command displays and sets the current time zone for the system.\r\n" +" 2. If no parameters are used, it shows the current time zone.\r\n" +" 3. If a valid hh:mm parameter is provided, the time zone\r\n" +" information is updated.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To display all available time zones:\r\n" +" Shell> timezone -l\r\n" +" \r\n" +" * To set the time zone:\r\n" +" Shell> timezone -s -7:00\r\n" +" \r\n" +" * To display detailed information for the current time zone:\r\n" +" Shell> timezone -f\r\n" + +#string STR_GET_HELP_LS #language en-US "" +".TH ls 0 "Lists the contents of a directory or file information."\r\n" +".SH NAME\r\n" +"Lists the contents of a directory or file information.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"LS [-r] [-a[attrib]][-sfo][file]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -r - Displays recursively (including subdirectories).\r\n" +" -a - Displays files with a specified attribute. If \r\n" +" attribute is not specified, all files are listed. If -a is not\r\n" +" specified, all non-system and non-hidden files are listed.\r\n" +" -sfo - Displays information in Standard-Format Output.\r\n" +" attrib - Specifies a file attribute list value:\r\n" +" a - Archive\r\n" +" s - System\r\n" +" h - Hidden\r\n" +" r - Read-only\r\n" +" d - Directory\r\n" +" file - Specifies a name of a file or directory (wildcards are permitted).\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command lists directory contents or file information. If no file\r\n" +" name or directory name is specified, the current working directory\r\n" +" is assumed.\r\n" +" 2. The contents of a directory are listed if all of the following are true:\r\n" +" - If option -r is not specified.\r\n" +" - If no wildcard characters are specified in the file parameter.\r\n" +" - If the file specified represents an existing directory.\r\n" +" 3. In all other cases, the command functions as follows:\r\n" +" - All files/directories that match the specified name are displayed.\r\n" +" - The -r flag determines whether a recursive search is performed.\r\n" +" - The option flag -a[attrib] only displays those\r\n" +" files with the attributes that are specified.\r\n" +" - If more than one attribute is specified, only the files that have all\r\n" +" those attributes are listed.\r\n" +" - If -a is followed by nothing, then all files/directories are\r\n" +" displayed, regardless of their attributes.\r\n" +" - If -a itself is not specified, then all files except system and\r\n" +" hidden files are displayed.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To hide files by adding the hidden or system attribute to them:\r\n" +" fs0:\> attrib +s +h *.efi\r\n" +" \r\n" +" * To display all, except the files/directories with 'h' or 's' attribute:\r\n" +" fs0:\> ls\r\n" +" \r\n" +" * To display files with all attributes in the current directory:\r\n" +" fs0:\> ls -a\r\n" +" \r\n" +" * To display files with read-only attributes in the current directory:\r\n" +" fs0:\> ls -ar\r\n" +" \r\n" +" * To display the files with attribute of 's':\r\n" +" fs0:\> ls -as isabus.efi\r\n" +" \r\n" +" * To display all in fs0:\efi directory recursively:\r\n" +" fs0:\> ls -r -a efi\r\n" +" \r\n" +" * To display files with a specified type in the current directory: \r\n" +" recursively:\r\n" +" fs0:\> ls -r -a *.efi -b\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_NOT_FOUND The requested file or directory was not found.\r\n" + +#string STR_GET_HELP_LOAD #language en-US "" +".TH load 0 "Loads a UEFI driver into memory."\r\n" +".SH NAME\r\n" +"Loads a UEFI driver into memory.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"LOAD [-nc] file [file...]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -nc - Loads the driver, but does not connect the driver.\r\n" +" File - Specifies a file that contains the image of the UEFI driver (wildcards are\r\n" +" permitted).\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command loads a driver into memory. It can load multiple files at\r\n" +" one time. The file name supports wildcards.\r\n" +" 2. If the -nc flag is not specified, this command attempts to connect the\r\n" +" driver to a proper device. It might also cause previously loaded drivers\r\n" +" to be connected to their corresponding devices.\r\n" +" 3. Use the 'UNLOAD' command to unload a driver.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To load a driver:\r\n" +" fs0:\> load Isabus.efi\r\n" +" \r\n" +" * To load multiple drivers:\r\n" +" fs0:\> load Isabus.efi IsaSerial.efi\r\n" +" \r\n" +" * To load multiple drivers using file name wildcards:\r\n" +" fs0:\> load Isa*.efi\r\n" +" \r\n" +" * To load a driver without connecting it to a device:\r\n" +" fs0:\> load -nc IsaBus.efi\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_NOT_FOUND The requested file was not found.\r\n" + +#string STR_GET_HELP_VOL #language en-US "" +".TH vol 0 "Displays or modifies information about a disk volume."\r\n" +".SH NAME\r\n" +"Displays or modifies information about a disk volume.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"VOL [fs] [-n ]\r\n" +"VOL [fs] [-d]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -n - Displays or modifies a new volume label.\r\n" +" -d - Displays or modifies an empty volume label.\r\n" +" fs - Specifies the name of the file system.\r\n" +" VolumeLabel - Specifies a volume label.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. The following characters cannot be used in a volume label:\r\n" +" % ^ * + = [ ] | : ; \" < > ? / . \r\n" +" 2. No spaces are allowed in a volume label.\r\n" +" 3. This command displays the volume information for the specified file\r\n" +" system. If fs is not specified, the current file system is used.\r\n" +" 4. If -n is specified, the volume label for fs is set to\r\n" +" VolumeLabel.\r\n" +" 5. The maximum length for volume label is 11 characters.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To display the volume of the current file system:\r\n" +" fs0:\> vol\r\n" +" \r\n" +" * To change the label of fs0:\r\n" +" Shell> vol fs0 -n help_test\r\n" +" \r\n" +" * To delete the volume label of fs0:\r\n" +" fs0:\> vol fs0 -d\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_NOT_FOUND The target file-system was not found.\r\n" + diff --git a/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Vol.c b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Vol.c new file mode 100644 index 0000000000..f911c7eae8 --- /dev/null +++ b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Vol.c @@ -0,0 +1,313 @@ +/** @file + Main file for vol shell level 2 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
+ Copyright (c) 2011 - 2015, 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 + +/** + Print the info or change the volume info. + + @param[in] Path String with starting path. + @param[in] Delete TRUE to delete the volume label. FALSE otherwise. + @param[in] Name New name to set to the volume label. + + @retval SHELL_SUCCESS The operation was sucessful. +**/ +SHELL_STATUS +HandleVol( + IN CONST CHAR16 *Path, + IN CONST BOOLEAN Delete, + IN CONST CHAR16 *Name OPTIONAL + ) +{ + EFI_STATUS Status; + SHELL_STATUS ShellStatus; + EFI_FILE_SYSTEM_INFO *SysInfo; + UINTN SysInfoSize; + SHELL_FILE_HANDLE ShellFileHandle; + EFI_FILE_PROTOCOL *EfiFpHandle; + UINTN Size1; + UINTN Size2; + + ShellStatus = SHELL_SUCCESS; + + if ( + Name != NULL && ( + StrStr(Name, L"%") != NULL || + StrStr(Name, L"^") != NULL || + StrStr(Name, L"*") != NULL || + StrStr(Name, L"+") != NULL || + StrStr(Name, L"=") != NULL || + StrStr(Name, L"[") != NULL || + StrStr(Name, L"]") != NULL || + StrStr(Name, L"|") != NULL || + StrStr(Name, L":") != NULL || + StrStr(Name, L";") != NULL || + StrStr(Name, L"\"") != NULL || + StrStr(Name, L"<") != NULL || + StrStr(Name, L">") != NULL || + StrStr(Name, L"?") != NULL || + StrStr(Name, L"/") != NULL || + StrStr(Name, L" ") != NULL ) + ){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"vol", Name); + return (SHELL_INVALID_PARAMETER); + } + + Status = gEfiShellProtocol->OpenFileByName( + Path, + &ShellFileHandle, + Name != NULL?EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE:EFI_FILE_MODE_READ); + + if (EFI_ERROR(Status) || ShellFileHandle == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel2HiiHandle, L"vol", Path); + return (SHELL_ACCESS_DENIED); + } + + // + // 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(SysInfo != NULL); + + if (Delete) { + *((CHAR16 *) SysInfo->VolumeLabel) = CHAR_NULL; + SysInfo->Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize(SysInfo->VolumeLabel); + Status = EfiFpHandle->SetInfo( + EfiFpHandle, + &gEfiFileSystemInfoGuid, + (UINTN)SysInfo->Size, + SysInfo); + } else if (Name != NULL) { + Size1 = StrSize(Name); + Size2 = StrSize(SysInfo->VolumeLabel); + if (Size1 > Size2) { + SysInfo = ReallocatePool((UINTN)SysInfo->Size, (UINTN)SysInfo->Size + Size1 - Size2, SysInfo); + if (SysInfo == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellLevel2HiiHandle, L"vol"); + ShellStatus = SHELL_OUT_OF_RESOURCES; + } + } + if (SysInfo != NULL) { + StrCpyS ( (CHAR16 *) SysInfo->VolumeLabel, + (Size1>Size2? Size1/sizeof(CHAR16) : Size2/sizeof(CHAR16)), + Name + ); + SysInfo->Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + Size1; + Status = EfiFpHandle->SetInfo( + EfiFpHandle, + &gEfiFileSystemInfoGuid, + (UINTN)SysInfo->Size, + SysInfo); + } + } + + FreePool(SysInfo); + + if (Delete || Name != NULL) { + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_AD), gShellLevel2HiiHandle, L"vol", Path); + ShellStatus = SHELL_ACCESS_DENIED; + } + } + + SysInfoSize = 0; + SysInfo = NULL; + + Status = EfiFpHandle->GetInfo( + EfiFpHandle, + &gEfiFileSystemInfoGuid, + &SysInfoSize, + SysInfo); + + if (Status == EFI_BUFFER_TOO_SMALL) { + SysInfo = AllocateZeroPool(SysInfoSize); + Status = EfiFpHandle->GetInfo( + EfiFpHandle, + &gEfiFileSystemInfoGuid, + &SysInfoSize, + SysInfo); + } + + gEfiShellProtocol->CloseFile(ShellFileHandle); + + ASSERT(SysInfo != NULL); + + if (SysInfo != NULL) { + // + // print VolumeInfo table + // + ShellPrintHiiEx ( + 0, + gST->ConOut->Mode->CursorRow, + NULL, + STRING_TOKEN (STR_VOL_VOLINFO), + gShellLevel2HiiHandle, + SysInfo->VolumeLabel, + SysInfo->ReadOnly?L"r":L"rw", + SysInfo->VolumeSize, + SysInfo->FreeSpace, + SysInfo->BlockSize + ); + SHELL_FREE_NON_NULL(SysInfo); + } + + return (ShellStatus); +} + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-d", TypeFlag}, + {L"-n", TypeValue}, + {NULL, TypeMax} + }; + +/** + Function for 'Vol' 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 +ShellCommandRunVol ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + CONST CHAR16 *PathName; + CONST CHAR16 *CurDir; + BOOLEAN DeleteMode; + CHAR16 *FullPath; + CHAR16 *TempSpot; + UINTN Length; + CONST CHAR16 *NewName; + + Length = 0; + ProblemParam = NULL; + ShellStatus = SHELL_SUCCESS; + PathName = NULL; + CurDir = NULL; + FullPath = NULL; + + // + // 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 (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, L"vol", 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, L"vol"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + 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, L"vol"); + } else { + PathName = CurDir; + } + } + if (PathName != NULL) { + TempSpot = StrStr(PathName, L":"); + if (TempSpot != NULL) { + *TempSpot = CHAR_NULL; + } + TempSpot = StrStr(PathName, L"\\"); + if (TempSpot != NULL) { + *TempSpot = CHAR_NULL; + } + StrnCatGrow(&FullPath, &Length, PathName, 0); + StrnCatGrow(&FullPath, &Length, L":\\", 0); + DeleteMode = ShellCommandLineGetFlag(Package, L"-d"); + NewName = ShellCommandLineGetValue(Package, L"-n"); + if (DeleteMode && ShellCommandLineGetFlag(Package, L"-n")) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CONFLICT), gShellLevel2HiiHandle, L"vol", L"-d", L"-n"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetFlag(Package, L"-n") && NewName == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellLevel2HiiHandle, L"vol", L"-n"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (NewName != NULL && StrLen(NewName) > 11) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellLevel2HiiHandle, L"vol", NewName, L"-n"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellStatus == SHELL_SUCCESS) { + ShellStatus = HandleVol( + FullPath, + DeleteMode, + NewName + ); + } + } + } + } + + SHELL_FREE_NON_NULL(FullPath); + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + + return (ShellStatus); +} -- cgit v1.2.3