]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/Application/Shell/FileHandleWrappers.c
ShellPkg: Do not write the UNICODE BOM on ConOut.
[mirror_edk2.git] / ShellPkg / Application / Shell / FileHandleWrappers.c
index 2ca13cb3f3f73ad482ca52c6e89bfa65bc69b6d0..a9117bee92ae61e12d0b22d844eb287f71d10e52 100644 (file)
@@ -2,7 +2,9 @@
   EFI_FILE_PROTOCOL wrappers for other items (Like Environment Variables,\r
   StdIn, StdOut, StdErr, etc...).\r
 \r
-  Copyright (c) 2009 - 2011, 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
   which accompanies this distribution.  The full text of the license may be found at\r
@@ -158,9 +160,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
@@ -416,7 +420,7 @@ FileInterfaceStdInRead(
     gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);\r
     Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
     if (EFI_ERROR (Status)) {\r
-      continue;\r
+      break;\r
     }\r
 \r
     //\r
@@ -508,21 +512,25 @@ FileInterfaceStdInRead(
         if (StrStr(CurrentString + TabPos, L":") == NULL) {\r
           Cwd = ShellInfoObject.NewEfiShellProtocol->GetCurDir(NULL);\r
           if (Cwd != NULL) {\r
-            StrCpy(TabStr, Cwd);\r
+            StrnCpyS(TabStr, (*BufferSize)/sizeof(CHAR16), Cwd, (*BufferSize)/sizeof(CHAR16) - 1);\r
+            StrCatS(TabStr, (*BufferSize)/sizeof(CHAR16), L"\\");\r
             if (TabStr[StrLen(TabStr)-1] == L'\\' && *(CurrentString + TabPos) == L'\\' ) {\r
               TabStr[StrLen(TabStr)-1] = CHAR_NULL;\r
             }\r
-            StrnCat(TabStr, CurrentString + TabPos, (StringLen - TabPos) * sizeof (CHAR16));\r
+            StrnCatS( TabStr, \r
+                      (*BufferSize)/sizeof(CHAR16), \r
+                      CurrentString + TabPos, \r
+                      StringLen - TabPos\r
+                      );\r
           } else {\r
-            StrCpy(TabStr, L"");\r
-            StrnCat(TabStr, CurrentString + TabPos, (StringLen - TabPos) * sizeof (CHAR16));\r
+            *TabStr = CHAR_NULL;\r
+            StrnCatS(TabStr, (*BufferSize)/sizeof(CHAR16), CurrentString + TabPos, StringLen - TabPos);\r
           }\r
         } else {\r
-          StrCpy(TabStr, CurrentString + TabPos);\r
+          StrnCpyS(TabStr, (*BufferSize)/sizeof(CHAR16), CurrentString + TabPos, (*BufferSize)/sizeof(CHAR16) - 1);\r
         }\r
-        StrCat(TabStr, L"*");\r
+        StrnCatS(TabStr, (*BufferSize)/sizeof(CHAR16), L"*", (*BufferSize)/sizeof(CHAR16) - 1 - StrLen(TabStr));\r
         FoundFileList = NULL;\r
-//        TabStr = PathCleanUpDirectories(TabStr);\r
         Status  = ShellInfoObject.NewEfiShellProtocol->FindFiles(TabStr, &FoundFileList);\r
         for ( TempStr = CurrentString\r
             ; *TempStr == L' '\r
@@ -848,7 +856,7 @@ FileInterfaceStdInRead(
   //\r
   ASSERT(FoundFileList == NULL);\r
 \r
-  return EFI_SUCCESS;\r
+  return Status;\r
 }\r
 \r
 //\r
@@ -950,8 +958,48 @@ FileInterfaceEnvClose(
   IN EFI_FILE_PROTOCOL *This\r
   )\r
 {\r
+  VOID*       NewBuffer;\r
+  UINTN       NewSize;\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // Most if not all UEFI commands will have an '\r\n' at the end of any output. \r
+  // Since the output was redirected to a variable, it does not make sense to \r
+  // keep this.  So, before closing, strip the trailing '\r\n' from the variable\r
+  // if it exists.\r
+  //\r
+  NewBuffer   = NULL;\r
+  NewSize     = 0;\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
+    if (NewBuffer == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }  \r
+    Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer);\r
+  }\r
+  \r
+  if (!EFI_ERROR(Status) && NewBuffer != NULL) {\r
+    \r
+    if (StrSize(NewBuffer) > 6)\r
+    {\r
+      if ((((CHAR16*)NewBuffer)[(StrSize(NewBuffer)/2) - 2] == CHAR_LINEFEED) \r
+           && (((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
+        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
+      }\r
+    }\r
+  } \r
+  \r
+  SHELL_FREE_NON_NULL(NewBuffer);\r
   FreePool((EFI_FILE_PROTOCOL_ENVIRONMENT*)This);\r
-  return (EFI_SUCCESS);\r
+  return (Status);\r
 }\r
 \r
 /**\r
@@ -1100,6 +1148,7 @@ CreateFileInterfaceEnv(
   )\r
 {\r
   EFI_FILE_PROTOCOL_ENVIRONMENT  *EnvFileInterface;\r
+  UINTN                          EnvNameSize;\r
 \r
   if (EnvName == NULL) {\r
     return (NULL);\r
@@ -1108,7 +1157,8 @@ CreateFileInterfaceEnv(
   //\r
   // Get some memory\r
   //\r
-  EnvFileInterface = AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_ENVIRONMENT)+StrSize(EnvName));\r
+  EnvNameSize = StrSize(EnvName);\r
+  EnvFileInterface = AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_ENVIRONMENT)+EnvNameSize);\r
   if (EnvFileInterface == NULL){\r
     return (NULL);\r
   }\r
@@ -1126,8 +1176,8 @@ CreateFileInterfaceEnv(
   EnvFileInterface->Flush       = FileInterfaceNopGeneric;\r
   EnvFileInterface->Delete      = FileInterfaceEnvDelete;\r
   EnvFileInterface->Read        = FileInterfaceEnvRead;\r
-\r
-  StrCpy(EnvFileInterface->Name, EnvName);\r
+  \r
+  CopyMem(EnvFileInterface->Name, EnvName, EnvNameSize);\r
 \r
   //\r
   // Assign the different members for Volatile and Non-Volatile variables\r
@@ -1275,6 +1325,7 @@ typedef struct {
   UINT64                Position;\r
   UINT64                BufferSize;\r
   BOOLEAN               Unicode;\r
+  UINT64                FileSize;\r
 } EFI_FILE_PROTOCOL_MEM;\r
 \r
 /**\r
@@ -1293,7 +1344,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
@@ -1338,17 +1389,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) + 10, MemFile->Buffer);\r
+      MemFile->BufferSize += (*BufferSize) + 10;\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
@@ -1359,12 +1414,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) + 10, MemFile->Buffer);\r
+      MemFile->BufferSize += AsciiStrSize(AsciiBuffer) + 10;\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
@@ -1387,11 +1443,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
@@ -1460,6 +1519,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
@@ -1624,8 +1694,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
@@ -1636,10 +1708,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