]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/Application/Shell/ShellProtocol.c
ShellPkg: Fix the incorrect return status in function FindFiles()
[mirror_edk2.git] / ShellPkg / Application / Shell / ShellProtocol.c
index 798f5476f6db36e61ab089efab0813f5c5057eb9..6f292507a9b63a753d1c77cd4cecb4ff6b26aa6d 100644 (file)
@@ -2,7 +2,8 @@
   Member functions of EFI_SHELL_PROTOCOL and functions for creation,\r
   manipulation, and initialization of EFI_SHELL_PROTOCOL.\r
 \r
-  Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>\r
+  (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>\r
+  Copyright (c) 2009 - 2016, 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
@@ -15,6 +16,8 @@
 \r
 #include "Shell.h"\r
 \r
+#define INIT_NAME_BUFFER_SIZE  128\r
+\r
 /**\r
   Close an open file handle.\r
 \r
@@ -182,6 +185,9 @@ EfiShellSetMap(
        ){\r
           if (StringNoCaseCompare(&MapListNode->MapName, &Mapping) == 0) {\r
             RemoveEntryList(&MapListNode->Link);\r
+            SHELL_FREE_NON_NULL(MapListNode->DevicePath);\r
+            SHELL_FREE_NON_NULL(MapListNode->MapName);\r
+            SHELL_FREE_NON_NULL(MapListNode->CurrentDirectoryPath);\r
             FreePool(MapListNode);\r
             return (EFI_SUCCESS);\r
           }\r
@@ -446,38 +452,40 @@ EfiShellGetFilePathFromDevicePath(
           ; FilePath = (FILEPATH_DEVICE_PATH*)NextDevicePathNode (&FilePath->Header)\r
          ){\r
         //\r
-        // all the rest should be file path nodes\r
+        // If any node is not a file path node, then the conversion can not be completed\r
         //\r
         if ((DevicePathType(&FilePath->Header) != MEDIA_DEVICE_PATH) ||\r
             (DevicePathSubType(&FilePath->Header) != MEDIA_FILEPATH_DP)) {\r
           FreePool(PathForReturn);\r
-          PathForReturn = NULL;\r
-          ASSERT(FALSE);\r
-        } else {\r
-          //\r
-          // append the path part onto the filepath.\r
-          //\r
-          ASSERT((PathForReturn == NULL && PathSize == 0) || (PathForReturn != NULL));\r
-\r
-          AlignedNode = AllocateCopyPool (DevicePathNodeLength(FilePath), FilePath);\r
-          ASSERT (AlignedNode != NULL);\r
-\r
-          // File Path Device Path Nodes 'can optionally add a "\" separator to\r
-          //  the beginning and/or the end of the Path Name string.'\r
-          // (UEFI Spec 2.4 section 9.3.6.4).\r
-          // If necessary, add a "\", but otherwise don't\r
-          // (This is specified in the above section, and also implied by the\r
-          //  UEFI Shell spec section 3.7)\r
-          if ((PathSize != 0)                        &&\r
-              (PathForReturn != NULL)                &&\r
-              (PathForReturn[PathSize - 1] != L'\\') &&\r
-              (AlignedNode->PathName[0]    != L'\\')) {\r
-            PathForReturn = StrnCatGrow (&PathForReturn, &PathSize, L"\\", 1);\r
-          }\r
+          return NULL;\r
+        }\r
+\r
+        //\r
+        // append the path part onto the filepath.\r
+        //\r
+        ASSERT((PathForReturn == NULL && PathSize == 0) || (PathForReturn != NULL));\r
+\r
+        AlignedNode = AllocateCopyPool (DevicePathNodeLength(FilePath), FilePath);\r
+        if (AlignedNode == NULL) {\r
+          FreePool (PathForReturn);\r
+          return NULL;\r
+        }\r
 \r
-          PathForReturn = StrnCatGrow(&PathForReturn, &PathSize, AlignedNode->PathName, 0);\r
-          FreePool(AlignedNode);\r
+        // File Path Device Path Nodes 'can optionally add a "\" separator to\r
+        //  the beginning and/or the end of the Path Name string.'\r
+        // (UEFI Spec 2.4 section 9.3.6.4).\r
+        // If necessary, add a "\", but otherwise don't\r
+        // (This is specified in the above section, and also implied by the\r
+        //  UEFI Shell spec section 3.7)\r
+        if ((PathSize != 0)                        &&\r
+            (PathForReturn != NULL)                &&\r
+            (PathForReturn[PathSize - 1] != L'\\') &&\r
+            (AlignedNode->PathName[0]    != L'\\')) {\r
+          PathForReturn = StrnCatGrow (&PathForReturn, &PathSize, L"\\", 1);\r
         }\r
+\r
+        PathForReturn = StrnCatGrow(&PathForReturn, &PathSize, AlignedNode->PathName, 0);\r
+        FreePool(AlignedNode);\r
       } // for loop of remaining nodes\r
     }\r
     if (PathForReturn != NULL) {\r
@@ -529,18 +537,18 @@ EfiShellGetDevicePathFromFilePath(
     if (Cwd == NULL) {\r
       return (NULL);\r
     }\r
-    Size = StrSize(Cwd);\r
-    Size += StrSize(Path);\r
+    Size = StrSize(Cwd) + StrSize(Path);\r
     NewPath = AllocateZeroPool(Size);\r
     if (NewPath == NULL) {\r
       return (NULL);\r
     }\r
-    StrCpy(NewPath, Cwd);\r
+    StrCpyS(NewPath, Size/sizeof(CHAR16), Cwd);\r
+    StrCatS(NewPath, Size/sizeof(CHAR16), L"\\");\r
     if (*Path == L'\\') {\r
       Path++;\r
       while (PathRemoveLastItem(NewPath)) ;\r
     }\r
-    StrCat(NewPath, Path);\r
+    StrCatS(NewPath, Size/sizeof(CHAR16), Path);\r
     DevicePathForReturn = EfiShellGetDevicePathFromFilePath(NewPath);\r
     FreePool(NewPath);\r
     return (DevicePathForReturn);\r
@@ -1124,13 +1132,18 @@ EfiShellCreateFile(
 {\r
   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
   EFI_STATUS                Status;\r
+  BOOLEAN                   Volatile;\r
 \r
   //\r
   // Is this for an environment variable\r
   // do we start with >v\r
   //\r
   if (StrStr(FileName, L">v") == FileName) {\r
-    if (!IsVolatileEnv(FileName+2)) {\r
+    Status = IsVolatileEnv (FileName + 2, &Volatile);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+    if (!Volatile) {\r
       return (EFI_INVALID_PARAMETER);\r
     }\r
     *FileHandle = CreateFileInterfaceEnv(FileName+2);\r
@@ -1240,6 +1253,7 @@ EfiShellOpenFileByName(
 {\r
   EFI_DEVICE_PATH_PROTOCOL        *DevicePath;\r
   EFI_STATUS                      Status;\r
+  BOOLEAN                         Volatile;\r
 \r
   *FileHandle = NULL;\r
 \r
@@ -1299,7 +1313,11 @@ EfiShellOpenFileByName(
   // do we start with >v\r
   //\r
   if (StrStr(FileName, L">v") == FileName) {\r
-    if (!IsVolatileEnv(FileName+2) &&\r
+    Status = IsVolatileEnv (FileName + 2, &Volatile);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+    if (!Volatile &&\r
         ((OpenMode & EFI_FILE_MODE_WRITE) != 0)) {\r
       return (EFI_INVALID_PARAMETER);\r
     }\r
@@ -1359,6 +1377,7 @@ EfiShellDeleteFileByName(
   //\r
   // now delete the file\r
   //\r
+  ShellFileHandleRemove(FileHandle);\r
   return (ShellInfoObject.NewEfiShellProtocol->DeleteFile(FileHandle));\r
 }\r
 \r
@@ -1401,8 +1420,6 @@ EfiShellEnablePageBreak (
                                 is NULL, then the current shell environment is used.\r
                             \r
   @param[out] StartImageStatus  Returned status from gBS->StartImage.\r
-  @param[out] ExitDataSize      ExitDataSize as returned from gBS->StartImage\r
-  @param[out] ExitData          ExitData as returned from gBS->StartImage\r
 \r
   @retval EFI_SUCCESS       The command executed successfully. The  status code\r
                             returned by the command is pointed to by StatusCode.\r
@@ -1417,9 +1434,7 @@ InternalShellExecuteDevicePath(
   IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
   IN CONST CHAR16                   *CommandLine OPTIONAL,\r
   IN CONST CHAR16                   **Environment OPTIONAL,\r
-  OUT EFI_STATUS                    *StartImageStatus OPTIONAL,\r
-  OUT UINTN                         *ExitDataSize OPTIONAL,\r
-  OUT CHAR16                        **ExitData OPTIONAL\r
+  OUT EFI_STATUS                    *StartImageStatus OPTIONAL\r
   )\r
 {\r
   EFI_STATUS                    Status;\r
@@ -1429,26 +1444,30 @@ InternalShellExecuteDevicePath(
   EFI_LOADED_IMAGE_PROTOCOL     *LoadedImage;\r
   LIST_ENTRY                    OrigEnvs;\r
   EFI_SHELL_PARAMETERS_PROTOCOL ShellParamsProtocol;\r
-  UINTN                         InternalExitDataSize;\r
-  UINTN                         *ExitDataSizePtr;\r
   CHAR16                        *ImagePath;\r
   UINTN                         Index;\r
-\r
-  // ExitDataSize is not OPTIONAL for gBS->BootServices, provide somewhere for\r
-  // it to be dumped if the caller doesn't want it.\r
-  if (ExitData == NULL) {\r
-    ExitDataSizePtr = &InternalExitDataSize;\r
-  } else {\r
-    ExitDataSizePtr = ExitDataSize;\r
-  }\r
+  CHAR16                        *Walker;\r
+  CHAR16                        *NewCmdLine;\r
 \r
   if (ParentImageHandle == NULL) {\r
     return (EFI_INVALID_PARAMETER);\r
   }\r
 \r
   InitializeListHead(&OrigEnvs);\r
+  ZeroMem(&ShellParamsProtocol, sizeof(EFI_SHELL_PARAMETERS_PROTOCOL));\r
 \r
   NewHandle = NULL;\r
+  \r
+  NewCmdLine = AllocateCopyPool (StrSize (CommandLine), CommandLine);\r
+  if (NewCmdLine == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  for (Walker = NewCmdLine; Walker != NULL && *Walker != CHAR_NULL ; Walker++) {\r
+    if (*Walker == L'^' && *(Walker+1) == L'#') {\r
+      CopyMem(Walker, Walker+1, StrSize(Walker) - sizeof(Walker[0]));\r
+    }\r
+  }\r
 \r
   //\r
   // Load the image with:\r
@@ -1466,6 +1485,7 @@ InternalShellExecuteDevicePath(
     if (NewHandle != NULL) {\r
       gBS->UnloadImage(NewHandle);\r
     }\r
+    FreePool (NewCmdLine);\r
     return (Status);\r
   }\r
   Status = gBS->OpenProtocol(\r
@@ -1477,10 +1497,24 @@ InternalShellExecuteDevicePath(
     EFI_OPEN_PROTOCOL_GET_PROTOCOL);\r
 \r
   if (!EFI_ERROR(Status)) {\r
+    //\r
+    // If the image is not an app abort it.\r
+    //\r
+    if (LoadedImage->ImageCodeType != EfiLoaderCode){\r
+      ShellPrintHiiEx(\r
+        -1, \r
+        -1, \r
+        NULL,\r
+        STRING_TOKEN (STR_SHELL_IMAGE_NOT_APP),\r
+        ShellInfoObject.HiiHandle\r
+      );\r
+      goto UnloadImage;\r
+    }\r
+\r
     ASSERT(LoadedImage->LoadOptionsSize == 0);\r
-    if (CommandLine != NULL) {\r
-      LoadedImage->LoadOptionsSize  = (UINT32)StrSize(CommandLine);\r
-      LoadedImage->LoadOptions      = (VOID*)CommandLine;\r
+    if (NewCmdLine != NULL) {\r
+      LoadedImage->LoadOptionsSize  = (UINT32)StrSize(NewCmdLine);\r
+      LoadedImage->LoadOptions      = (VOID*)NewCmdLine;\r
     }\r
 \r
     //\r
@@ -1499,7 +1533,7 @@ InternalShellExecuteDevicePath(
     ShellParamsProtocol.StdIn   = ShellInfoObject.NewShellParametersProtocol->StdIn;\r
     ShellParamsProtocol.StdOut  = ShellInfoObject.NewShellParametersProtocol->StdOut;\r
     ShellParamsProtocol.StdErr  = ShellInfoObject.NewShellParametersProtocol->StdErr;\r
-    Status = UpdateArgcArgv(&ShellParamsProtocol, CommandLine, NULL, NULL);\r
+    Status = UpdateArgcArgv(&ShellParamsProtocol, NewCmdLine, Efi_Application, NULL, NULL);\r
     ASSERT_EFI_ERROR(Status);\r
     //\r
     // Replace Argv[0] with the full path of the binary we're executing:\r
@@ -1534,13 +1568,13 @@ InternalShellExecuteDevicePath(
     ///@todo initialize and install ShellInterface protocol on the new image for compatibility if - PcdGetBool(PcdShellSupportOldProtocols)\r
 \r
     //\r
-    // now start the image, passing up exit data if the caller requested it\r
+    // now start the image and if the caller wanted the return code pass it to them...\r
     //\r
     if (!EFI_ERROR(Status)) {\r
       StartStatus      = gBS->StartImage(\r
                           NewHandle,\r
-                          ExitDataSizePtr,\r
-                          ExitData\r
+                          0,\r
+                          NULL\r
                           );\r
       if (StartImageStatus != NULL) {\r
         *StartImageStatus = StartStatus;\r
@@ -1578,8 +1612,113 @@ FreeAlloc:
     ASSERT_EFI_ERROR (CleanupStatus);\r
   }\r
 \r
+  FreePool (NewCmdLine);\r
+\r
   return(Status);\r
 }\r
+\r
+/**\r
+  internal worker function to load and run an image in the current shell.\r
+\r
+  @param CommandLine            Points to the NULL-terminated UCS-2 encoded string\r
+                                containing the command line. If NULL then the command-\r
+                                line will be empty.\r
+  @param Environment            Points to a NULL-terminated array of environment\r
+                                variables with the format 'x=y', where x is the\r
+                                environment variable name and y is the value. If this\r
+                                is NULL, then the current shell environment is used.\r
+                \r
+  @param[out] StartImageStatus  Returned status from the command line.\r
+\r
+  @retval EFI_SUCCESS       The command executed successfully. The  status code\r
+                            returned by the command is pointed to by StatusCode.\r
+  @retval EFI_INVALID_PARAMETER The parameters are invalid.\r
+  @retval EFI_OUT_OF_RESOURCES Out of resources.\r
+  @retval EFI_UNSUPPORTED   Nested shell invocations are not allowed.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InternalShellExecute(\r
+  IN CONST CHAR16                   *CommandLine OPTIONAL,\r
+  IN CONST CHAR16                   **Environment OPTIONAL,\r
+  OUT EFI_STATUS                    *StartImageStatus OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  EFI_STATUS                    CleanupStatus;\r
+  LIST_ENTRY                    OrigEnvs;\r
+\r
+  InitializeListHead(&OrigEnvs);\r
+\r
+  //\r
+  // Save our current environment settings for later restoration if necessary\r
+  //\r
+  if (Environment != NULL) {\r
+    Status = GetEnvironmentVariableList(&OrigEnvs);\r
+    if (!EFI_ERROR(Status)) {\r
+      Status = SetEnvironmentVariables(Environment);\r
+    } else {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  Status = RunShellCommand(CommandLine, StartImageStatus);\r
+\r
+  // Restore environment variables\r
+  if (!IsListEmpty(&OrigEnvs)) {\r
+    CleanupStatus = SetEnvironmentVariableList(&OrigEnvs);\r
+    ASSERT_EFI_ERROR (CleanupStatus);\r
+  }\r
+\r
+  return(Status);\r
+}\r
+\r
+/**\r
+  Determine if the UEFI Shell is currently running with nesting enabled or disabled.\r
+\r
+  @retval FALSE   nesting is required\r
+  @retval other   nesting is enabled\r
+**/\r
+STATIC\r
+BOOLEAN\r
+EFIAPI\r
+NestingEnabled(\r
+)\r
+{\r
+  EFI_STATUS  Status;\r
+  CHAR16      *Temp;\r
+  CHAR16      *Temp2;\r
+  UINTN       TempSize;\r
+  BOOLEAN     RetVal;\r
+\r
+  RetVal = TRUE;\r
+  Temp   = NULL;\r
+  Temp2  = NULL;\r
+\r
+  if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoNest) {\r
+    TempSize = 0;\r
+    Temp     = NULL;\r
+    Status = SHELL_GET_ENVIRONMENT_VARIABLE(mNoNestingEnvVarName, &TempSize, Temp);\r
+    if (Status == EFI_BUFFER_TOO_SMALL) {\r
+      Temp = AllocateZeroPool(TempSize + sizeof(CHAR16));\r
+      if (Temp != NULL) {\r
+        Status = SHELL_GET_ENVIRONMENT_VARIABLE(mNoNestingEnvVarName, &TempSize, Temp);\r
+      }\r
+    }\r
+    Temp2 = StrnCatGrow(&Temp2, NULL, mNoNestingTrue, 0);\r
+    if (Temp != NULL && Temp2 != NULL && StringNoCaseCompare(&Temp, &Temp2) == 0) {\r
+      //\r
+      // Use the no nesting method.\r
+      //\r
+      RetVal = FALSE;\r
+    }\r
+  }\r
+\r
+  SHELL_FREE_NON_NULL(Temp);\r
+  SHELL_FREE_NON_NULL(Temp2);\r
+  return (RetVal);\r
+}\r
+\r
 /**\r
   Execute the command line.\r
 \r
@@ -1603,7 +1742,7 @@ FreeAlloc:
                             variables with the format 'x=y', where x is the\r
                             environment variable name and y is the value. If this\r
                             is NULL, then the current shell environment is used.\r
-  @param StatusCode         Points to the status code returned by the command.\r
+  @param StatusCode         Points to the status code returned by the CommandLine.\r
 \r
   @retval EFI_SUCCESS       The command executed successfully. The  status code\r
                             returned by the command is pointed to by StatusCode.\r
@@ -1627,67 +1766,48 @@ EfiShellExecute(
   CHAR16                    *Temp;\r
   EFI_DEVICE_PATH_PROTOCOL  *DevPath;\r
   UINTN                     Size;\r
-  UINTN                     ExitDataSize;\r
-  CHAR16                    *ExitData;\r
 \r
   if ((PcdGet8(PcdShellSupportLevel) < 1)) {\r
     return (EFI_UNSUPPORTED);\r
   }\r
 \r
-  DevPath = AppendDevicePath (ShellInfoObject.ImageDevPath, ShellInfoObject.FileDevPath);\r
+  if (NestingEnabled()) {\r
+    DevPath = AppendDevicePath (ShellInfoObject.ImageDevPath, ShellInfoObject.FileDevPath);\r
 \r
-  DEBUG_CODE_BEGIN();\r
-  Temp = ConvertDevicePathToText(ShellInfoObject.FileDevPath, TRUE, TRUE);\r
-  FreePool(Temp);\r
-  Temp = ConvertDevicePathToText(ShellInfoObject.ImageDevPath, TRUE, TRUE);\r
-  FreePool(Temp);\r
-  Temp = ConvertDevicePathToText(DevPath, TRUE, TRUE);\r
-  FreePool(Temp);\r
-  DEBUG_CODE_END();\r
+    DEBUG_CODE_BEGIN();\r
+    Temp = ConvertDevicePathToText(ShellInfoObject.FileDevPath, TRUE, TRUE);\r
+    FreePool(Temp);\r
+    Temp = ConvertDevicePathToText(ShellInfoObject.ImageDevPath, TRUE, TRUE);\r
+    FreePool(Temp);\r
+    Temp = ConvertDevicePathToText(DevPath, TRUE, TRUE);\r
+    FreePool(Temp);\r
+    DEBUG_CODE_END();\r
 \r
-  Temp = NULL;\r
-  Size = 0;\r
-  ASSERT((Temp == NULL && Size == 0) || (Temp != NULL));\r
-  StrnCatGrow(&Temp, &Size, L"Shell.efi -_exit ", 0);\r
-  StrnCatGrow(&Temp, &Size, CommandLine, 0);\r
-\r
-  Status = InternalShellExecuteDevicePath(\r
-    ParentImageHandle,\r
-    DevPath,\r
-    Temp,\r
-    (CONST CHAR16**)Environment,\r
-    StatusCode,\r
-    &ExitDataSize,\r
-    &ExitData);\r
-\r
-    if (Status == EFI_ABORTED) {\r
-      // If the command exited with an error, the shell should put the exit\r
-      // status in ExitData, preceded by a null-terminated string.\r
-      ASSERT (ExitDataSize == StrSize (ExitData) + sizeof (SHELL_STATUS));\r
-\r
-      if (StatusCode != NULL) {\r
-        // Skip the null-terminated string\r
-        ExitData += StrLen (ExitData) + 1;\r
-\r
-        // Use CopyMem to avoid alignment faults\r
-        CopyMem (StatusCode, ExitData, sizeof (SHELL_STATUS));\r
-\r
-        // Convert from SHELL_STATUS to EFI_STATUS\r
-        // EFI_STATUSes have top bit set when they are errors.\r
-        // (See UEFI Spec Appendix D)\r
-        if (*StatusCode != SHELL_SUCCESS) {\r
-          *StatusCode = (EFI_STATUS) *StatusCode | MAX_BIT;\r
-        }\r
-      }\r
-      FreePool (ExitData);\r
-      Status = EFI_SUCCESS;\r
-    }\r
+    Temp = NULL;\r
+    Size = 0;\r
+    ASSERT((Temp == NULL && Size == 0) || (Temp != NULL));\r
+    StrnCatGrow(&Temp, &Size, L"Shell.efi -_exit ", 0);\r
+    StrnCatGrow(&Temp, &Size, CommandLine, 0);\r
+\r
+    Status = InternalShellExecuteDevicePath(\r
+      ParentImageHandle,\r
+      DevPath,\r
+      Temp,\r
+      (CONST CHAR16**)Environment,\r
+      StatusCode);\r
+\r
+    //\r
+    // de-allocate and return\r
+    //\r
+    FreePool(DevPath);\r
+    FreePool(Temp);\r
+  } else {\r
+    Status = InternalShellExecute(\r
+      (CONST CHAR16*)CommandLine,\r
+      (CONST CHAR16**)Environment,\r
+      StatusCode);\r
+  }\r
 \r
-  //\r
-  // de-allocate and return\r
-  //\r
-  FreePool(DevPath);\r
-  FreePool(Temp);\r
   return(Status);\r
 }\r
 \r
@@ -1845,10 +1965,9 @@ InternalDuplicateShellFileInfo(
   if (NewNode == NULL) {\r
     return (NULL);\r
   }\r
-  NewNode->FullName = AllocateZeroPool(StrSize(Node->FullName));\r
-\r
-  NewNode->FileName = AllocateZeroPool(StrSize(Node->FileName));\r
-  NewNode->Info     = AllocateZeroPool((UINTN)Node->Info->Size);\r
+  NewNode->FullName = AllocateCopyPool(StrSize(Node->FullName), Node->FullName);\r
+  NewNode->FileName = AllocateCopyPool(StrSize(Node->FileName), Node->FileName);\r
+  NewNode->Info     = AllocateCopyPool((UINTN)Node->Info->Size, Node->Info);\r
   if ( NewNode->FullName == NULL\r
     || NewNode->FileName == NULL\r
     || NewNode->Info == NULL\r
@@ -1864,9 +1983,6 @@ InternalDuplicateShellFileInfo(
   if (!Save) {\r
     Node->Handle = NULL;\r
   }\r
-  StrCpy((CHAR16*)NewNode->FullName, Node->FullName);\r
-  StrCpy((CHAR16*)NewNode->FileName, Node->FileName);\r
-  CopyMem(NewNode->Info, Node->Info, (UINTN)Node->Info->Size);\r
 \r
   return((EFI_SHELL_FILE_INFO*)NewNode);\r
 }\r
@@ -2029,6 +2145,14 @@ EfiShellFindFilesInDir(
       ; !EFI_ERROR(Status) && !NoFile\r
       ; Status = FileHandleFindNextFile(FileDirHandle, FileInfo, &NoFile)\r
      ){\r
+    if (ShellFileList == NULL) {\r
+      ShellFileList = (EFI_SHELL_FILE_INFO*)AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));\r
+      if (ShellFileList == NULL) {\r
+        SHELL_FREE_NON_NULL (BasePath);\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+      InitializeListHead(&ShellFileList->Link);\r
+    }\r
     //\r
     // allocate a new EFI_SHELL_FILE_INFO and populate it...\r
     //\r
@@ -2038,11 +2162,12 @@ EfiShellFindFilesInDir(
       FileInfo->FileName,\r
       NULL,         // no handle since not open\r
       FileInfo);\r
-\r
-    if (ShellFileList == NULL) {\r
-      ShellFileList = (EFI_SHELL_FILE_INFO*)AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));\r
-      ASSERT(ShellFileList != NULL);\r
-      InitializeListHead(&ShellFileList->Link);\r
+    if (ShellFileListItem == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      //\r
+      // Free resources outside the loop.\r
+      //\r
+      break;\r
     }\r
     InsertTailList(&ShellFileList->Link, &ShellFileListItem->Link);\r
   }\r
@@ -2054,7 +2179,7 @@ EfiShellFindFilesInDir(
   }\r
   SHELL_FREE_NON_NULL(BasePath);\r
   return(Status);\r
-  }\r
+}\r
 \r
 /**\r
   Get the GUID value from a human readable name.\r
@@ -2247,8 +2372,11 @@ ShellSearchHandle(
      ; NextFilePatternStart++);\r
 \r
   CurrentFilePattern = AllocateZeroPool((NextFilePatternStart-FilePattern+1)*sizeof(CHAR16));\r
-  ASSERT(CurrentFilePattern != NULL);\r
-  StrnCpy(CurrentFilePattern, FilePattern, NextFilePatternStart-FilePattern);\r
+  if (CurrentFilePattern == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  StrnCpyS(CurrentFilePattern, NextFilePatternStart-FilePattern+1, FilePattern, NextFilePatternStart-FilePattern);\r
 \r
   if (CurrentFilePattern[0]   == CHAR_NULL\r
     &&NextFilePatternStart[0] == CHAR_NULL\r
@@ -2306,15 +2434,14 @@ ShellSearchHandle(
          ){\r
         if (UnicodeCollation->MetaiMatch(UnicodeCollation, (CHAR16*)ShellInfoNode->FileName, CurrentFilePattern)){\r
           if (ShellInfoNode->FullName != NULL && StrStr(ShellInfoNode->FullName, L":") == NULL) {\r
-            Size = StrSize(ShellInfoNode->FullName);\r
-            Size += StrSize(MapName) + sizeof(CHAR16);\r
+            Size = StrSize (ShellInfoNode->FullName) + StrSize (MapName);\r
             NewFullName = AllocateZeroPool(Size);\r
             if (NewFullName == NULL) {\r
               Status = EFI_OUT_OF_RESOURCES;\r
             } else {\r
-              StrCpy(NewFullName, MapName);\r
-              StrCat(NewFullName, ShellInfoNode->FullName+1);\r
-              FreePool((VOID*)ShellInfoNode->FullName);\r
+              StrCpyS(NewFullName, Size / sizeof(CHAR16), MapName);\r
+              StrCatS(NewFullName, Size / sizeof(CHAR16), ShellInfoNode->FullName);\r
+              FreePool ((VOID *) ShellInfoNode->FullName);\r
               ShellInfoNode->FullName = NewFullName;\r
             }\r
           }\r
@@ -2344,6 +2471,8 @@ ShellSearchHandle(
               // recurse with the next part of the pattern\r
               //\r
               Status = ShellSearchHandle(NextFilePatternStart, UnicodeCollation, ShellInfoNode->Handle, FileList, ShellInfoNode, MapName);\r
+              EfiShellClose(ShellInfoNode->Handle);\r
+              ShellInfoNode->Handle = NULL;\r
             }\r
           } else if (!EFI_ERROR(Status)) {\r
             //\r
@@ -2354,7 +2483,6 @@ ShellSearchHandle(
             // copy the information we need into a new Node\r
             //\r
             NewShellNode = InternalDuplicateShellFileInfo(ShellInfoNode, FALSE);\r
-            ASSERT(NewShellNode != NULL);\r
             if (NewShellNode == NULL) {\r
               Status = EFI_OUT_OF_RESOURCES;\r
             }\r
@@ -2381,6 +2509,10 @@ ShellSearchHandle(
     }\r
   }\r
 \r
+  if (*FileList == NULL || (*FileList != NULL && IsListEmpty(&(*FileList)->Link))) {\r
+    Status = EFI_NOT_FOUND;\r
+  }\r
+\r
   FreePool(CurrentFilePattern);\r
   return (Status);\r
 }\r
@@ -2436,16 +2568,15 @@ EfiShellFindFiles(
   RootDevicePath = NULL;\r
   RootFileHandle = NULL;\r
   MapName        = NULL;\r
-  PatternCopy = AllocateZeroPool(StrSize(FilePattern));\r
+  PatternCopy = AllocateCopyPool(StrSize(FilePattern), FilePattern);\r
   if (PatternCopy == NULL) {\r
     return (EFI_OUT_OF_RESOURCES);\r
   }\r
-  StrCpy(PatternCopy, FilePattern);\r
 \r
   PatternCopy = PathCleanUpDirectories(PatternCopy);\r
 \r
-  Count = StrStr(PatternCopy, L":") - PatternCopy;\r
-  Count += 2;\r
+  Count = StrStr(PatternCopy, L":") - PatternCopy + 1;\r
+  ASSERT (Count <= StrLen (PatternCopy));\r
 \r
   ASSERT(MapName == NULL);\r
   MapName = StrnCatGrow(&MapName, NULL, PatternCopy, Count);\r
@@ -2463,6 +2594,7 @@ EfiShellFindFiles(
             ; PatternCurrentLocation++);\r
         PatternCurrentLocation++;\r
         Status = ShellSearchHandle(PatternCurrentLocation, gUnicodeCollation, RootFileHandle, FileList, NULL, MapName);\r
+        EfiShellClose(RootFileHandle);\r
       }\r
       FreePool(RootDevicePath);\r
     }\r
@@ -2524,6 +2656,7 @@ EfiShellOpenFileList(
     CurDir = EfiShellGetCurDir(NULL);\r
     ASSERT((Path2 == NULL && Path2Size == 0) || (Path2 != NULL));\r
     StrnCatGrow(&Path2, &Path2Size, CurDir, 0);\r
+    StrnCatGrow(&Path2, &Path2Size, L"\\", 0);\r
     if (*Path == L'\\') {\r
       Path++;\r
       while (PathRemoveLastItem(Path2)) ;\r
@@ -2586,8 +2719,8 @@ EfiShellOpenFileList(
                                 multiple environment variables are being returned, Attributes\r
                                 is undefined.\r
 \r
-  @retval NULL                  The environment variable doesn\92t exist.\r
-  @return                       A non-NULL value points to the variable\92s value. The returned\r
+  @retval NULL                  The environment variable doesn't exist.\r
+  @return                       A non-NULL value points to the variable's value. The returned\r
                                 pointer does not need to be freed by the caller.\r
 **/\r
 CONST CHAR16 *\r
