diff options
author | Guo Mang <mang.guo@intel.com> | 2017-04-27 11:20:30 +0800 |
---|---|---|
committer | Guo Mang <mang.guo@intel.com> | 2017-04-27 11:20:30 +0800 |
commit | 878342a9d5543bd15129f38a4330aa4dd6c71739 (patch) | |
tree | 4e3545d9b983537c46272fd588297054a9b2736e /Core/ShellPkg/Library/UefiShellLevel2CommandsLib | |
parent | 77711a420aeb77cf10af13672c921bb29a0a74c2 (diff) | |
download | edk2-platforms-878342a9d5543bd15129f38a4330aa4dd6c71739.tar.xz |
ShellPkg: Move to new location
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Guo Mang <mang.guo@intel.com>
Diffstat (limited to 'Core/ShellPkg/Library/UefiShellLevel2CommandsLib')
18 files changed, 9030 insertions, 0 deletions
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.<BR>
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ 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<BR>
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>
+ 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.<BR>
+ Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
+ 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 <Guid/FileSystemInfo.h>
+#include <Guid/FileSystemVolumeLabelInfo.h>
+
+/**
+ 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.<BR>
+ Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
+ 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.<BR>
+ Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
+ 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 <Guid/FileSystemInfo.h>
+
+/**
+ 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"<DIR>":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.<BR>
+ (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+
+ 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 <Protocol/SimpleFileSystem.h>
+#include <Protocol/BlockIo.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HandleParsingLib.h>
+#include <Library/SortLib.h>
+
+/**
+ 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.<BR>
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ 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.<BR>
+ Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
+ 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.<BR>
+ Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
+ 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.<BR>
+ Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
+ 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.<BR>
+ Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
+ 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.<BR>
+ Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
+ 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.<BR>
+ Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
+ 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.<BR>
+ 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.<BR>
+ 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 <Uefi.h>
+
+#include <Guid/GlobalVariable.h>
+#include <Guid/ShellLibHiiGuid.h>
+
+#include <Protocol/Shell.h>
+#include <Protocol/ShellParameters.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/UnicodeCollation.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/ShellCommandLib.h>
+#include <Library/ShellLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/HiiLib.h>
+#include <Library/SortLib.h>
+#include <Library/FileHandleLib.h>
+
+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. <BR>
+#
+# 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.<BR>
+// Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
+// 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 <sname>]\r\n"
+"MAP [[-r][-v][-c][-f][-u][-t <type[,type...]>][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 <Instance>] [-s <Instance>]\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 <Instance> - 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 <Instance> - 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 <sname>]\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 <VolumeLabel>]\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.<BR>
+ Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
+ 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 <Guid/FileSystemInfo.h>
+#include <Guid/FileSystemVolumeLabelInfo.h>
+
+/**
+ 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);
+}
|