]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/Application/Shell/FileHandleWrappers.c
ShellPkg: Fix the coding style issue
[mirror_edk2.git] / ShellPkg / Application / Shell / FileHandleWrappers.c
index 8a71502459995bd18bd8c6ecf0ae32b2ff1850c5..18f4169c7d3ae899fe0bdd7647113aaa9c8e96f0 100644 (file)
@@ -2,7 +2,8 @@
   EFI_FILE_PROTOCOL wrappers for other items (Like Environment Variables,\r
   StdIn, StdOut, StdErr, etc...).\r
 \r
-  Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>\r
+  Copyright 2016 Dell Inc.\r
+  Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>\r
   (C) Copyright 2013 Hewlett-Packard Development Company, L.P.<BR>\r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
@@ -17,6 +18,8 @@
 #include "Shell.h"\r
 #include "FileHandleInternal.h"\r
 \r
+#define MEM_WRITE_REALLOC_OVERHEAD 1024\r
+\r
 /**\r
   File style interface for console (Open).  \r
   \r
@@ -159,9 +162,11 @@ FileInterfaceStdOutWrite(
 {\r
   if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut) {\r
     return (EFI_UNSUPPORTED);\r
-  } else {\r
-    return (gST->ConOut->OutputString(gST->ConOut, Buffer));\r
   }\r
+  if (*((CHAR16 *)Buffer) == gUnicodeFileTag) {\r
+    return (gST->ConOut->OutputString(gST->ConOut, (CHAR16 *)Buffer + 1));\r
+  }\r
+  return (gST->ConOut->OutputString(gST->ConOut, Buffer));\r
 }\r
 \r
 /**\r
@@ -287,6 +292,144 @@ FileInterfaceNulWrite(
   return (EFI_SUCCESS);\r
 }\r
 \r
+/**\r
+  Create the TAB completion list.\r
+\r
+  @param[in]  InputString       The command line to expand.\r
+  @param[in]  StringLen         Length of the command line.\r
+  @param[in]  BufferSize        Buffer size.\r
+  @param[in, out] TabCompletionList Return the TAB completion list.\r
+  @param[in, out] TabUpdatePos      Return the TAB update position.\r
+**/\r
+EFI_STATUS\r
+CreateTabCompletionList (\r
+  IN CONST CHAR16             *InputString,\r
+  IN CONST UINTN              StringLen, \r
+  IN CONST UINTN              BufferSize,\r
+  IN OUT EFI_SHELL_FILE_INFO  **TabCompletionList,\r
+  IN OUT   UINTN              *TabUpdatePos\r
+)\r
+{\r
+  BOOLEAN             InQuotation;\r
+  UINTN               TabPos;\r
+  UINTN               Index;\r
+  CONST CHAR16        *Cwd;\r
+  EFI_STATUS          Status;\r
+  CHAR16              *TabStr;\r
+  EFI_SHELL_FILE_INFO *FileList;\r
+  EFI_SHELL_FILE_INFO *FileInfo;\r
+  EFI_SHELL_FILE_INFO *TempFileInfo;\r
+\r
+  //\r
+  // Allocate buffers\r
+  //\r
+  TabStr = AllocateZeroPool (BufferSize);\r
+  if (TabStr == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // handle auto complete of file and directory names...\r
+  // E.g.: cd fs0:\EFI\Bo<TAB>\r
+  //          ^        ^\r
+  //          TabPos   TabUpdatePos\r
+  //\r
+  TabPos        = 0;\r
+  *TabUpdatePos = 0;\r
+  FileList      = NULL;\r
+  InQuotation   = FALSE;\r
+  for (Index = 0; Index < StringLen; Index++) {\r
+    switch (InputString[Index]) {\r
+    case L'\"':\r
+      InQuotation = (BOOLEAN) (!InQuotation);\r
+      break;\r
+\r
+    case L' ':\r
+      if (!InQuotation) {\r
+        TabPos = Index + 1;\r
+        *TabUpdatePos = TabPos;\r
+      }\r
+      break;\r
+\r
+    case L':':\r
+      //\r
+      // handle the case "fs0:<TAB>"\r
+      // Update the TabUpdatePos as well.\r
+      //\r
+    case L'\\':\r
+      *TabUpdatePos = Index + 1;\r
+      break;\r
+\r
+    default:\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (StrStr (InputString + TabPos, L":") == NULL) {\r
+    //\r
+    // If file path doesn't contain ":", ...\r
+    //\r
+    Cwd = ShellInfoObject.NewEfiShellProtocol->GetCurDir (NULL);\r
+    if (Cwd != NULL) {\r
+      if (InputString[TabPos] != L'\\') {\r
+        //\r
+        // and it doesn't begin with "\\", it's a path relative to current directory.\r
+        // TabStr = "<cwd>\\"\r
+        //\r
+        StrnCpyS (TabStr, BufferSize / sizeof (CHAR16), Cwd, (BufferSize) / sizeof (CHAR16) - 1);\r
+        StrCatS (TabStr, (BufferSize) / sizeof (CHAR16), L"\\");\r
+      } else {\r
+        //\r
+        // and it begins with "\\", it's a path pointing to root directory of current map.\r
+        // TabStr = "fsx:"\r
+        //\r
+        Index = StrStr (Cwd, L":") - Cwd + 1;\r
+        StrnCpyS (TabStr, BufferSize / sizeof (CHAR16), Cwd, Index);\r
+      }\r
+    }\r
+  }\r
+  StrnCatS (TabStr, (BufferSize) / sizeof (CHAR16), InputString + TabPos, StringLen - TabPos);\r
+  StrnCatS (TabStr, (BufferSize) / sizeof (CHAR16), L"*", (BufferSize) / sizeof (CHAR16) - 1 - StrLen (TabStr));\r
+  Status  = ShellInfoObject.NewEfiShellProtocol->FindFiles(TabStr, &FileList);\r
+\r
+  //\r
+  // Filter out the non-directory for "CD" command\r
+  // Filter "." and ".." for all\r
+  //\r
+  if (!EFI_ERROR (Status) && FileList != NULL) {\r
+    //\r
+    // Skip the spaces in the beginning\r
+    //\r
+    while (*InputString == L' ') {\r
+      InputString++;\r
+    }\r
+\r
+    for (FileInfo = (EFI_SHELL_FILE_INFO *) GetFirstNode (&FileList->Link); !IsNull (&FileList->Link, &FileInfo->Link); ) {\r
+      if (((StrCmp (FileInfo->FileName, L".") == 0) || (StrCmp (FileInfo->FileName, L"..") == 0)) ||\r
+          (((InputString[0] == L'c' || InputString[0] == L'C') && (InputString[1] == L'd' || InputString[1] == L'D')) &&\r
+           (ShellIsDirectory (FileInfo->FullName) != EFI_SUCCESS))) {\r
+        TempFileInfo = FileInfo;\r
+        FileInfo = (EFI_SHELL_FILE_INFO *) RemoveEntryList (&FileInfo->Link);\r
+        InternalFreeShellFileInfoNode (TempFileInfo);\r
+      } else {\r
+        FileInfo = (EFI_SHELL_FILE_INFO *) GetNextNode (&FileList->Link, &FileInfo->Link);\r
+      }\r
+    }\r
+  }\r
+\r
+  if (FileList != NULL && !IsListEmpty (&FileList->Link)) {\r
+    Status = EFI_SUCCESS;\r
+  } else {\r
+    ShellInfoObject.NewEfiShellProtocol->FreeFileList (&FileList);\r
+    Status = EFI_NOT_FOUND;\r
+  }\r
+\r
+  FreePool (TabStr);\r
+\r
+  *TabCompletionList = FileList;\r
+  return Status;\r
+}\r
+\r
 /**\r
   File style interface for console (Read).\r
 \r
@@ -321,6 +464,7 @@ FileInterfaceStdInRead(
 {\r
   CHAR16              *CurrentString;\r
   BOOLEAN             Done;\r
+  UINTN               TabUpdatePos;   // Start index of the string updated by TAB stroke\r
   UINTN               Column;         // Column of current cursor\r
   UINTN               Row;            // Row of current cursor\r
   UINTN               StartColumn;    // Column at the beginning of the line\r
@@ -329,7 +473,6 @@ FileInterfaceStdInRead(
   UINTN               StringLen;      // Total length of the line\r
   UINTN               StringCurPos;   // Line index corresponding to the cursor\r
   UINTN               MaxStr;         // Maximum possible line length\r
-  UINTN               Index;\r
   UINTN               TotalColumn;     // Num of columns in the console\r
   UINTN               TotalRow;       // Num of rows in the console\r
   UINTN               SkipLength;\r
@@ -343,18 +486,10 @@ FileInterfaceStdInRead(
   BOOLEAN             InScrolling;\r
   EFI_STATUS          Status;\r
   BOOLEAN             InTabScrolling; // Whether in TAB-completion state\r
-  EFI_SHELL_FILE_INFO *FoundFileList;\r
-  EFI_SHELL_FILE_INFO *TabLinePos;\r
-  EFI_SHELL_FILE_INFO *TempPos;\r
-  CHAR16              *TabStr;\r
-  CHAR16              *TabOutputStr;\r
-  BOOLEAN             InQuotationMode;\r
-  CHAR16              *TempStr;\r
-  UINTN               TabPos;         // Start index of the string to search for TAB completion.\r
-  UINTN               TabUpdatePos;   // Start index of the string updated by TAB stroke\r
-//  UINTN               Count;\r
+  EFI_SHELL_FILE_INFO *TabCompleteList;\r
+  EFI_SHELL_FILE_INFO *TabCurrent;\r
   UINTN               EventIndex;\r
-  CONST CHAR16        *Cwd;\r
+  CHAR16              *TabOutputStr;\r
 \r
   //\r
   // If buffer is not large enough to hold a CHAR16, return minimum buffer size\r
@@ -375,24 +510,10 @@ FileInterfaceStdInRead(
   InScrolling       = FALSE;\r
   InTabScrolling    = FALSE;\r
   Status            = EFI_SUCCESS;\r
-  TabLinePos        = NULL;\r
-  FoundFileList     = NULL;\r
-  TempPos           = NULL;\r
-  TabPos            = 0;\r
+  TabOutputStr      = NULL;\r
   TabUpdatePos      = 0;\r
-\r
-  //\r
-  // Allocate buffers\r
-  //\r
-  TabStr            = AllocateZeroPool (*BufferSize);\r
-  if (TabStr == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-  TabOutputStr      = AllocateZeroPool (*BufferSize);\r
-  if (TabOutputStr == NULL) {\r
-    FreePool(TabStr);\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
+  TabCompleteList   = NULL;\r
+  TabCurrent        = NULL;\r
 \r
   //\r
   // Get the screen setting and the current cursor location\r
@@ -417,6 +538,12 @@ FileInterfaceStdInRead(
     gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);\r
     Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
     if (EFI_ERROR (Status)) {\r
+\r
+      if (Status == EFI_NOT_READY)\r
+        continue;\r
+\r
+      ZeroMem (CurrentString, MaxStr * sizeof(CHAR16));\r
+      StringLen = 0;\r
       break;\r
     }\r
 \r
@@ -443,11 +570,11 @@ FileInterfaceStdInRead(
     // If we are quitting TAB scrolling...\r
     //\r
     if (InTabScrolling && Key.UnicodeChar != CHAR_TAB) {\r
-        if (FoundFileList != NULL) {\r
-          ShellInfoObject.NewEfiShellProtocol->FreeFileList (&FoundFileList);\r
-          DEBUG_CODE(FoundFileList = NULL;);\r
-        }\r
-        InTabScrolling = FALSE;\r
+      if (TabCompleteList != NULL) {\r
+        ShellInfoObject.NewEfiShellProtocol->FreeFileList (&TabCompleteList);\r
+        DEBUG_CODE(TabCompleteList = NULL;);\r
+      }\r
+      InTabScrolling = FALSE;\r
     }\r
 \r
     switch (Key.UnicodeChar) {\r
@@ -480,95 +607,39 @@ FileInterfaceStdInRead(
       break;\r
 \r
     case CHAR_TAB:\r
-      //\r
-      // handle auto complete of file and directory names...\r
-      //\r
-      if (InTabScrolling) {\r
-        ASSERT(FoundFileList != NULL);\r
-        ASSERT(TabLinePos != NULL);\r
-        TabLinePos = (EFI_SHELL_FILE_INFO*)GetNextNode(&(FoundFileList->Link), &TabLinePos->Link);\r
-        if (IsNull(&(FoundFileList->Link), &TabLinePos->Link)) {\r
-          TabLinePos = (EFI_SHELL_FILE_INFO*)GetNextNode(&(FoundFileList->Link), &TabLinePos->Link);\r
-        }\r
-      } else {\r
-        TabPos          = 0;\r
-        TabUpdatePos    = 0;\r
-        InQuotationMode = FALSE;\r
-        for (Index = 0; Index < StringLen; Index++) {\r
-          if (CurrentString[Index] == L'\"') {\r
-            InQuotationMode = (BOOLEAN)(!InQuotationMode);\r
-          }\r
-          if (CurrentString[Index] == L' ' && !InQuotationMode) {\r
-            TabPos = Index + 1;\r
-            TabUpdatePos = Index + 1;\r
-          }\r
-          if (CurrentString[Index] == L'\\') {\r
-            TabUpdatePos = Index + 1;\r
-          }\r
+      if (!InTabScrolling) {\r
+        TabCurrent = NULL;\r
+        //\r
+        // Initialize a tab complete operation.\r
+        //\r
+        Status = CreateTabCompletionList (CurrentString, StringLen, *BufferSize, &TabCompleteList, &TabUpdatePos);\r
+        if (!EFI_ERROR(Status)) {\r
+          InTabScrolling = TRUE;\r
         }\r
-        if (StrStr(CurrentString + TabPos, L":") == NULL) {\r
-          Cwd = ShellInfoObject.NewEfiShellProtocol->GetCurDir(NULL);\r
-          if (Cwd != NULL) {\r
-            StrCpyS(TabStr, (*BufferSize)/sizeof(CHAR16), Cwd);\r
-            if (TabStr[StrLen(TabStr)-1] == L'\\' && *(CurrentString + TabPos) == L'\\' ) {\r
-              TabStr[StrLen(TabStr)-1] = CHAR_NULL;\r
-            }\r
-            StrnCatS( TabStr, \r
-                      (*BufferSize)/sizeof(CHAR16), \r
-                      CurrentString + TabPos, \r
-                      StringLen - TabPos\r
-                      );\r
-          } else {\r
-            *TabStr = CHAR_NULL;\r
-            StrnCatS(TabStr, (*BufferSize)/sizeof(CHAR16), CurrentString + TabPos, StringLen - TabPos);\r
-          }\r
+\r
+        //\r
+        // We do not set up the replacement.\r
+        // The next section will do that.\r
+        //\r
+      }\r
+\r
+      if (InTabScrolling) {\r
+        //\r
+        // We are in a tab complete operation.\r
+        // set up the next replacement.\r
+        //\r
+        ASSERT(TabCompleteList != NULL);\r
+        if (TabCurrent == NULL) {\r
+          TabCurrent = (EFI_SHELL_FILE_INFO*) GetFirstNode (&TabCompleteList->Link);\r
         } else {\r
-          StrCpyS(TabStr, (*BufferSize)/sizeof(CHAR16), CurrentString + TabPos);\r
+          TabCurrent = (EFI_SHELL_FILE_INFO*) GetNextNode (&TabCompleteList->Link, &TabCurrent->Link);\r
         }\r
-        StrnCatS(TabStr, (*BufferSize)/sizeof(CHAR16), L"*", (*BufferSize)/sizeof(CHAR16) - 1 - StrLen(TabStr));\r
-        FoundFileList = NULL;\r
-        Status  = ShellInfoObject.NewEfiShellProtocol->FindFiles(TabStr, &FoundFileList);\r
-        for ( TempStr = CurrentString\r
-            ; *TempStr == L' '\r
-            ; TempStr++); // note the ';'... empty for loop\r
+\r
         //\r
-        // make sure we have a list before we do anything more...\r
+        // Skip over the empty list beginning node\r
         //\r
-        if (EFI_ERROR (Status) || FoundFileList == NULL) {\r
-          InTabScrolling = FALSE;\r
-          TabLinePos = NULL;\r
-          continue;\r
-        } else {\r
-          //\r
-          // enumerate through the list of files\r
-          //\r
-          for ( TempPos = (EFI_SHELL_FILE_INFO*)GetFirstNode(&(FoundFileList->Link))\r
-              ; !IsNull(&FoundFileList->Link, &TempPos->Link)\r
-              ; TempPos = (EFI_SHELL_FILE_INFO*)GetNextNode(&(FoundFileList->Link), &(TempPos->Link))\r
-             ){\r
-            //\r
-            // If "cd" is typed, only directory name will be auto-complete filled\r
-            // in either case . and .. will be removed.\r
-            //\r
-            if ((((TempStr[0] == L'c' || TempStr[0] == L'C') &&\r
-                (TempStr[1] == L'd' || TempStr[1] == L'D')\r
-               ) && ((ShellIsDirectory(TempPos->FullName) != EFI_SUCCESS)\r
-                ||(StrCmp(TempPos->FileName, L".") == 0)\r
-                ||(StrCmp(TempPos->FileName, L"..") == 0)\r
-               )) || ((StrCmp(TempPos->FileName, L".") == 0)\r
-                ||(StrCmp(TempPos->FileName, L"..") == 0))){\r
-                TabLinePos = TempPos;\r
-                TempPos = (EFI_SHELL_FILE_INFO*)(RemoveEntryList(&(TempPos->Link))->BackLink);\r
-                InternalFreeShellFileInfoNode(TabLinePos);\r
-            }\r
-          }\r
-          if (FoundFileList != NULL && !IsListEmpty(&FoundFileList->Link)) {\r
-            TabLinePos = (EFI_SHELL_FILE_INFO*)GetFirstNode(&FoundFileList->Link);\r
-            InTabScrolling = TRUE;\r
-          } else {\r
-            FreePool(FoundFileList);\r
-            FoundFileList = NULL;\r
-          }\r
+        if (IsNull(&TabCompleteList->Link, &TabCurrent->Link)) {\r
+          TabCurrent = (EFI_SHELL_FILE_INFO*) GetNextNode (&TabCompleteList->Link, &TabCurrent->Link);\r
         }\r
       }\r
       break;\r
@@ -709,23 +780,31 @@ FileInterfaceStdInRead(
     // the next file or directory name\r
     //\r
     if (InTabScrolling) {\r
+      TabOutputStr = AllocateZeroPool (*BufferSize);\r
+      if (TabOutputStr == NULL) {\r
+        Status = EFI_OUT_OF_RESOURCES;\r
+      }\r
+    }\r
+\r
+    if (InTabScrolling && TabOutputStr != NULL) {\r
+\r
       //\r
       // Adjust the column and row to the start of TAB-completion string.\r
       //\r
       Column = (StartColumn + TabUpdatePos) % TotalColumn;\r
       Row -= (StartColumn + StringCurPos) / TotalColumn - (StartColumn + TabUpdatePos) / TotalColumn;\r
-      OutputLength = StrLen (TabLinePos->FileName);\r
+      OutputLength = StrLen (TabCurrent->FileName);\r
       //\r
       // if the output string contains  blank space, quotation marks L'\"'\r
       // should be added to the output.\r
       //\r
-      if (StrStr(TabLinePos->FileName, L" ") != NULL){\r
+      if (StrStr(TabCurrent->FileName, L" ") != NULL){\r
         TabOutputStr[0] = L'\"';\r
-        CopyMem (TabOutputStr + 1, TabLinePos->FileName, OutputLength * sizeof (CHAR16));\r
+        CopyMem (TabOutputStr + 1, TabCurrent->FileName, OutputLength * sizeof (CHAR16));\r
         TabOutputStr[OutputLength + 1] = L'\"';\r
         TabOutputStr[OutputLength + 2] = CHAR_NULL;\r
       } else {\r
-        CopyMem (TabOutputStr, TabLinePos->FileName, OutputLength * sizeof (CHAR16));\r
+        CopyMem (TabOutputStr, TabCurrent->FileName, OutputLength * sizeof (CHAR16));\r
         TabOutputStr[OutputLength] = CHAR_NULL;\r
       }\r
       OutputLength = StrLen (TabOutputStr) < MaxStr - 1 ? StrLen (TabOutputStr) : MaxStr - 1;\r
@@ -736,6 +815,8 @@ FileInterfaceStdInRead(
       if (StringLen > TabUpdatePos + OutputLength) {\r
         Delete = StringLen - TabUpdatePos - OutputLength;\r
       }\r
+\r
+      FreePool(TabOutputStr);\r
     }\r
 \r
     //\r
@@ -839,8 +920,6 @@ FileInterfaceStdInRead(
     AddLineToCommandHistory(CurrentString);\r
   }\r
 \r
-  FreePool (TabStr);\r
-  FreePool (TabOutputStr);\r
   //\r
   // Return the data to the caller\r
   //\r
@@ -850,7 +929,10 @@ FileInterfaceStdInRead(
   // if this was used it should be deallocated by now...\r
   // prevent memory leaks...\r
   //\r
-  ASSERT(FoundFileList == NULL);\r
+  if (TabCompleteList != NULL) {\r
+    ShellInfoObject.NewEfiShellProtocol->FreeFileList (&TabCompleteList);\r
+  }\r
+  ASSERT(TabCompleteList == NULL);\r
 \r
   return Status;\r
 }\r
@@ -957,6 +1039,7 @@ FileInterfaceEnvClose(
   VOID*       NewBuffer;\r
   UINTN       NewSize;\r
   EFI_STATUS  Status;\r
+  BOOLEAN     Volatile;\r
 \r
   //\r
   // Most if not all UEFI commands will have an '\r\n' at the end of any output. \r
@@ -967,6 +1050,11 @@ FileInterfaceEnvClose(
   NewBuffer   = NULL;\r
   NewSize     = 0;\r
 \r
+  Status = IsVolatileEnv (((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &Volatile);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
   Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer);\r
   if (Status == EFI_BUFFER_TOO_SMALL) {\r
     NewBuffer = AllocateZeroPool(NewSize + sizeof(CHAR16));\r
@@ -984,8 +1072,8 @@ FileInterfaceEnvClose(
            && (((CHAR16*)NewBuffer)[(StrSize(NewBuffer)/2) - 3] == CHAR_CARRIAGE_RETURN)) {\r
         ((CHAR16*)NewBuffer)[(StrSize(NewBuffer)/2) - 3] = CHAR_NULL;   \r
       }\r
-    \r
-      if (IsVolatileEnv(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name)) {\r
+\r
+      if (Volatile) {\r
         Status = SHELL_SET_ENVIRONMENT_VARIABLE_V(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, StrSize(NewBuffer), NewBuffer);\r
       } else {\r
         Status = SHELL_SET_ENVIRONMENT_VARIABLE_NV(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, StrSize(NewBuffer), NewBuffer);\r
@@ -1138,18 +1226,24 @@ FileInterfaceEnvNonVolWrite(
   @return other     a pointer to an EFI_FILE_PROTOCOL structure\r
 **/\r
 EFI_FILE_PROTOCOL*\r
-EFIAPI\r
 CreateFileInterfaceEnv(\r
   IN CONST CHAR16 *EnvName\r
   )\r
 {\r
+  EFI_STATUS                     Status;\r
   EFI_FILE_PROTOCOL_ENVIRONMENT  *EnvFileInterface;\r
   UINTN                          EnvNameSize;\r
+  BOOLEAN                        Volatile;\r
 \r
   if (EnvName == NULL) {\r
     return (NULL);\r
   }\r
 \r
+  Status = IsVolatileEnv (EnvName, &Volatile);\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+\r
   //\r
   // Get some memory\r
   //\r
@@ -1178,7 +1272,7 @@ CreateFileInterfaceEnv(
   //\r
   // Assign the different members for Volatile and Non-Volatile variables\r
   //\r
-  if (IsVolatileEnv(EnvName)) {\r
+  if (Volatile) {\r
     EnvFileInterface->Write       = FileInterfaceEnvVolWrite;\r
   } else {\r
     EnvFileInterface->Write       = FileInterfaceEnvNonVolWrite;\r
@@ -1194,7 +1288,6 @@ CreateFileInterfaceEnv(
   @param[in, out] Row         Current row of the cursor position\r
 **/\r
 VOID\r
-EFIAPI\r
 MoveCursorBackward (\r
   IN     UINTN                   LineLength,\r
   IN OUT UINTN                   *Column,\r
@@ -1224,7 +1317,6 @@ MoveCursorBackward (
   @param[in, out] Row         Current row of the cursor position\r
 **/\r
 VOID\r
-EFIAPI\r
 MoveCursorForward (\r
   IN     UINTN                   LineLength,\r
   IN     UINTN                   TotalRow,\r
@@ -1256,7 +1348,6 @@ MoveCursorForward (
   @param[in] StartColumn  which column to start at\r
 **/\r
 VOID\r
-EFIAPI\r
 PrintCommandHistory (\r
   IN CONST UINTN TotalCols,\r
   IN CONST UINTN TotalRows,\r
@@ -1321,6 +1412,7 @@ typedef struct {
   UINT64                Position;\r
   UINT64                BufferSize;\r
   BOOLEAN               Unicode;\r
+  UINT64                FileSize;\r
 } EFI_FILE_PROTOCOL_MEM;\r
 \r
 /**\r
@@ -1339,7 +1431,7 @@ FileInterfaceMemSetPosition(
   OUT UINT64 Position\r
   )\r
 {\r
-  if (Position <= ((EFI_FILE_PROTOCOL_MEM*)This)->BufferSize) {\r
+  if (Position <= ((EFI_FILE_PROTOCOL_MEM*)This)->FileSize) {\r
     ((EFI_FILE_PROTOCOL_MEM*)This)->Position = Position;\r
     return (EFI_SUCCESS);\r
   } else {\r
@@ -1384,17 +1476,21 @@ FileInterfaceMemWrite(
   IN VOID *Buffer\r
   )\r
 {\r
-  CHAR8 *AsciiBuffer;\r
-  if (((EFI_FILE_PROTOCOL_MEM*)This)->Unicode) {\r
+  CHAR8                  *AsciiBuffer;\r
+  EFI_FILE_PROTOCOL_MEM  *MemFile;\r
+\r
+  MemFile = (EFI_FILE_PROTOCOL_MEM *) This;\r
+  if (MemFile->Unicode) {\r
     //\r
     // Unicode\r
     //\r
-    if ((UINTN)(((EFI_FILE_PROTOCOL_MEM*)This)->Position + (*BufferSize)) > (UINTN)(((EFI_FILE_PROTOCOL_MEM*)This)->BufferSize)) {\r
-      ((EFI_FILE_PROTOCOL_MEM*)This)->Buffer = ReallocatePool((UINTN)(((EFI_FILE_PROTOCOL_MEM*)This)->BufferSize), (UINTN)(((EFI_FILE_PROTOCOL_MEM*)This)->BufferSize) + (*BufferSize) + 10, ((EFI_FILE_PROTOCOL_MEM*)This)->Buffer);\r
-      ((EFI_FILE_PROTOCOL_MEM*)This)->BufferSize += (*BufferSize) + 10;\r
+    if ((UINTN)(MemFile->Position + (*BufferSize)) > (UINTN)(MemFile->BufferSize)) {\r
+      MemFile->Buffer = ReallocatePool((UINTN)(MemFile->BufferSize), (UINTN)(MemFile->BufferSize) + (*BufferSize) + MEM_WRITE_REALLOC_OVERHEAD, MemFile->Buffer);\r
+      MemFile->BufferSize += (*BufferSize) + MEM_WRITE_REALLOC_OVERHEAD;\r
     }\r
-    CopyMem(((UINT8*)((EFI_FILE_PROTOCOL_MEM*)This)->Buffer) + ((EFI_FILE_PROTOCOL_MEM*)This)->Position, Buffer, *BufferSize);\r
-    ((EFI_FILE_PROTOCOL_MEM*)This)->Position += (*BufferSize);\r
+    CopyMem(((UINT8*)MemFile->Buffer) + MemFile->Position, Buffer, *BufferSize);\r
+    MemFile->Position += (*BufferSize);\r
+    MemFile->FileSize = MemFile->Position;\r
     return (EFI_SUCCESS);\r
   } else {\r
     //\r
@@ -1405,12 +1501,13 @@ FileInterfaceMemWrite(
       return (EFI_OUT_OF_RESOURCES);\r
     }\r
     AsciiSPrint(AsciiBuffer, *BufferSize, "%S", Buffer);\r
-    if ((UINTN)(((EFI_FILE_PROTOCOL_MEM*)This)->Position + AsciiStrSize(AsciiBuffer)) > (UINTN)(((EFI_FILE_PROTOCOL_MEM*)This)->BufferSize)) {\r
-      ((EFI_FILE_PROTOCOL_MEM*)This)->Buffer = ReallocatePool((UINTN)(((EFI_FILE_PROTOCOL_MEM*)This)->BufferSize), (UINTN)(((EFI_FILE_PROTOCOL_MEM*)This)->BufferSize) + AsciiStrSize(AsciiBuffer) + 10, ((EFI_FILE_PROTOCOL_MEM*)This)->Buffer);\r
-      ((EFI_FILE_PROTOCOL_MEM*)This)->BufferSize += AsciiStrSize(AsciiBuffer) + 10;\r
+    if ((UINTN)(MemFile->Position + AsciiStrSize(AsciiBuffer)) > (UINTN)(MemFile->BufferSize)) {\r
+      MemFile->Buffer = ReallocatePool((UINTN)(MemFile->BufferSize), (UINTN)(MemFile->BufferSize) + AsciiStrSize(AsciiBuffer) + MEM_WRITE_REALLOC_OVERHEAD, MemFile->Buffer);\r
+      MemFile->BufferSize += AsciiStrSize(AsciiBuffer) + MEM_WRITE_REALLOC_OVERHEAD;\r
     }\r
-    CopyMem(((UINT8*)((EFI_FILE_PROTOCOL_MEM*)This)->Buffer) + ((EFI_FILE_PROTOCOL_MEM*)This)->Position, AsciiBuffer, AsciiStrSize(AsciiBuffer));\r
-    ((EFI_FILE_PROTOCOL_MEM*)This)->Position += AsciiStrSize(AsciiBuffer);\r
+    CopyMem(((UINT8*)MemFile->Buffer) + MemFile->Position, AsciiBuffer, AsciiStrSize(AsciiBuffer));\r
+    MemFile->Position += (*BufferSize / sizeof(CHAR16));\r
+    MemFile->FileSize = MemFile->Position;\r
     FreePool(AsciiBuffer);\r
     return (EFI_SUCCESS);\r
   }\r
@@ -1433,11 +1530,14 @@ FileInterfaceMemRead(
   IN VOID *Buffer\r
   )\r
 {\r
-  if (*BufferSize > (UINTN)((((EFI_FILE_PROTOCOL_MEM*)This)->BufferSize) - (UINTN)(((EFI_FILE_PROTOCOL_MEM*)This)->Position))) {\r
-    (*BufferSize) = (UINTN)((((EFI_FILE_PROTOCOL_MEM*)This)->BufferSize) - (UINTN)(((EFI_FILE_PROTOCOL_MEM*)This)->Position));\r
+  EFI_FILE_PROTOCOL_MEM  *MemFile;\r
+\r
+  MemFile = (EFI_FILE_PROTOCOL_MEM *) This;\r
+  if (*BufferSize > (UINTN)((MemFile->FileSize) - (UINTN)(MemFile->Position))) {\r
+    (*BufferSize) = (UINTN)((MemFile->FileSize) - (UINTN)(MemFile->Position));\r
   }\r
-  CopyMem(Buffer, ((UINT8*)((EFI_FILE_PROTOCOL_MEM*)This)->Buffer) + ((EFI_FILE_PROTOCOL_MEM*)This)->Position, (*BufferSize));\r
-  ((EFI_FILE_PROTOCOL_MEM*)This)->Position = ((EFI_FILE_PROTOCOL_MEM*)This)->Position + (*BufferSize);\r
+  CopyMem(Buffer, ((UINT8*)MemFile->Buffer) + MemFile->Position, (*BufferSize));\r
+  MemFile->Position = MemFile->Position + (*BufferSize);\r
   return (EFI_SUCCESS);\r
 }\r
 \r
@@ -1471,7 +1571,6 @@ FileInterfaceMemClose(
   @return other     A pointer to an EFI_FILE_PROTOCOL structure.\r
 **/\r
 EFI_FILE_PROTOCOL*\r
-EFIAPI\r
 CreateFileInterfaceMem(\r
   IN CONST BOOLEAN Unicode\r
   )\r
@@ -1506,6 +1605,17 @@ CreateFileInterfaceMem(
   ASSERT(FileInterface->BufferSize  == 0);\r
   ASSERT(FileInterface->Position    == 0);\r
 \r
+  if (Unicode) {\r
+    FileInterface->Buffer = AllocateZeroPool(sizeof(gUnicodeFileTag));\r
+    if (FileInterface->Buffer == NULL) {\r
+      FreePool (FileInterface);\r
+      return NULL;\r
+    }\r
+    *((CHAR16 *) (FileInterface->Buffer)) = EFI_UNICODE_BYTE_ORDER_MARK;\r
+    FileInterface->BufferSize = 2;\r
+    FileInterface->Position = 2;\r
+  }\r
+\r
   return ((EFI_FILE_PROTOCOL *)FileInterface);\r
 }\r
 \r
@@ -1670,8 +1780,10 @@ FileInterfaceFileRead(
   OUT VOID                    *Buffer\r
   )\r
 {\r
-  CHAR8       *AsciiBuffer;\r
+  CHAR8       *AsciiStrBuffer;\r
+  CHAR16      *UscStrBuffer;\r
   UINTN       Size;\r
+  UINTN       CharNum;\r
   EFI_STATUS  Status;\r
   if (((EFI_FILE_PROTOCOL_FILE*)This)->Unicode) {\r
     //\r
@@ -1682,10 +1794,27 @@ FileInterfaceFileRead(
     //\r
     // Ascii\r
     //\r
-    AsciiBuffer = AllocateZeroPool((Size = *BufferSize));\r
-    Status = (((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Read(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, &Size, AsciiBuffer));\r
-    UnicodeSPrint(Buffer, *BufferSize, L"%a", AsciiBuffer);\r
-    FreePool(AsciiBuffer);\r
+    Size  = (*BufferSize) / sizeof(CHAR16);\r
+    AsciiStrBuffer = AllocateZeroPool(Size + sizeof(CHAR8));\r
+    if (AsciiStrBuffer == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    UscStrBuffer = AllocateZeroPool(*BufferSize + sizeof(CHAR16));\r
+    if (UscStrBuffer== NULL) {\r
+      SHELL_FREE_NON_NULL(AsciiStrBuffer);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    Status = (((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Read(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, &Size, AsciiStrBuffer));\r
+    if (!EFI_ERROR(Status)) {\r
+      CharNum = UnicodeSPrint(UscStrBuffer, *BufferSize + sizeof(CHAR16), L"%a", AsciiStrBuffer);\r
+      if (CharNum == Size) {\r
+        CopyMem (Buffer, UscStrBuffer, *BufferSize);\r
+      } else {\r
+        Status = EFI_UNSUPPORTED;\r
+      }\r
+    }\r
+    SHELL_FREE_NON_NULL(AsciiStrBuffer);\r
+    SHELL_FREE_NON_NULL(UscStrBuffer);\r
     return (Status);\r
   }\r
 }\r