@@ -2600,7 +2733,6 @@ EfiShellGetEnvEx(
   EFI_STATUS  Status;\r
   VOID        *Buffer;\r
   UINTN       Size;\r
-  LIST_ENTRY  List;\r
   ENV_VAR_LIST *Node;\r
   CHAR16      *CurrentWriteLocation;\r
 \r
@@ -2608,21 +2740,13 @@ EfiShellGetEnvEx(
   Buffer = NULL;\r
 \r
   if (Name == NULL) {\r
-    //\r
-    // Get all our environment variables\r
-    //\r
-    InitializeListHead(&List);\r
-    Status = GetEnvironmentVariableList(&List);\r
-    if (EFI_ERROR(Status)){\r
-      return (NULL);\r
-    }\r
 \r
     //\r
     // Build the semi-colon delimited list. (2 passes)\r
     //\r
-    for ( Node = (ENV_VAR_LIST*)GetFirstNode(&List)\r
-      ; !IsNull(&List, &Node->Link)\r
-      ; Node = (ENV_VAR_LIST*)GetNextNode(&List, &Node->Link)\r
+    for ( Node = (ENV_VAR_LIST*)GetFirstNode(&gShellEnvVarList.Link)\r
+      ; !IsNull(&gShellEnvVarList.Link, &Node->Link)\r
+      ; Node = (ENV_VAR_LIST*)GetNextNode(&gShellEnvVarList.Link, &Node->Link)\r
      ){\r
       ASSERT(Node->Key != NULL);\r
       Size += StrSize(Node->Key);\r
@@ -2632,54 +2756,59 @@ EfiShellGetEnvEx(
 \r
     Buffer = AllocateZeroPool(Size);\r
     if (Buffer == NULL) {\r
-      if (!IsListEmpty (&List)) {\r
-        FreeEnvironmentVariableList(&List);\r
-      }\r
       return (NULL);\r
     }\r
     CurrentWriteLocation = (CHAR16*)Buffer;\r
 \r
-    for ( Node = (ENV_VAR_LIST*)GetFirstNode(&List)\r
-      ; !IsNull(&List, &Node->Link)\r
-      ; Node = (ENV_VAR_LIST*)GetNextNode(&List, &Node->Link)\r
+    for ( Node = (ENV_VAR_LIST*)GetFirstNode(&gShellEnvVarList.Link)\r
+      ; !IsNull(&gShellEnvVarList.Link, &Node->Link)\r
+      ; Node = (ENV_VAR_LIST*)GetNextNode(&gShellEnvVarList.Link, &Node->Link)\r
      ){\r
       ASSERT(Node->Key != NULL);\r
-      StrCpy(CurrentWriteLocation, Node->Key);\r
+      StrCpyS( CurrentWriteLocation, \r
+                (Size)/sizeof(CHAR16) - (CurrentWriteLocation - ((CHAR16*)Buffer)), \r
+                Node->Key\r
+                );\r
       CurrentWriteLocation += StrLen(CurrentWriteLocation) + 1;\r
     }\r
 \r
-    //\r
-    // Free the list...\r
-    //\r
-    if (!IsListEmpty (&List)) {\r
-      FreeEnvironmentVariableList(&List);\r
-    }\r
   } else {\r
     //\r
     // We are doing a specific environment variable\r
     //\r
+    Status = ShellFindEnvVarInList(Name, (CHAR16**)&Buffer, &Size, Attributes);\r
 \r
-    //\r
-    // get the size we need for this EnvVariable\r
-    //\r
-    Status = SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(Name, Attributes, &Size, Buffer);\r
-    if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    if (EFI_ERROR(Status)){\r
       //\r
-      // Allocate the space and recall the get function\r
+      // get the size we need for this EnvVariable\r
       //\r
-      Buffer = AllocateZeroPool(Size);\r
-      ASSERT(Buffer != NULL);\r
       Status = SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(Name, Attributes, &Size, Buffer);\r
-    }\r
-    //\r
-    // we didnt get it (might not exist)\r
-    // free the memory if we allocated any and return NULL\r
-    //\r
-    if (EFI_ERROR(Status)) {\r
-      if (Buffer != NULL) {\r
-        FreePool(Buffer);\r
+      if (Status == EFI_BUFFER_TOO_SMALL) {\r
+        //\r
+        // Allocate the space and recall the get function\r
+        //\r
+        Buffer = AllocateZeroPool(Size);\r
+        Status = SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(Name, Attributes, &Size, Buffer);\r
+      }\r
+      //\r
+      // we didnt get it (might not exist)\r
+      // free the memory if we allocated any and return NULL\r
+      //\r
+      if (EFI_ERROR(Status)) {\r
+        if (Buffer != NULL) {\r
+          FreePool(Buffer);\r
+        }\r
+        return (NULL);\r
+      } else {\r
+        //\r
+        // If we did not find the environment variable in the gShellEnvVarList\r
+        // but get it from UEFI variable storage successfully then we need update\r
+        // the gShellEnvVarList.\r
+        //\r
+        ShellFreeEnvVarList ();\r
+        Status = ShellInitEnvVarList ();\r
+        ASSERT (Status == EFI_SUCCESS);\r
       }\r
-      return (NULL);\r
     }\r
   }\r
 \r
@@ -2739,16 +2868,29 @@ InternalEfiShellSetEnv(
   IN BOOLEAN Volatile\r
   )\r
 {\r
+  EFI_STATUS      Status;\r
+\r
   if (Value == NULL || StrLen(Value) == 0) {\r
-    return (SHELL_DELETE_ENVIRONMENT_VARIABLE(Name));\r
+    Status = SHELL_DELETE_ENVIRONMENT_VARIABLE(Name);\r
+    if (!EFI_ERROR(Status)) {\r
+      ShellRemvoeEnvVarFromList(Name);\r
+    }\r
   } else {\r
     SHELL_DELETE_ENVIRONMENT_VARIABLE(Name);\r
-    if (Volatile) {\r
-      return (SHELL_SET_ENVIRONMENT_VARIABLE_V(Name, StrSize(Value), Value));\r
-    } else {\r
-      return (SHELL_SET_ENVIRONMENT_VARIABLE_NV(Name, StrSize(Value), Value));\r
+    Status = ShellAddEnvVarToList(\r
+               Name, Value, StrSize(Value),\r
+               EFI_VARIABLE_BOOTSERVICE_ACCESS | (Volatile ? 0 : EFI_VARIABLE_NON_VOLATILE)\r
+               );\r
+    if (!EFI_ERROR (Status)) {\r
+      Status = Volatile\r
+             ? SHELL_SET_ENVIRONMENT_VARIABLE_V(Name, StrSize(Value), Value)\r
+             : SHELL_SET_ENVIRONMENT_VARIABLE_NV(Name, StrSize(Value), Value);\r
+      if (EFI_ERROR (Status)) {\r
+        ShellRemvoeEnvVarFromList(Name);\r
+      }\r
     }\r
   }\r
+  return Status;\r
 }\r
 \r
 /**\r
@@ -2810,6 +2952,11 @@ EfiShellSetEnv(
         gUnicodeCollation,\r
         (CHAR16*)Name,\r
         L"uefiversion") == 0\r
+    ||(!ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoNest &&\r
+      gUnicodeCollation->StriColl(\r
+        gUnicodeCollation,\r
+        (CHAR16*)Name,\r
+        (CHAR16*)mNoNestingEnvVarName) == 0)\r
        ){\r
     return (EFI_INVALID_PARAMETER);\r
   }\r
@@ -2824,6 +2971,8 @@ EfiShellSetEnv(
   FileSystemMapping. In both cases, the returned name includes the file system\r
   mapping (i.e. fs0:\current-dir).\r
 \r
+  Note that the current directory string should exclude the tailing backslash character.\r
+\r
   @param FileSystemMapping      A pointer to the file system mapping. If NULL,\r
                                 then the current working directory is returned.\r
 \r
@@ -2879,6 +3028,8 @@ EfiShellGetCurDir(
   If the current working directory or the current working file system is changed then the\r
   %cwd% environment variable will be updated\r
 \r
+  Note that the current directory string should exclude the tailing backslash character.\r
+\r
   @param FileSystem             A pointer to the file system's mapped name. If NULL, then the current working\r
                                 directory is changed.\r
   @param Dir                    Points to the NULL-terminated directory on the device specified by FileSystem.\r
@@ -2946,6 +3097,8 @@ EfiShellSetCurDir(
     }\r
 \r
     if (MapListItem == NULL) {\r
+      FreePool (DirectoryName);\r
+      SHELL_FREE_NON_NULL(MapName);\r
       return (EFI_NOT_FOUND);\r
     }\r
 \r
@@ -2962,19 +3115,23 @@ EfiShellSetCurDir(
         ASSERT((MapListItem->CurrentDirectoryPath == NULL && Size == 0) || (MapListItem->CurrentDirectoryPath != NULL));\r
         MapListItem->CurrentDirectoryPath = StrnCatGrow(&MapListItem->CurrentDirectoryPath, &Size, DirectoryName+StrLen(MapName), 0);\r
       }\r
+      FreePool (MapName);\r
     } else {\r
       ASSERT((MapListItem->CurrentDirectoryPath == NULL && Size == 0) || (MapListItem->CurrentDirectoryPath != NULL));\r
       MapListItem->CurrentDirectoryPath = StrnCatGrow(&MapListItem->CurrentDirectoryPath, &Size, DirectoryName, 0);\r
     }\r
-    if ((MapListItem->CurrentDirectoryPath != NULL && MapListItem->CurrentDirectoryPath[StrLen(MapListItem->CurrentDirectoryPath)-1] != L'\\') || (MapListItem->CurrentDirectoryPath == NULL)) {\r
+    if ((MapListItem->CurrentDirectoryPath != NULL && MapListItem->CurrentDirectoryPath[StrLen(MapListItem->CurrentDirectoryPath)-1] == L'\\') || (MapListItem->CurrentDirectoryPath == NULL)) {\r
       ASSERT((MapListItem->CurrentDirectoryPath == NULL && Size == 0) || (MapListItem->CurrentDirectoryPath != NULL));\r
-      MapListItem->CurrentDirectoryPath = StrnCatGrow(&MapListItem->CurrentDirectoryPath, &Size, L"\\", 0);\r
+      if (MapListItem->CurrentDirectoryPath != NULL) {\r
+        MapListItem->CurrentDirectoryPath[StrLen(MapListItem->CurrentDirectoryPath)-1] = CHAR_NULL;\r
+    }\r
     }\r
   } else {\r
     //\r
     // cant have a mapping in the directory...\r
     //\r
     if (StrStr(DirectoryName, L":") != NULL) {\r
+      FreePool (DirectoryName);\r
       return (EFI_INVALID_PARAMETER);\r
     }\r
     //\r
@@ -2982,6 +3139,7 @@ EfiShellSetCurDir(
     //\r
     MapListItem = ShellCommandFindMapItem(FileSystem);\r
     if (MapListItem == NULL) {\r
+      FreePool (DirectoryName);\r
       return (EFI_INVALID_PARAMETER);\r
     }\r
 //    gShellCurDir = MapListItem;\r
@@ -3000,12 +3158,13 @@ EfiShellSetCurDir(
       MapListItem->CurrentDirectoryPath = StrnCatGrow(&MapListItem->CurrentDirectoryPath, &Size, L"\\", 0);\r
       ASSERT((MapListItem->CurrentDirectoryPath == NULL && Size == 0) || (MapListItem->CurrentDirectoryPath != NULL));\r
       MapListItem->CurrentDirectoryPath = StrnCatGrow(&MapListItem->CurrentDirectoryPath, &Size, DirectoryName, 0);\r
-      if (MapListItem->CurrentDirectoryPath != NULL && MapListItem->CurrentDirectoryPath[StrLen(MapListItem->CurrentDirectoryPath)-1] != L'\\') {\r
+      if (MapListItem->CurrentDirectoryPath != NULL && MapListItem->CurrentDirectoryPath[StrLen(MapListItem->CurrentDirectoryPath)-1] == L'\\') {\r
         ASSERT((MapListItem->CurrentDirectoryPath == NULL && Size == 0) || (MapListItem->CurrentDirectoryPath != NULL));\r
-        MapListItem->CurrentDirectoryPath = StrnCatGrow(&MapListItem->CurrentDirectoryPath, &Size, L"\\", 0);\r
+        MapListItem->CurrentDirectoryPath[StrLen(MapListItem->CurrentDirectoryPath)-1] = CHAR_NULL;\r
       }\r
     }\r
   }\r
+  FreePool (DirectoryName);\r
   //\r
   // if updated the current directory then update the environment variable\r
   //\r
@@ -3074,9 +3233,15 @@ EfiShellGetHelpText(
     && (Command[StrLen(Command)-4] == L'.')\r
     ) {\r
       FixCommand = AllocateZeroPool(StrSize(Command) - 4 * sizeof (CHAR16));\r
-      ASSERT(FixCommand != NULL);\r
+      if (FixCommand == NULL) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
 \r
-      StrnCpy(FixCommand, Command, StrLen(Command)-4);\r
+      StrnCpyS( FixCommand, \r
+                (StrSize(Command) - 4 * sizeof (CHAR16))/sizeof(CHAR16), \r
+                Command, \r
+                StrLen(Command)-4\r
+                );\r
       Status = ProcessManFile(FixCommand, FixCommand, Sections, NULL, HelpText);\r
       FreePool(FixCommand);\r
       return Status;\r
@@ -3134,20 +3299,17 @@ EFIAPI
 InternalEfiShellGetListAlias(\r
   )\r
 {\r
-  UINT64            MaxStorSize;\r
-  UINT64            RemStorSize;\r
-  UINT64            MaxVarSize;\r
+  \r
   EFI_STATUS        Status;\r
   EFI_GUID          Guid;\r
   CHAR16            *VariableName;\r
   UINTN             NameSize;\r
+  UINTN             NameBufferSize;\r
   CHAR16            *RetVal;\r
   UINTN             RetSize;\r
 \r
-  Status = gRT->QueryVariableInfo(EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS, &MaxStorSize, &RemStorSize, &MaxVarSize);\r
-  ASSERT_EFI_ERROR(Status);\r
-\r
-  VariableName  = AllocateZeroPool((UINTN)MaxVarSize);\r
+  NameBufferSize = INIT_NAME_BUFFER_SIZE;\r
+  VariableName  = AllocateZeroPool(NameBufferSize);\r
   RetSize       = 0;\r
   RetVal        = NULL;\r
 \r
@@ -3158,22 +3320,38 @@ InternalEfiShellGetListAlias(
   VariableName[0] = CHAR_NULL;\r
 \r
   while (TRUE) {\r
-    NameSize = (UINTN)MaxVarSize;\r
+    NameSize = NameBufferSize;\r
     Status = gRT->GetNextVariableName(&NameSize, VariableName, &Guid);\r
     if (Status == EFI_NOT_FOUND){\r
       break;\r
-    }\r
-    ASSERT_EFI_ERROR(Status);\r
-    if (EFI_ERROR(Status)) {\r
+    } else if (Status == EFI_BUFFER_TOO_SMALL) {\r
+      NameBufferSize = NameSize > NameBufferSize * 2 ? NameSize : NameBufferSize * 2;\r
+      SHELL_FREE_NON_NULL(VariableName);\r
+      VariableName = AllocateZeroPool(NameBufferSize);\r
+      if (VariableName == NULL) {\r
+        Status = EFI_OUT_OF_RESOURCES;\r
+        SHELL_FREE_NON_NULL(RetVal);\r
+        RetVal = NULL;\r
+        break;\r
+      }\r
+      \r
+      NameSize = NameBufferSize;\r
+      Status = gRT->GetNextVariableName(&NameSize, VariableName, &Guid);\r
+    }\r
+    \r
+    if (EFI_ERROR (Status)) {\r
+      SHELL_FREE_NON_NULL(RetVal);\r
+      RetVal = NULL;\r
       break;\r
     }\r
+    \r
     if (CompareGuid(&Guid, &gShellAliasGuid)){\r
       ASSERT((RetVal == NULL && RetSize == 0) || (RetVal != NULL));\r
       RetVal = StrnCatGrow(&RetVal, &RetSize, VariableName, 0);\r
       RetVal = StrnCatGrow(&RetVal, &RetSize, L";", 0);\r
     } // compare guid\r
   } // while\r
-  FreePool(VariableName);\r
+  SHELL_FREE_NON_NULL(VariableName);\r
 \r
   return (RetVal);\r
 }\r
@@ -3186,7 +3364,7 @@ InternalEfiShellGetListAlias(
   \r
   @return        The null-terminated string converted into all lowercase.  \r
 **/\r
-STATIC CHAR16 *\r
+CHAR16 *\r
 ToLower (\r
   CHAR16 *Str\r
   )\r
@@ -3231,15 +3409,20 @@ EfiShellGetAlias(
   UINT32      Attribs;\r
   EFI_STATUS  Status;\r
   CHAR16      *AliasLower;\r
+  CHAR16      *AliasVal;\r
 \r
   // Convert to lowercase to make aliases case-insensitive\r
   if (Alias != NULL) {\r
     AliasLower = AllocateCopyPool (StrSize (Alias), Alias);\r
-    ASSERT (AliasLower != NULL);\r
+    if (AliasLower == NULL) {\r
+      return NULL;\r
+    }\r
     ToLower (AliasLower);\r
 \r
     if (Volatile == NULL) {\r
-      return (AddBufferToFreeList(GetVariable(AliasLower, &gShellAliasGuid)));\r
+      GetVariable2 (AliasLower, &gShellAliasGuid, (VOID **)&AliasVal, NULL);\r
+      FreePool(AliasLower);\r
+      return (AddBufferToFreeList(AliasVal));\r
     }\r
     RetSize = 0;\r
     RetVal = NULL;\r
@@ -3252,6 +3435,7 @@ EfiShellGetAlias(
       if (RetVal != NULL) {\r
         FreePool(RetVal);\r
       }\r
+      FreePool(AliasLower);\r
       return (NULL);\r
     }\r
     if ((EFI_VARIABLE_NON_VOLATILE & Attribs) == EFI_VARIABLE_NON_VOLATILE) {\r
@@ -3296,7 +3480,9 @@ InternalSetAlias(
   // Convert to lowercase to make aliases case-insensitive\r
   if (Alias != NULL) {\r
     AliasLower = AllocateCopyPool (StrSize (Alias), Alias);\r
-    ASSERT (AliasLower != NULL);\r
+    if (AliasLower == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
     ToLower (AliasLower);\r
   } else {\r
     AliasLower = NULL;\r
@@ -3379,7 +3565,7 @@ EfiShellSetAlias(
 \r
 // Pure FILE_HANDLE operations are passed to FileHandleLib\r
 // these functions are indicated by the *\r
-EFI_SHELL_PROTOCOL21         mShellProtocol = {\r
+EFI_SHELL_PROTOCOL         mShellProtocol = {\r
   EfiShellExecute,\r
   EfiShellGetEnv,\r
   EfiShellSetEnv,\r
@@ -3420,8 +3606,8 @@ EFI_SHELL_PROTOCOL21         mShellProtocol = {
   EfiShellOpenRoot,\r
   EfiShellOpenRootByHandle,\r
   NULL,\r
-  2, // SHELL_MAJOR_VERSION,\r
-  1, // SHELL_MINOR_VERSION,\r
+  SHELL_MAJOR_VERSION,\r
+  SHELL_MINOR_VERSION,\r
 \r
   // New for UEFI Shell 2.1\r
   EfiShellRegisterGuidName,\r
@@ -3447,7 +3633,7 @@ EFI_SHELL_PROTOCOL21         mShellProtocol = {
 EFI_STATUS\r
 EFIAPI\r
 CreatePopulateInstallShellProtocol (\r
-  IN OUT EFI_SHELL_PROTOCOL21  **NewShell\r
+  IN OUT EFI_SHELL_PROTOCOL  **NewShell\r
   )\r
 {\r
   EFI_STATUS                  Status;\r
@@ -3455,6 +3641,7 @@ CreatePopulateInstallShellProtocol (
   EFI_HANDLE                  *Buffer;\r
   UINTN                       HandleCounter;\r
   SHELL_PROTOCOL_HANDLE_LIST  *OldProtocolNode;\r
+  EFI_SHELL_PROTOCOL          *OldShell;\r
 \r
   if (NewShell == NULL) {\r
     return (EFI_INVALID_PARAMETER);\r
@@ -3506,20 +3693,27 @@ CreatePopulateInstallShellProtocol (
     // now overwrite each of them, but save the info to restore when we end.\r
     //\r
     for (HandleCounter = 0 ; HandleCounter < (BufferSize/sizeof(EFI_HANDLE)) ; HandleCounter++) {\r
-      OldProtocolNode = AllocateZeroPool(sizeof(SHELL_PROTOCOL_HANDLE_LIST));\r
-      ASSERT(OldProtocolNode != NULL);\r
       Status = gBS->OpenProtocol(Buffer[HandleCounter],\r
                                 &gEfiShellProtocolGuid,\r
-                                (VOID **) &(OldProtocolNode->Interface),\r
+                                (VOID **) &OldShell,\r
                                 gImageHandle,\r
                                 NULL,\r
                                 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
                                );\r
       if (!EFI_ERROR(Status)) {\r
+        OldProtocolNode = AllocateZeroPool(sizeof(SHELL_PROTOCOL_HANDLE_LIST));\r
+        if (OldProtocolNode == NULL) {\r
+          if (!IsListEmpty (&ShellInfoObject.OldShellList.Link)) {\r
+            CleanUpShellProtocol (&mShellProtocol);\r
+          }\r
+          Status = EFI_OUT_OF_RESOURCES;\r
+          break;\r
+        }\r
         //\r
         // reinstall over the old one...\r
         //\r
-        OldProtocolNode->Handle = Buffer[HandleCounter];\r
+        OldProtocolNode->Handle    = Buffer[HandleCounter];\r
+        OldProtocolNode->Interface = OldShell;\r
         Status = gBS->ReinstallProtocolInterface(\r
                             OldProtocolNode->Handle,\r
                             &gEfiShellProtocolGuid,\r
@@ -3572,38 +3766,50 @@ CreatePopulateInstallShellProtocol (
   @retval EFI_SUCCESS       The operation was successful.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 CleanUpShellProtocol (\r
-  IN OUT EFI_SHELL_PROTOCOL21  *NewShell\r
+  IN OUT EFI_SHELL_PROTOCOL  *NewShell\r
   )\r
 {\r
-  EFI_STATUS                        Status;\r
   SHELL_PROTOCOL_HANDLE_LIST        *Node2;\r
-  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleEx;\r
 \r
   //\r
   // if we need to restore old protocols...\r
   //\r
   if (!IsListEmpty(&ShellInfoObject.OldShellList.Link)) {\r
-    for (Node2 = (SHELL_PROTOCOL_HANDLE_LIST *)GetFirstNode(&ShellInfoObject.OldShellList.Link)\r
+    for (Node2 = (SHELL_PROTOCOL_HANDLE_LIST *) GetFirstNode (&ShellInfoObject.OldShellList.Link)\r
          ; !IsListEmpty (&ShellInfoObject.OldShellList.Link)\r
-         ; Node2 = (SHELL_PROTOCOL_HANDLE_LIST *)GetFirstNode(&ShellInfoObject.OldShellList.Link)\r
-        ){\r
-      RemoveEntryList(&Node2->Link);\r
-      Status = gBS->ReinstallProtocolInterface(Node2->Handle,\r
-                                               &gEfiShellProtocolGuid,\r
-                                               NewShell,\r
-                                               Node2->Interface);\r
-      FreePool(Node2);\r
+         ; Node2 = (SHELL_PROTOCOL_HANDLE_LIST *) GetFirstNode (&ShellInfoObject.OldShellList.Link)\r
+         ) {\r
+      RemoveEntryList (&Node2->Link);\r
+      gBS->ReinstallProtocolInterface (Node2->Handle, &gEfiShellProtocolGuid, NewShell, Node2->Interface);\r
+      FreePool (Node2);\r
     }\r
   } else {\r
     //\r
     // no need to restore\r
     //\r
-    Status = gBS->UninstallProtocolInterface(gImageHandle,\r
-                                             &gEfiShellProtocolGuid,\r
-                                             NewShell);\r
+    gBS->UninstallProtocolInterface (gImageHandle, &gEfiShellProtocolGuid, NewShell);\r
   }\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Cleanup the shell environment.\r
+\r
+  @param[in, out] NewShell   The pointer to the new shell protocol structure.\r
+\r
+  @retval EFI_SUCCESS       The operation was successful.\r
+**/\r
+EFI_STATUS\r
+CleanUpShellEnvironment (\r
+  IN OUT EFI_SHELL_PROTOCOL  *NewShell\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleEx;\r
+  \r
+  CleanUpShellProtocol (NewShell);\r
+\r
   Status = gBS->CloseEvent(NewShell->ExecutionBreak);\r
   NewShell->ExecutionBreak = NULL;\r
 \r