]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/Library/UefiShellLib/UefiShellLib.c
ShellPkg: Fix spelling mistake for occurred
[mirror_edk2.git] / ShellPkg / Library / UefiShellLib / UefiShellLib.c
index 5271d19490eedd50ff7694d3a0650e873ed4e2ec..c4749941a648b4083834c2debd05df07e7380dbf 100644 (file)
 /** @file\r
   Provides interface to shell functionality for shell commands and applications.\r
 \r
-  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
-  This program and the accompanying materials\r
-  are licensed and made available under the terms and conditions of the BSD License\r
-  which accompanies this distribution.  The full text of the license may be found at\r
-  http://opensource.org/licenses/bsd-license.php\r
-\r
-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+  (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
+  Copyright 2016-2018 Dell Technologies.<BR>\r
+  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
 #include "UefiShellLib.h"\r
-\r
-#define MAX_FILE_NAME_LEN 522 // (20 * (6+5+2))+1) unicode characters from EFI FAT spec (doubled for bytes)\r
-#define FIND_XXXXX_FILE_BUFFER_SIZE (SIZE_OF_EFI_FILE_INFO + MAX_FILE_NAME_LEN)\r
+#include <Library/SortLib.h>\r
+#include <Library/BaseLib.h>\r
 \r
 //\r
-// This is not static since it's extern in the .h file\r
+// globals...\r
 //\r
 SHELL_PARAM_ITEM EmptyParamList[] = {\r
   {NULL, TypeMax}\r
   };\r
+SHELL_PARAM_ITEM SfoParamList[] = {\r
+  {L"-sfo", TypeFlag},\r
+  {NULL, TypeMax}\r
+  };\r
+EFI_SHELL_ENVIRONMENT2        *mEfiShellEnvironment2;\r
+EFI_SHELL_INTERFACE           *mEfiShellInterface;\r
+EFI_SHELL_PROTOCOL            *gEfiShellProtocol;\r
+EFI_SHELL_PARAMETERS_PROTOCOL *gEfiShellParametersProtocol;\r
+EFI_HANDLE                    mEfiShellEnvironment2Handle;\r
+FILE_HANDLE_FUNCTION_MAP      FileFunctionMap;\r
+EFI_UNICODE_COLLATION_PROTOCOL  *mUnicodeCollationProtocol;\r
 \r
-//\r
-// Static file globals for the shell library\r
-//\r
-STATIC EFI_SHELL_ENVIRONMENT2        *mEfiShellEnvironment2;\r
-STATIC EFI_SHELL_INTERFACE           *mEfiShellInterface;\r
-STATIC EFI_SHELL_PROTOCOL            *mEfiShellProtocol;\r
-STATIC EFI_SHELL_PARAMETERS_PROTOCOL *mEfiShellParametersProtocol;\r
-STATIC EFI_HANDLE                    mEfiShellEnvironment2Handle;\r
-STATIC FILE_HANDLE_FUNCTION_MAP      FileFunctionMap;\r
-STATIC UINTN                         mTotalParameterCount;\r
-STATIC CHAR16                        *mPostReplaceFormat;\r
-STATIC CHAR16                        *mPostReplaceFormat2;\r
+/**\r
+  Return a clean, fully-qualified version of an input path.  If the return value\r
+  is non-NULL the caller must free the memory when it is no longer needed.\r
+\r
+  If asserts are disabled, and if the input parameter is NULL, NULL is returned.\r
+\r
+  If there is not enough memory available to create the fully-qualified path or\r
+  a copy of the input path, NULL is returned.\r
+\r
+  If there is no working directory, a clean copy of Path is returned.\r
+\r
+  Otherwise, the current file system or working directory (as appropriate) is\r
+  prepended to Path and the resulting path is cleaned and returned.\r
+\r
+  NOTE: If the input path is an empty string, then the current working directory\r
+  (if it exists) is returned.  In other words, an empty input path is treated\r
+  exactly the same as ".".\r
+\r
+  @param[in] Path  A pointer to some file or directory path.\r
+\r
+  @retval NULL          The input path is NULL or out of memory.\r
+\r
+  @retval non-NULL      A pointer to a clean, fully-qualified version of Path.\r
+                        If there is no working directory, then a pointer to a\r
+                        clean, but not necessarily fully-qualified version of\r
+                        Path.  The caller must free this memory when it is no\r
+                        longer needed.\r
+**/\r
+CHAR16*\r
+EFIAPI\r
+FullyQualifyPath(\r
+  IN     CONST CHAR16     *Path\r
+  )\r
+{\r
+  CONST CHAR16         *WorkingPath;\r
+  CONST CHAR16         *InputPath;\r
+  CHAR16               *CharPtr;\r
+  CHAR16               *InputFileSystem;\r
+  UINTN                FileSystemCharCount;\r
+  CHAR16               *FullyQualifiedPath;\r
+  UINTN                Size;\r
+\r
+  FullyQualifiedPath = NULL;\r
+\r
+  ASSERT(Path != NULL);\r
+  //\r
+  // Handle erroneous input when asserts are disabled.\r
+  //\r
+  if (Path == NULL) {\r
+    return NULL;\r
+  }\r
+  //\r
+  // In paths that contain ":", like fs0:dir/file.ext and fs2:\fqpath\file.ext,\r
+  // we  have to consider the file system part separately from the "path" part.\r
+  // If there is a file system in the path, we have to get the current working\r
+  // directory for that file system. Then we need to use the part of the path\r
+  // following the ":".  If a path does not contain ":", we use it as given.\r
+  //\r
+  InputPath = StrStr(Path, L":");\r
+  if (InputPath != NULL) {\r
+    InputPath++;\r
+    FileSystemCharCount = ((UINTN)InputPath - (UINTN)Path + sizeof(CHAR16)) / sizeof(CHAR16);\r
+    InputFileSystem = AllocateCopyPool(FileSystemCharCount * sizeof(CHAR16), Path);\r
+    if (InputFileSystem != NULL) {\r
+      InputFileSystem[FileSystemCharCount - 1] = CHAR_NULL;\r
+    }\r
+    WorkingPath = ShellGetCurrentDir(InputFileSystem);\r
+    SHELL_FREE_NON_NULL(InputFileSystem);\r
+  } else {\r
+    InputPath = Path;\r
+    WorkingPath = ShellGetEnvironmentVariable(L"cwd");\r
+  }\r
+\r
+  if (WorkingPath == NULL) {\r
+    //\r
+    // With no working directory, all we can do is copy and clean the input path.\r
+    //\r
+    FullyQualifiedPath = AllocateCopyPool(StrSize(Path), Path);\r
+  } else {\r
+    //\r
+    // Allocate space for both strings plus one more character.\r
+    //\r
+    Size = StrSize(WorkingPath) + StrSize(InputPath);\r
+    FullyQualifiedPath = AllocateZeroPool(Size);\r
+    if (FullyQualifiedPath == NULL) {\r
+      //\r
+      // Try to copy and clean just the input. No harm if not enough memory.\r
+      //\r
+      FullyQualifiedPath = AllocateCopyPool(StrSize(Path), Path);\r
+    } else {\r
+      if (*InputPath == L'\\' || *InputPath == L'/') {\r
+        //\r
+        // Absolute path: start with the current working directory, then\r
+        // truncate the new path after the file system part.\r
+        //\r
+        StrCpyS(FullyQualifiedPath, Size/sizeof(CHAR16), WorkingPath);\r
+        CharPtr = StrStr(FullyQualifiedPath, L":");\r
+        if (CharPtr != NULL) {\r
+          *(CharPtr + 1) = CHAR_NULL;\r
+        }\r
+      } else {\r
+        //\r
+        // Relative path: start with the working directory and append "\".\r
+        //\r
+        StrCpyS(FullyQualifiedPath, Size/sizeof(CHAR16), WorkingPath);\r
+        StrCatS(FullyQualifiedPath, Size/sizeof(CHAR16), L"\\");\r
+      }\r
+      //\r
+      // Now append the absolute or relative path.\r
+      //\r
+      StrCatS(FullyQualifiedPath, Size/sizeof(CHAR16), InputPath);\r
+    }\r
+  }\r
+\r
+  PathCleanUpDirectories(FullyQualifiedPath);\r
+\r
+  return FullyQualifiedPath;\r
+}\r
 \r
 /**\r
   Check if a Unicode character is a hexadecimal character.\r
 \r
   This internal function checks if a Unicode character is a\r
-  decimal character.  The valid hexadecimal character is\r
+  numeric character.  The valid hexadecimal characters are\r
   L'0' to L'9', L'a' to L'f', or L'A' to L'F'.\r
 \r
-\r
   @param  Char  The character to check against.\r
 \r
   @retval TRUE  If the Char is a hexadecmial character.\r
@@ -55,18 +166,46 @@ BOOLEAN
 EFIAPI\r
 ShellIsHexaDecimalDigitCharacter (\r
   IN      CHAR16                    Char\r
-  ) {\r
+  )\r
+{\r
   return (BOOLEAN) ((Char >= L'0' && Char <= L'9') || (Char >= L'A' && Char <= L'F') || (Char >= L'a' && Char <= L'f'));\r
 }\r
 \r
 /**\r
-  helper function to find ShellEnvironment2 for constructor\r
+  Check if a Unicode character is a decimal character.\r
+\r
+  This internal function checks if a Unicode character is a\r
+  decimal character.  The valid characters are\r
+  L'0' to L'9'.\r
+\r
+\r
+  @param  Char  The character to check against.\r
+\r
+  @retval TRUE  If the Char is a hexadecmial character.\r
+  @retval FALSE If the Char is not a hexadecmial character.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+ShellIsDecimalDigitCharacter (\r
+  IN      CHAR16                    Char\r
+  )\r
+{\r
+  return (BOOLEAN) (Char >= L'0' && Char <= L'9');\r
+}\r
+\r
+/**\r
+  Helper function to find ShellEnvironment2 for constructor.\r
+\r
+  @param[in] ImageHandle    A copy of the calling image's handle.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES    Memory allocation failed.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 ShellFindSE2 (\r
   IN EFI_HANDLE        ImageHandle\r
-  ) {\r
+  )\r
+{\r
   EFI_STATUS  Status;\r
   EFI_HANDLE  *Buffer;\r
   UINTN       BufferSize;\r
@@ -80,11 +219,11 @@ ShellFindSE2 (
                              ImageHandle,\r
                              NULL,\r
                              EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
-                             );\r
+                            );\r
   //\r
   // look for the mEfiShellEnvironment2 protocol at a higher level\r
   //\r
-  if (EFI_ERROR (Status) || !(CompareGuid (&mEfiShellEnvironment2->SESGuid, &gEfiShellEnvironment2ExtGuid) != FALSE)){\r
+  if (EFI_ERROR (Status) || !(CompareGuid (&mEfiShellEnvironment2->SESGuid, &gEfiShellEnvironment2ExtGuid))){\r
     //\r
     // figure out how big of a buffer we need.\r
     //\r
@@ -93,19 +232,21 @@ ShellFindSE2 (
                                 NULL, // ignored for ByProtocol\r
                                 &BufferSize,\r
                                 Buffer\r
-                                );\r
+                               );\r
     //\r
     // maybe it's not there???\r
     //\r
     if (Status == EFI_BUFFER_TOO_SMALL) {\r
-      Buffer = (EFI_HANDLE*)AllocatePool(BufferSize);\r
-      ASSERT(Buffer != NULL);\r
+      Buffer = (EFI_HANDLE*)AllocateZeroPool(BufferSize);\r
+      if (Buffer == NULL) {\r
+        return (EFI_OUT_OF_RESOURCES);\r
+      }\r
       Status = gBS->LocateHandle (ByProtocol,\r
                                   &gEfiShellEnvironment2Guid,\r
                                   NULL, // ignored for ByProtocol\r
                                   &BufferSize,\r
                                   Buffer\r
-                                  );\r
+                                 );\r
     }\r
     if (!EFI_ERROR (Status) && Buffer != NULL) {\r
       //\r
@@ -119,8 +260,8 @@ ShellFindSE2 (
                                    ImageHandle,\r
                                    NULL,\r
                                    EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
-                                   );\r
-         if (CompareGuid (&mEfiShellEnvironment2->SESGuid, &gEfiShellEnvironment2ExtGuid) != FALSE) {\r
+                                  );\r
+         if (CompareGuid (&mEfiShellEnvironment2->SESGuid, &gEfiShellEnvironment2ExtGuid)) {\r
           mEfiShellEnvironment2Handle = Buffer[HandleIndex];\r
           Status = EFI_SUCCESS;\r
           break;\r
@@ -134,49 +275,65 @@ ShellFindSE2 (
   return (Status);\r
 }\r
 \r
+/**\r
+  Function to do most of the work of the constructor.  Allows for calling\r
+  multiple times without complete re-initialization.\r
+\r
+  @param[in] ImageHandle  A copy of the ImageHandle.\r
+  @param[in] SystemTable  A pointer to the SystemTable for the application.\r
+\r
+  @retval EFI_SUCCESS   The operationw as successful.\r
+**/\r
 EFI_STATUS\r
