]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/Application/Shell/ShellProtocol.c
ShellPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / ShellPkg / Application / Shell / ShellProtocol.c
index def3bd35c208e6a7a669a744e55db1cd338231ee..5e529b6568a9fcfdea2057efc67b54bd9bda817c 100644 (file)
@@ -3,14 +3,9 @@
   manipulation, and initialization of EFI_SHELL_PROTOCOL.\r
 \r
   (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>\r
-  Copyright (c) 2009 - 2015, 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 (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -49,7 +44,6 @@ EfiShellClose (
   @retval FALSE     gEfiBlockIoProtocolGuid was not found.\r
 **/\r
 BOOLEAN\r
-EFIAPI\r
 InternalShellProtocolIsBlockIoPresent(\r
   IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
   )\r
@@ -79,7 +73,6 @@ InternalShellProtocolIsBlockIoPresent(
   @retval FALSE     gEfiSimpleFileSystemProtocolGuid was not found.\r
 **/\r
 BOOLEAN\r
-EFIAPI\r
 InternalShellProtocolIsSimpleFileSystemPresent(\r
   IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
   )\r
@@ -99,41 +92,6 @@ InternalShellProtocolIsSimpleFileSystemPresent(
   return (FALSE);\r
 }\r
 \r
-/**\r
-  Internal worker debug helper function to print out maps as they are added.\r
-\r
-  @param[in] Mapping        string mapping that has been added\r
-  @param[in] DevicePath     pointer to device path that has been mapped.\r
-\r
-  @retval EFI_SUCCESS   the operation was successful.\r
-  @return other         an error ocurred\r
-\r
-  @sa LocateHandle\r
-  @sa OpenProtocol\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-InternalShellProtocolDebugPrintMessage (\r
-  IN CONST CHAR16                   *Mapping,\r
-  IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
-  )\r
-{\r
-  EFI_STATUS                        Status;\r
-  CHAR16                            *Temp;\r
-\r
-  Status = EFI_SUCCESS;\r
-  DEBUG_CODE_BEGIN();\r
-\r
-  if (Mapping != NULL) {\r
-    DEBUG((EFI_D_INFO, "Added new map item:\"%S\"\r\n", Mapping));\r
-  }\r
-  Temp = ConvertDevicePathToText(DevicePath, TRUE, TRUE);\r
-  DEBUG((EFI_D_INFO, "DevicePath: %S\r\n", Temp));\r
-  FreePool(Temp);\r
-\r
-  DEBUG_CODE_END();\r
-  return (Status);\r
-}\r
 \r
 /**\r
   This function creates a mapping for a device path.\r
@@ -185,6 +143,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
@@ -463,7 +424,10 @@ EfiShellGetFilePathFromDevicePath(
         ASSERT((PathForReturn == NULL && PathSize == 0) || (PathForReturn != NULL));\r
 \r
         AlignedNode = AllocateCopyPool (DevicePathNodeLength(FilePath), FilePath);\r
-        ASSERT (AlignedNode != NULL);\r
+        if (AlignedNode == NULL) {\r
+          FreePool (PathForReturn);\r
+          return NULL;\r
+        }\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
@@ -473,7 +437,7 @@ EfiShellGetFilePathFromDevicePath(
         //  UEFI Shell spec section 3.7)\r
         if ((PathSize != 0)                        &&\r
             (PathForReturn != NULL)                &&\r
-            (PathForReturn[PathSize - 1] != L'\\') &&\r
+            (PathForReturn[PathSize / sizeof (CHAR16) - 1] != L'\\') &&\r
             (AlignedNode->PathName[0]    != L'\\')) {\r
           PathForReturn = StrnCatGrow (&PathForReturn, &PathSize, L"\\", 1);\r
         }\r
@@ -594,7 +558,8 @@ EfiShellGetDevicePathFromFilePath(
   //\r
   // build the full device path\r
   //\r
-  if (*(Path+StrLen(MapName)+1) == CHAR_NULL) {\r
+  if ((*(Path+StrLen(MapName)) != CHAR_NULL) &&\r
+      (*(Path+StrLen(MapName)+1) == CHAR_NULL)) {\r
     DevicePathForReturn = FileDevicePath(Handle, L"\\");\r
   } else {\r
     DevicePathForReturn = FileDevicePath(Handle, Path+StrLen(MapName));\r
@@ -822,7 +787,8 @@ EfiShellGetDeviceName(
   @retval EFI_NOT_FOUND         EFI_SIMPLE_FILE_SYSTEM could not be found or the root directory\r
                                 could not be opened.\r
   @retval EFI_VOLUME_CORRUPTED  The data structures in the volume were corrupted.\r
-  @retval EFI_DEVICE_ERROR      The device had an error\r
+  @retval EFI_DEVICE_ERROR      The device had an error.\r
+  @retval Others                Error status returned from EFI_SIMPLE_FILE_SYSTEM_PROTOCOL->OpenVolume().\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
@@ -862,8 +828,12 @@ EfiShellOpenRootByHandle(
   // Open the root volume now...\r
   //\r
   Status = SimpleFileSystem->OpenVolume(SimpleFileSystem, &RealFileHandle);\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
+\r
   *FileHandle = ConvertEfiFileProtocolToShellHandle(RealFileHandle, EfiShellGetMapFromDevicePath(&DevPath));\r
-  return (Status);\r
+  return (EFI_SUCCESS);\r
 }\r
 \r
 /**\r
@@ -944,7 +914,6 @@ EfiShellBatchIsActive (
   @retval other                   an error ocurred.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 InternalOpenFileDevicePath(\r
   IN OUT EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
   OUT SHELL_FILE_HANDLE           *FileHandle,\r
@@ -1126,13 +1095,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
@@ -1171,7 +1145,7 @@ EfiShellCreateFile(
   @retval EFI_ACCESS_DENIED       Guid already is assigned a name.\r
 **/\r
 EFI_STATUS\r
-EFIAPI \r
+EFIAPI\r
 EfiShellRegisterGuidName(\r
   IN CONST EFI_GUID *Guid,\r
   IN CONST CHAR16   *GuidName\r
@@ -1242,6 +1216,7 @@ EfiShellOpenFileByName(
 {\r
   EFI_DEVICE_PATH_PROTOCOL        *DevicePath;\r
   EFI_STATUS                      Status;\r
+  BOOLEAN                         Volatile;\r
 \r
   *FileHandle = NULL;\r
 \r
@@ -1275,9 +1250,10 @@ EfiShellOpenFileByName(
   }\r
 \r
   //\r
-  // Is this for NUL file\r
+  // Is this for NUL / NULL file\r
   //\r
-  if (StrCmp(FileName, L"NUL") == 0) {\r
+  if ((gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16*)FileName, L"NUL") == 0) ||\r
+      (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16*)FileName, L"NULL") == 0)) {\r
     *FileHandle = &FileInterfaceNulFile;\r
     return (EFI_SUCCESS);\r
   }\r
@@ -1301,7 +1277,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
@@ -1313,7 +1293,7 @@ EfiShellOpenFileByName(
   // We are opening a regular file.\r
   //\r
   DevicePath = EfiShellGetDevicePathFromFilePath(FileName);\r
-//  DEBUG_CODE(InternalShellProtocolDebugPrintMessage (NULL, DevicePath););\r
+\r
   if (DevicePath == NULL) {\r
     return (EFI_NOT_FOUND);\r
   }\r
@@ -1361,6 +1341,7 @@ EfiShellDeleteFileByName(
   //\r
   // now delete the file\r
   //\r
+  ShellFileHandleRemove(FileHandle);\r
   return (ShellInfoObject.NewEfiShellProtocol->DeleteFile(FileHandle));\r
 }\r
 \r
@@ -1401,7 +1382,7 @@ EfiShellEnablePageBreak (
                                 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
+\r
   @param[out] StartImageStatus  Returned status from gBS->StartImage.\r
 \r
   @retval EFI_SUCCESS       The command executed successfully. The  status code\r
@@ -1411,7 +1392,6 @@ EfiShellEnablePageBreak (
   @retval EFI_UNSUPPORTED   Nested shell invocations are not allowed.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 InternalShellExecuteDevicePath(\r
   IN CONST EFI_HANDLE               *ParentImageHandle,\r
   IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
@@ -1437,9 +1417,10 @@ InternalShellExecuteDevicePath(
   }\r
 \r
   InitializeListHead(&OrigEnvs);\r
+  ZeroMem(&ShellParamsProtocol, sizeof(EFI_SHELL_PARAMETERS_PROTOCOL));\r
 \r
   NewHandle = NULL;\r
-  \r
+\r
   NewCmdLine = AllocateCopyPool (StrSize (CommandLine), CommandLine);\r
   if (NewCmdLine == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
@@ -1467,6 +1448,7 @@ InternalShellExecuteDevicePath(
     if (NewHandle != NULL) {\r
       gBS->UnloadImage(NewHandle);\r
     }\r
+    FreePool (NewCmdLine);\r
     return (Status);\r
   }\r
   Status = gBS->OpenProtocol(\r
@@ -1478,6 +1460,20 @@ 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 (NewCmdLine != NULL) {\r
       LoadedImage->LoadOptionsSize  = (UINT32)StrSize(NewCmdLine);\r
@@ -1583,6 +1579,108 @@ FreeAlloc:
 \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
+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
+NestingEnabled(\r
+  VOID\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
@@ -1606,7 +1704,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
@@ -1630,19 +1728,14 @@ EfiShellExecute(
   CHAR16                    *Temp;\r
   EFI_DEVICE_PATH_PROTOCOL  *DevPath;\r
   UINTN                     Size;\r
-  EFI_STATUS                CalleeStatusCode;\r
 \r
-  CalleeStatusCode = EFI_SUCCESS;\r
-  \r
   if ((PcdGet8(PcdShellSupportLevel) < 1)) {\r
     return (EFI_UNSUPPORTED);\r
   }\r
 \r
-  if (Environment != NULL) {\r
-    // If Environment isn't null, load a new image of the shell with its own\r
-    // environment\r
+  if (NestingEnabled()) {\r
     DevPath = AppendDevicePath (ShellInfoObject.ImageDevPath, ShellInfoObject.FileDevPath);\r
\r
+\r
     DEBUG_CODE_BEGIN();\r
     Temp = ConvertDevicePathToText(ShellInfoObject.FileDevPath, TRUE, TRUE);\r
     FreePool(Temp);\r
@@ -1655,7 +1748,7 @@ EfiShellExecute(
     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, L"Shell.efi -exit ", 0);\r
     StrnCatGrow(&Temp, &Size, CommandLine, 0);\r
 \r
     Status = InternalShellExecuteDevicePath(\r
@@ -1671,19 +1764,10 @@ EfiShellExecute(
     FreePool(DevPath);\r
     FreePool(Temp);\r
   } else {\r
-    // If Environment is NULL, we are free to use and mutate the current shell\r
-    // environment. This is much faster as uses much less memory.\r
-\r
-    if (CommandLine == NULL) {\r
-      CommandLine = L"";\r
-    }\r
-\r
-    Status = RunShellCommand (CommandLine, &CalleeStatusCode);\r
-\r
-    // Pass up the command's exit code if the caller wants it\r
-    if (StatusCode != NULL) {\r
-      *StatusCode = (EFI_STATUS) CalleeStatusCode;\r
-    }\r
+    Status = InternalShellExecute(\r
+      (CONST CHAR16*)CommandLine,\r
+      (CONST CHAR16**)Environment,\r
+      StatusCode);\r
   }\r
 \r
   return(Status);\r
@@ -1698,7 +1782,6 @@ EfiShellExecute(
   @param FileListNode     pointer to the list node to free\r
 **/\r
 VOID\r
-EFIAPI\r
 InternalFreeShellFileInfoNode(\r
   IN EFI_SHELL_FILE_INFO *FileListNode\r
   )\r
@@ -1826,7 +1909,6 @@ typedef struct {
   @return != NULL     a pointer to the new node\r
 **/\r
 EFI_SHELL_FILE_INFO*\r
-EFIAPI\r
 InternalDuplicateShellFileInfo(\r
   IN       EFI_SHELL_FILE_INFO *Node,\r
   IN BOOLEAN                   Save\r
@@ -1879,7 +1961,6 @@ InternalDuplicateShellFileInfo(
   @return                     a pointer to the newly allocated structure.\r
 **/\r
 EFI_SHELL_FILE_INFO *\r
-EFIAPI\r
 CreateAndPopulateShellFileInfo(\r
   IN CONST CHAR16 *BasePath,\r
   IN CONST EFI_STATUS Status,\r
@@ -2023,6 +2104,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
@@ -2032,11 +2121,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
@@ -2068,7 +2158,7 @@ EfiShellFindFilesInDir(
   @retval EFI_NOT_FOUND           GuidName is not a known GUID Name.\r
 **/\r
 EFI_STATUS\r
-EFIAPI \r
+EFIAPI\r
 EfiShellGetGuidFromName(\r
   IN  CONST CHAR16   *GuidName,\r
   OUT       EFI_GUID *Guid\r
@@ -2080,11 +2170,11 @@ EfiShellGetGuidFromName(
   if (Guid == NULL || GuidName == NULL) {\r
     return (EFI_INVALID_PARAMETER);\r
   }\r
\r
+\r
   Status = GetGuidFromStringName(GuidName, NULL, &NewGuid);\r
 \r
   if (!EFI_ERROR(Status)) {\r
-    CopyGuid(NewGuid, Guid);\r
+    CopyGuid(Guid, NewGuid);\r
   }\r
 \r
   return (Status);\r
@@ -2108,7 +2198,7 @@ EfiShellGetGuidFromName(
   @retval EFI_NOT_FOUND           Guid is not assigned a name.\r
 **/\r
 EFI_STATUS\r
-EFIAPI \r
+EFIAPI\r
 EfiShellGetGuidName(\r
   IN  CONST EFI_GUID *Guid,\r
   OUT CONST CHAR16   **GuidName\r
@@ -2131,53 +2221,7 @@ EfiShellGetGuidName(
   return (EFI_SUCCESS);\r
 }\r
 \r
-/**\r
-  Updates a file name to be preceeded by the mapped drive name\r
-\r
-  @param[in] BasePath      the Mapped drive name to prepend\r
-  @param[in, out] Path     pointer to pointer to the file name to update.\r
-\r
-  @retval EFI_SUCCESS\r
-  @retval EFI_OUT_OF_RESOURCES\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-UpdateFileName(\r
-  IN CONST CHAR16 *BasePath,\r
-  IN OUT CHAR16   **Path\r
-  )\r
-{\r
-  CHAR16              *Path2;\r
-  UINTN               Path2Size;\r
-\r
-  Path2Size = 0;\r
-  Path2 = NULL;\r
 \r
-  ASSERT(Path      != NULL);\r
-  ASSERT(*Path     != NULL);\r
-  ASSERT(BasePath  != NULL);\r
-\r
-  //\r
-  // convert a local path to an absolute path\r
-  //\r
-  if (StrStr(*Path, L":") == NULL) {\r
-    ASSERT((Path2 == NULL && Path2Size == 0) || (Path2 != NULL));\r
-    StrnCatGrow(&Path2, &Path2Size, BasePath, 0);\r
-    if (Path2 == NULL) {\r
-      return (EFI_OUT_OF_RESOURCES);\r
-    }\r
-    ASSERT((Path2 == NULL && Path2Size == 0) || (Path2 != NULL));\r
-    StrnCatGrow(&Path2, &Path2Size, (*Path)[0] == L'\\'?(*Path) + 1 :*Path, 0);\r
-    if (Path2 == NULL) {\r
-      return (EFI_OUT_OF_RESOURCES);\r
-    }\r
-  }\r
-\r
-  FreePool(*Path);\r
-  (*Path) = Path2;\r
-\r
-  return (EFI_SUCCESS);\r
-}\r
 \r
 /**\r
   If FileHandle is a directory then the function reads from FileHandle and reads in\r
@@ -2202,7 +2246,6 @@ UpdateFileName(
   @retval EFI_OUT_OF_RESOURCES  a memory allocation failed\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 ShellSearchHandle(\r
   IN     CONST CHAR16                         *FilePattern,\r
   IN           EFI_UNICODE_COLLATION_PROTOCOL *UnicodeCollation,\r
@@ -2241,7 +2284,10 @@ ShellSearchHandle(
      ; NextFilePatternStart++);\r
 \r
   CurrentFilePattern = AllocateZeroPool((NextFilePatternStart-FilePattern+1)*sizeof(CHAR16));\r
-  ASSERT(CurrentFilePattern != NULL);\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
@@ -2300,15 +2346,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
-              StrCpyS(NewFullName, Size/sizeof(CHAR16), MapName);\r
-              StrCatS(NewFullName, Size/sizeof(CHAR16), 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
@@ -2338,6 +2383,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
@@ -2348,7 +2395,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
@@ -2375,6 +2421,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
@@ -2437,8 +2487,8 @@ EfiShellFindFiles(
 \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
@@ -2456,6 +2506,7 @@ EfiShellFindFiles(
             ; PatternCurrentLocation++);\r
         PatternCurrentLocation++;\r
         Status = ShellSearchHandle(PatternCurrentLocation, gUnicodeCollation, RootFileHandle, FileList, NULL, MapName);\r
+        EfiShellClose(RootFileHandle);\r
       }\r
       FreePool(RootDevicePath);\r
     }\r
@@ -2585,7 +2636,7 @@ EfiShellOpenFileList(
                                 pointer does not need to be freed by the caller.\r
 **/\r
 CONST CHAR16 *\r
-EFIAPI \r
+EFIAPI\r
 EfiShellGetEnvEx(\r
   IN  CONST CHAR16 *Name,\r
   OUT       UINT32 *Attributes OPTIONAL\r
@@ -2594,7 +2645,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
@@ -2602,21 +2652,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
@@ -2626,56 +2668,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
-      StrCpyS( CurrentWriteLocation, \r
-                (Size)/sizeof(CHAR16) - (CurrentWriteLocation - ((CHAR16*)Buffer)), \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
       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
@@ -2728,23 +2773,35 @@ EfiShellGetEnv(
   @retval EFI_SUCCESS           The environment variable was successfully updated.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 InternalEfiShellSetEnv(\r
   IN CONST CHAR16 *Name,\r
   IN CONST CHAR16 *Value,\r
   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) - sizeof (CHAR16), Value)\r
+             : SHELL_SET_ENVIRONMENT_VARIABLE_NV (Name, StrSize (Value) - sizeof (CHAR16), Value);\r
+      if (EFI_ERROR (Status)) {\r
+        ShellRemvoeEnvVarFromList(Name);\r
+      }\r
     }\r
   }\r
+  return Status;\r
 }\r
 \r
 /**\r
@@ -2782,31 +2839,15 @@ EfiShellSetEnv(
   //\r
   // Make sure we dont 'set' a predefined read only variable\r
   //\r
-  if (gUnicodeCollation->StriColl(\r
-        gUnicodeCollation,\r
-        (CHAR16*)Name,\r
-        L"cwd") == 0\r
-    ||gUnicodeCollation->StriColl(\r
-        gUnicodeCollation,\r
-        (CHAR16*)Name,\r
-        L"Lasterror") == 0\r
-    ||gUnicodeCollation->StriColl(\r
-        gUnicodeCollation,\r
-        (CHAR16*)Name,\r
-        L"profiles") == 0\r
-    ||gUnicodeCollation->StriColl(\r
-        gUnicodeCollation,\r
-        (CHAR16*)Name,\r
-        L"uefishellsupport") == 0\r
-    ||gUnicodeCollation->StriColl(\r
-        gUnicodeCollation,\r
-        (CHAR16*)Name,\r
-        L"uefishellversion") == 0\r
-    ||gUnicodeCollation->StriColl(\r
-        gUnicodeCollation,\r
-        (CHAR16*)Name,\r
-        L"uefiversion") == 0\r
-       ){\r
+  if ((StrCmp (Name, L"cwd") == 0) ||\r
+      (StrCmp (Name, L"lasterror") == 0) ||\r
+      (StrCmp (Name, L"profiles") == 0) ||\r
+      (StrCmp (Name, L"uefishellsupport") == 0) ||\r
+      (StrCmp (Name, L"uefishellversion") == 0) ||\r
+      (StrCmp (Name, L"uefiversion") == 0) ||\r
+      (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoNest &&\r
+       StrCmp (Name, mNoNestingEnvVarName) == 0)\r
+     ) {\r
     return (EFI_INVALID_PARAMETER);\r
   }\r
   return (InternalEfiShellSetEnv(Name, Value, Volatile));\r
@@ -2819,7 +2860,7 @@ EfiShellSetEnv(
   FileSystemMapping is not NULL, it returns the current directory associated with the\r
   FileSystemMapping. In both cases, the returned name includes the file system\r
   mapping (i.e. fs0:\current-dir).\r
-  \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
@@ -2939,13 +2980,15 @@ EfiShellSetCurDir(
       // make that the current file system mapping\r
       //\r
       if (MapListItem != NULL) {\r
-        gShellCurDir = MapListItem;\r
+        gShellCurMapping = MapListItem;\r
       }\r
     } else {\r
-      MapListItem = gShellCurDir;\r
+      MapListItem = gShellCurMapping;\r
     }\r
 \r
     if (MapListItem == NULL) {\r
+      FreePool (DirectoryName);\r
+      SHELL_FREE_NON_NULL(MapName);\r
       return (EFI_NOT_FOUND);\r
     }\r
 \r
@@ -2962,6 +3005,7 @@ 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
@@ -2970,13 +3014,14 @@ EfiShellSetCurDir(
       ASSERT((MapListItem->CurrentDirectoryPath == NULL && Size == 0) || (MapListItem->CurrentDirectoryPath != NULL));\r
       if (MapListItem->CurrentDirectoryPath != NULL) {\r
         MapListItem->CurrentDirectoryPath[StrLen(MapListItem->CurrentDirectoryPath)-1] = CHAR_NULL;\r
-      }\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
@@ -2984,9 +3029,10 @@ EfiShellSetCurDir(
     //\r
     MapListItem = ShellCommandFindMapItem(FileSystem);\r
     if (MapListItem == NULL) {\r
+      FreePool (DirectoryName);\r
       return (EFI_INVALID_PARAMETER);\r
     }\r
-//    gShellCurDir = MapListItem;\r
+//    gShellCurMapping = MapListItem;\r
     if (DirectoryName != NULL) {\r
       //\r
       // change current dir on that file system\r
@@ -3008,10 +3054,11 @@ EfiShellSetCurDir(
       }\r
     }\r
   }\r
+  FreePool (DirectoryName);\r
   //\r
   // if updated the current directory then update the environment variable\r
   //\r
-  if (MapListItem == gShellCurDir) {\r
+  if (MapListItem == gShellCurMapping) {\r
     Size = 0;\r
     ASSERT((TempString == NULL && Size == 0) || (TempString != NULL));\r
     StrnCatGrow(&TempString, &Size, MapListItem->MapName, 0);\r
@@ -3076,11 +3123,13 @@ 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
-      StrnCpyS( FixCommand, \r
-                (StrSize(Command) - 4 * sizeof (CHAR16))/sizeof(CHAR16), \r
-                Command, \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
@@ -3136,11 +3185,11 @@ EfiShellIsRootShell(
   @return !NULL   a list of all alias'\r
 **/\r
 CHAR16 *\r
-EFIAPI\r
 InternalEfiShellGetListAlias(\r
+  VOID\r
   )\r
 {\r
-  \r
+\r
   EFI_STATUS        Status;\r
   EFI_GUID          Guid;\r
   CHAR16            *VariableName;\r
@@ -3175,17 +3224,17 @@ InternalEfiShellGetListAlias(
         RetVal = NULL;\r
         break;\r
       }\r
-      \r
+\r
       NameSize = NameBufferSize;\r
       Status = gRT->GetNextVariableName(&NameSize, VariableName, &Guid);\r
     }\r
-    \r
+\r
     if (EFI_ERROR (Status)) {\r
       SHELL_FREE_NON_NULL(RetVal);\r
       RetVal = NULL;\r
       break;\r
     }\r
-    \r
+\r
     if (CompareGuid(&Guid, &gShellAliasGuid)){\r
       ASSERT((RetVal == NULL && RetSize == 0) || (RetVal != NULL));\r
       RetVal = StrnCatGrow(&RetVal, &RetSize, VariableName, 0);\r
@@ -3200,10 +3249,10 @@ InternalEfiShellGetListAlias(
 /**\r
   Convert a null-terminated unicode string, in-place, to all lowercase.\r
   Then return it.\r
-  \r
+\r
   @param  Str    The null-terminated string to be converted to all lowercase.\r
-  \r
-  @return        The null-terminated string converted into all lowercase.  \r
+\r
+  @return        The null-terminated string converted into all lowercase.\r
 **/\r
 CHAR16 *\r
 ToLower (\r
@@ -3230,7 +3279,7 @@ ToLower (
   @param[out] Volatile          upon return of a single command if TRUE indicates\r
                                 this is stored in a volatile fashion.  FALSE otherwise.\r
 \r
-  @return                              If Alias is not NULL, it will return a pointer to\r
+  @return                        If Alias is not NULL, it will return a pointer to\r
                                 the NULL-terminated command for that alias.\r
                                 If Alias is NULL, ReturnedData points to a ';'\r
                                 delimited list of alias (e.g.\r
@@ -3255,11 +3304,14 @@ EfiShellGetAlias(
   // 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
       GetVariable2 (AliasLower, &gShellAliasGuid, (VOID **)&AliasVal, NULL);\r
+      FreePool(AliasLower);\r
       return (AddBufferToFreeList(AliasVal));\r
     }\r
     RetSize = 0;\r
@@ -3273,6 +3325,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
@@ -3304,7 +3357,6 @@ EfiShellGetAlias(
   @retval EFI_NOT_FOUND         the Alias intended to be deleted was not found\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 InternalSetAlias(\r
   IN CONST CHAR16 *Command,\r
   IN CONST CHAR16 *Alias,\r
@@ -3313,38 +3365,40 @@ InternalSetAlias(
 {\r
   EFI_STATUS  Status;\r
   CHAR16      *AliasLower;\r
+  BOOLEAN     DeleteAlias;\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
-    ToLower (AliasLower);\r
-  } else {\r
-    AliasLower = NULL;\r
-  }\r
-\r
-  //\r
-  // We must be trying to remove one if Alias is NULL\r
-  //\r
+  DeleteAlias = FALSE;\r
   if (Alias == NULL) {\r
     //\r
+    // We must be trying to remove one if Alias is NULL\r
     // remove an alias (but passed in COMMAND parameter)\r
     //\r
-    Status = (gRT->SetVariable((CHAR16*)Command, &gShellAliasGuid, 0, 0, NULL));\r
-  } else {\r
-    //\r
-    // Add and replace are the same\r
-    //\r
-\r
-    // We dont check the error return on purpose since the variable may not exist.\r
-    gRT->SetVariable((CHAR16*)Command, &gShellAliasGuid, 0, 0, NULL);\r
+    Alias       = Command;\r
+    DeleteAlias = TRUE;\r
+  }\r
+  ASSERT (Alias != NULL);\r
 \r
-    Status = (gRT->SetVariable((CHAR16*)Alias, &gShellAliasGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS|(Volatile?0:EFI_VARIABLE_NON_VOLATILE), StrSize(Command), (VOID*)Command));\r
+  //\r
+  // Convert to lowercase to make aliases case-insensitive\r
+  //\r
+  AliasLower = AllocateCopyPool (StrSize (Alias), Alias);\r
+  if (AliasLower == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
   }\r
+  ToLower (AliasLower);\r
 \r
-  if (Alias != NULL) {\r
-    FreePool (AliasLower);\r
+  if (DeleteAlias) {\r
+    Status = gRT->SetVariable (AliasLower, &gShellAliasGuid, 0, 0, NULL);\r
+  } else {\r
+    Status = gRT->SetVariable (\r
+                    AliasLower, &gShellAliasGuid,\r
+                    EFI_VARIABLE_BOOTSERVICE_ACCESS | (Volatile ? 0 : EFI_VARIABLE_NON_VOLATILE),\r
+                    StrSize (Command), (VOID *) Command\r
+                    );\r
   }\r
+\r
+  FreePool (AliasLower);\r
+\r
   return Status;\r
 }\r
 \r
@@ -3466,7 +3520,6 @@ EFI_SHELL_PROTOCOL         mShellProtocol = {
   @return                 An error from LocateHandle, CreateEvent, or other core function.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 CreatePopulateInstallShellProtocol (\r
   IN OUT EFI_SHELL_PROTOCOL  **NewShell\r
   )\r
@@ -3476,6 +3529,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
@@ -3527,20 +3581,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
@@ -3593,38 +3654,50 @@ CreatePopulateInstallShellProtocol (
   @retval EFI_SUCCESS       The operation was successful.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 CleanUpShellProtocol (\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
@@ -3665,28 +3738,27 @@ NotificationFunction(
   if ( ((KeyData->Key.UnicodeChar == L'c') &&\r
         (KeyData->KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED) || KeyData->KeyState.KeyShiftState  == (EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED))) ||\r
       (KeyData->Key.UnicodeChar == 3)\r
-      ){ \r
+      ){\r
     if (ShellInfoObject.NewEfiShellProtocol->ExecutionBreak == NULL) {\r
       return (EFI_UNSUPPORTED);\r
     }\r
     return (gBS->SignalEvent(ShellInfoObject.NewEfiShellProtocol->ExecutionBreak));\r
   } else if  ((KeyData->Key.UnicodeChar == L's') &&\r
               (KeyData->KeyState.KeyShiftState  == (EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED) || KeyData->KeyState.KeyShiftState  == (EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED))\r
-              ){ \r
+              ){\r
     ShellInfoObject.HaltOutput = TRUE;\r
   }\r
   return (EFI_SUCCESS);\r
 }\r
 \r
 /**\r
-  Function to start monitoring for CTRL-C using SimpleTextInputEx.  This \r
+  Function to start monitoring for CTRL-C using SimpleTextInputEx.  This\r
   feature's enabled state was not known when the shell initially launched.\r
 \r
   @retval EFI_SUCCESS           The feature is enabled.\r
   @retval EFI_OUT_OF_RESOURCES  There is not enough mnemory available.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 InernalEfiShellStartMonitor(\r
   VOID\r
   )\r
@@ -3704,8 +3776,8 @@ InernalEfiShellStartMonitor(
     EFI_OPEN_PROTOCOL_GET_PROTOCOL);\r
   if (EFI_ERROR(Status)) {\r
     ShellPrintHiiEx(\r
-      -1, \r
-      -1, \r
+      -1,\r
+      -1,\r
       NULL,\r
       STRING_TOKEN (STR_SHELL_NO_IN_EX),\r
       ShellInfoObject.HiiHandle);\r
@@ -3726,7 +3798,7 @@ InernalEfiShellStartMonitor(
     &KeyData,\r
     NotificationFunction,\r
     &ShellInfoObject.CtrlCNotifyHandle1);\r
-  \r
+\r
   KeyData.KeyState.KeyShiftState  = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED;\r
   if (!EFI_ERROR(Status)) {\r
     Status = SimpleEx->RegisterKeyNotify(\r