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
#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
{\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
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
{\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
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
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
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
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
// 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
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
// 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
if (StringLen > TabUpdatePos + OutputLength) {\r
Delete = StringLen - TabUpdatePos - OutputLength;\r
}\r
+\r
+ FreePool(TabOutputStr);\r
}\r
\r
//\r
AddLineToCommandHistory(CurrentString);\r
}\r
\r
- FreePool (TabStr);\r
- FreePool (TabOutputStr);\r
//\r
// Return the data to the caller\r
//\r
// 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
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
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
&& (((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
@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
//\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
@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
@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
@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
UINT64 Position;\r
UINT64 BufferSize;\r
BOOLEAN Unicode;\r
+ UINT64 FileSize;\r
} EFI_FILE_PROTOCOL_MEM;\r
\r
/**\r
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
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
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
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
@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
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
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
//\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