-EFIAPI\r
 ShellLibConstructorWorker (\r
   IN EFI_HANDLE        ImageHandle,\r
   IN EFI_SYSTEM_TABLE  *SystemTable\r
-  ) {\r
-  EFI_STATUS Status;\r
-\r
-  mPostReplaceFormat = AllocateZeroPool (PcdGet16 (PcdShellPrintBufferSize));\r
-  ASSERT (mPostReplaceFormat != NULL);\r
-  mPostReplaceFormat2 = AllocateZeroPool (PcdGet16 (PcdShellPrintBufferSize));\r
-  ASSERT (mPostReplaceFormat2 != NULL);\r
-\r
-  //\r
-  // Set the parameter count to an invalid number\r
-  //\r
-  mTotalParameterCount = (UINTN)(-1);\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
 \r
-  //\r
-  // UEFI 2.0 shell interfaces (used preferentially)\r
-  //\r
-  Status = gBS->OpenProtocol(ImageHandle,\r
-                             &gEfiShellProtocolGuid,\r
-                             (VOID **)&mEfiShellProtocol,\r
-                             ImageHandle,\r
-                             NULL,\r
-                             EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
-                             );\r
-  if (EFI_ERROR(Status)) {\r
-    mEfiShellProtocol = NULL;\r
+  if (gEfiShellProtocol == NULL) {\r
+    //\r
+    // UEFI 2.0 shell interfaces (used preferentially)\r
+    //\r
+    Status = gBS->OpenProtocol (\r
+      ImageHandle,\r
+      &gEfiShellProtocolGuid,\r
+      (VOID **)&gEfiShellProtocol,\r
+      ImageHandle,\r
+      NULL,\r
+      EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+    );\r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // Search for the shell protocol\r
+      //\r
+      Status = gBS->LocateProtocol (\r
+        &gEfiShellProtocolGuid,\r
+        NULL,\r
+        (VOID **)&gEfiShellProtocol\r
+      );\r
+      if (EFI_ERROR (Status)) {\r
+        gEfiShellProtocol = NULL;\r
+      }\r
+    }\r
   }\r
-  Status = gBS->OpenProtocol(ImageHandle,\r
-                             &gEfiShellParametersProtocolGuid,\r
-                             (VOID **)&mEfiShellParametersProtocol,\r
-                             ImageHandle,\r
-                             NULL,\r
-                             EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
-                             );\r
-  if (EFI_ERROR(Status)) {\r
-    mEfiShellParametersProtocol = NULL;\r
+\r
+  if (gEfiShellParametersProtocol == NULL) {\r
+    Status = gBS->OpenProtocol (\r
+      ImageHandle,\r
+      &gEfiShellParametersProtocolGuid,\r
+      (VOID **)&gEfiShellParametersProtocol,\r
+      ImageHandle,\r
+      NULL,\r
+      EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+    );\r
+    if (EFI_ERROR (Status)) {\r
+      gEfiShellParametersProtocol = NULL;\r
+    }\r
   }\r
 \r
-  if (mEfiShellParametersProtocol == NULL || mEfiShellProtocol == NULL) {\r
+  if (gEfiShellProtocol == NULL) {\r
     //\r
     // Moved to seperate function due to complexity\r
     //\r
@@ -192,38 +349,43 @@ ShellLibConstructorWorker (
                                ImageHandle,\r
                                NULL,\r
                                EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
-                               );\r
+                              );\r
     if (EFI_ERROR(Status)) {\r
       mEfiShellInterface = NULL;\r
     }\r
   }\r
+\r
   //\r
-  // only success getting 2 of either the old or new, but no 1/2 and 1/2\r
+  // Getting either EDK Shell's ShellEnvironment2 and ShellInterface protocol\r
+  //  or UEFI Shell's Shell protocol.\r
+  // When ShellLib is linked to a driver producing DynamicCommand protocol,\r
+  //  ShellParameters protocol is set by DynamicCommand.Handler().\r
   //\r
-  if ((mEfiShellEnvironment2 != NULL && mEfiShellInterface          != NULL) ||\r
-      (mEfiShellProtocol     != NULL && mEfiShellParametersProtocol != NULL)    ) {\r
-    if (mEfiShellProtocol != NULL) {\r
-      FileFunctionMap.GetFileInfo     = mEfiShellProtocol->GetFileInfo;\r
-      FileFunctionMap.SetFileInfo     = mEfiShellProtocol->SetFileInfo;\r
-      FileFunctionMap.ReadFile        = mEfiShellProtocol->ReadFile;\r
-      FileFunctionMap.WriteFile       = mEfiShellProtocol->WriteFile;\r
-      FileFunctionMap.CloseFile       = mEfiShellProtocol->CloseFile;\r
-      FileFunctionMap.DeleteFile      = mEfiShellProtocol->DeleteFile;\r
-      FileFunctionMap.GetFilePosition = mEfiShellProtocol->GetFilePosition;\r
-      FileFunctionMap.SetFilePosition = mEfiShellProtocol->SetFilePosition;\r
-      FileFunctionMap.FlushFile       = mEfiShellProtocol->FlushFile;\r
-      FileFunctionMap.GetFileSize     = mEfiShellProtocol->GetFileSize;\r
+  if ((mEfiShellEnvironment2 != NULL && mEfiShellInterface != NULL) ||\r
+      (gEfiShellProtocol     != NULL)\r
+      ) {\r
+    if (gEfiShellProtocol != NULL) {\r
+      FileFunctionMap.GetFileInfo     = gEfiShellProtocol->GetFileInfo;\r
+      FileFunctionMap.SetFileInfo     = gEfiShellProtocol->SetFileInfo;\r
+      FileFunctionMap.ReadFile        = gEfiShellProtocol->ReadFile;\r
+      FileFunctionMap.WriteFile       = gEfiShellProtocol->WriteFile;\r
+      FileFunctionMap.CloseFile       = gEfiShellProtocol->CloseFile;\r
+      FileFunctionMap.DeleteFile      = gEfiShellProtocol->DeleteFile;\r
+      FileFunctionMap.GetFilePosition = gEfiShellProtocol->GetFilePosition;\r
+      FileFunctionMap.SetFilePosition = gEfiShellProtocol->SetFilePosition;\r
+      FileFunctionMap.FlushFile       = gEfiShellProtocol->FlushFile;\r
+      FileFunctionMap.GetFileSize     = gEfiShellProtocol->GetFileSize;\r
     } else {\r
-      FileFunctionMap.GetFileInfo     = FileHandleGetInfo;\r
-      FileFunctionMap.SetFileInfo     = FileHandleSetInfo;\r
-      FileFunctionMap.ReadFile        = FileHandleRead;\r
-      FileFunctionMap.WriteFile       = FileHandleWrite;\r
-      FileFunctionMap.CloseFile       = FileHandleClose;\r
-      FileFunctionMap.DeleteFile      = FileHandleDelete;\r
-      FileFunctionMap.GetFilePosition = FileHandleGetPosition;\r
-      FileFunctionMap.SetFilePosition = FileHandleSetPosition;\r
-      FileFunctionMap.FlushFile       = FileHandleFlush;\r
-      FileFunctionMap.GetFileSize     = FileHandleGetSize;\r
+      FileFunctionMap.GetFileInfo     = (EFI_SHELL_GET_FILE_INFO)FileHandleGetInfo;\r
+      FileFunctionMap.SetFileInfo     = (EFI_SHELL_SET_FILE_INFO)FileHandleSetInfo;\r
+      FileFunctionMap.ReadFile        = (EFI_SHELL_READ_FILE)FileHandleRead;\r
+      FileFunctionMap.WriteFile       = (EFI_SHELL_WRITE_FILE)FileHandleWrite;\r
+      FileFunctionMap.CloseFile       = (EFI_SHELL_CLOSE_FILE)FileHandleClose;\r
+      FileFunctionMap.DeleteFile      = (EFI_SHELL_DELETE_FILE)FileHandleDelete;\r
+      FileFunctionMap.GetFilePosition = (EFI_SHELL_GET_FILE_POSITION)FileHandleGetPosition;\r
+      FileFunctionMap.SetFilePosition = (EFI_SHELL_SET_FILE_POSITION)FileHandleSetPosition;\r
+      FileFunctionMap.FlushFile       = (EFI_SHELL_FLUSH_FILE)FileHandleFlush;\r
+      FileFunctionMap.GetFileSize     = (EFI_SHELL_GET_FILE_SIZE)FileHandleGetSize;\r
     }\r
     return (EFI_SUCCESS);\r
   }\r
@@ -245,16 +407,14 @@ EFIAPI
 ShellLibConstructor (\r
   IN EFI_HANDLE        ImageHandle,\r
   IN EFI_SYSTEM_TABLE  *SystemTable\r
-  ) {\r
-\r
-\r
+  )\r
+{\r
   mEfiShellEnvironment2       = NULL;\r
-  mEfiShellProtocol           = NULL;\r
-  mEfiShellParametersProtocol = NULL;\r
+  gEfiShellProtocol           = NULL;\r
+  gEfiShellParametersProtocol = NULL;\r
   mEfiShellInterface          = NULL;\r
   mEfiShellEnvironment2Handle = NULL;\r
-  mPostReplaceFormat          = NULL;\r
-  mPostReplaceFormat2         = NULL;\r
+  mUnicodeCollationProtocol   = NULL;\r
 \r
   //\r
   // verify that auto initialize is not set false\r
@@ -267,52 +427,60 @@ ShellLibConstructor (
 }\r
 \r
 /**\r
-  Destructory for the library.  free any resources.\r
+  Destructor for the library.  free any resources.\r
+\r
+  @param[in] ImageHandle  A copy of the ImageHandle.\r
+  @param[in] SystemTable  A pointer to the SystemTable for the application.\r
+\r
+  @retval EFI_SUCCESS   The operation was successful.\r
+  @return               An error from the CloseProtocol function.\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
 ShellLibDestructor (\r
   IN EFI_HANDLE        ImageHandle,\r
   IN EFI_SYSTEM_TABLE  *SystemTable\r
-  ) {\r
+  )\r
+{\r
+  EFI_STATUS           Status;\r
+\r
   if (mEfiShellEnvironment2 != NULL) {\r
-    gBS->CloseProtocol(mEfiShellEnvironment2Handle==NULL?ImageHandle:mEfiShellEnvironment2Handle,\r
+    Status = gBS->CloseProtocol(mEfiShellEnvironment2Handle==NULL?ImageHandle:mEfiShellEnvironment2Handle,\r
                        &gEfiShellEnvironment2Guid,\r
                        ImageHandle,\r
                        NULL);\r
-    mEfiShellEnvironment2 = NULL;\r
+    if (!EFI_ERROR (Status)) {\r
+      mEfiShellEnvironment2       = NULL;\r
+      mEfiShellEnvironment2Handle = NULL;\r
+    }\r
   }\r
   if (mEfiShellInterface != NULL) {\r
-    gBS->CloseProtocol(ImageHandle,\r
+    Status = gBS->CloseProtocol(ImageHandle,\r
                        &gEfiShellInterfaceGuid,\r
                        ImageHandle,\r
                        NULL);\r
-    mEfiShellInterface = NULL;\r
+    if (!EFI_ERROR (Status)) {\r
+      mEfiShellInterface = NULL;\r
+    }\r
   }\r
-  if (mEfiShellProtocol != NULL) {\r
-    gBS->CloseProtocol(ImageHandle,\r
+  if (gEfiShellProtocol != NULL) {\r
+    Status = gBS->CloseProtocol(ImageHandle,\r
                        &gEfiShellProtocolGuid,\r
                        ImageHandle,\r
                        NULL);\r
-    mEfiShellProtocol = NULL;\r
+    if (!EFI_ERROR (Status)) {\r
+      gEfiShellProtocol = NULL;\r
+    }\r
   }\r
-  if (mEfiShellParametersProtocol != NULL) {\r
-    gBS->CloseProtocol(ImageHandle,\r
+  if (gEfiShellParametersProtocol != NULL) {\r
+    Status = gBS->CloseProtocol(ImageHandle,\r
                        &gEfiShellParametersProtocolGuid,\r
                        ImageHandle,\r
                        NULL);\r
-    mEfiShellParametersProtocol = NULL;\r
-  }\r
-  mEfiShellEnvironment2Handle = NULL;\r
-\r
-  if (mPostReplaceFormat != NULL) {\r
-    FreePool(mPostReplaceFormat);\r
-  }\r
-  if (mPostReplaceFormat2 != NULL) {\r
-    FreePool(mPostReplaceFormat2);\r
+    if (!EFI_ERROR (Status)) {\r
+      gEfiShellParametersProtocol = NULL;\r
+    }\r
   }\r
-  mPostReplaceFormat          = NULL;\r
-  mPostReplaceFormat2         = NULL;\r
 \r
   return (EFI_SUCCESS);\r
 }\r
@@ -333,7 +501,11 @@ ShellLibDestructor (
 EFI_STATUS\r
 EFIAPI\r
 ShellInitialize (\r
-  ) {\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+\r
   //\r
   // if auto initialize is not false then skip\r
   //\r
@@ -344,7 +516,8 @@ ShellInitialize (
   //\r
   // deinit the current stuff\r
   //\r
-  ASSERT_EFI_ERROR(ShellLibDestructor(gImageHandle, gST));\r
+  Status = ShellLibDestructor (gImageHandle, gST);\r
+  ASSERT_EFI_ERROR (Status);\r
 \r
   //\r
   // init the new stuff\r
@@ -369,35 +542,38 @@ ShellInitialize (
 EFI_FILE_INFO*\r
 EFIAPI\r
 ShellGetFileInfo (\r
-  IN EFI_FILE_HANDLE            FileHandle\r
-  ) {\r
+  IN SHELL_FILE_HANDLE                     FileHandle\r
+  )\r
+{\r
   return (FileFunctionMap.GetFileInfo(FileHandle));\r
 }\r
 \r
 /**\r
-  This function will set the information about the file for the opened handle\r
+  This function sets the information about the file for the opened handle\r
   specified.\r
 \r
-  @param  FileHandle            The file handle of the file for which information\r
-  is being set\r
+  @param[in]  FileHandle        The file handle of the file for which information\r
+                                is being set.\r
 \r
-  @param  FileInfo              The infotmation to set.\r
+  @param[in]  FileInfo          The information to set.\r
 \r
-  @retval EFI_SUCCESS          The information was set.\r
-  @retval EFI_UNSUPPORTED The InformationType is not known.\r
-  @retval EFI_NO_MEDIA         The device has no medium.\r
-  @retval EFI_DEVICE_ERROR     The device reported an error.\r
-  @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
-  @retval EFI_WRITE_PROTECTED  The file or medium is write protected.\r
-  @retval EFI_ACCESS_DENIED    The file was opened read only.\r
-  @retval EFI_VOLUME_FULL      The volume is full.\r
+  @retval EFI_SUCCESS           The information was set.\r
+  @retval EFI_INVALID_PARAMETER A parameter was out of range or invalid.\r
+  @retval EFI_UNSUPPORTED       The FileHandle does not support FileInfo.\r
+  @retval EFI_NO_MEDIA          The device has no medium.\r
+  @retval EFI_DEVICE_ERROR      The device reported an error.\r
+  @retval EFI_VOLUME_CORRUPTED  The file system structures are corrupted.\r
+  @retval EFI_WRITE_PROTECTED   The file or medium is write protected.\r
+  @retval EFI_ACCESS_DENIED     The file was opened read only.\r
+  @retval EFI_VOLUME_FULL       The volume is full.\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
 ShellSetFileInfo (\r
-  IN EFI_FILE_HANDLE           FileHandle,\r
+  IN SHELL_FILE_HANDLE                    FileHandle,\r
   IN EFI_FILE_INFO              *FileInfo\r
-  ) {\r
+  )\r
+{\r
   return (FileFunctionMap.SetFileInfo(FileHandle, FileInfo));\r
 }\r
 \r
@@ -407,58 +583,54 @@ ShellSetFileInfo (
   This function opens a file with the open mode according to the file path. The\r
   Attributes is valid only for EFI_FILE_MODE_CREATE.\r
 \r
-  @param  FilePath                 on input the device path to the file.  On output\r
+  @param  FilePath        on input the device path to the file.  On output\r
                           the remaining device path.\r
-  @param  DeviceHandle         pointer to the system device handle.\r
-  @param  FileHandle             pointer to the file handle.\r
-  @param  OpenMode                 the mode to open the file with.\r
-  @param  Attributes             the file's file attributes.\r
-\r
-  @retval EFI_SUCCESS                  The information was set.\r
-  @retval EFI_INVALID_PARAMETER        One of the parameters has an invalid value.\r
-  @retval EFI_UNSUPPORTED            Could not open the file path.\r
-  @retval EFI_NOT_FOUND                The specified file could not be found on the\r
+  @param  FileHandle      pointer to the file handle.\r
+  @param  OpenMode        the mode to open the file with.\r
+  @param  Attributes      the file's file attributes.\r
+\r
+  @retval EFI_SUCCESS           The information was set.\r
+  @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
+  @retval EFI_UNSUPPORTED       Could not open the file path.\r
+  @retval EFI_NOT_FOUND         The specified file could not be found on the\r
                                 device or the file system could not be found on\r
                                 the device.\r
-  @retval EFI_NO_MEDIA               The device has no medium.\r
-  @retval EFI_MEDIA_CHANGED        The device has a different medium in it or the\r
+  @retval EFI_NO_MEDIA          The device has no medium.\r
+  @retval EFI_MEDIA_CHANGED     The device has a different medium in it or the\r
                                 medium is no longer supported.\r
-  @retval EFI_DEVICE_ERROR         The device reported an error.\r
-  @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
-  @retval EFI_WRITE_PROTECTED    The file or medium is write protected.\r
-  @retval EFI_ACCESS_DENIED    The file was opened read only.\r
-  @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the\r
+  @retval EFI_DEVICE_ERROR      The device reported an error.\r
+  @retval EFI_VOLUME_CORRUPTED  The file system structures are corrupted.\r
+  @retval EFI_WRITE_PROTECTED   The file or medium is write protected.\r
+  @retval EFI_ACCESS_DENIED     The file was opened read only.\r
+  @retval EFI_OUT_OF_RESOURCES  Not enough resources were available to open the\r
                                 file.\r
-  @retval EFI_VOLUME_FULL            The volume is full.\r
+  @retval EFI_VOLUME_FULL       The volume is full.\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
 ShellOpenFileByDevicePath(\r
-  IN OUT EFI_DEVICE_PATH_PROTOCOL        **FilePath,\r
-  OUT EFI_HANDLE                       *DeviceHandle,\r
-  OUT EFI_FILE_HANDLE                  *FileHandle,\r
-  IN UINT64                            OpenMode,\r
-  IN UINT64                            Attributes\r
-  ) {\r
-  CHAR16      *FileName;\r
-  EFI_STATUS  Status;\r
-  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *EfiSimpleFileSystemProtocol;\r
-  EFI_FILE_HANDLE LastHandle;\r
+  IN OUT EFI_DEVICE_PATH_PROTOCOL     **FilePath,\r
+  OUT SHELL_FILE_HANDLE               *FileHandle,\r
+  IN UINT64                           OpenMode,\r
+  IN UINT64                           Attributes\r
+  )\r
+{\r
+  CHAR16                          *FileName;\r
+  EFI_STATUS                      Status;\r
+  EFI_FILE_PROTOCOL               *File;\r
+\r
+  if (FilePath == NULL || FileHandle == NULL) {\r
+    return (EFI_INVALID_PARAMETER);\r
+  }\r
 \r
-  //\r
-  // ASERT for FileHandle, FilePath, and DeviceHandle being NULL\r
-  //\r
-  ASSERT(FilePath != NULL);\r
-  ASSERT(FileHandle != NULL);\r
-  ASSERT(DeviceHandle != NULL);\r
   //\r
   // which shell interface should we use\r
   //\r
-  if (mEfiShellProtocol != NULL) {\r
+  if (gEfiShellProtocol != NULL) {\r
     //\r
     // use UEFI Shell 2.0 method.\r
     //\r
-    FileName = mEfiShellProtocol->GetFilePathFromDevicePath(*FilePath);\r
+    FileName = gEfiShellProtocol->GetFilePathFromDevicePath(*FilePath);\r
     if (FileName == NULL) {\r
       return (EFI_INVALID_PARAMETER);\r
     }\r
@@ -471,83 +643,15 @@ ShellOpenFileByDevicePath(
   //\r
   // use old shell method.\r
   //\r
-  Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid,\r
-                                  FilePath,\r
-                                  DeviceHandle);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-  Status = gBS->OpenProtocol(*DeviceHandle,\r
-                             &gEfiSimpleFileSystemProtocolGuid,\r
-                             (VOID**)&EfiSimpleFileSystemProtocol,\r
-                             gImageHandle,\r
-                             NULL,\r
-                             EFI_OPEN_PROTOCOL_GET_PROTOCOL);\r
+  Status = EfiOpenFileByDevicePath (FilePath, &File, OpenMode, Attributes);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
-  Status = EfiSimpleFileSystemProtocol->OpenVolume(EfiSimpleFileSystemProtocol, FileHandle);\r
-  if (EFI_ERROR (Status)) {\r
-    FileHandle = NULL;\r
-    return Status;\r
-  }\r
 \r
   //\r
-  // go down directories one node at a time.\r
+  // This is a weak spot since if the undefined SHELL_FILE_HANDLE format changes this must change also!\r
   //\r
-  while (!IsDevicePathEnd (*FilePath)) {\r
-    //\r
-    // For file system access each node should be a file path component\r
-    //\r
-    if (DevicePathType    (*FilePath) != MEDIA_DEVICE_PATH ||\r
-        DevicePathSubType (*FilePath) != MEDIA_FILEPATH_DP\r
-        ) {\r
-      FileHandle = NULL;\r
-      return (EFI_INVALID_PARAMETER);\r
-    }\r
-    //\r
-    // Open this file path node\r
-    //\r
-    LastHandle  = *FileHandle;\r
-    *FileHandle = NULL;\r
-\r
-    //\r
-    // Try to test opening an existing file\r
-    //\r
-    Status = LastHandle->Open (\r
-                          LastHandle,\r
-                          FileHandle,\r
-                          ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,\r
-                          OpenMode &~EFI_FILE_MODE_CREATE,\r
-                          0\r
-                          );\r
-\r
-    //\r
-    // see if the error was that it needs to be created\r
-    //\r
-    if ((EFI_ERROR (Status)) && (OpenMode != (OpenMode &~EFI_FILE_MODE_CREATE))) {\r
-      Status = LastHandle->Open (\r
-                            LastHandle,\r
-                            FileHandle,\r
-                            ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,\r
-                            OpenMode,\r
-                            Attributes\r
-                            );\r
-    }\r
-    //\r
-    // Close the last node\r
-    //\r
-    LastHandle->Close (LastHandle);\r
-\r
-    if (EFI_ERROR(Status)) {\r
-      return (Status);\r
-    }\r
-\r
-    //\r
-    // Get the next node\r
-    //\r
-    *FilePath = NextDevicePathNode (*FilePath);\r
-  }\r
+  *FileHandle = (VOID*)File;\r
   return (EFI_SUCCESS);\r
 }\r
 \r
@@ -558,61 +662,110 @@ ShellOpenFileByDevicePath(
   otherwise, the Filehandle is NULL. The Attributes is valid only for\r
   EFI_FILE_MODE_CREATE.\r
 \r
-  if FileNAme is NULL then ASSERT()\r
+  if FileName is NULL then ASSERT()\r
 \r
-  @param  FileName               pointer to file name\r
-  @param  FileHandle           pointer to the file handle.\r
-  @param  OpenMode               the mode to open the file with.\r
-  @param  Attributes           the file's file attributes.\r
+  @param  FileName      pointer to file name\r
+  @param  FileHandle    pointer to the file handle.\r
+  @param  OpenMode      the mode to open the file with.\r
+  @param  Attributes    the file's file attributes.\r
 \r
-  @retval EFI_SUCCESS                  The information was set.\r
-  @retval EFI_INVALID_PARAMETER        One of the parameters has an invalid value.\r
-  @retval EFI_UNSUPPORTED            Could not open the file path.\r
-  @retval EFI_NOT_FOUND                The specified file could not be found on the\r
+  @retval EFI_SUCCESS           The information was set.\r
+  @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
+  @retval EFI_UNSUPPORTED       Could not open the file path.\r
+  @retval EFI_NOT_FOUND         The specified file could not be found on the\r
                                 device or the file system could not be found\r
                                 on the device.\r
-  @retval EFI_NO_MEDIA               The device has no medium.\r
-  @retval EFI_MEDIA_CHANGED        The device has a different medium in it or the\r
+  @retval EFI_NO_MEDIA          The device has no medium.\r
+  @retval EFI_MEDIA_CHANGED     The device has a different medium in it or the\r
                                 medium is no longer supported.\r
-  @retval EFI_DEVICE_ERROR         The device reported an error.\r
-  @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
-  @retval EFI_WRITE_PROTECTED    The file or medium is write protected.\r
-  @retval EFI_ACCESS_DENIED        The file was opened read only.\r
-  @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the\r
+  @retval EFI_DEVICE_ERROR      The device reported an error.\r
+  @retval EFI_VOLUME_CORRUPTED  The file system structures are corrupted.\r
+  @retval EFI_WRITE_PROTECTED   The file or medium is write protected.\r
+  @retval EFI_ACCESS_DENIED     The file was opened read only.\r
+  @retval EFI_OUT_OF_RESOURCES  Not enough resources were available to open the\r
                                 file.\r
-  @retval EFI_VOLUME_FULL            The volume is full.\r
+  @retval EFI_VOLUME_FULL       The volume is full.\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
 ShellOpenFileByName(\r
-  IN CONST CHAR16                          *FileName,\r
-  OUT EFI_FILE_HANDLE           *FileHandle,\r
+  IN CONST CHAR16               *FileName,\r
+  OUT SHELL_FILE_HANDLE         *FileHandle,\r
   IN UINT64                     OpenMode,\r
-  IN UINT64                            Attributes\r
-  ) {\r
-  EFI_HANDLE                    DeviceHandle;\r
+  IN UINT64                     Attributes\r
+  )\r
+{\r
   EFI_DEVICE_PATH_PROTOCOL      *FilePath;\r
   EFI_STATUS                    Status;\r
   EFI_FILE_INFO                 *FileInfo;\r
+  CHAR16                        *FileNameCopy;\r
+  EFI_STATUS                    Status2;\r
 \r
   //\r
   // ASSERT if FileName is NULL\r
   //\r
   ASSERT(FileName != NULL);\r
 \r
-  if (mEfiShellProtocol != NULL) {\r
+  if (FileName == NULL) {\r
+    return (EFI_INVALID_PARAMETER);\r
+  }\r
+\r
+  if (gEfiShellProtocol != NULL) {\r
+    if ((OpenMode & EFI_FILE_MODE_CREATE) == EFI_FILE_MODE_CREATE) {\r
+\r
+      //\r
+      // Create only a directory\r
+      //\r
+      if ((Attributes & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY) {\r
+        return ShellCreateDirectory(FileName, FileHandle);\r
+      }\r
+\r
+      //\r
+      // Create the directory to create the file in\r
+      //\r
+      FileNameCopy = AllocateCopyPool (StrSize (FileName), FileName);\r
+      if (FileNameCopy == NULL) {\r
+        return (EFI_OUT_OF_RESOURCES);\r
+      }\r
+      PathCleanUpDirectories (FileNameCopy);\r
+      if (PathRemoveLastItem (FileNameCopy)) {\r
+        if (!EFI_ERROR(ShellCreateDirectory (FileNameCopy, FileHandle))) {\r
+          ShellCloseFile (FileHandle);\r
+        }\r
+      }\r
+      SHELL_FREE_NON_NULL (FileNameCopy);\r
+    }\r
+\r
     //\r
-    // Use UEFI Shell 2.0 method\r
+    // Use UEFI Shell 2.0 method to create the file\r
     //\r
-    Status = mEfiShellProtocol->OpenFileByName(FileName,\r
+    Status = gEfiShellProtocol->OpenFileByName(FileName,\r
                                                FileHandle,\r
                                                OpenMode);\r
-    if (!EFI_ERROR(Status) && ((OpenMode & EFI_FILE_MODE_CREATE) != 0)){\r
+    if (EFI_ERROR(Status)) {\r
+      return Status;\r
+    }\r
+\r
+    if (mUnicodeCollationProtocol == NULL) {\r
+      Status = gBS->LocateProtocol (&gEfiUnicodeCollation2ProtocolGuid, NULL, (VOID**)&mUnicodeCollationProtocol);\r
+      if (EFI_ERROR (Status)) {\r
+        gEfiShellProtocol->CloseFile (*FileHandle);\r
+        return Status;\r
+      }\r
+    }\r
+\r
+    if ((mUnicodeCollationProtocol->StriColl (mUnicodeCollationProtocol, (CHAR16*)FileName, L"NUL") != 0) &&\r
+        (mUnicodeCollationProtocol->StriColl (mUnicodeCollationProtocol, (CHAR16*)FileName, L"NULL") != 0) &&\r
+         !EFI_ERROR(Status) && ((OpenMode & EFI_FILE_MODE_CREATE) != 0)){\r
       FileInfo = FileFunctionMap.GetFileInfo(*FileHandle);\r
       ASSERT(FileInfo != NULL);\r
       FileInfo->Attribute = Attributes;\r
-      Status = FileFunctionMap.SetFileInfo(*FileHandle, FileInfo);\r
+      Status2 = FileFunctionMap.SetFileInfo(*FileHandle, FileInfo);\r
       FreePool(FileInfo);\r
+      if (EFI_ERROR (Status2)) {\r
+        gEfiShellProtocol->CloseFile(*FileHandle);\r
+      }\r
+      Status = Status2;\r
     }\r
     return (Status);\r
   }\r
@@ -623,12 +776,11 @@ ShellOpenFileByName(
   //\r
   ASSERT(mEfiShellEnvironment2 != NULL);\r
   FilePath = mEfiShellEnvironment2->NameToPath ((CHAR16*)FileName);\r
-  if (FileDevicePath != NULL) {\r
+  if (FilePath != NULL) {\r
     return (ShellOpenFileByDevicePath(&FilePath,\r
-                                      &DeviceHandle,\r
                                       FileHandle,\r
                                       OpenMode,\r
-                                      Attributes ));\r
+                                      Attributes));\r
   }\r
   return (EFI_DEVICE_ERROR);\r
 }\r
@@ -639,47 +791,48 @@ ShellOpenFileByName(
   otherwise, the Filehandle is NULL. If the directory already existed, this\r
   function opens the existing directory.\r
 \r
-  @param  DirectoryName                pointer to directory name\r
-  @param  FileHandle             pointer to the file handle.\r
+  @param  DirectoryName   pointer to directory name\r
+  @param  FileHandle      pointer to the file handle.\r
 \r
-  @retval EFI_SUCCESS                  The information was set.\r
-  @retval EFI_INVALID_PARAMETER        One of the parameters has an invalid value.\r
-  @retval EFI_UNSUPPORTED            Could not open the file path.\r
-  @retval EFI_NOT_FOUND                The specified file could not be found on the\r
+  @retval EFI_SUCCESS           The information was set.\r
+  @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
+  @retval EFI_UNSUPPORTED       Could not open the file path.\r
+  @retval EFI_NOT_FOUND         The specified file could not be found on the\r
                                 device or the file system could not be found\r
                                 on the device.\r
-  @retval EFI_NO_MEDIA               The device has no medium.\r
-  @retval EFI_MEDIA_CHANGED        The device has a different medium in it or the\r
+  @retval EFI_NO_MEDIA          The device has no medium.\r
+  @retval EFI_MEDIA_CHANGED     The device has a different medium in it or the\r
                                 medium is no longer supported.\r
-  @retval EFI_DEVICE_ERROR         The device reported an error.\r
-  @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
-  @retval EFI_WRITE_PROTECTED    The file or medium is write protected.\r
-  @retval EFI_ACCESS_DENIED        The file was opened read only.\r
-  @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the\r
+  @retval EFI_DEVICE_ERROR      The device reported an error.\r
+  @retval EFI_VOLUME_CORRUPTED  The file system structures are corrupted.\r
+  @retval EFI_WRITE_PROTECTED   The file or medium is write protected.\r
+  @retval EFI_ACCESS_DENIED     The file was opened read only.\r
+  @retval EFI_OUT_OF_RESOURCES  Not enough resources were available to open the\r
                                 file.\r
-  @retval EFI_VOLUME_FULL            The volume is full.\r
+  @retval EFI_VOLUME_FULL       The volume is full.\r
   @sa ShellOpenFileByName\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
 ShellCreateDirectory(\r
   IN CONST CHAR16             *DirectoryName,\r
-  OUT EFI_FILE_HANDLE         *FileHandle\r
-  ) {\r
-  if (mEfiShellProtocol != NULL) {\r
+  OUT SHELL_FILE_HANDLE                  *FileHandle\r
+  )\r
+{\r
+  if (gEfiShellProtocol != NULL) {\r
     //\r
     // Use UEFI Shell 2.0 method\r
     //\r
-    return (mEfiShellProtocol->CreateFile(DirectoryName,\r
+    return (gEfiShellProtocol->CreateFile(DirectoryName,\r
                           EFI_FILE_DIRECTORY,\r
                           FileHandle\r
-                          ));\r
+                         ));\r
   } else {\r
     return (ShellOpenFileByName(DirectoryName,\r
                                 FileHandle,\r
                                 EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,\r
                                 EFI_FILE_DIRECTORY\r
-                                ));\r
+                               ));\r
   }\r
 }\r
 \r
@@ -704,21 +857,22 @@ ShellCreateDirectory(
                                 the number of bytes written.\r
   @param Buffer                 the buffer to put read data into.\r
 \r
-  @retval EFI_SUCCESS            Data was read.\r
-  @retval EFI_NO_MEDIA         The device has no media.\r
-  @retval EFI_DEVICE_ERROR     The device reported an error.\r
-  @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
-  @retval EFI_BUFFER_TO_SMALL  Buffer is too small. ReadSize contains required\r
+  @retval EFI_SUCCESS           Data was read.\r
+  @retval EFI_NO_MEDIA          The device has no media.\r
+  @retval EFI_DEVICE_ERROR  The device reported an error.\r
+  @retval EFI_VOLUME_CORRUPTED  The file system structures are corrupted.\r
+  @retval EFI_BUFFER_TO_SMALL Buffer is too small. ReadSize contains required\r
                                 size.\r
 \r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
 ShellReadFile(\r
-  IN EFI_FILE_HANDLE            FileHandle,\r
+  IN SHELL_FILE_HANDLE                     FileHandle,\r
   IN OUT UINTN                  *BufferSize,\r
   OUT VOID                      *Buffer\r
-  ) {\r
+  )\r
+{\r
   return (FileFunctionMap.ReadFile(FileHandle, BufferSize, Buffer));\r
 }\r
 \r
@@ -738,22 +892,23 @@ ShellReadFile(
                               the number of bytes written.\r
   @param Buffer               the buffer containing data to write is stored.\r
 \r
- @retval EFI_SUCCESS           Data was written.\r
- @retval EFI_UNSUPPORTED           Writes to an open directory are not supported.\r
- @retval EFI_NO_MEDIA          The device has no media.\r
- @retval EFI_DEVICE_ERROR          The device reported an error.\r
- @retval EFI_VOLUME_CORRUPTED  The file system structures are corrupted.\r
- @retval EFI_WRITE_PROTECTED   The device is write-protected.\r
- @retval EFI_ACCESS_DENIED       The file was open for read only.\r
- @retval EFI_VOLUME_FULL           The volume is full.\r
+ @retval EFI_SUCCESS          Data was written.\r
+ @retval EFI_UNSUPPORTED      Writes to an open directory are not supported.\r
+ @retval EFI_NO_MEDIA         The device has no media.\r
+ @retval EFI_DEVICE_ERROR     The device reported an error.\r
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
+ @retval EFI_WRITE_PROTECTED  The device is write-protected.\r
+ @retval EFI_ACCESS_DENIED    The file was open for read only.\r
+ @retval EFI_VOLUME_FULL      The volume is full.\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
 ShellWriteFile(\r
-  IN EFI_FILE_HANDLE            FileHandle,\r
+  IN SHELL_FILE_HANDLE          FileHandle,\r
   IN OUT UINTN                  *BufferSize,\r
   IN VOID                       *Buffer\r
-  ) {\r
+  )\r
+{\r
   return (FileFunctionMap.WriteFile(FileHandle, BufferSize, Buffer));\r
 }\r
 \r
@@ -771,8 +926,9 @@ ShellWriteFile(
 EFI_STATUS\r
 EFIAPI\r
 ShellCloseFile (\r
-  IN EFI_FILE_HANDLE            *FileHandle\r
-  ) {\r
+  IN SHELL_FILE_HANDLE                     *FileHandle\r
+  )\r
+{\r
   return (FileFunctionMap.CloseFile(*FileHandle));\r
 }\r
 \r
@@ -788,13 +944,14 @@ ShellCloseFile (
   @retval EFI_SUCCESS           the file was closed sucessfully\r
   @retval EFI_WARN_DELETE_FAILURE the handle was closed, but the file was not\r
                                 deleted\r
-  @retval INVALID_PARAMETER            One of the parameters has an invalid value.\r
+  @retval INVALID_PARAMETER     One of the parameters has an invalid value.\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
 ShellDeleteFile (\r
-  IN EFI_FILE_HANDLE           *FileHandle\r
-  ) {\r
+  IN SHELL_FILE_HANDLE            *FileHandle\r
+  )\r
+{\r
   return (FileFunctionMap.DeleteFile(*FileHandle));\r
 }\r
 \r
@@ -820,9 +977,10 @@ ShellDeleteFile (
 EFI_STATUS\r
 EFIAPI\r
 ShellSetFilePosition (\r
-  IN EFI_FILE_HANDLE           FileHandle,\r
-  IN UINT64            Position\r
-  ) {\r
+  IN SHELL_FILE_HANDLE              FileHandle,\r
+  IN UINT64             Position\r
+  )\r
+{\r
   return (FileFunctionMap.SetFilePosition(FileHandle, Position));\r
 }\r
 \r
@@ -844,9 +1002,10 @@ ShellSetFilePosition (
 EFI_STATUS\r
 EFIAPI\r
 ShellGetFilePosition (\r
-  IN EFI_FILE_HANDLE            FileHandle,\r
+  IN SHELL_FILE_HANDLE                     FileHandle,\r
   OUT UINT64                    *Position\r
-  ) {\r
+  )\r
+{\r
   return (FileFunctionMap.GetFilePosition(FileHandle, Position));\r
 }\r
 /**\r
@@ -866,20 +1025,25 @@ ShellGetFilePosition (
 EFI_STATUS\r
 EFIAPI\r
 ShellFlushFile (\r
-  IN EFI_FILE_HANDLE            FileHandle\r
-  ) {\r
+  IN SHELL_FILE_HANDLE                     FileHandle\r
+  )\r
+{\r
   return (FileFunctionMap.FlushFile(FileHandle));\r
 }\r
 \r
-/**\r
-  Retrieves the first file from a directory\r
+/** Retrieve first entry from a directory.\r
+\r
+  This function takes an open directory handle and gets information from the\r
+  first entry in the directory.  A buffer is allocated to contain\r
+  the information and a pointer to the buffer is returned in *Buffer.  The\r
+  caller can use ShellFindNextFile() to get subsequent directory entries.\r
 \r
-  This function opens a directory and gets the first file's info in the\r
-  directory. Caller can use ShellFindNextFile() to get other files.  When\r
-  complete the caller is responsible for calling FreePool() on Buffer.\r
+  The buffer will be freed by ShellFindNextFile() when the last directory\r
+  entry is read.  Otherwise, the caller must free the buffer, using FreePool,\r
+  when finished with it.\r
 \r
-  @param DirHandle              The file handle of the directory to search\r
-  @param Buffer                 Pointer to buffer for file's information\r
+  @param[in]  DirHandle         The file handle of the directory to search.\r
+  @param[out] Buffer            The pointer to the buffer for the file's information.\r
 \r
   @retval EFI_SUCCESS           Found the first file.\r
   @retval EFI_NOT_FOUND         Cannot find the directory.\r
@@ -892,27 +1056,27 @@ ShellFlushFile (
 EFI_STATUS\r
 EFIAPI\r
 ShellFindFirstFile (\r
-  IN EFI_FILE_HANDLE            DirHandle,\r
+  IN SHELL_FILE_HANDLE                     DirHandle,\r
   OUT EFI_FILE_INFO             **Buffer\r
-  ) {\r
+  )\r
+{\r
   //\r
   // pass to file handle lib\r
   //\r
   return (FileHandleFindFirstFile(DirHandle, Buffer));\r
 }\r
-/**\r
-  Retrieves the next file in a directory.\r
+/** Retrieve next entries from a directory.\r
 \r
-  To use this function, caller must call the LibFindFirstFile() to get the\r
-  first file, and then use this function get other files. This function can be\r
-  called for several times to get each file's information in the directory. If\r
-  the call of ShellFindNextFile() got the last file in the directory, the next\r
-  call of this function has no file to get. *NoFile will be set to TRUE and the\r
-  Buffer memory will be automatically freed.\r
+  To use this function, the caller must first call the ShellFindFirstFile()\r
+  function to get the first directory entry.  Subsequent directory entries are\r
+  retrieved by using the ShellFindNextFile() function.  This function can\r
+  be called several times to get each entry from the directory.  If the call of\r
+  ShellFindNextFile() retrieved the last directory entry, the next call of\r
+  this function will set *NoFile to TRUE and free the buffer.\r
 \r
-  @param DirHandle              the file handle of the directory\r
-  @param Buffer                                    pointer to buffer for file's information\r
-  @param NoFile                                    pointer to boolean when last file is found\r
+  @param[in]  DirHandle         The file handle of the directory.\r
+  @param[out] Buffer            The pointer to buffer for file's information.\r
+  @param[out] NoFile            The pointer to boolean when last file is found.\r
 \r
   @retval EFI_SUCCESS           Found the next file, or reached last file\r
   @retval EFI_NO_MEDIA          The device has no media.\r
@@ -922,10 +1086,11 @@ ShellFindFirstFile (
 EFI_STATUS\r
 EFIAPI\r
 ShellFindNextFile(\r
-  IN EFI_FILE_HANDLE             DirHandle,\r
+  IN SHELL_FILE_HANDLE                      DirHandle,\r
   OUT EFI_FILE_INFO              *Buffer,\r
   OUT BOOLEAN                    *NoFile\r
-  ) {\r
+  )\r
+{\r
   //\r
   // pass to file handle lib\r
   //\r
@@ -949,9 +1114,10 @@ ShellFindNextFile(
 EFI_STATUS\r
 EFIAPI\r
 ShellGetFileSize (\r
-  IN EFI_FILE_HANDLE            FileHandle,\r
+  IN SHELL_FILE_HANDLE                     FileHandle,\r
   OUT UINT64                    *Size\r
-  ) {\r
+  )\r
+{\r
   return (FileFunctionMap.GetFileSize(FileHandle, Size));\r
 }\r
 /**\r
@@ -971,12 +1137,12 @@ ShellGetExecutionBreakFlag(
   //\r
   // Check for UEFI Shell 2.0 protocols\r
   //\r
-  if (mEfiShellProtocol != NULL) {\r
+  if (gEfiShellProtocol != NULL) {\r
 \r
     //\r
     // We are using UEFI Shell 2.0; see if the event has been triggered\r
     //\r
-    if (gBS->CheckEvent(mEfiShellProtocol->ExecutionBreak) != EFI_SUCCESS) {\r
+    if (gBS->CheckEvent(gEfiShellProtocol->ExecutionBreak) != EFI_SUCCESS) {\r
       return (FALSE);\r
     }\r
     return (TRUE);\r
@@ -985,8 +1151,11 @@ ShellGetExecutionBreakFlag(
   //\r
   // using EFI Shell; call the function to check\r
   //\r
-  ASSERT(mEfiShellEnvironment2 != NULL);\r
-  return (mEfiShellEnvironment2->GetExecutionBreak());\r
+  if (mEfiShellEnvironment2 != NULL) {\r
+    return (mEfiShellEnvironment2->GetExecutionBreak());\r
+  }\r
+\r
+  return (FALSE);\r
 }\r
 /**\r
   return the value of an environment variable\r
@@ -1008,19 +1177,18 @@ ShellGetEnvironmentVariable (
   //\r
   // Check for UEFI Shell 2.0 protocols\r
   //\r
-  if (mEfiShellProtocol != NULL) {\r
-    return (mEfiShellProtocol->GetEnv(EnvKey));\r
+  if (gEfiShellProtocol != NULL) {\r
+    return (gEfiShellProtocol->GetEnv(EnvKey));\r
   }\r
 \r
   //\r
-  // ASSERT that we must have EFI shell\r
+  // Check for EFI shell\r
   //\r
-  ASSERT(mEfiShellEnvironment2 != NULL);\r
+  if (mEfiShellEnvironment2 != NULL) {\r
+    return (mEfiShellEnvironment2->GetEnv((CHAR16*)EnvKey));\r
+  }\r
 \r
-  //\r
-  // using EFI Shell\r
-  //\r
-  return (mEfiShellEnvironment2->GetEnv((CHAR16*)EnvKey));\r
+  return NULL;\r
 }\r
 /**\r
   set the value of an environment variable\r
@@ -1053,8 +1221,8 @@ ShellSetEnvironmentVariable (
   //\r
   // Check for UEFI Shell 2.0 protocols\r
   //\r
-  if (mEfiShellProtocol != NULL) {\r
-    return (mEfiShellProtocol->SetEnv(EnvKey, EnvVal, Volatile));\r
+  if (gEfiShellProtocol != NULL) {\r
+    return (gEfiShellProtocol->SetEnv(EnvKey, EnvVal, Volatile));\r
   }\r
 \r
   //\r
@@ -1062,33 +1230,36 @@ ShellSetEnvironmentVariable (
   //\r
   return (EFI_UNSUPPORTED);\r
 }\r
+\r
 /**\r
-  cause the shell to parse and execute a command line.\r
+  Cause the shell to parse and execute a command line.\r
 \r
   This function creates a nested instance of the shell and executes the specified\r
-command (CommandLine) with the specified environment (Environment). Upon return,\r
-the status code returned by the specified command is placed in StatusCode.\r
-If Environment is NULL, then the current environment is used and all changes made\r
-by the commands executed will be reflected in the current environment. If the\r
-Environment is non-NULL, then the changes made will be discarded.\r
-The CommandLine is executed from the current working directory on the current\r
-device.\r
-\r
-EnvironmentVariables and Status are only supported for UEFI Shell 2.0.\r
-Output is only supported for pre-UEFI Shell 2.0\r
-\r
-  @param ImageHandle            Parent image that is starting the operation\r
-  @param CommandLine            pointer to NULL terminated command line.\r
-  @param Output                 true to display debug output.  false to hide it.\r
-  @param EnvironmentVariables   optional pointer to array of environment variables\r
-                                in the form "x=y".  if NULL current set is used.\r
-  @param Status                 the status of the run command line.\r
-\r
-  @retval EFI_SUCCESS           the operation completed sucessfully.  Status\r
-                                contains the status code returned.\r
-  @retval EFI_INVALID_PARAMETER a parameter contains an invalid value\r
-  @retval EFI_OUT_OF_RESOURCES  out of resources\r
-  @retval EFI_UNSUPPORTED       the operation is not allowed.\r
+  command (CommandLine) with the specified environment (Environment). Upon return,\r
+  the status code returned by the specified command is placed in StatusCode.\r
+  If Environment is NULL, then the current environment is used and all changes made\r
+  by the commands executed will be reflected in the current environment. If the\r
+  Environment is non-NULL, then the changes made will be discarded.\r
+  The CommandLine is executed from the current working directory on the current\r
+  device.\r
+\r
+  The EnvironmentVariables pararemeter is ignored in a pre-UEFI Shell 2.0\r
+  environment.  The values pointed to by the parameters will be unchanged by the\r
+  ShellExecute() function.  The Output parameter has no effect in a\r
+  UEFI Shell 2.0 environment.\r
+\r
+  @param[in] ParentHandle         The parent image starting the operation.\r
+  @param[in] CommandLine          The pointer to a NULL terminated command line.\r
+  @param[in] Output               True to display debug output.  False to hide it.\r
+  @param[in] EnvironmentVariables Optional pointer to array of environment variables\r
+                                  in the form "x=y".  If NULL, the current set is used.\r
+  @param[out] Status              The status of the run command line.\r
+\r
+  @retval EFI_SUCCESS             The operation completed sucessfully.  Status\r
+                                  contains the status code returned.\r
+  @retval EFI_INVALID_PARAMETER   A parameter contains an invalid value.\r
+  @retval EFI_OUT_OF_RESOURCES    Out of resources.\r
+  @retval EFI_UNSUPPORTED         The operation is not allowed.\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
@@ -1100,30 +1271,66 @@ ShellExecute (
   OUT EFI_STATUS                *Status OPTIONAL\r
   )\r
 {\r
+  EFI_STATUS                CmdStatus;\r
   //\r
   // Check for UEFI Shell 2.0 protocols\r
   //\r
-  if (mEfiShellProtocol != NULL) {\r
+  if (gEfiShellProtocol != NULL) {\r
     //\r
     // Call UEFI Shell 2.0 version (not using Output parameter)\r
     //\r
-    return (mEfiShellProtocol->Execute(ParentHandle,\r
+    return (gEfiShellProtocol->Execute(ParentHandle,\r
                                       CommandLine,\r
                                       EnvironmentVariables,\r
                                       Status));\r
   }\r
+\r
   //\r
-  // ASSERT that we must have EFI shell\r
-  //\r
-  ASSERT(mEfiShellEnvironment2 != NULL);\r
-  //\r
-  // Call EFI Shell version (not using EnvironmentVariables or Status parameters)\r
-  // Due to oddity in the EFI shell we want to dereference the ParentHandle here\r
+  // Check for EFI shell\r
   //\r
-  return (mEfiShellEnvironment2->Execute(*ParentHandle,\r
-                                        CommandLine,\r
-                                        Output));\r
+  if (mEfiShellEnvironment2 != NULL) {\r
+    //\r
+    // Call EFI Shell version.\r
+    //\r
+    // Due to an unfixable bug in the EdkShell implementation, we must\r
+    // dereference "ParentHandle" here:\r
+    //\r
+    // 1. The EFI shell installs the EFI_SHELL_ENVIRONMENT2 protocol,\r
+    //    identified by gEfiShellEnvironment2Guid.\r
+    // 2. The Execute() member function takes "ParentImageHandle" as first\r
+    //    parameter, with type (EFI_HANDLE*).\r
+    // 3. In the EdkShell implementation, SEnvExecute() implements the\r
+    //    Execute() member function. It passes "ParentImageHandle" correctly to\r
+    //    SEnvDoExecute().\r
+    // 4. SEnvDoExecute() takes the (EFI_HANDLE*), and passes it directly --\r
+    //    without de-referencing -- to the HandleProtocol() boot service.\r
+    // 5. But HandleProtocol() takes an EFI_HANDLE.\r
+    //\r
+    // Therefore we must\r
+    // - de-reference "ParentHandle" here, to mask the bug in\r
+    //   SEnvDoExecute(), and\r
+    // - pass the resultant EFI_HANDLE as an (EFI_HANDLE*).\r
+    //\r
+    CmdStatus = (mEfiShellEnvironment2->Execute((EFI_HANDLE *)*ParentHandle,\r
+                                          CommandLine,\r
+                                          Output));\r
+    //\r
+    // No Status output parameter so just use the returned status\r
+    //\r
+    if (Status != NULL) {\r
+      *Status = CmdStatus;\r
+    }\r
+    //\r
+    // If there was an error, we can't tell if it was from the command or from\r
+    // the Execute() function, so we'll just assume the shell ran successfully\r
+    // and the error came from the command.\r
+    //\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  return (EFI_UNSUPPORTED);\r
 }\r
+\r
 /**\r
   Retreives the current directory path\r
 \r
@@ -1131,6 +1338,8 @@ ShellExecute (
   name. If the DeviceName is not NULL, it returns the current directory name\r
   on specified drive.\r
 \r
+  Note that the current directory string should exclude the tailing backslash character.\r
+\r
   @param DeviceName             the name of the drive to get directory on\r
 \r
   @retval NULL                  the directory does not exist\r
@@ -1139,20 +1348,24 @@ ShellExecute (
 CONST CHAR16*\r
 EFIAPI\r
 ShellGetCurrentDir (\r
-  IN CHAR16                     *DeviceName OPTIONAL\r
+  IN CHAR16                     * CONST DeviceName OPTIONAL\r
   )\r
 {\r
   //\r
   // Check for UEFI Shell 2.0 protocols\r
   //\r
-  if (mEfiShellProtocol != NULL) {\r
-    return (mEfiShellProtocol->GetCurDir(DeviceName));\r
+  if (gEfiShellProtocol != NULL) {\r
+    return (gEfiShellProtocol->GetCurDir(DeviceName));\r
   }\r
+\r
   //\r
-  // ASSERT that we must have EFI shell\r
+  // Check for EFI shell\r
   //\r
-  ASSERT(mEfiShellEnvironment2 != NULL);\r
-  return (mEfiShellEnvironment2->CurDir(DeviceName));\r
+  if (mEfiShellEnvironment2 != NULL) {\r
+    return (mEfiShellEnvironment2->CurDir(DeviceName));\r
+  }\r
+\r
+  return (NULL);\r
 }\r
 /**\r
   sets (enabled or disabled) the page break mode\r
@@ -1175,43 +1388,45 @@ ShellSetPageBreakMode (
     //\r
     // check for UEFI Shell 2.0\r
     //\r
-    if (mEfiShellProtocol != NULL) {\r
+    if (gEfiShellProtocol != NULL) {\r
       //\r
       // Enable with UEFI 2.0 Shell\r
       //\r
-      mEfiShellProtocol->EnablePageBreak();\r
+      gEfiShellProtocol->EnablePageBreak();\r
       return;\r
     } else {\r
       //\r
-      // ASSERT that must have EFI Shell\r
-      //\r
-      ASSERT(mEfiShellEnvironment2 != NULL);\r
+      // Check for EFI shell\r
       //\r
-      // Enable with EFI Shell\r
-      //\r
-      mEfiShellEnvironment2->EnablePageBreak (DEFAULT_INIT_ROW, DEFAULT_AUTO_LF);\r
-      return;\r
+      if (mEfiShellEnvironment2 != NULL) {\r
+        //\r
+        // Enable with EFI Shell\r
+        //\r
+        mEfiShellEnvironment2->EnablePageBreak (DEFAULT_INIT_ROW, DEFAULT_AUTO_LF);\r
+        return;\r
+      }\r
     }\r
   } else {\r
     //\r
     // check for UEFI Shell 2.0\r
     //\r
-    if (mEfiShellProtocol != NULL) {\r
+    if (gEfiShellProtocol != NULL) {\r
       //\r
       // Disable with UEFI 2.0 Shell\r
       //\r
-      mEfiShellProtocol->DisablePageBreak();\r
+      gEfiShellProtocol->DisablePageBreak();\r
       return;\r
     } else {\r
       //\r
-      // ASSERT that must have EFI Shell\r
-      //\r
-      ASSERT(mEfiShellEnvironment2 != NULL);\r
+      // Check for EFI shell\r
       //\r
-      // Disable with EFI Shell\r
-      //\r
-      mEfiShellEnvironment2->DisablePageBreak ();\r
-      return;\r
+      if (mEfiShellEnvironment2 != NULL) {\r
+        //\r
+        // Disable with EFI Shell\r
+        //\r
+        mEfiShellEnvironment2->DisablePageBreak ();\r
+        return;\r
+      }\r
     }\r
   }\r
 }\r
@@ -1225,7 +1440,7 @@ typedef struct {
   EFI_STATUS Status;\r
   CHAR16 *FullName;\r
   CHAR16 *FileName;\r
-  EFI_FILE_HANDLE Handle;\r
+  SHELL_FILE_HANDLE          Handle;\r
   EFI_FILE_INFO *Info;\r
 } EFI_SHELL_FILE_INFO_NO_CONST;\r
 \r
@@ -1239,12 +1454,11 @@ typedef struct {
   the ShellCloseFileMetaArg function.\r
 \r
   @param[in] FileList           the EFI shell list type\r
-  @param[in,out] ListHead      the list to add to\r
+  @param[in, out] ListHead      the list to add to\r
 \r
   @retval the resultant head of the double linked new format list;\r
 **/\r
 LIST_ENTRY*\r
-EFIAPI\r
 InternalShellConvertFileListType (\r
   IN LIST_ENTRY                 *FileList,\r
   IN OUT LIST_ENTRY             *ListHead\r
@@ -1265,11 +1479,18 @@ InternalShellConvertFileListType (
   //\r
   for (Link = FileList->ForwardLink; Link != FileList; Link = Link->ForwardLink) {\r
     OldInfo = CR (Link, SHELL_FILE_ARG, Link, SHELL_FILE_ARG_SIGNATURE);\r
+    ASSERT(OldInfo           != NULL);\r
+\r
+    //\r
+    // Skip ones that failed to open...\r
+    //\r
+    if (OldInfo->Status != EFI_SUCCESS) {\r
+      continue;\r
+    }\r
 \r
     //\r
     // make sure the old list was valid\r
     //\r
-    ASSERT(OldInfo           != NULL);\r
     ASSERT(OldInfo->Info     != NULL);\r
     ASSERT(OldInfo->FullName != NULL);\r
     ASSERT(OldInfo->FileName != NULL);\r
@@ -1278,6 +1499,11 @@ InternalShellConvertFileListType (
     // allocate a new EFI_SHELL_FILE_INFO object\r
     //\r
     NewInfo               = AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));\r
+    if (NewInfo == NULL) {\r
+      ShellCloseFileMetaArg((EFI_SHELL_FILE_INFO**)(&ListHead));\r
+      ListHead = NULL;\r
+      break;\r
+    }\r
 \r
     //\r
     // copy the simple items\r
@@ -1291,23 +1517,29 @@ InternalShellConvertFileListType (
     //\r
     // allocate new space to copy strings and structure\r
     //\r
-    NewInfo->FullName     = AllocateZeroPool(StrSize(OldInfo->FullName));\r
-    NewInfo->FileName     = AllocateZeroPool(StrSize(OldInfo->FileName));\r
-    NewInfo->Info         = AllocateZeroPool((UINTN)OldInfo->Info->Size);\r
+    NewInfo->FullName     = AllocateCopyPool(StrSize(OldInfo->FullName), OldInfo->FullName);\r
+    NewInfo->FileName     = AllocateCopyPool(StrSize(OldInfo->FileName), OldInfo->FileName);\r
+    NewInfo->Info         = AllocateCopyPool((UINTN)OldInfo->Info->Size, OldInfo->Info);\r
 \r
     //\r
     // make sure all the memory allocations were sucessful\r
     //\r
-    ASSERT(NewInfo->FullName != NULL);\r
-    ASSERT(NewInfo->FileName != NULL);\r
-    ASSERT(NewInfo->Info     != NULL);\r
+    if (NULL == NewInfo->FullName || NewInfo->FileName == NULL || NewInfo->Info == NULL) {\r
+      //\r
+      // Free the partially allocated new node\r
+      //\r
+      SHELL_FREE_NON_NULL(NewInfo->FullName);\r
+      SHELL_FREE_NON_NULL(NewInfo->FileName);\r
+      SHELL_FREE_NON_NULL(NewInfo->Info);\r
+      SHELL_FREE_NON_NULL(NewInfo);\r
 \r
-    //\r
-    // Copt the strings and structure\r
-    //\r
-    StrCpy(NewInfo->FullName, OldInfo->FullName);\r
-    StrCpy(NewInfo->FileName, OldInfo->FileName);\r
-    gBS->CopyMem (NewInfo->Info, OldInfo->Info, (UINTN)OldInfo->Info->Size);\r
+      //\r
+      // Free the previously converted stuff\r
+      //\r
+      ShellCloseFileMetaArg((EFI_SHELL_FILE_INFO**)(&ListHead));\r
+      ListHead = NULL;\r
+      break;\r
+    }\r
 \r
     //\r
     // add that to the list\r
@@ -1320,8 +1552,8 @@ InternalShellConvertFileListType (
   Opens a group of files based on a path.\r
 \r
   This function uses the Arg to open all the matching files. Each matched\r
-  file has a SHELL_FILE_ARG structure to record the file information. These\r
-  structures are placed on the list ListHead. Users can get the SHELL_FILE_ARG\r
+  file has a SHELL_FILE_INFO structure to record the file information. These\r
+  structures are placed on the list ListHead. Users can get the SHELL_FILE_INFO\r
   structures from ListHead to access each file. This function supports wildcards\r
   and will process '?' and '*' as such.  the list must be freed with a call to\r
   ShellCloseFileMetaArg().\r
@@ -1335,8 +1567,6 @@ InternalShellConvertFileListType (
 \r
   @retval EFI_SUCCESS           the operation was sucessful and the list head\r
                                 contains the list of opened files\r
-  #retval EFI_UNSUPPORTED       a previous ShellOpenFileMetaArg must be closed first.\r
-                                *ListHead is set to NULL.\r
   @return != EFI_SUCCESS        the operation failed\r
 \r
   @sa InternalShellConvertFileListType\r
@@ -1351,6 +1581,7 @@ ShellOpenFileMetaArg (
 {\r
   EFI_STATUS                    Status;\r
   LIST_ENTRY                    mOldStyleFileList;\r
+  CHAR16                        *CleanFilePathStr;\r
 \r
   //\r
   // ASSERT that Arg and ListHead are not NULL\r
@@ -1358,74 +1589,101 @@ ShellOpenFileMetaArg (
   ASSERT(Arg      != NULL);\r
   ASSERT(ListHead != NULL);\r
 \r
+  CleanFilePathStr = NULL;\r
+\r
+  Status = InternalShellStripQuotes (Arg, &CleanFilePathStr);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
   //\r
   // Check for UEFI Shell 2.0 protocols\r
   //\r
-  if (mEfiShellProtocol != NULL) {\r
+  if (gEfiShellProtocol != NULL) {\r
     if (*ListHead == NULL) {\r
       *ListHead = (EFI_SHELL_FILE_INFO*)AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));\r
       if (*ListHead == NULL) {\r
+        FreePool(CleanFilePathStr);\r
         return (EFI_OUT_OF_RESOURCES);\r
       }\r
       InitializeListHead(&((*ListHead)->Link));\r
     }\r
-    Status = mEfiShellProtocol->OpenFileList(Arg,\r
+    Status = gEfiShellProtocol->OpenFileList(CleanFilePathStr,\r
                                            OpenMode,\r
                                            ListHead);\r
     if (EFI_ERROR(Status)) {\r
-      mEfiShellProtocol->RemoveDupInFileList(ListHead);\r
+      gEfiShellProtocol->RemoveDupInFileList(ListHead);\r
     } else {\r
-      Status = mEfiShellProtocol->RemoveDupInFileList(ListHead);\r
+      Status = gEfiShellProtocol->RemoveDupInFileList(ListHead);\r
+    }\r
+    if (*ListHead != NULL && IsListEmpty(&(*ListHead)->Link)) {\r
+      FreePool(*ListHead);\r
+      FreePool(CleanFilePathStr);\r
+      *ListHead = NULL;\r
+      return (EFI_NOT_FOUND);\r
     }\r
+    FreePool(CleanFilePathStr);\r
     return (Status);\r
   }\r
 \r
   //\r
-  // ASSERT that we must have EFI shell\r
+  // Check for EFI shell\r
   //\r
-  ASSERT(mEfiShellEnvironment2 != NULL);\r
-\r
-  //\r
-  // make sure the list head is initialized\r
-  //\r
-  InitializeListHead(&mOldStyleFileList);\r
+  if (mEfiShellEnvironment2 != NULL) {\r
+    //\r
+    // make sure the list head is initialized\r
+    //\r
+    InitializeListHead(&mOldStyleFileList);\r
 \r
-  //\r
-  // Get the EFI Shell list of files\r
-  //\r
-  Status = mEfiShellEnvironment2->FileMetaArg(Arg, &mOldStyleFileList);\r
-  if (EFI_ERROR(Status)) {\r
-    *ListHead = NULL;\r
-    return (Status);\r
-  }\r
+    //\r
+    // Get the EFI Shell list of files\r
+    //\r
+    Status = mEfiShellEnvironment2->FileMetaArg(CleanFilePathStr, &mOldStyleFileList);\r
+    if (EFI_ERROR(Status)) {\r
+      *ListHead = NULL;\r
+      FreePool(CleanFilePathStr);\r
+      return (Status);\r
+    }\r
 \r
-  if (*ListHead == NULL) {\r
-    *ListHead = (EFI_SHELL_FILE_INFO    *)AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));\r
     if (*ListHead == NULL) {\r
-      return (EFI_OUT_OF_RESOURCES);\r
+      *ListHead = (EFI_SHELL_FILE_INFO    *)AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));\r
+      if (*ListHead == NULL) {\r
+        FreePool(CleanFilePathStr);\r
+        return (EFI_OUT_OF_RESOURCES);\r
+      }\r
+      InitializeListHead(&((*ListHead)->Link));\r
     }\r
-  }\r
 \r
-  //\r
-  // Convert that to equivalent of UEFI Shell 2.0 structure\r
-  //\r
-  InternalShellConvertFileListType(&mOldStyleFileList, &(*ListHead)->Link);\r
+    //\r
+    // Convert that to equivalent of UEFI Shell 2.0 structure\r
+    //\r
+    InternalShellConvertFileListType(&mOldStyleFileList, &(*ListHead)->Link);\r
 \r
-  //\r
-  // Free the EFI Shell version that was converted.\r
-  //\r
-  mEfiShellEnvironment2->FreeFileList(&mOldStyleFileList);\r
+    //\r
+    // Free the EFI Shell version that was converted.\r
+    //\r
+    mEfiShellEnvironment2->FreeFileList(&mOldStyleFileList);\r
 \r
-  return (Status);\r
+    if ((*ListHead)->Link.ForwardLink == (*ListHead)->Link.BackLink && (*ListHead)->Link.BackLink == &((*ListHead)->Link)) {\r
+      FreePool(*ListHead);\r
+      *ListHead = NULL;\r
+      Status = EFI_NOT_FOUND;\r
+    }\r
+    FreePool(CleanFilePathStr);\r
+    return (Status);\r
+  }\r
+\r
+  FreePool(CleanFilePathStr);\r
+  return (EFI_UNSUPPORTED);\r
 }\r
 /**\r
-  Free the linked list returned from ShellOpenFileMetaArg\r
+  Free the linked list returned from ShellOpenFileMetaArg.\r
 \r
-  if ListHead is NULL then ASSERT()\r
+  if ListHead is NULL then ASSERT().\r
 \r
-  @param ListHead               the pointer to free\r
+  @param ListHead               the pointer to free.\r
 \r
-  @retval EFI_SUCCESS           the operation was sucessful\r
+  @retval EFI_SUCCESS           the operation was sucessful.\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
@@ -1443,25 +1701,28 @@ ShellCloseFileMetaArg (
   //\r
   // Check for UEFI Shell 2.0 protocols\r
   //\r
-  if (mEfiShellProtocol != NULL) {\r
-    return (mEfiShellProtocol->FreeFileList(ListHead));\r
-  } else {\r
+  if (gEfiShellProtocol != NULL) {\r
+    return (gEfiShellProtocol->FreeFileList(ListHead));\r
+  } else if (mEfiShellEnvironment2 != NULL) {\r
     //\r
     // Since this is EFI Shell version we need to free our internally made copy\r
     // of the list\r
     //\r
     for ( Node = GetFirstNode(&(*ListHead)->Link)\r
-        ; IsListEmpty(&(*ListHead)->Link) == FALSE\r
+        ; *ListHead != NULL && !IsListEmpty(&(*ListHead)->Link)\r
         ; Node = GetFirstNode(&(*ListHead)->Link)) {\r
       RemoveEntryList(Node);\r
-      ((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Handle->Close(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Handle);\r
+      ((EFI_FILE_PROTOCOL*)((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Handle)->Close(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Handle);\r
       FreePool(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->FullName);\r
       FreePool(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->FileName);\r
       FreePool(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Info);\r
       FreePool((EFI_SHELL_FILE_INFO_NO_CONST*)Node);\r
     }\r
+    SHELL_FREE_NON_NULL(*ListHead);\r
     return EFI_SUCCESS;\r
   }\r
+\r
+  return (EFI_UNSUPPORTED);\r
 }\r
 \r
 /**\r
@@ -1483,7 +1744,7 @@ ShellFindFilePath (
   )\r
 {\r
   CONST CHAR16      *Path;\r
-  EFI_FILE_HANDLE   Handle;\r
+  SHELL_FILE_HANDLE Handle;\r
   EFI_STATUS        Status;\r
   CHAR16            *RetVal;\r
   CHAR16            *TestPath;\r
@@ -1493,45 +1754,85 @@ ShellFindFilePath (
 \r
   RetVal = NULL;\r
 \r
+  //\r
+  // First make sure its not an absolute path.\r
+  //\r
+  Status = ShellOpenFileByName(FileName, &Handle, EFI_FILE_MODE_READ, 0);\r
+  if (!EFI_ERROR(Status)){\r
+    if (FileHandleIsDirectory(Handle) != EFI_SUCCESS) {\r
+      ASSERT(RetVal == NULL);\r
+      RetVal = StrnCatGrow(&RetVal, NULL, FileName, 0);\r
+      ShellCloseFile(&Handle);\r
+      return (RetVal);\r
+    } else {\r
+      ShellCloseFile(&Handle);\r
+    }\r
+  }\r
+\r
   Path = ShellGetEnvironmentVariable(L"cwd");\r
   if (Path != NULL) {\r
-    Size = StrSize(Path);\r
+    Size = StrSize(Path) + sizeof(CHAR16);\r
     Size += StrSize(FileName);\r
     TestPath = AllocateZeroPool(Size);\r
-    StrCpy(TestPath, Path);\r
-    StrCat(TestPath, FileName);\r
+    if (TestPath == NULL) {\r
+      return (NULL);\r
+    }\r
+    StrCpyS(TestPath, Size/sizeof(CHAR16), Path);\r
+    StrCatS(TestPath, Size/sizeof(CHAR16), L"\\");\r
+    StrCatS(TestPath, Size/sizeof(CHAR16), FileName);\r
     Status = ShellOpenFileByName(TestPath, &Handle, EFI_FILE_MODE_READ, 0);\r
     if (!EFI_ERROR(Status)){\r
-      RetVal = StrnCatGrow(&RetVal, NULL, TestPath, 0);\r
-      ShellCloseFile(&Handle);\r
-      FreePool(TestPath);\r
-      return (RetVal);\r
+      if (FileHandleIsDirectory(Handle) != EFI_SUCCESS) {\r
+        ASSERT(RetVal == NULL);\r
+        RetVal = StrnCatGrow(&RetVal, NULL, TestPath, 0);\r
+        ShellCloseFile(&Handle);\r
+        FreePool(TestPath);\r
+        return (RetVal);\r
+      } else {\r
+        ShellCloseFile(&Handle);\r
+      }\r
     }\r
     FreePool(TestPath);\r
   }\r
   Path = ShellGetEnvironmentVariable(L"path");\r
   if (Path != NULL) {\r
-    Size = StrSize(Path);\r
+    Size = StrSize(Path)+sizeof(CHAR16);\r
     Size += StrSize(FileName);\r
     TestPath = AllocateZeroPool(Size);\r
+    if (TestPath == NULL) {\r
+      return (NULL);\r
+    }\r
     Walker = (CHAR16*)Path;\r
     do {\r
       CopyMem(TestPath, Walker, StrSize(Walker));\r
-      TempChar = StrStr(TestPath, L";");\r
-      if (TempChar != NULL) {\r
-        *TempChar = CHAR_NULL;\r
-      }\r
-      StrCat(TestPath, FileName);\r
-      if (StrStr(Walker, L";") != NULL) {\r
-        Walker = StrStr(Walker, L";") + 1;\r
-      } else {\r
-        Walker = NULL;\r
-      }\r
-      Status = ShellOpenFileByName(TestPath, &Handle, EFI_FILE_MODE_READ, 0);\r
-      if (!EFI_ERROR(Status)){\r
-        RetVal = StrnCatGrow(&RetVal, NULL, TestPath, 0);\r
-        ShellCloseFile(&Handle);\r
-        break;\r
+      if (TestPath != NULL) {\r
+        TempChar = StrStr(TestPath, L";");\r
+        if (TempChar != NULL) {\r
+          *TempChar = CHAR_NULL;\r
+        }\r
+        if (TestPath[StrLen(TestPath)-1] != L'\\') {\r
+          StrCatS(TestPath, Size/sizeof(CHAR16), L"\\");\r
+        }\r
+        if (FileName[0] == L'\\') {\r
+          FileName++;\r
+        }\r
+        StrCatS(TestPath, Size/sizeof(CHAR16), FileName);\r
+        if (StrStr(Walker, L";") != NULL) {\r
+          Walker = StrStr(Walker, L";") + 1;\r
+        } else {\r
+          Walker = NULL;\r
+        }\r
+        Status = ShellOpenFileByName(TestPath, &Handle, EFI_FILE_MODE_READ, 0);\r
+        if (!EFI_ERROR(Status)){\r
+          if (FileHandleIsDirectory(Handle) != EFI_SUCCESS) {\r
+            ASSERT(RetVal == NULL);\r
+            RetVal = StrnCatGrow(&RetVal, NULL, TestPath, 0);\r
+            ShellCloseFile(&Handle);\r
+            break;\r
+          } else {\r
+            ShellCloseFile(&Handle);\r
+          }\r
+        }\r
       }\r
     } while (Walker != NULL && Walker[0] != CHAR_NULL);\r
     FreePool(TestPath);\r
@@ -1567,6 +1868,7 @@ ShellFindFilePathEx (
   CONST CHAR16      *ExtensionWalker;\r
   UINTN             Size;\r
   CHAR16            *TempChar;\r
+  CHAR16            *TempChar2;\r
 \r
   ASSERT(FileName != NULL);\r
   if (FileExtension == NULL) {\r
@@ -1579,10 +1881,13 @@ ShellFindFilePathEx (
   Size =  StrSize(FileName);\r
   Size += StrSize(FileExtension);\r
   TestPath = AllocateZeroPool(Size);\r
-  for (ExtensionWalker = FileExtension ;  ; ExtensionWalker = StrStr(ExtensionWalker, L";") + 1 ){\r
-    StrCpy(TestPath, FileName);\r
+  if (TestPath == NULL) {\r
+    return (NULL);\r
+  }\r
+  for (ExtensionWalker = FileExtension, TempChar2 = (CHAR16*)FileExtension;  TempChar2 != NULL ; ExtensionWalker = TempChar2 + 1){\r
+    StrCpyS(TestPath, Size/sizeof(CHAR16), FileName);\r
     if (ExtensionWalker != NULL) {\r
-      StrCat(TestPath, ExtensionWalker);\r
+      StrCatS(TestPath, Size/sizeof(CHAR16), ExtensionWalker);\r
     }\r
     TempChar = StrStr(TestPath, L";");\r
     if (TempChar != NULL) {\r
@@ -1592,12 +1897,8 @@ ShellFindFilePathEx (
     if (RetVal != NULL) {\r
       break;\r
     }\r
-    //\r
-    // Must be after first loop...\r
-    //\r
-    if (StrStr(ExtensionWalker, L";") == NULL) {\r
-      break;\r
-    }\r
+    ASSERT(ExtensionWalker != NULL);\r
+    TempChar2 = StrStr(ExtensionWalker, L";");\r
   }\r
   FreePool(TestPath);\r
   return (RetVal);\r
@@ -1606,7 +1907,7 @@ ShellFindFilePathEx (
 typedef struct {\r
   LIST_ENTRY     Link;\r
   CHAR16         *Name;\r
-  ParamType      Type;\r
+  SHELL_PARAM_TYPE      Type;\r
   CHAR16         *Value;\r
   UINTN          OriginalPosition;\r
 } SHELL_PARAM_PACKAGE;\r
@@ -1619,21 +1920,22 @@ typedef struct {
   if Name is NULL then ASSERT();\r
   if Type is NULL then ASSERT();\r
 \r
-  @param Type                   pointer to type of parameter if it was found\r
   @param Name                   pointer to Name of parameter found\r
   @param CheckList              List to check against\r
+  @param Type                   pointer to type of parameter if it was found\r
 \r
   @retval TRUE                  the Parameter was found.  Type is valid.\r
   @retval FALSE                 the Parameter was not found.  Type is not valid.\r
 **/\r
 BOOLEAN\r
-EFIAPI\r
 InternalIsOnCheckList (\r
   IN CONST CHAR16               *Name,\r
   IN CONST SHELL_PARAM_ITEM     *CheckList,\r
-  OUT ParamType                 *Type\r
-  ) {\r
+  OUT SHELL_PARAM_TYPE          *Type\r
+  )\r
+{\r
   SHELL_PARAM_ITEM              *TempListItem;\r
+  CHAR16                        *TempString;\r
 \r
   //\r
   // ASSERT that all 3 pointer parameters aren't NULL\r
@@ -1647,7 +1949,8 @@ InternalIsOnCheckList (
   //\r
   if ((StrCmp(Name, L"-?") == 0) ||\r
       (StrCmp(Name, L"-b") == 0)\r
-      ) {\r
+     ) {\r
+     *Type = TypeFlag;\r
      return (TRUE);\r
   }\r
 \r
@@ -1659,10 +1962,22 @@ InternalIsOnCheckList (
     // If the Type is TypeStart only check the first characters of the passed in param\r
     // If it matches set the type and return TRUE\r
     //\r
-    if (TempListItem->Type == TypeStart && StrnCmp(Name, TempListItem->Name, StrLen(TempListItem->Name)) == 0) {\r
-      *Type = TempListItem->Type;\r
-      return (TRUE);\r
-    } else if (StrCmp(Name, TempListItem->Name) == 0) {\r
+    if (TempListItem->Type == TypeStart) {\r
+      if (StrnCmp(Name, TempListItem->Name, StrLen(TempListItem->Name)) == 0) {\r
+        *Type = TempListItem->Type;\r
+        return (TRUE);\r
+      }\r
+      TempString = NULL;\r
+      TempString = StrnCatGrow(&TempString, NULL, Name, StrLen(TempListItem->Name));\r
+      if (TempString != NULL) {\r
+        if (StringNoCaseCompare(&TempString, &TempListItem->Name) == 0) {\r
+          *Type = TempListItem->Type;\r
+          FreePool(TempString);\r
+          return (TRUE);\r
+        }\r
+        FreePool(TempString);\r
+      }\r
+    } else if (StringNoCaseCompare(&Name, &TempListItem->Name) == 0) {\r
       *Type = TempListItem->Type;\r
       return (TRUE);\r
     }\r
@@ -1673,16 +1988,18 @@ InternalIsOnCheckList (
 /**\r
   Checks the string for indicators of "flag" status.  this is a leading '/', '-', or '+'\r
 \r
-  @param Name                   pointer to Name of parameter found\r
+  @param[in] Name               pointer to Name of parameter found\r
+  @param[in] AlwaysAllowNumbers TRUE to allow numbers, FALSE to not.\r
+  @param[in] TimeNumbers        TRUE to allow numbers with ":", FALSE otherwise.\r
 \r
   @retval TRUE                  the Parameter is a flag.\r
-  @retval FALSE                 the Parameter not a flag\r
+  @retval FALSE                 the Parameter not a flag.\r
 **/\r
 BOOLEAN\r
-EFIAPI\r
 InternalIsFlag (\r
   IN CONST CHAR16               *Name,\r
-  IN BOOLEAN                    AlwaysAllowNumbers\r
+  IN CONST BOOLEAN              AlwaysAllowNumbers,\r
+  IN CONST BOOLEAN              TimeNumbers\r
   )\r
 {\r
   //\r
@@ -1693,17 +2010,17 @@ InternalIsFlag (
   //\r
   // If we accept numbers then dont return TRUE. (they will be values)\r
   //\r
-  if (((Name[0] == L'-' || Name[0] == L'+') && ShellIsHexaDecimalDigitCharacter(Name[1])) && AlwaysAllowNumbers != FALSE) {\r
+  if (((Name[0] == L'-' || Name[0] == L'+') && InternalShellIsHexOrDecimalNumber(Name+1, FALSE, FALSE, TimeNumbers)) && AlwaysAllowNumbers) {\r
     return (FALSE);\r
   }\r
 \r
   //\r
-  // If the Name has a / or - as the first character return TRUE\r
+  // If the Name has a /, +, or - as the first character return TRUE\r
   //\r
   if ((Name[0] == L'/') ||\r
       (Name[0] == L'-') ||\r
       (Name[0] == L'+')\r
-      ) {\r
+     ) {\r
       return (TRUE);\r
   }\r
   return (FALSE);\r
@@ -1714,14 +2031,15 @@ InternalIsFlag (
 \r
   If no initialization is required, then return RETURN_SUCCESS.\r
 \r
-  @param CheckList              pointer to list of parameters to check\r
-  @param CheckPackage           pointer to pointer to list checked values\r
-  @param ProblemParam           optional pointer to pointer to unicode string for\r
+  @param[in] CheckList          pointer to list of parameters to check\r
+  @param[out] CheckPackage      pointer to pointer to list checked values\r
+  @param[out] ProblemParam      optional pointer to pointer to unicode string for\r
                                 the paramater that caused failure.  If used then the\r
                                 caller is responsible for freeing the memory.\r
-  @param AutoPageBreak          will automatically set PageBreakEnabled for "b" parameter\r
-  @param Argc                   Count of parameters in Argv\r
-  @param Argv                   pointer to array of parameters\r
+  @param[in] AutoPageBreak      will automatically set PageBreakEnabled for "b" parameter\r
+  @param[in] Argv               pointer to array of parameters\r
+  @param[in] Argc               Count of parameters in Argv\r
+  @param[in] AlwaysAllowNumbers TRUE to allow numbers always, FALSE otherwise.\r
 \r
   @retval EFI_SUCCESS           The operation completed sucessfully.\r
   @retval EFI_OUT_OF_RESOURCES  A memory allocation failed\r
@@ -1733,9 +2051,7 @@ InternalIsFlag (
                                 the invalid command line argument was returned in\r
                                 ProblemParam if provided.\r
 **/\r
-STATIC\r
 EFI_STATUS\r
-EFIAPI\r
 InternalCommandLineParse (\r
   IN CONST SHELL_PARAM_ITEM     *CheckList,\r
   OUT LIST_ENTRY                **CheckPackage,\r
@@ -1744,22 +2060,27 @@ InternalCommandLineParse (
   IN CONST CHAR16               **Argv,\r
   IN UINTN                      Argc,\r
   IN BOOLEAN                    AlwaysAllowNumbers\r
-  ) {\r
+  )\r
+{\r
   UINTN                         LoopCounter;\r
-  ParamType                     CurrentItemType;\r
+  SHELL_PARAM_TYPE              CurrentItemType;\r
   SHELL_PARAM_PACKAGE           *CurrentItemPackage;\r
   UINTN                         GetItemValue;\r
   UINTN                         ValueSize;\r
+  UINTN                         Count;\r
+  CONST CHAR16                  *TempPointer;\r
+  UINTN                         CurrentValueSize;\r
+  CHAR16                        *NewValue;\r
 \r
   CurrentItemPackage = NULL;\r
-  mTotalParameterCount = 0;\r
   GetItemValue = 0;\r
   ValueSize = 0;\r
+  Count = 0;\r
 \r
   //\r
   // If there is only 1 item we dont need to do anything\r
   //\r
-  if (Argc <= 1) {\r
+  if (Argc < 1) {\r
     *CheckPackage = NULL;\r
     return (EFI_SUCCESS);\r
   }\r
@@ -1774,6 +2095,10 @@ InternalCommandLineParse (
   // initialize the linked list\r
   //\r
   *CheckPackage = (LIST_ENTRY*)AllocateZeroPool(sizeof(LIST_ENTRY));\r
+  if (*CheckPackage == NULL) {\r
+    return (EFI_OUT_OF_RESOURCES);\r
+  }\r
+\r
   InitializeListHead(*CheckPackage);\r
 \r
   //\r
@@ -1784,7 +2109,7 @@ InternalCommandLineParse (
       //\r
       // do nothing for NULL argv\r
       //\r
-    } else if (InternalIsOnCheckList(Argv[LoopCounter], CheckList, &CurrentItemType) != FALSE) {\r
+    } else if (InternalIsOnCheckList(Argv[LoopCounter], CheckList, &CurrentItemType)) {\r
       //\r
       // We might have leftover if last parameter didnt have optional value\r
       //\r
@@ -1795,11 +2120,18 @@ InternalCommandLineParse (
       //\r
       // this is a flag\r
       //\r
-      CurrentItemPackage = AllocatePool(sizeof(SHELL_PARAM_PACKAGE));\r
-      ASSERT(CurrentItemPackage != NULL);\r
-      CurrentItemPackage->Name  = AllocatePool(StrSize(Argv[LoopCounter]));\r
-      ASSERT(CurrentItemPackage->Name != NULL);\r
-      StrCpy(CurrentItemPackage->Name,  Argv[LoopCounter]);\r
+      CurrentItemPackage = AllocateZeroPool(sizeof(SHELL_PARAM_PACKAGE));\r
+      if (CurrentItemPackage == NULL) {\r
+        ShellCommandLineFreeVarList(*CheckPackage);\r
+        *CheckPackage = NULL;\r
+        return (EFI_OUT_OF_RESOURCES);\r
+      }\r
+      CurrentItemPackage->Name  = AllocateCopyPool(StrSize(Argv[LoopCounter]), Argv[LoopCounter]);\r
+      if (CurrentItemPackage->Name == NULL) {\r
+        ShellCommandLineFreeVarList(*CheckPackage);\r
+        *CheckPackage = NULL;\r
+        return (EFI_OUT_OF_RESOURCES);\r
+      }\r
       CurrentItemPackage->Type  = CurrentItemType;\r
       CurrentItemPackage->OriginalPosition = (UINTN)(-1);\r
       CurrentItemPackage->Value = NULL;\r
@@ -1812,6 +2144,7 @@ InternalCommandLineParse (
         // possibly trigger the next loop(s) to populate the value of this item\r
         //\r
         case TypeValue:\r
+        case TypeTimeValue:\r
           GetItemValue = 1;\r
           ValueSize = 0;\r
           break;\r
@@ -1831,48 +2164,76 @@ InternalCommandLineParse (
           ASSERT(GetItemValue == 0);\r
           break;\r
       }\r
-    } else if (GetItemValue != 0 && InternalIsFlag(Argv[LoopCounter], AlwaysAllowNumbers) == FALSE) {\r
-      ASSERT(CurrentItemPackage != NULL);\r
+    } else if (GetItemValue != 0 && CurrentItemPackage != NULL && !InternalIsFlag(Argv[LoopCounter], AlwaysAllowNumbers, (BOOLEAN)(CurrentItemPackage->Type == TypeTimeValue))) {\r
       //\r
       // get the item VALUE for a previous flag\r
       //\r
-      CurrentItemPackage->Value = ReallocatePool(ValueSize, ValueSize + StrSize(Argv[LoopCounter]) + sizeof(CHAR16), CurrentItemPackage->Value);\r
-      ASSERT(CurrentItemPackage->Value != NULL);\r
+      CurrentValueSize = ValueSize + StrSize(Argv[LoopCounter]) + sizeof(CHAR16);\r
+      NewValue = ReallocatePool(ValueSize, CurrentValueSize, CurrentItemPackage->Value);\r
+      if (NewValue == NULL) {\r
+        SHELL_FREE_NON_NULL (CurrentItemPackage->Value);\r
+        SHELL_FREE_NON_NULL (CurrentItemPackage);\r
+        ShellCommandLineFreeVarList (*CheckPackage);\r
+        *CheckPackage = NULL;\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+      CurrentItemPackage->Value = NewValue;\r
       if (ValueSize == 0) {\r
-        StrCpy(CurrentItemPackage->Value, Argv[LoopCounter]);\r
+        StrCpyS( CurrentItemPackage->Value,\r
+                  CurrentValueSize/sizeof(CHAR16),\r
+                  Argv[LoopCounter]\r
+                  );\r
       } else {\r
-        StrCat(CurrentItemPackage->Value, L" ");\r
-        StrCat(CurrentItemPackage->Value, Argv[LoopCounter]);\r
+        StrCatS( CurrentItemPackage->Value,\r
+                  CurrentValueSize/sizeof(CHAR16),\r
+                  L" "\r
+                  );\r
+        StrCatS( CurrentItemPackage->Value,\r
+                  CurrentValueSize/sizeof(CHAR16),\r
+                  Argv[LoopCounter]\r
+                  );\r
       }\r
       ValueSize += StrSize(Argv[LoopCounter]) + sizeof(CHAR16);\r
+\r
       GetItemValue--;\r
       if (GetItemValue == 0) {\r
         InsertHeadList(*CheckPackage, &CurrentItemPackage->Link);\r
       }\r
-    } else if (InternalIsFlag(Argv[LoopCounter], AlwaysAllowNumbers) == FALSE) {\r
+    } else if (!InternalIsFlag(Argv[LoopCounter], AlwaysAllowNumbers, FALSE)){\r
       //\r
       // add this one as a non-flag\r
       //\r
-      CurrentItemPackage = AllocatePool(sizeof(SHELL_PARAM_PACKAGE));\r
-      ASSERT(CurrentItemPackage != NULL);\r
+\r
+      TempPointer = Argv[LoopCounter];\r
+      if ((*TempPointer == L'^' && *(TempPointer+1) == L'-')\r
+       || (*TempPointer == L'^' && *(TempPointer+1) == L'/')\r
+       || (*TempPointer == L'^' && *(TempPointer+1) == L'+')\r
+      ){\r
+        TempPointer++;\r
+      }\r
+      CurrentItemPackage = AllocateZeroPool(sizeof(SHELL_PARAM_PACKAGE));\r
+      if (CurrentItemPackage == NULL) {\r
+        ShellCommandLineFreeVarList(*CheckPackage);\r
+        *CheckPackage = NULL;\r
+        return (EFI_OUT_OF_RESOURCES);\r
+      }\r
       CurrentItemPackage->Name  = NULL;\r
       CurrentItemPackage->Type  = TypePosition;\r
-      CurrentItemPackage->Value = AllocatePool(StrSize(Argv[LoopCounter]));\r
-      ASSERT(CurrentItemPackage->Value != NULL);\r
-      StrCpy(CurrentItemPackage->Value, Argv[LoopCounter]);\r
-      CurrentItemPackage->OriginalPosition = mTotalParameterCount++;\r
+      CurrentItemPackage->Value = AllocateCopyPool(StrSize(TempPointer), TempPointer);\r
+      if (CurrentItemPackage->Value == NULL) {\r
+        ShellCommandLineFreeVarList(*CheckPackage);\r
+        *CheckPackage = NULL;\r
+        return (EFI_OUT_OF_RESOURCES);\r
+      }\r
+      CurrentItemPackage->OriginalPosition = Count++;\r
       InsertHeadList(*CheckPackage, &CurrentItemPackage->Link);\r
-    } else if (ProblemParam) {\r
+    } else {\r
       //\r
       // this was a non-recognised flag... error!\r
       //\r
-      *ProblemParam = AllocatePool(StrSize(Argv[LoopCounter]));\r
-      ASSERT(*ProblemParam != NULL);\r
-      StrCpy(*ProblemParam, Argv[LoopCounter]);\r
-      ShellCommandLineFreeVarList(*CheckPackage);\r
-      *CheckPackage = NULL;\r
-      return (EFI_VOLUME_CORRUPTED);\r
-    } else {\r
+      if (ProblemParam != NULL) {\r
+        *ProblemParam = AllocateCopyPool(StrSize(Argv[LoopCounter]), Argv[LoopCounter]);\r
+      }\r
       ShellCommandLineFreeVarList(*CheckPackage);\r
       *CheckPackage = NULL;\r
       return (EFI_VOLUME_CORRUPTED);\r
@@ -1897,23 +2258,22 @@ InternalCommandLineParse (
 \r
   If no initialization is required, then return RETURN_SUCCESS.\r
 \r
-  @param CheckList              pointer to list of parameters to check\r
-  @param CheckPackage           pointer to pointer to list checked values\r
-  @param ProblemParam           optional pointer to pointer to unicode string for\r
+  @param[in] CheckList          The pointer to list of parameters to check.\r
+  @param[out] CheckPackage      The package of checked values.\r
+  @param[out] ProblemParam      Optional pointer to pointer to unicode string for\r
                                 the paramater that caused failure.\r
-  @param AutoPageBreak          will automatically set PageBreakEnabled for "b" parameter\r
+  @param[in] AutoPageBreak      Will automatically set PageBreakEnabled.\r
+  @param[in] AlwaysAllowNumbers Will never fail for number based flags.\r
 \r
   @retval EFI_SUCCESS           The operation completed sucessfully.\r
-  @retval EFI_OUT_OF_RESOURCES  A memory allocation failed\r
-  @retval EFI_INVALID_PARAMETER A parameter was invalid\r
-  @retval EFI_VOLUME_CORRUPTED  the command line was corrupt.  an argument was\r
-                                duplicated.  the duplicated command line argument\r
-                                was returned in ProblemParam if provided.\r
-  @retval EFI_DEVICE_ERROR      the commands contained 2 opposing arguments.  one\r
+  @retval EFI_OUT_OF_RESOURCES  A memory allocation failed.\r
+  @retval EFI_INVALID_PARAMETER A parameter was invalid.\r
+  @retval EFI_VOLUME_CORRUPTED  The command line was corrupt.\r
+  @retval EFI_DEVICE_ERROR      The commands contained 2 opposing arguments.  One\r
                                 of the command line arguments was returned in\r
                                 ProblemParam if provided.\r
-  @retval EFI_NOT_FOUND         a argument required a value that was missing.\r
-                                the invalid command line argument was returned in\r
+  @retval EFI_NOT_FOUND         A argument required a value that was missing.\r
+                                The invalid command line argument was returned in\r
                                 ProblemParam if provided.\r
 **/\r
 EFI_STATUS\r
@@ -1924,7 +2284,8 @@ ShellCommandLineParseEx (
   OUT CHAR16                    **ProblemParam OPTIONAL,\r
   IN BOOLEAN                    AutoPageBreak,\r
   IN BOOLEAN                    AlwaysAllowNumbers\r
-  ) {\r
+  )\r
+{\r
   //\r
   // ASSERT that CheckList and CheckPackage aren't NULL\r
   //\r
@@ -1934,13 +2295,13 @@ ShellCommandLineParseEx (
   //\r
   // Check for UEFI Shell 2.0 protocols\r
   //\r
-  if (mEfiShellParametersProtocol != NULL) {\r
+  if (gEfiShellParametersProtocol != NULL) {\r
     return (InternalCommandLineParse(CheckList,\r
                                      CheckPackage,\r
                                      ProblemParam,\r
                                      AutoPageBreak,\r
-                                     (CONST CHAR16**) mEfiShellParametersProtocol->Argv,\r
-                                     mEfiShellParametersProtocol->Argc,\r
+                                     (CONST CHAR16**) gEfiShellParametersProtocol->Argv,\r
+                                     gEfiShellParametersProtocol->Argc,\r
                                      AlwaysAllowNumbers));\r
   }\r
 \r
@@ -1973,7 +2334,8 @@ VOID
 EFIAPI\r
 ShellCommandLineFreeVarList (\r
   IN LIST_ENTRY                 *CheckPackage\r
-  ) {\r
+  )\r
+{\r
   LIST_ENTRY                    *Node;\r
 \r
   //\r
@@ -1987,9 +2349,9 @@ ShellCommandLineFreeVarList (
   // for each node in the list\r
   //\r
   for ( Node = GetFirstNode(CheckPackage)\r
-      ; IsListEmpty(CheckPackage) == FALSE\r
+      ; !IsListEmpty(CheckPackage)\r
       ; Node = GetFirstNode(CheckPackage)\r
-      ){\r
+     ){\r
     //\r
     // Remove it from the list\r
     //\r
@@ -2036,20 +2398,17 @@ ShellCommandLineFreeVarList (
 BOOLEAN\r
 EFIAPI\r
 ShellCommandLineGetFlag (\r
-  IN CONST LIST_ENTRY           *CheckPackage,\r
-  IN CHAR16                     *KeyString\r
-  ) {\r
+  IN CONST LIST_ENTRY         * CONST CheckPackage,\r
+  IN CONST CHAR16             * CONST KeyString\r
+  )\r
+{\r
   LIST_ENTRY                    *Node;\r
+  CHAR16                        *TempString;\r
 \r
   //\r
-  // ASSERT that both CheckPackage and KeyString aren't NULL\r
+  // return FALSE for no package or KeyString is NULL\r
   //\r
-  ASSERT(KeyString != NULL);\r
-\r
-  //\r
-  // return FALSE for no package\r
-  //\r
-  if (CheckPackage == NULL) {\r
+  if (CheckPackage == NULL || KeyString == NULL) {\r
     return (FALSE);\r
   }\r
 \r
@@ -2067,11 +2426,20 @@ ShellCommandLineGetFlag (
       //\r
       // If Type is TypeStart then only compare the begining of the strings\r
       //\r
-      if ( ((SHELL_PARAM_PACKAGE*)Node)->Type == TypeStart\r
-        && StrnCmp(KeyString, ((SHELL_PARAM_PACKAGE*)Node)->Name, StrLen(KeyString)) == 0\r
-        ){\r
-        return (TRUE);\r
-      } else if (StrCmp(KeyString, ((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) {\r
+      if (((SHELL_PARAM_PACKAGE*)Node)->Type == TypeStart) {\r
+        if (StrnCmp(KeyString, ((SHELL_PARAM_PACKAGE*)Node)->Name, StrLen(KeyString)) == 0) {\r
+          return (TRUE);\r
+        }\r
+        TempString = NULL;\r
+        TempString = StrnCatGrow(&TempString, NULL, KeyString, StrLen(((SHELL_PARAM_PACKAGE*)Node)->Name));\r
+        if (TempString != NULL) {\r
+          if (StringNoCaseCompare(&KeyString, &((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) {\r
+            FreePool(TempString);\r
+            return (TRUE);\r
+          }\r
+          FreePool(TempString);\r
+        }\r
+      } else if (StringNoCaseCompare(&KeyString, &((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) {\r
         return (TRUE);\r
       }\r
     }\r
@@ -2079,30 +2447,32 @@ ShellCommandLineGetFlag (
   return (FALSE);\r
 }\r
 /**\r
-  returns value from command line argument\r
+  Returns value from command line argument.\r
 \r
-  value parameters are in the form of "-<Key> value" or "/<Key> value"\r
+  Value parameters are in the form of "-<Key> value" or "/<Key> value".\r
 \r
-  if CheckPackage is NULL, then return NULL;\r
+  If CheckPackage is NULL, then return NULL.\r
 \r
-  @param CheckPackage           The package of parsed command line arguments\r
-  @param KeyString              the Key of the command line argument to check for\r
+  @param[in] CheckPackage       The package of parsed command line arguments.\r
+  @param[in] KeyString          The Key of the command line argument to check for.\r
 \r
-  @retval NULL                  the flag is not on the command line\r
-  @return !=NULL                pointer to unicode string of the value\r
-  **/\r
+  @retval NULL                  The flag is not on the command line.\r
+  @retval !=NULL                The pointer to unicode string of the value.\r
+**/\r
 CONST CHAR16*\r
 EFIAPI\r
 ShellCommandLineGetValue (\r
   IN CONST LIST_ENTRY           *CheckPackage,\r
   IN CHAR16                     *KeyString\r
-  ) {\r
+  )\r
+{\r
   LIST_ENTRY                    *Node;\r
+  CHAR16                        *TempString;\r
 \r
   //\r
-  // check for CheckPackage == NULL\r
+  // return NULL for no package or KeyString is NULL\r
   //\r
-  if (CheckPackage == NULL) {\r
+  if (CheckPackage == NULL || KeyString == NULL) {\r
     return (NULL);\r
   }\r
 \r
@@ -2114,48 +2484,53 @@ ShellCommandLineGetValue (
       ; Node = GetNextNode(CheckPackage, Node)\r
       ){\r
     //\r
-    // If the Name matches, return the value (name can be NULL)\r
+    // If the Name matches, return TRUE (and there may be NULL name)\r
     //\r
     if (((SHELL_PARAM_PACKAGE*)Node)->Name != NULL) {\r
       //\r
       // If Type is TypeStart then only compare the begining of the strings\r
       //\r
-      if ( ((SHELL_PARAM_PACKAGE*)Node)->Type == TypeStart\r
-        && StrnCmp(KeyString, ((SHELL_PARAM_PACKAGE*)Node)->Name, StrLen(KeyString)) == 0\r
-        ){\r
-        //\r
-        // return the string part after the flag\r
-        //\r
-        return (((SHELL_PARAM_PACKAGE*)Node)->Name + StrLen(KeyString));\r
-      } else if (StrCmp(KeyString, ((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) {\r
-        //\r
-        // return the value\r
-        //\r
+      if (((SHELL_PARAM_PACKAGE*)Node)->Type == TypeStart) {\r
+        if (StrnCmp(KeyString, ((SHELL_PARAM_PACKAGE*)Node)->Name, StrLen(KeyString)) == 0) {\r
+          return (((SHELL_PARAM_PACKAGE*)Node)->Name + StrLen(KeyString));\r
+        }\r
+        TempString = NULL;\r
+        TempString = StrnCatGrow(&TempString, NULL, KeyString, StrLen(((SHELL_PARAM_PACKAGE*)Node)->Name));\r
+        if (TempString != NULL) {\r
+          if (StringNoCaseCompare(&KeyString, &((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) {\r
+            FreePool(TempString);\r
+            return (((SHELL_PARAM_PACKAGE*)Node)->Name + StrLen(KeyString));\r
+          }\r
+          FreePool(TempString);\r
+        }\r
+      } else if (StringNoCaseCompare(&KeyString, &((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) {\r
         return (((SHELL_PARAM_PACKAGE*)Node)->Value);\r
       }\r
     }\r
   }\r
   return (NULL);\r
 }\r
+\r
 /**\r
-  returns raw value from command line argument\r
+  Returns raw value from command line argument.\r
 \r
-  raw value parameters are in the form of "value" in a specific position in the list\r
+  Raw value parameters are in the form of "value" in a specific position in the list.\r
 \r
-  if CheckPackage is NULL, then return NULL;\r
+  If CheckPackage is NULL, then return NULL.\r
 \r
-  @param CheckPackage           The package of parsed command line arguments\r
-  @param Position               the position of the value\r
+  @param[in] CheckPackage       The package of parsed command line arguments.\r
+  @param[in] Position           The position of the value.\r
 \r
-  @retval NULL                  the flag is not on the command line\r
-  @return !=NULL                pointer to unicode string of the value\r
+  @retval NULL                  The flag is not on the command line.\r
+  @retval !=NULL                The pointer to unicode string of the value.\r
   **/\r
 CONST CHAR16*\r
 EFIAPI\r
 ShellCommandLineGetRawValue (\r
-  IN CONST LIST_ENTRY           *CheckPackage,\r
-  IN UINT32                     Position\r
-  ) {\r
+  IN CONST LIST_ENTRY           * CONST CheckPackage,\r
+  IN UINTN                      Position\r
+  )\r
+{\r
   LIST_ENTRY                    *Node;\r
 \r
   //\r
@@ -2171,7 +2546,7 @@ ShellCommandLineGetRawValue (
   for ( Node = GetFirstNode(CheckPackage)\r
       ; !IsNull (CheckPackage, Node)\r
       ; Node = GetNextNode(CheckPackage, Node)\r
-      ){\r
+     ){\r
     //\r
     // If the position matches, return the value\r
     //\r
@@ -2187,20 +2562,36 @@ ShellCommandLineGetRawValue (
 \r
   this will not include flags.\r
 \r
+  @param[in] CheckPackage       The package of parsed command line arguments.\r
+\r
   @retval (UINTN)-1     No parsing has ocurred\r
   @return other         The number of value parameters found\r
 **/\r
 UINTN\r
 EFIAPI\r
 ShellCommandLineGetCount(\r
-  VOID\r
+  IN CONST LIST_ENTRY              *CheckPackage\r
   )\r
 {\r
-  return (mTotalParameterCount);\r
+  LIST_ENTRY  *Node1;\r
+  UINTN       Count;\r
+\r
+  if (CheckPackage == NULL) {\r
+    return (0);\r
+  }\r
+  for ( Node1 = GetFirstNode(CheckPackage), Count = 0\r
+      ; !IsNull (CheckPackage, Node1)\r
+      ; Node1 = GetNextNode(CheckPackage, Node1)\r
+     ){\r
+    if (((SHELL_PARAM_PACKAGE*)Node1)->Name == NULL) {\r
+      Count++;\r
+    }\r
+  }\r
+  return (Count);\r
 }\r
 \r
 /**\r
-  Determins if a parameter is duplicated.\r
+  Determines if a parameter is duplicated.\r
 \r
   If Param is not NULL then it will point to a callee allocated string buffer\r
   with the parameter value if a duplicate is found.\r
@@ -2228,12 +2619,12 @@ ShellCommandLineCheckDuplicate (
   for ( Node1 = GetFirstNode(CheckPackage)\r
       ; !IsNull (CheckPackage, Node1)\r
       ; Node1 = GetNextNode(CheckPackage, Node1)\r
-      ){\r
+     ){\r
     for ( Node2 = GetNextNode(CheckPackage, Node1)\r
         ; !IsNull (CheckPackage, Node2)\r
         ; Node2 = GetNextNode(CheckPackage, Node2)\r
-        ){\r
-      if (StrCmp(((SHELL_PARAM_PACKAGE*)Node1)->Name, ((SHELL_PARAM_PACKAGE*)Node2)->Name) == 0) {\r
+       ){\r
+      if ((((SHELL_PARAM_PACKAGE*)Node1)->Name != NULL) && (((SHELL_PARAM_PACKAGE*)Node2)->Name != NULL) && StrCmp(((SHELL_PARAM_PACKAGE*)Node1)->Name, ((SHELL_PARAM_PACKAGE*)Node2)->Name) == 0) {\r
         if (Param != NULL) {\r
           *Param = NULL;\r
           *Param = StrnCatGrow(Param, NULL, ((SHELL_PARAM_PACKAGE*)Node1)->Name, 0);\r
@@ -2253,13 +2644,14 @@ ShellCommandLineCheckDuplicate (
 \r
   If the string would grow bigger than NewSize it will halt and return error.\r
 \r
-  @param[in] SourceString             String with source buffer\r
-  @param[in,out] NewString           String with resultant buffer\r
-  @param[in] NewSize                  Size in bytes of NewString\r
-  @param[in] FindTarget               String to look for\r
-  @param[in[ ReplaceWith              String to replace FindTarget with\r
-  @param[in] SkipPreCarrot            If TRUE will skip a FindTarget that has a '^'\r
-                                      immediately before it.\r
+  @param[in] SourceString              The string with source buffer.\r
+  @param[in, out] NewString            The string with resultant buffer.\r
+  @param[in] NewSize                   The size in bytes of NewString.\r
+  @param[in] FindTarget                The string to look for.\r
+  @param[in] ReplaceWith               The string to replace FindTarget with.\r
+  @param[in] SkipPreCarrot             If TRUE will skip a FindTarget that has a '^'\r
+                                       immediately before it.\r
+  @param[in] ParameterReplacing        If TRUE will add "" around items with spaces.\r
 \r
   @retval EFI_INVALID_PARAMETER       SourceString was NULL.\r
   @retval EFI_INVALID_PARAMETER       NewString was NULL.\r
@@ -2269,54 +2661,71 @@ ShellCommandLineCheckDuplicate (
   @retval EFI_INVALID_PARAMETER       SourceString had length < 1.\r
   @retval EFI_BUFFER_TOO_SMALL        NewSize was less than the minimum size to hold\r
                                       the new string (truncation occurred).\r
-  @retval EFI_SUCCESS                 the string was sucessfully copied with replacement.\r
+  @retval EFI_SUCCESS                 The string was successfully copied with replacement.\r
 **/\r
-\r
 EFI_STATUS\r
 EFIAPI\r
-ShellCopySearchAndReplace2(\r
+ShellCopySearchAndReplace(\r
   IN CHAR16 CONST                     *SourceString,\r
-  IN CHAR16                           *NewString,\r
+  IN OUT CHAR16                       *NewString,\r
   IN UINTN                            NewSize,\r
   IN CONST CHAR16                     *FindTarget,\r
   IN CONST CHAR16                     *ReplaceWith,\r
-  IN CONST BOOLEAN                    SkipPreCarrot\r
+  IN CONST BOOLEAN                    SkipPreCarrot,\r
+  IN CONST BOOLEAN                    ParameterReplacing\r
   )\r
 {\r
   UINTN Size;\r
+  CHAR16 *Replace;\r
+\r
   if ( (SourceString == NULL)\r
     || (NewString    == NULL)\r
     || (FindTarget   == NULL)\r
     || (ReplaceWith  == NULL)\r
     || (StrLen(FindTarget) < 1)\r
     || (StrLen(SourceString) < 1)\r
-    ){\r
+   ){\r
     return (EFI_INVALID_PARAMETER);\r
   }\r
-  NewString = SetMem16(NewString, NewSize, CHAR_NULL);\r
+  Replace = NULL;\r
+  if (StrStr(ReplaceWith, L" ") == NULL || !ParameterReplacing) {\r
+    Replace = StrnCatGrow(&Replace, NULL, ReplaceWith, 0);\r
+  } else {\r
+    Replace = AllocateZeroPool(StrSize(ReplaceWith) + 2*sizeof(CHAR16));\r
+    if (Replace != NULL) {\r
+      UnicodeSPrint(Replace, StrSize(ReplaceWith) + 2*sizeof(CHAR16), L"\"%s\"", ReplaceWith);\r
+    }\r
+  }\r
+  if (Replace == NULL) {\r
+    return (EFI_OUT_OF_RESOURCES);\r
+  }\r
+  NewString = ZeroMem(NewString, NewSize);\r
   while (*SourceString != CHAR_NULL) {\r
     //\r
-    // if we find the FindTarget and either Skip == FALSE or Skip == TRUE and we\r
+    // if we find the FindTarget and either Skip == FALSE or Skip  and we\r
     // dont have a carrot do a replace...\r
     //\r
     if (StrnCmp(SourceString, FindTarget, StrLen(FindTarget)) == 0\r
-      && ((SkipPreCarrot && *(SourceString-1) != L'^') || SkipPreCarrot == FALSE)\r
-      ){\r
+      && ((SkipPreCarrot && *(SourceString-1) != L'^') || !SkipPreCarrot)\r
+     ){\r
       SourceString += StrLen(FindTarget);\r
       Size = StrSize(NewString);\r
-      if ((Size + (StrLen(ReplaceWith)*sizeof(CHAR16))) > NewSize) {\r
+      if ((Size + (StrLen(Replace)*sizeof(CHAR16))) > NewSize) {\r
+        FreePool(Replace);\r
         return (EFI_BUFFER_TOO_SMALL);\r
       }\r
-      StrCat(NewString, ReplaceWith);\r
+      StrCatS(NewString, NewSize/sizeof(CHAR16), Replace);\r
     } else {\r
       Size = StrSize(NewString);\r
       if (Size + sizeof(CHAR16) > NewSize) {\r
+        FreePool(Replace);\r
         return (EFI_BUFFER_TOO_SMALL);\r
       }\r
-      StrnCat(NewString, SourceString, 1);\r
+      StrnCatS(NewString, NewSize/sizeof(CHAR16), SourceString, 1);\r
       SourceString++;\r
     }\r
   }\r
+  FreePool(Replace);\r
   return (EFI_SUCCESS);\r
 }\r
 \r
@@ -2331,22 +2740,26 @@ ShellCopySearchAndReplace2(
   @retval !EFI_SUCCESS    The operation failed.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 InternalPrintTo (\r
   IN CONST CHAR16 *String\r
   )\r
 {\r
   UINTN Size;\r
   Size = StrSize(String) - sizeof(CHAR16);\r
-  if (mEfiShellParametersProtocol != NULL) {\r
-    return (mEfiShellParametersProtocol->StdOut->Write(mEfiShellParametersProtocol->StdOut, &Size, (VOID*)String));\r
+  if (Size == 0) {\r
+    return (EFI_SUCCESS);\r
+  }\r
+  if (gEfiShellParametersProtocol != NULL) {\r
+    return (gEfiShellProtocol->WriteFile(gEfiShellParametersProtocol->StdOut, &Size, (VOID*)String));\r
   }\r
   if (mEfiShellInterface          != NULL) {\r
+    if (mEfiShellInterface->RedirArgc == 0) {\r
     //\r
     // Divide in half for old shell.  Must be string length not size.\r
-    //\r
-    Size /= 2;\r
-    return (         mEfiShellInterface->StdOut->Write(mEfiShellInterface->StdOut,          &Size, (VOID*)String));\r
+      //\r
+      Size /=2;  // Divide in half only when no redirection.\r
+    }\r
+    return (mEfiShellInterface->StdOut->Write(mEfiShellInterface->StdOut,          &Size, (VOID*)String));\r
   }\r
   ASSERT(FALSE);\r
   return (EFI_UNSUPPORTED);\r
@@ -2373,54 +2786,64 @@ InternalPrintTo (
 \r
   Note: The background color is controlled by the shell command cls.\r
 \r
-  @param[in] Row        the row to print at\r
   @param[in] Col        the column to print at\r
+  @param[in] Row        the row to print at\r
   @param[in] Format     the format string\r
   @param[in] Marker     the marker for the variable argument list\r
 \r
-  @return the number of characters printed to the screen\r
+  @return EFI_SUCCESS           The operation was successful.\r
+  @return EFI_DEVICE_ERROR      The console device reported an error.\r
 **/\r
-\r
-UINTN\r
-EFIAPI\r
+EFI_STATUS\r
 InternalShellPrintWorker(\r
   IN INT32                Col OPTIONAL,\r
   IN INT32                Row OPTIONAL,\r
   IN CONST CHAR16         *Format,\r
-  VA_LIST                 Marker\r
+  IN VA_LIST              Marker\r
   )\r
 {\r
-  UINTN             Return;\r
   EFI_STATUS        Status;\r
-  UINTN             NormalAttribute;\r
   CHAR16            *ResumeLocation;\r
   CHAR16            *FormatWalker;\r
+  UINTN             OriginalAttribute;\r
+  CHAR16            *mPostReplaceFormat;\r
+  CHAR16            *mPostReplaceFormat2;\r
+\r
+  mPostReplaceFormat = AllocateZeroPool (PcdGet16 (PcdShellPrintBufferSize));\r
+  mPostReplaceFormat2 = AllocateZeroPool (PcdGet16 (PcdShellPrintBufferSize));\r
+\r
+  if (mPostReplaceFormat == NULL || mPostReplaceFormat2 == NULL) {\r
+    SHELL_FREE_NON_NULL(mPostReplaceFormat);\r
+    SHELL_FREE_NON_NULL(mPostReplaceFormat2);\r
+    return (EFI_OUT_OF_RESOURCES);\r
+  }\r
+\r
+  Status            = EFI_SUCCESS;\r
+  OriginalAttribute = gST->ConOut->Mode->Attribute;\r
 \r
   //\r
   // Back and forth each time fixing up 1 of our flags...\r
   //\r
-  Status = ShellLibCopySearchAndReplace(Format,             mPostReplaceFormat,  PcdGet16 (PcdShellPrintBufferSize), L"%N", L"%%N");\r
+  Status = ShellCopySearchAndReplace(Format,             mPostReplaceFormat,  PcdGet16 (PcdShellPrintBufferSize), L"%N", L"%%N", FALSE, FALSE);\r
   ASSERT_EFI_ERROR(Status);\r
-  Status = ShellLibCopySearchAndReplace(mPostReplaceFormat,  mPostReplaceFormat2, PcdGet16 (PcdShellPrintBufferSize), L"%E", L"%%E");\r
+  Status = ShellCopySearchAndReplace(mPostReplaceFormat,  mPostReplaceFormat2, PcdGet16 (PcdShellPrintBufferSize), L"%E", L"%%E", FALSE, FALSE);\r
   ASSERT_EFI_ERROR(Status);\r
-  Status = ShellLibCopySearchAndReplace(mPostReplaceFormat2, mPostReplaceFormat,  PcdGet16 (PcdShellPrintBufferSize), L"%H", L"%%H");\r
+  Status = ShellCopySearchAndReplace(mPostReplaceFormat2, mPostReplaceFormat,  PcdGet16 (PcdShellPrintBufferSize), L"%H", L"%%H", FALSE, FALSE);\r
   ASSERT_EFI_ERROR(Status);\r
-  Status = ShellLibCopySearchAndReplace(mPostReplaceFormat,  mPostReplaceFormat2, PcdGet16 (PcdShellPrintBufferSize), L"%B", L"%%B");\r
+  Status = ShellCopySearchAndReplace(mPostReplaceFormat,  mPostReplaceFormat2, PcdGet16 (PcdShellPrintBufferSize), L"%B", L"%%B", FALSE, FALSE);\r
   ASSERT_EFI_ERROR(Status);\r
-  Status = ShellLibCopySearchAndReplace(mPostReplaceFormat2, mPostReplaceFormat,  PcdGet16 (PcdShellPrintBufferSize), L"%V", L"%%V");\r
+  Status = ShellCopySearchAndReplace(mPostReplaceFormat2, mPostReplaceFormat,  PcdGet16 (PcdShellPrintBufferSize), L"%V", L"%%V", FALSE, FALSE);\r
   ASSERT_EFI_ERROR(Status);\r
 \r
   //\r
   // Use the last buffer from replacing to print from...\r
   //\r
-  Return = UnicodeVSPrint (mPostReplaceFormat2, PcdGet16 (PcdShellPrintBufferSize), mPostReplaceFormat, Marker);\r
+  UnicodeVSPrint (mPostReplaceFormat2, PcdGet16 (PcdShellPrintBufferSize), mPostReplaceFormat, Marker);\r
 \r
   if (Col != -1 && Row != -1) {\r
     Status = gST->ConOut->SetCursorPosition(gST->ConOut, Col, Row);\r
-    ASSERT_EFI_ERROR(Status);\r
   }\r
 \r
-  NormalAttribute = gST->ConOut->Mode->Attribute;\r
   FormatWalker = mPostReplaceFormat2;\r
   while (*FormatWalker != CHAR_NULL) {\r
     //\r
@@ -2433,42 +2856,61 @@ InternalShellPrintWorker(
     //\r
     // print the current FormatWalker string\r
     //\r
-    Status = InternalPrintTo(FormatWalker);\r
-    ASSERT_EFI_ERROR(Status);\r
+    if (StrLen(FormatWalker)>0) {\r
+      Status = InternalPrintTo(FormatWalker);\r
+      if (EFI_ERROR(Status)) {\r
+        break;\r
+      }\r
+    }\r
+\r
     //\r
     // update the attribute\r
     //\r
     if (ResumeLocation != NULL) {\r
-      switch (*(ResumeLocation+1)) {\r
-        case (L'N'):\r
-          gST->ConOut->SetAttribute(gST->ConOut, NormalAttribute);\r
-          break;\r
-        case (L'E'):\r
-          gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_YELLOW, ((NormalAttribute&(BIT4|BIT5|BIT6))>>4)));\r
-          break;\r
-        case (L'H'):\r
-          gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_WHITE, ((NormalAttribute&(BIT4|BIT5|BIT6))>>4)));\r
-          break;\r
-        case (L'B'):\r
-          gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_BLUE, ((NormalAttribute&(BIT4|BIT5|BIT6))>>4)));\r
-          break;\r
-        case (L'V'):\r
-          gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_GREEN, ((NormalAttribute&(BIT4|BIT5|BIT6))>>4)));\r
-          break;\r
-        default:\r
-          //\r
-          // Print a simple '%' symbol\r
-          //\r
-          Status = InternalPrintTo(L"%");\r
-          ASSERT_EFI_ERROR(Status);\r
-          ResumeLocation = ResumeLocation - 1;\r
-          break;\r
+      if ((ResumeLocation != mPostReplaceFormat2) && (*(ResumeLocation-1) == L'^')) {\r
+        //\r
+        // Move cursor back 1 position to overwrite the ^\r
+        //\r
+        gST->ConOut->SetCursorPosition(gST->ConOut, gST->ConOut->Mode->CursorColumn - 1, gST->ConOut->Mode->CursorRow);\r
+\r
+        //\r
+        // Print a simple '%' symbol\r
+        //\r
+        Status = InternalPrintTo(L"%");\r
+        ResumeLocation = ResumeLocation - 1;\r
+      } else {\r
+        switch (*(ResumeLocation+1)) {\r
+          case (L'N'):\r
+            gST->ConOut->SetAttribute(gST->ConOut, OriginalAttribute);\r
+            break;\r
+          case (L'E'):\r
+            gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_YELLOW, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)));\r
+            break;\r
+          case (L'H'):\r
+            gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_WHITE, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)));\r
+            break;\r
+          case (L'B'):\r
+            gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_LIGHTBLUE, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)));\r
+            break;\r
+          case (L'V'):\r
+            gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_LIGHTGREEN, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)));\r
+            break;\r
+          default:\r
+            //\r
+            // Print a simple '%' symbol\r
+            //\r
+            Status = InternalPrintTo(L"%");\r
+            if (EFI_ERROR(Status)) {\r
+              break;\r
+            }\r
+            ResumeLocation = ResumeLocation - 1;\r
+            break;\r
+        }\r
       }\r
     } else {\r
       //\r
       // reset to normal now...\r
       //\r
-      gST->ConOut->SetAttribute(gST->ConOut, NormalAttribute);\r
       break;\r
     }\r
 \r
@@ -2478,7 +2920,11 @@ InternalShellPrintWorker(
     FormatWalker = ResumeLocation + 2;\r
   }\r
 \r
-  return (Return);\r
+  gST->ConOut->SetAttribute(gST->ConOut, OriginalAttribute);\r
+\r
+  SHELL_FREE_NON_NULL(mPostReplaceFormat);\r
+  SHELL_FREE_NON_NULL(mPostReplaceFormat2);\r
+  return (Status);\r
 }\r
 \r
 /**\r
@@ -2502,14 +2948,15 @@ InternalShellPrintWorker(
 \r
   Note: The background color is controlled by the shell command cls.\r
 \r
-  @param[in] Row        the row to print at\r
   @param[in] Col        the column to print at\r
+  @param[in] Row        the row to print at\r
   @param[in] Format     the format string\r
+  @param[in] ...        The variable argument list.\r
 \r
-  @return the number of characters printed to the screen\r
+  @return EFI_SUCCESS           The printing was successful.\r
+  @return EFI_DEVICE_ERROR      The console device reported an error.\r
 **/\r
-\r
-UINTN\r
+EFI_STATUS\r
 EFIAPI\r
 ShellPrintEx(\r
   IN INT32                Col OPTIONAL,\r
@@ -2519,11 +2966,14 @@ ShellPrintEx(
   )\r
 {\r
   VA_LIST           Marker;\r
-  EFI_STATUS        Status;\r
+  EFI_STATUS        RetVal;\r
+  if (Format == NULL) {\r
+    return (EFI_INVALID_PARAMETER);\r
+  }\r
   VA_START (Marker, Format);\r
-  Status = InternalShellPrintWorker(Col, Row, Format, Marker);\r
+  RetVal = InternalShellPrintWorker(Col, Row, Format, Marker);\r
   VA_END(Marker);\r
-  return(Status);\r
+  return(RetVal);\r
 }\r
 \r
 /**\r
@@ -2547,37 +2997,40 @@ ShellPrintEx(
 \r
   Note: The background color is controlled by the shell command cls.\r
 \r
-  @param[in] Row                The row to print at.\r
   @param[in] Col                The column to print at.\r
+  @param[in] Row                The row to print at.\r
   @param[in] Language           The language of the string to retrieve.  If this parameter\r
                                 is NULL, then the current platform language is used.\r
   @param[in] HiiFormatStringId  The format string Id for getting from Hii.\r
   @param[in] HiiFormatHandle    The format string Handle for getting from Hii.\r
+  @param[in] ...                The variable argument list.\r
 \r
-  @return the number of characters printed to the screen.\r
+  @return EFI_SUCCESS           The printing was successful.\r
+  @return EFI_DEVICE_ERROR      The console device reported an error.\r
 **/\r
-UINTN\r
+EFI_STATUS\r
 EFIAPI\r
 ShellPrintHiiEx(\r
   IN INT32                Col OPTIONAL,\r
   IN INT32                Row OPTIONAL,\r
   IN CONST CHAR8          *Language OPTIONAL,\r
   IN CONST EFI_STRING_ID  HiiFormatStringId,\r
-  IN CONST EFI_HANDLE     HiiFormatHandle,\r
+  IN CONST EFI_HII_HANDLE HiiFormatHandle,\r
   ...\r
   )\r
 {\r
   VA_LIST           Marker;\r
   CHAR16            *HiiFormatString;\r
-  UINTN             RetVal;\r
+  EFI_STATUS        RetVal;\r
+\r
+  RetVal = EFI_DEVICE_ERROR;\r
 \r
   VA_START (Marker, HiiFormatHandle);\r
   HiiFormatString = HiiGetString(HiiFormatHandle, HiiFormatStringId, Language);\r
-  ASSERT(HiiFormatString != NULL);\r
-\r
-  RetVal = InternalShellPrintWorker(Col, Row, HiiFormatString, Marker);\r
-\r
-  FreePool(HiiFormatString);\r
+  if (HiiFormatString != NULL) {\r
+    RetVal = InternalShellPrintWorker (Col, Row, HiiFormatString, Marker);\r
+    SHELL_FREE_NON_NULL (HiiFormatString);\r
+  }\r
   VA_END(Marker);\r
 \r
   return (RetVal);\r
@@ -2588,9 +3041,10 @@ ShellPrintHiiEx(
 \r
   @param[in] DirName      Path to directory to test.\r
 \r
-  @retval EFI_SUCCESS     The Path represents a directory\r
-  @retval EFI_NOT_FOUND   The Path does not represent a directory\r
-  @return other           The path failed to open\r
+  @retval EFI_SUCCESS             The Path represents a directory\r
+  @retval EFI_NOT_FOUND           The Path does not represent a directory\r
+  @retval EFI_OUT_OF_RESOURCES    A memory allocation failed.\r
+  @return                         The path failed to open\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
@@ -2599,14 +3053,44 @@ ShellIsDirectory(
   )\r
 {\r
   EFI_STATUS        Status;\r
-  EFI_FILE_HANDLE   Handle;\r
+  SHELL_FILE_HANDLE Handle;\r
+  CHAR16            *TempLocation;\r
+  CHAR16            *TempLocation2;\r
 \r
   ASSERT(DirName != NULL);\r
 \r
-  Handle = NULL;\r
+  Handle        = NULL;\r
+  TempLocation  = NULL;\r
 \r
   Status = ShellOpenFileByName(DirName, &Handle, EFI_FILE_MODE_READ, 0);\r
   if (EFI_ERROR(Status)) {\r
+    //\r
+    // try good logic first.\r
+    //\r
+    if (gEfiShellProtocol != NULL) {\r
+      TempLocation  = StrnCatGrow(&TempLocation, NULL, DirName, 0);\r
+      if (TempLocation == NULL) {\r
+        ShellCloseFile(&Handle);\r
+        return (EFI_OUT_OF_RESOURCES);\r
+      }\r
+      TempLocation2 = StrStr(TempLocation, L":");\r
+      if (TempLocation2 != NULL && StrLen(StrStr(TempLocation, L":")) == 2) {\r
+        *(TempLocation2+1) = CHAR_NULL;\r
+      }\r
+      if (gEfiShellProtocol->GetDevicePathFromMap(TempLocation) != NULL) {\r
+        FreePool(TempLocation);\r
+        return (EFI_SUCCESS);\r
+      }\r
+      FreePool(TempLocation);\r
+    } else {\r
+      //\r
+      // probably a map name?!?!!?\r
+      //\r
+      TempLocation = StrStr(DirName, L"\\");\r
+      if (TempLocation != NULL && *(TempLocation+1) == CHAR_NULL) {\r
+        return (EFI_SUCCESS);\r
+      }\r
+    }\r
     return (Status);\r
   }\r
 \r
@@ -2634,7 +3118,7 @@ ShellIsFile(
   )\r
 {\r
   EFI_STATUS        Status;\r
-  EFI_FILE_HANDLE   Handle;\r
+  SHELL_FILE_HANDLE            Handle;\r
 \r
   ASSERT(Name != NULL);\r
 \r
@@ -2670,12 +3154,13 @@ EFI_STATUS
 EFIAPI\r
 ShellIsFileInPath(\r
   IN CONST CHAR16 *Name\r
-  ) {\r
+  )\r
+{\r
   CHAR16      *NewName;\r
   EFI_STATUS  Status;\r
 \r
   if (!EFI_ERROR(ShellIsFile(Name))) {\r
-    return (TRUE);\r
+    return (EFI_SUCCESS);\r
   }\r
 \r
   NewName = ShellFindFilePath(Name);\r
@@ -2686,13 +3171,41 @@ ShellIsFileInPath(
   FreePool(NewName);\r
   return (Status);\r
 }\r
+\r
+/**\r
+  Function return the number converted from a hex representation of a number.\r
+\r
+  Note: this function cannot be used when (UINTN)(-1), (0xFFFFFFFF) may be a valid\r
+  result.  Use ShellConvertStringToUint64 instead.\r
+\r
+  @param[in] String   String representation of a number.\r
+\r
+  @return             The unsigned integer result of the conversion.\r
+  @retval (UINTN)(-1) An error occurred.\r
+**/\r
+UINTN\r
+EFIAPI\r
+ShellHexStrToUintn(\r
+  IN CONST CHAR16 *String\r
+  )\r
+{\r
+  UINT64        RetVal;\r
+\r
+  if (!EFI_ERROR(ShellConvertStringToUint64(String, &RetVal, TRUE, TRUE))) {\r
+    return ((UINTN)RetVal);\r
+  }\r
+\r
+  return ((UINTN)(-1));\r
+}\r
+\r
 /**\r
   Function to determine whether a string is decimal or hex representation of a number\r
-  and return the number converted from the string.\r
+  and return the number converted from the string.  Spaces are always skipped.\r
 \r
   @param[in] String   String representation of a number\r
 \r
-  @retval all         the number\r
+  @return             the number\r
+  @retval (UINTN)(-1) An error ocurred.\r
 **/\r
 UINTN\r
 EFIAPI\r
@@ -2700,17 +3213,19 @@ ShellStrToUintn(
   IN CONST CHAR16 *String\r
   )\r
 {\r
-  CONST CHAR16  *Walker;\r
-  for (Walker = String; Walker != NULL && *Walker != CHAR_NULL && *Walker == L' '; Walker++);\r
-  if (Walker == NULL || *Walker == CHAR_NULL) {\r
-    ASSERT(FALSE);\r
-    return ((UINTN)(-1));\r
-  } else {\r
-    if (StrnCmp(Walker, L"0x", 2) == 0 || StrnCmp(Walker, L"0X", 2) == 0){\r
-      return (StrHexToUintn(Walker));\r
-    }\r
-    return (StrDecimalToUintn(Walker));\r
+  UINT64        RetVal;\r
+  BOOLEAN       Hex;\r
+\r
+  Hex = FALSE;\r
+\r
+  if (!InternalShellIsHexOrDecimalNumber(String, Hex, TRUE, FALSE)) {\r
+    Hex = TRUE;\r
+  }\r
+\r
+  if (!EFI_ERROR(ShellConvertStringToUint64(String, &RetVal, Hex, TRUE))) {\r
+    return ((UINTN)RetVal);\r
   }\r
+  return ((UINTN)(-1));\r
 }\r
 \r
 /**\r
@@ -2735,8 +3250,8 @@ ShellStrToUintn(
   if Destination's current length (including NULL terminator) is already more then\r
   CurrentSize, then ASSERT()\r
 \r
-  @param[in,out] Destination   The String to append onto\r
-  @param[in,out] CurrentSize   on call the number of bytes in Destination.  On\r
+  @param[in, out] Destination   The String to append onto\r
+  @param[in, out] CurrentSize   on call the number of bytes in Destination.  On\r
                                 return possibly the new size (still in bytes).  if NULL\r
                                 then allocate whatever is needed.\r
   @param[in]      Source        The String to append from\r
@@ -2800,17 +3315,1078 @@ StrnCatGrow (
   //\r
   if (CurrentSize != NULL) {\r
     NewSize = *CurrentSize;\r
-    while (NewSize < (DestinationStartSize + (Count*sizeof(CHAR16)))) {\r
-      NewSize += 2 * Count * sizeof(CHAR16);\r
+    if (NewSize < DestinationStartSize + (Count * sizeof(CHAR16))) {\r
+      while (NewSize < (DestinationStartSize + (Count*sizeof(CHAR16)))) {\r
+        NewSize += 2 * Count * sizeof(CHAR16);\r
+      }\r
+      *Destination = ReallocatePool(*CurrentSize, NewSize, *Destination);\r
+      *CurrentSize = NewSize;\r
     }\r
-    *Destination = ReallocatePool(*CurrentSize, NewSize, *Destination);\r
-    *CurrentSize = NewSize;\r
   } else {\r
-    *Destination = AllocateZeroPool((Count+1)*sizeof(CHAR16));\r
+    NewSize = (Count+1)*sizeof(CHAR16);\r
+    *Destination = AllocateZeroPool(NewSize);\r
   }\r
 \r
   //\r
   // Now use standard StrnCat on a big enough buffer\r
   //\r
-  return StrnCat(*Destination, Source, Count);\r
+  if (*Destination == NULL) {\r
+    return (NULL);\r
+  }\r
+\r
+  StrnCatS(*Destination, NewSize/sizeof(CHAR16), Source, Count);\r
+  return *Destination;\r
+}\r
+\r
+/**\r
+  Prompt the user and return the resultant answer to the requestor.\r
+\r
+  This function will display the requested question on the shell prompt and then\r
+  wait for an appropriate answer to be input from the console.\r
+\r
+  if the SHELL_PROMPT_REQUEST_TYPE is SHELL_PROMPT_REQUEST_TYPE_YESNO, ShellPromptResponseTypeQuitContinue\r
+  or SHELL_PROMPT_REQUEST_TYPE_YESNOCANCEL then *Response is of type SHELL_PROMPT_RESPONSE.\r
+\r
+  if the SHELL_PROMPT_REQUEST_TYPE is ShellPromptResponseTypeFreeform then *Response is of type\r
+  CHAR16*.\r
+\r
+  In either case *Response must be callee freed if Response was not NULL;\r
+\r
+  @param Type                     What type of question is asked.  This is used to filter the input\r
+                                  to prevent invalid answers to question.\r
+  @param Prompt                   Pointer to string prompt to use to request input.\r
+  @param Response                 Pointer to Response which will be populated upon return.\r
+\r
+  @retval EFI_SUCCESS             The operation was sucessful.\r
+  @retval EFI_UNSUPPORTED         The operation is not supported as requested.\r
+  @retval EFI_INVALID_PARAMETER   A parameter was invalid.\r
+  @return other                   The operation failed.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellPromptForResponse (\r
+  IN SHELL_PROMPT_REQUEST_TYPE   Type,\r
+  IN CHAR16         *Prompt OPTIONAL,\r
+  IN OUT VOID       **Response OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS        Status;\r
+  EFI_INPUT_KEY     Key;\r
+  UINTN             EventIndex;\r
+  SHELL_PROMPT_RESPONSE          *Resp;\r
+  UINTN             Size;\r
+  CHAR16            *Buffer;\r
+\r
+  Status  = EFI_UNSUPPORTED;\r
+  Resp    = NULL;\r
+  Buffer  = NULL;\r
+  Size    = 0;\r
+  if (Type != ShellPromptResponseTypeFreeform) {\r
+    Resp = (SHELL_PROMPT_RESPONSE*)AllocateZeroPool(sizeof(SHELL_PROMPT_RESPONSE));\r
+    if (Resp == NULL) {\r
+      if (Response != NULL) {\r
+        *Response = NULL;\r
+      }\r
+      return (EFI_OUT_OF_RESOURCES);\r
+    }\r
+  }\r
+\r
+  switch(Type) {\r
+    case ShellPromptResponseTypeQuitContinue:\r
+      if (Prompt != NULL) {\r
+        ShellPrintEx(-1, -1, L"%s", Prompt);\r
+      }\r
+      //\r
+      // wait for valid response\r
+      //\r
+      gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);\r
+      Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+      if (EFI_ERROR(Status)) {\r
+        break;\r
+      }\r
+      ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);\r
+      if (Key.UnicodeChar == L'Q' || Key.UnicodeChar ==L'q') {\r
+        *Resp = ShellPromptResponseQuit;\r
+      } else {\r
+        *Resp = ShellPromptResponseContinue;\r
+      }\r
+      break;\r
+    case ShellPromptResponseTypeYesNoCancel:\r
+       if (Prompt != NULL) {\r
+        ShellPrintEx(-1, -1, L"%s", Prompt);\r
+      }\r
+      //\r
+      // wait for valid response\r
+      //\r
+      *Resp = ShellPromptResponseMax;\r
+      while (*Resp == ShellPromptResponseMax) {\r
+        if (ShellGetExecutionBreakFlag()) {\r
+          Status = EFI_ABORTED;\r
+          break;\r
+        }\r
+        gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);\r
+        Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+        if (EFI_ERROR(Status)) {\r
+          break;\r
+        }\r
+        ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);\r
+        switch (Key.UnicodeChar) {\r
+          case L'Y':\r
+          case L'y':\r
+            *Resp = ShellPromptResponseYes;\r
+            break;\r
+          case L'N':\r
+          case L'n':\r
+            *Resp = ShellPromptResponseNo;\r
+            break;\r
+          case L'C':\r
+          case L'c':\r
+            *Resp = ShellPromptResponseCancel;\r
+            break;\r
+        }\r
+      }\r
+      break;\r
+      case ShellPromptResponseTypeYesNoAllCancel:\r
+       if (Prompt != NULL) {\r
+        ShellPrintEx(-1, -1, L"%s", Prompt);\r
+      }\r
+      //\r
+      // wait for valid response\r
+      //\r
+      *Resp = ShellPromptResponseMax;\r
+      while (*Resp == ShellPromptResponseMax) {\r
+        if (ShellGetExecutionBreakFlag()) {\r
+          Status = EFI_ABORTED;\r
+          break;\r
+        }\r
+        gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);\r
+        Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+        if (EFI_ERROR(Status)) {\r
+          break;\r
+        }\r
+\r
+        if (Key.UnicodeChar <= 127 && Key.UnicodeChar >= 32) {\r
+          ShellPrintEx (-1, -1, L"%c", Key.UnicodeChar);\r
+        }\r
+\r
+        switch (Key.UnicodeChar) {\r
+          case L'Y':\r
+          case L'y':\r
+            *Resp = ShellPromptResponseYes;\r
+            break;\r
+          case L'N':\r
+          case L'n':\r
+            *Resp = ShellPromptResponseNo;\r
+            break;\r
+          case L'A':\r
+          case L'a':\r
+            *Resp = ShellPromptResponseAll;\r
+            break;\r
+          case L'C':\r
+          case L'c':\r
+            *Resp = ShellPromptResponseCancel;\r
+            break;\r
+        }\r
+      }\r
+      break;\r
+    case ShellPromptResponseTypeEnterContinue:\r
+    case ShellPromptResponseTypeAnyKeyContinue:\r
+      if (Prompt != NULL) {\r
+        ShellPrintEx(-1, -1, L"%s", Prompt);\r
+      }\r
+      //\r
+      // wait for valid response\r
+      //\r
+      *Resp = ShellPromptResponseMax;\r
+      while (*Resp == ShellPromptResponseMax) {\r
+        if (ShellGetExecutionBreakFlag()) {\r
+          Status = EFI_ABORTED;\r
+          break;\r
+        }\r
+        gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);\r
+        if (Type == ShellPromptResponseTypeEnterContinue) {\r
+          Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+          if (EFI_ERROR(Status)) {\r
+            break;\r
+          }\r
+          ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);\r
+          if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
+            *Resp = ShellPromptResponseContinue;\r
+            break;\r
+          }\r
+        }\r
+        if (Type == ShellPromptResponseTypeAnyKeyContinue) {\r
+          Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+          ASSERT_EFI_ERROR(Status);\r
+          *Resp = ShellPromptResponseContinue;\r
+          break;\r
+        }\r
+      }\r
+      break;\r
+    case ShellPromptResponseTypeYesNo:\r
+       if (Prompt != NULL) {\r
+        ShellPrintEx(-1, -1, L"%s", Prompt);\r
+      }\r
+      //\r
+      // wait for valid response\r
+      //\r
+      *Resp = ShellPromptResponseMax;\r
+      while (*Resp == ShellPromptResponseMax) {\r
+        if (ShellGetExecutionBreakFlag()) {\r
+          Status = EFI_ABORTED;\r
+          break;\r
+        }\r
+        gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);\r
+        Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+        if (EFI_ERROR(Status)) {\r
+          break;\r
+        }\r
+        ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);\r
+        switch (Key.UnicodeChar) {\r
+          case L'Y':\r
+          case L'y':\r
+            *Resp = ShellPromptResponseYes;\r
+            break;\r
+          case L'N':\r
+          case L'n':\r
+            *Resp = ShellPromptResponseNo;\r
+            break;\r
+        }\r
+      }\r
+      break;\r
+    case ShellPromptResponseTypeFreeform:\r
+      if (Prompt != NULL) {\r
+        ShellPrintEx(-1, -1, L"%s", Prompt);\r
+      }\r
+      while(1) {\r
+        if (ShellGetExecutionBreakFlag()) {\r
+          Status = EFI_ABORTED;\r
+          break;\r
+        }\r
+        gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);\r
+        Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+        if (EFI_ERROR(Status)) {\r
+          break;\r
+        }\r
+        ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);\r
+        if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
+          break;\r
+        }\r
+        ASSERT((Buffer == NULL && Size == 0) || (Buffer != NULL));\r
+        StrnCatGrow(&Buffer, &Size, &Key.UnicodeChar, 1);\r
+      }\r
+      break;\r
+    //\r
+    // This is the location to add new prompt types.\r
+    // If your new type loops remember to add ExecutionBreak support.\r
+    //\r
+    default:\r
+      ASSERT(FALSE);\r
+  }\r
+\r
+  if (Response != NULL) {\r
+    if (Resp != NULL) {\r
+      *Response = Resp;\r
+    } else if (Buffer != NULL) {\r
+      *Response = Buffer;\r
+    } else {\r
+      *Response = NULL;\r
+    }\r
+  } else {\r
+    if (Resp != NULL) {\r
+      FreePool(Resp);\r
+    }\r
+    if (Buffer != NULL) {\r
+      FreePool(Buffer);\r
+    }\r
+  }\r
+\r
+  ShellPrintEx(-1, -1, L"\r\n");\r
+  return (Status);\r
+}\r
+\r
+/**\r
+  Prompt the user and return the resultant answer to the requestor.\r
+\r
+  This function is the same as ShellPromptForResponse, except that the prompt is\r
+  automatically pulled from HII.\r
+\r
+  @param Type     What type of question is asked.  This is used to filter the input\r
+                  to prevent invalid answers to question.\r
+  @param[in] HiiFormatStringId  The format string Id for getting from Hii.\r
+  @param[in] HiiFormatHandle    The format string Handle for getting from Hii.\r
+  @param Response               Pointer to Response which will be populated upon return.\r
+\r
+  @retval EFI_SUCCESS the operation was sucessful.\r
+  @return other       the operation failed.\r
+\r
+  @sa ShellPromptForResponse\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellPromptForResponseHii (\r
+  IN SHELL_PROMPT_REQUEST_TYPE         Type,\r
+  IN CONST EFI_STRING_ID  HiiFormatStringId,\r
+  IN CONST EFI_HII_HANDLE HiiFormatHandle,\r
+  IN OUT VOID             **Response\r
+  )\r
+{\r
+  CHAR16      *Prompt;\r
+  EFI_STATUS  Status;\r
+\r
+  Prompt = HiiGetString(HiiFormatHandle, HiiFormatStringId, NULL);\r
+  Status = ShellPromptForResponse(Type, Prompt, Response);\r
+  FreePool(Prompt);\r
+  return (Status);\r
+}\r
+\r
+/**\r
+  Function to determin if an entire string is a valid number.\r
+\r
+  If Hex it must be preceeded with a 0x or has ForceHex, set TRUE.\r
+\r
+  @param[in] String       The string to evaluate.\r
+  @param[in] ForceHex     TRUE - always assume hex.\r
+  @param[in] StopAtSpace  TRUE to halt upon finding a space, FALSE to keep going.\r
+  @param[in] TimeNumbers        TRUE to allow numbers with ":", FALSE otherwise.\r
+\r
+  @retval TRUE        It is all numeric (dec/hex) characters.\r
+  @retval FALSE       There is a non-numeric character.\r
+**/\r
+BOOLEAN\r
+InternalShellIsHexOrDecimalNumber (\r
+  IN CONST CHAR16   *String,\r
+  IN CONST BOOLEAN  ForceHex,\r
+  IN CONST BOOLEAN  StopAtSpace,\r
+  IN CONST BOOLEAN  TimeNumbers\r
+  )\r
+{\r
+  BOOLEAN Hex;\r
+  BOOLEAN LeadingZero;\r
+\r
+  if (String == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // chop off a single negative sign\r
+  //\r
+  if (*String == L'-') {\r
+    String++;\r
+  }\r
+\r
+  if (*String == CHAR_NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // chop leading zeroes\r
+  //\r
+  LeadingZero = FALSE;\r
+  while(*String == L'0'){\r
+    String++;\r
+    LeadingZero = TRUE;\r
+  }\r
+  //\r
+  // allow '0x' or '0X', but not 'x' or 'X'\r
+  //\r
+  if (*String == L'x' || *String == L'X') {\r
+    if (!LeadingZero) {\r
+      //\r
+      // we got an x without a preceeding 0\r
+      //\r
+      return (FALSE);\r
+    }\r
+    String++;\r
+    Hex = TRUE;\r
+  } else if (ForceHex) {\r
+    Hex = TRUE;\r
+  } else {\r
+    Hex = FALSE;\r
+  }\r
+\r
+  //\r
+  // loop through the remaining characters and use the lib function\r
+  //\r
+  for ( ; *String != CHAR_NULL && !(StopAtSpace && *String == L' ') ; String++){\r
+    if (TimeNumbers && (String[0] == L':')) {\r
+      continue;\r
+    }\r
+    if (Hex) {\r
+      if (!ShellIsHexaDecimalDigitCharacter(*String)) {\r
+        return (FALSE);\r
+      }\r
+    } else {\r
+      if (!ShellIsDecimalDigitCharacter(*String)) {\r
+        return (FALSE);\r
+      }\r
+    }\r
+  }\r
+\r
+  return (TRUE);\r
 }\r
+\r
+/**\r
+  Function to determine if a given filename exists.\r
+\r
+  @param[in] Name         Path to test.\r
+\r
+  @retval EFI_SUCCESS     The Path represents a file.\r
+  @retval EFI_NOT_FOUND   The Path does not represent a file.\r
+  @retval other           The path failed to open.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellFileExists(\r
+  IN CONST CHAR16 *Name\r
+  )\r
+{\r
+  EFI_STATUS          Status;\r
+  EFI_SHELL_FILE_INFO *List;\r
+\r
+  ASSERT(Name != NULL);\r
+\r
+  List = NULL;\r
+  Status = ShellOpenFileMetaArg((CHAR16*)Name, EFI_FILE_MODE_READ, &List);\r
+  if (EFI_ERROR(Status)) {\r
+    return (Status);\r
+  }\r
+\r
+  ShellCloseFileMetaArg(&List);\r
+\r
+  return (EFI_SUCCESS);\r
+}\r
+\r
+/**\r
+  Convert a Unicode character to numerical value.\r
+\r
+  This internal function only deal with Unicode character\r
+  which maps to a valid hexadecimal ASII character, i.e.\r
+  L'0' to L'9', L'a' to L'f' or L'A' to L'F'. For other\r
+  Unicode character, the value returned does not make sense.\r
+\r
+  @param  Char  The character to convert.\r
+\r
+  @return The numerical value converted.\r
+\r
+**/\r
+UINTN\r
+InternalShellHexCharToUintn (\r
+  IN      CHAR16                    Char\r
+  )\r
+{\r
+  if (ShellIsDecimalDigitCharacter (Char)) {\r
+    return Char - L'0';\r
+  }\r
+\r
+  return (10 + CharToUpper (Char) - L'A');\r
+}\r
+\r
+/**\r
+  Convert a Null-terminated Unicode hexadecimal string to a value of type UINT64.\r
+\r
+  This function returns a value of type UINT64 by interpreting the contents\r
+  of the Unicode string specified by String as a hexadecimal number.\r
+  The format of the input Unicode string String is:\r
+\r
+                  [spaces][zeros][x][hexadecimal digits].\r
+\r
+  The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F].\r
+  The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix.\r
+  If "x" appears in the input string, it must be prefixed with at least one 0.\r
+  The function will ignore the pad space, which includes spaces or tab characters,\r
+  before [zeros], [x] or [hexadecimal digit]. The running zero before [x] or\r
+  [hexadecimal digit] will be ignored. Then, the decoding starts after [x] or the\r
+  first valid hexadecimal digit. Then, the function stops at the first character that is\r
+  a not a valid hexadecimal character or NULL, whichever one comes first.\r
+\r
+  If String has only pad spaces, then zero is returned.\r
+  If String has no leading pad spaces, leading zeros or valid hexadecimal digits,\r
+  then zero is returned.\r
+\r
+  @param[in]  String      A pointer to a Null-terminated Unicode string.\r
+  @param[out] Value       Upon a successful return the value of the conversion.\r
+  @param[in] StopAtSpace  FALSE to skip spaces.\r
+\r
+  @retval EFI_SUCCESS             The conversion was successful.\r
+  @retval EFI_INVALID_PARAMETER   A parameter was NULL or invalid.\r
+  @retval EFI_DEVICE_ERROR        An overflow occurred.\r
+**/\r
+EFI_STATUS\r
+InternalShellStrHexToUint64 (\r
+  IN CONST CHAR16   *String,\r
+     OUT   UINT64   *Value,\r
+  IN CONST BOOLEAN  StopAtSpace\r
+  )\r
+{\r
+  UINT64    Result;\r
+\r
+  if (String == NULL || StrSize(String) == 0 || Value == NULL) {\r
+    return (EFI_INVALID_PARAMETER);\r
+  }\r
+\r
+  //\r
+  // Ignore the pad spaces (space or tab)\r
+  //\r
+  while ((*String == L' ') || (*String == L'\t')) {\r
+    String++;\r
+  }\r
+\r
+  //\r
+  // Ignore leading Zeros after the spaces\r
+  //\r
+  while (*String == L'0') {\r
+    String++;\r
+  }\r
+\r
+  if (CharToUpper (*String) == L'X') {\r
+    if (*(String - 1) != L'0') {\r
+      return 0;\r
+    }\r
+    //\r
+    // Skip the 'X'\r
+    //\r
+    String++;\r
+  }\r
+\r
+  Result = 0;\r
+\r
+  //\r
+  // there is a space where there should't be\r
+  //\r
+  if (*String == L' ') {\r
+    return (EFI_INVALID_PARAMETER);\r
+  }\r
+\r
+  while (ShellIsHexaDecimalDigitCharacter (*String)) {\r
+    //\r
+    // If the Hex Number represented by String overflows according\r
+    // to the range defined by UINT64, then return EFI_DEVICE_ERROR.\r
+    //\r
+    if (!(Result <= (RShiftU64((((UINT64) ~0) - InternalShellHexCharToUintn (*String)), 4)))) {\r
+//    if (!(Result <= ((((UINT64) ~0) - InternalShellHexCharToUintn (*String)) >> 4))) {\r
+      return (EFI_DEVICE_ERROR);\r
+    }\r
+\r
+    Result = (LShiftU64(Result, 4));\r
+    Result += InternalShellHexCharToUintn (*String);\r
+    String++;\r
+\r
+    //\r
+    // stop at spaces if requested\r
+    //\r
+    if (StopAtSpace && *String == L' ') {\r
+      break;\r
+    }\r
+  }\r
+\r
+  *Value = Result;\r
+  return (EFI_SUCCESS);\r
+}\r
+\r
+/**\r
+  Convert a Null-terminated Unicode decimal string to a value of\r
+  type UINT64.\r
+\r
+  This function returns a value of type UINT64 by interpreting the contents\r
+  of the Unicode string specified by String as a decimal number. The format\r
+  of the input Unicode string String is:\r
+\r
+                  [spaces] [decimal digits].\r
+\r
+  The valid decimal digit character is in the range [0-9]. The\r
+  function will ignore the pad space, which includes spaces or\r
+  tab characters, before [decimal digits]. The running zero in the\r
+  beginning of [decimal digits] will be ignored. Then, the function\r
+  stops at the first character that is a not a valid decimal character\r
+  or a Null-terminator, whichever one comes first.\r
+\r
+  If String has only pad spaces, then 0 is returned.\r
+  If String has no pad spaces or valid decimal digits,\r
+  then 0 is returned.\r
+\r
+  @param[in]  String      A pointer to a Null-terminated Unicode string.\r
+  @param[out] Value       Upon a successful return the value of the conversion.\r
+  @param[in] StopAtSpace  FALSE to skip spaces.\r
+\r
+  @retval EFI_SUCCESS             The conversion was successful.\r
+  @retval EFI_INVALID_PARAMETER   A parameter was NULL or invalid.\r
+  @retval EFI_DEVICE_ERROR        An overflow occurred.\r
+**/\r
+EFI_STATUS\r
+InternalShellStrDecimalToUint64 (\r
+  IN CONST CHAR16 *String,\r
+     OUT   UINT64 *Value,\r
+  IN CONST BOOLEAN  StopAtSpace\r
+  )\r
+{\r
+  UINT64     Result;\r
+\r
+  if (String == NULL || StrSize (String) == 0 || Value == NULL) {\r
+    return (EFI_INVALID_PARAMETER);\r
+  }\r
+\r
+  //\r
+  // Ignore the pad spaces (space or tab)\r
+  //\r
+  while ((*String == L' ') || (*String == L'\t')) {\r
+    String++;\r
+  }\r
+\r
+  //\r
+  // Ignore leading Zeros after the spaces\r
+  //\r
+  while (*String == L'0') {\r
+    String++;\r
+  }\r
+\r
+  Result = 0;\r
+\r
+  //\r
+  // Stop upon space if requested\r
+  // (if the whole value was 0)\r
+  //\r
+  if (StopAtSpace && *String == L' ') {\r
+    *Value = Result;\r
+    return (EFI_SUCCESS);\r
+  }\r
+\r
+  while (ShellIsDecimalDigitCharacter (*String)) {\r
+    //\r
+    // If the number represented by String overflows according\r
+    // to the range defined by UINT64, then return EFI_DEVICE_ERROR.\r
+    //\r
+\r
+    if (!(Result <= (DivU64x32((((UINT64) ~0) - (*String - L'0')),10)))) {\r
+      return (EFI_DEVICE_ERROR);\r
+    }\r
+\r
+    Result = MultU64x32(Result, 10) + (*String - L'0');\r
+    String++;\r
+\r
+    //\r
+    // Stop at spaces if requested\r
+    //\r
+    if (StopAtSpace && *String == L' ') {\r
+      break;\r
+    }\r
+  }\r
+\r
+  *Value = Result;\r
+\r
+  return (EFI_SUCCESS);\r
+}\r
+\r
+/**\r
+  Function to verify and convert a string to its numerical value.\r
+\r
+  If Hex it must be preceeded with a 0x, 0X, or has ForceHex set TRUE.\r
+\r
+  @param[in] String       The string to evaluate.\r
+  @param[out] Value       Upon a successful return the value of the conversion.\r
+  @param[in] ForceHex     TRUE - always assume hex.\r
+  @param[in] StopAtSpace  FALSE to skip spaces.\r
+\r
+  @retval EFI_SUCCESS             The conversion was successful.\r
+  @retval EFI_INVALID_PARAMETER   String contained an invalid character.\r
+  @retval EFI_NOT_FOUND           String was a number, but Value was NULL.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellConvertStringToUint64(\r
+  IN CONST CHAR16   *String,\r
+     OUT   UINT64   *Value,\r
+  IN CONST BOOLEAN  ForceHex,\r
+  IN CONST BOOLEAN  StopAtSpace\r
+  )\r
+{\r
+  UINT64        RetVal;\r
+  CONST CHAR16  *Walker;\r
+  EFI_STATUS    Status;\r
+  BOOLEAN       Hex;\r
+\r
+  Hex = ForceHex;\r
+\r
+  if (!InternalShellIsHexOrDecimalNumber(String, Hex, StopAtSpace, FALSE)) {\r
+    if (!Hex) {\r
+      Hex = TRUE;\r
+      if (!InternalShellIsHexOrDecimalNumber(String, Hex, StopAtSpace, FALSE)) {\r
+        return (EFI_INVALID_PARAMETER);\r
+      }\r
+    } else {\r
+      return (EFI_INVALID_PARAMETER);\r
+    }\r
+  }\r
+\r
+  //\r
+  // Chop off leading spaces\r
+  //\r
+  for (Walker = String; Walker != NULL && *Walker != CHAR_NULL && *Walker == L' '; Walker++);\r
+\r
+  //\r
+  // make sure we have something left that is numeric.\r
+  //\r
+  if (Walker == NULL || *Walker == CHAR_NULL || !InternalShellIsHexOrDecimalNumber(Walker, Hex, StopAtSpace, FALSE)) {\r
+    return (EFI_INVALID_PARAMETER);\r
+  }\r
+\r
+  //\r
+  // do the conversion.\r
+  //\r
+  if (Hex || StrnCmp(Walker, L"0x", 2) == 0 || StrnCmp(Walker, L"0X", 2) == 0){\r
+    Status = InternalShellStrHexToUint64(Walker, &RetVal, StopAtSpace);\r
+  } else {\r
+    Status = InternalShellStrDecimalToUint64(Walker, &RetVal, StopAtSpace);\r
+  }\r
+\r
+  if (Value == NULL && !EFI_ERROR(Status)) {\r
+    return (EFI_NOT_FOUND);\r
+  }\r
+\r
+  if (Value != NULL) {\r
+    *Value = RetVal;\r
+  }\r
+\r
+  return (Status);\r
+}\r
+\r
+/**\r
+  Function to determin if an entire string is a valid number.\r
+\r
+  If Hex it must be preceeded with a 0x or has ForceHex, set TRUE.\r
+\r
+  @param[in] String       The string to evaluate.\r
+  @param[in] ForceHex     TRUE - always assume hex.\r
+  @param[in] StopAtSpace  TRUE to halt upon finding a space, FALSE to keep going.\r
+\r
+  @retval TRUE        It is all numeric (dec/hex) characters.\r
+  @retval FALSE       There is a non-numeric character.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+ShellIsHexOrDecimalNumber (\r
+  IN CONST CHAR16   *String,\r
+  IN CONST BOOLEAN  ForceHex,\r
+  IN CONST BOOLEAN  StopAtSpace\r
+  )\r
+{\r
+  if (ShellConvertStringToUint64(String, NULL, ForceHex, StopAtSpace) == EFI_NOT_FOUND) {\r
+    return (TRUE);\r
+  }\r
+  return (FALSE);\r
+}\r
+\r
+/**\r
+  Function to read a single line from a SHELL_FILE_HANDLE. The \n is not included in the returned\r
+  buffer.  The returned buffer must be callee freed.\r
+\r
+  If the position upon start is 0, then the Ascii Boolean will be set.  This should be\r
+  maintained and not changed for all operations with the same file.\r
+\r
+  @param[in]       Handle        SHELL_FILE_HANDLE to read from.\r
+  @param[in, out]  Ascii         Boolean value for indicating whether the file is\r
+                                 Ascii (TRUE) or UCS2 (FALSE).\r
+\r
+  @return                        The line of text from the file.\r
+  @retval NULL                   There was not enough memory available.\r
+\r
+  @sa ShellFileHandleReadLine\r
+**/\r
+CHAR16*\r
+EFIAPI\r
+ShellFileHandleReturnLine(\r
+  IN SHELL_FILE_HANDLE            Handle,\r
+  IN OUT BOOLEAN                *Ascii\r
+  )\r
+{\r
+  CHAR16          *RetVal;\r
+  UINTN           Size;\r
+  EFI_STATUS      Status;\r
+\r
+  Size = 0;\r
+  RetVal = NULL;\r
+\r
+  Status = ShellFileHandleReadLine(Handle, RetVal, &Size, FALSE, Ascii);\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    RetVal = AllocateZeroPool(Size);\r
+    if (RetVal == NULL) {\r
+      return (NULL);\r
+    }\r
+    Status = ShellFileHandleReadLine(Handle, RetVal, &Size, FALSE, Ascii);\r
+\r
+  }\r
+  if (Status == EFI_END_OF_FILE && RetVal != NULL && *RetVal != CHAR_NULL) {\r
+    Status = EFI_SUCCESS;\r
+  }\r
+  if (EFI_ERROR(Status) && (RetVal != NULL)) {\r
+    FreePool(RetVal);\r
+    RetVal = NULL;\r
+  }\r
+  return (RetVal);\r
+}\r
+\r
+/**\r
+  Function to read a single line (up to but not including the \n) from a SHELL_FILE_HANDLE.\r
+\r
+  If the position upon start is 0, then the Ascii Boolean will be set.  This should be\r
+  maintained and not changed for all operations with the same file.\r
+\r
+  NOTE: LINES THAT ARE RETURNED BY THIS FUNCTION ARE UCS2, EVEN IF THE FILE BEING READ\r
+        IS IN ASCII FORMAT.\r
+\r
+  @param[in]       Handle        SHELL_FILE_HANDLE to read from.\r
+  @param[in, out]  Buffer        The pointer to buffer to read into. If this function\r
+                                 returns EFI_SUCCESS, then on output Buffer will\r
+                                 contain a UCS2 string, even if the file being\r
+                                 read is ASCII.\r
+  @param[in, out]  Size          On input, pointer to number of bytes in Buffer.\r
+                                 On output, unchanged unless Buffer is too small\r
+                                 to contain the next line of the file. In that\r
+                                 case Size is set to the number of bytes needed\r
+                                 to hold the next line of the file (as a UCS2\r
+                                 string, even if it is an ASCII file).\r
+  @param[in]       Truncate      If the buffer is large enough, this has no effect.\r
+                                 If the buffer is is too small and Truncate is TRUE,\r
+                                 the line will be truncated.\r
+                                 If the buffer is is too small and Truncate is FALSE,\r
+                                 then no read will occur.\r
+\r
+  @param[in, out]  Ascii         Boolean value for indicating whether the file is\r
+                                 Ascii (TRUE) or UCS2 (FALSE).\r
+\r
+  @retval EFI_SUCCESS           The operation was successful.  The line is stored in\r
+                                Buffer.\r
+  @retval EFI_END_OF_FILE       There are no more lines in the file.\r
+  @retval EFI_INVALID_PARAMETER Handle was NULL.\r
+  @retval EFI_INVALID_PARAMETER Size was NULL.\r
+  @retval EFI_BUFFER_TOO_SMALL  Size was not large enough to store the line.\r
+                                Size was updated to the minimum space required.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellFileHandleReadLine(\r
+  IN SHELL_FILE_HANDLE          Handle,\r
+  IN OUT CHAR16                 *Buffer,\r
+  IN OUT UINTN                  *Size,\r
+  IN BOOLEAN                    Truncate,\r
+  IN OUT BOOLEAN                *Ascii\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  CHAR16      CharBuffer;\r
+  UINTN       CharSize;\r
+  UINTN       CountSoFar;\r
+  UINT64      OriginalFilePosition;\r
+\r
+\r
+  if (Handle == NULL\r
+    ||Size   == NULL\r
+   ){\r
+    return (EFI_INVALID_PARAMETER);\r
+  }\r
+  if (Buffer == NULL) {\r
+    ASSERT(*Size == 0);\r
+  } else {\r
+    *Buffer = CHAR_NULL;\r
+  }\r
+  gEfiShellProtocol->GetFilePosition(Handle, &OriginalFilePosition);\r
+  if (OriginalFilePosition == 0) {\r
+    CharSize = sizeof(CHAR16);\r
+    Status = gEfiShellProtocol->ReadFile(Handle, &CharSize, &CharBuffer);\r
+    ASSERT_EFI_ERROR(Status);\r
+    if (CharBuffer == gUnicodeFileTag) {\r
+      *Ascii = FALSE;\r
+    } else {\r
+      *Ascii = TRUE;\r
+      gEfiShellProtocol->SetFilePosition(Handle, OriginalFilePosition);\r
+    }\r
+  }\r
+\r
+  if (*Ascii) {\r
+    CharSize = sizeof(CHAR8);\r
+  } else {\r
+    CharSize = sizeof(CHAR16);\r
+  }\r
+  for (CountSoFar = 0;;CountSoFar++){\r
+    CharBuffer = 0;\r
+    Status = gEfiShellProtocol->ReadFile(Handle, &CharSize, &CharBuffer);\r
+    if (  EFI_ERROR(Status)\r
+       || CharSize == 0\r
+       || (CharBuffer == L'\n' && !(*Ascii))\r
+       || (CharBuffer ==  '\n' && *Ascii)\r
+     ){\r
+      if (CharSize == 0) {\r
+        Status = EFI_END_OF_FILE;\r
+      }\r
+      break;\r
+    }\r
+    //\r
+    // if we have space save it...\r
+    //\r
+    if ((CountSoFar+1)*sizeof(CHAR16) < *Size){\r
+      ASSERT(Buffer != NULL);\r
+      ((CHAR16*)Buffer)[CountSoFar] = CharBuffer;\r
+      ((CHAR16*)Buffer)[CountSoFar+1] = CHAR_NULL;\r
+    }\r
+  }\r
+\r
+  //\r
+  // if we ran out of space tell when...\r
+  //\r
+  if ((CountSoFar+1)*sizeof(CHAR16) > *Size){\r
+    *Size = (CountSoFar+1)*sizeof(CHAR16);\r
+    if (!Truncate) {\r
+      gEfiShellProtocol->SetFilePosition(Handle, OriginalFilePosition);\r
+    } else {\r
+      DEBUG((DEBUG_WARN, "The line was truncated in ShellFileHandleReadLine"));\r
+    }\r
+    return (EFI_BUFFER_TOO_SMALL);\r
+  }\r
+  while(Buffer[StrLen(Buffer)-1] == L'\r') {\r
+    Buffer[StrLen(Buffer)-1] = CHAR_NULL;\r
+  }\r
+\r
+  return (Status);\r
+}\r
+\r
+/**\r
+  Function to print help file / man page content in the spec from the UEFI Shell protocol GetHelpText function.\r
+\r
+  @param[in] CommandToGetHelpOn  Pointer to a string containing the command name of help file to be printed.\r
+  @param[in] SectionToGetHelpOn  Pointer to the section specifier(s).\r
+  @param[in] PrintCommandText    If TRUE, prints the command followed by the help content, otherwise prints\r
+                                 the help content only.\r
+  @retval EFI_DEVICE_ERROR       The help data format was incorrect.\r
+  @retval EFI_NOT_FOUND          The help data could not be found.\r
+  @retval EFI_SUCCESS            The operation was successful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellPrintHelp (\r
+  IN CONST CHAR16     *CommandToGetHelpOn,\r
+  IN CONST CHAR16     *SectionToGetHelpOn,\r
+  IN BOOLEAN          PrintCommandText\r
+  )\r
+{\r
+  EFI_STATUS          Status;\r
+  CHAR16              *OutText;\r
+\r
+  OutText = NULL;\r
+\r
+  //\r
+  // Get the string to print based\r
+  //\r
+  Status = gEfiShellProtocol->GetHelpText (CommandToGetHelpOn, SectionToGetHelpOn, &OutText);\r
+\r
+  //\r
+  // make sure we got a valid string\r
+  //\r
+  if (EFI_ERROR(Status)){\r
+    return Status;\r
+  }\r
+  if (OutText == NULL || StrLen(OutText) == 0) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  //\r
+  // Chop off trailing stuff we dont need\r
+  //\r
+  while (OutText[StrLen(OutText)-1] == L'\r' || OutText[StrLen(OutText)-1] == L'\n' || OutText[StrLen(OutText)-1] == L' ') {\r
+    OutText[StrLen(OutText)-1] = CHAR_NULL;\r
+  }\r
+\r
+  //\r
+  // Print this out to the console\r
+  //\r
+  if (PrintCommandText) {\r
+    ShellPrintEx(-1, -1, L"%H%-14s%N- %s\r\n", CommandToGetHelpOn, OutText);\r
+  } else {\r
+    ShellPrintEx(-1, -1, L"%N%s\r\n", OutText);\r
+  }\r
+\r
+  SHELL_FREE_NON_NULL(OutText);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Function to delete a file by name\r
+\r
+  @param[in]       FileName       Pointer to file name to delete.\r
+\r
+  @retval EFI_SUCCESS             the file was deleted sucessfully\r
+  @retval EFI_WARN_DELETE_FAILURE the handle was closed, but the file was not\r
+                                  deleted\r
+  @retval EFI_INVALID_PARAMETER   One of the parameters has an invalid value.\r
+  @retval EFI_NOT_FOUND           The specified file could not be found on the\r
+                                  device or the file system could not be found\r
+                                  on the device.\r
+  @retval EFI_NO_MEDIA            The device has no medium.\r
+  @retval EFI_MEDIA_CHANGED       The device has a different medium in it or the\r
+                                  medium is no longer supported.\r
+  @retval EFI_DEVICE_ERROR        The device reported an error.\r
+  @retval EFI_VOLUME_CORRUPTED    The file system structures are corrupted.\r
+  @retval EFI_WRITE_PROTECTED     The file or medium is write protected.\r
+  @retval EFI_ACCESS_DENIED       The file was opened read only.\r
+  @retval EFI_OUT_OF_RESOURCES    Not enough resources were available to open the\r
+                                  file.\r
+  @retval other                   The file failed to open\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellDeleteFileByName(\r
+  IN CONST CHAR16               *FileName\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  SHELL_FILE_HANDLE         FileHandle;\r
+\r
+  Status = ShellFileExists(FileName);\r
+\r
+  if (Status == EFI_SUCCESS){\r
+    Status = ShellOpenFileByName(FileName, &FileHandle, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, 0x0);\r
+    if (Status == EFI_SUCCESS){\r
+      Status = ShellDeleteFile(&FileHandle);\r
+    }\r
+  }\r
+\r
+  return(Status);\r
+\r
+}\r
+\r
+/**\r
+  Cleans off all the quotes in the string.\r
+\r
+  @param[in]     OriginalString   pointer to the string to be cleaned.\r
+  @param[out]   CleanString      The new string with all quotes removed.\r
+                                                  Memory allocated in the function and free\r
+                                                  by caller.\r
+\r
+  @retval EFI_SUCCESS   The operation was successful.\r
+**/\r
+EFI_STATUS\r
+InternalShellStripQuotes (\r
+  IN  CONST CHAR16     *OriginalString,\r
+  OUT CHAR16           **CleanString\r
+  )\r
+{\r
+  CHAR16            *Walker;\r
+\r
+  if (OriginalString == NULL || CleanString == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  *CleanString = AllocateCopyPool (StrSize (OriginalString), OriginalString);\r
+  if (*CleanString == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  for (Walker = *CleanString; Walker != NULL && *Walker != CHAR_NULL ; Walker++) {\r
+    if (*Walker == L'\"') {\r
+      CopyMem(Walker, Walker+1, StrSize(Walker) - sizeof(Walker[0]));\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r