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
#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
File style interface for console (GetInfo).\r
\r
- @param[in] This Ignored.\r
- @param[in] InformationType Ignored.\r
- @param[in,out] BufferSize Ignored.\r
- @param[out] Buffer Ignored.\r
+ @param[in] This Ignored.\r
+ @param[in] InformationType Ignored.\r
+ @param[in, out] BufferSize Ignored.\r
+ @param[out] Buffer Ignored.\r
\r
@retval EFI_UNSUPPORTED\r
**/\r
\r
Writes data to the screen.\r
\r
- @param[in] This The pointer to the EFI_FILE_PROTOCOL object.\r
- @param[in,out] BufferSize Size in bytes of Buffer.\r
- @param[in] Buffer The pointer to the buffer to write.\r
+ @param[in] This The pointer to the EFI_FILE_PROTOCOL object.\r
+ @param[in, out] BufferSize Size in bytes of Buffer.\r
+ @param[in] Buffer The pointer to the buffer to write.\r
\r
@retval EFI_UNSUPPORTED No output console is supported.\r
@return A return value from gST->ConOut->OutputString.\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
File style interface for StdIn (Write).\r
\r
- @param[in] This Ignored.\r
- @param[in,out] BufferSize Ignored.\r
- @param[in] Buffer Ignored.\r
+ @param[in] This Ignored.\r
+ @param[in, out] BufferSize Ignored.\r
+ @param[in] Buffer Ignored.\r
\r
@retval EFI_UNSUPPORTED\r
**/\r
\r
Writes error to the error output.\r
\r
- @param[in] This The pointer to the EFI_FILE_PROTOCOL object.\r
- @param[in,out] BufferSize Size in bytes of Buffer.\r
- @param[in] Buffer The pointer to the buffer to write.\r
+ @param[in] This The pointer to the EFI_FILE_PROTOCOL object.\r
+ @param[in, out] BufferSize Size in bytes of Buffer.\r
+ @param[in] Buffer The pointer to the buffer to write.\r
\r
@return A return value from gST->StdErr->OutputString.\r
**/\r
/**\r
File style interface for console StdOut (Read).\r
\r
- @param[in] This Ignored.\r
- @param[in,out] BufferSize Ignored.\r
- @param[out] Buffer Ignored.\r
+ @param[in] This Ignored.\r
+ @param[in, out] BufferSize Ignored.\r
+ @param[out] Buffer Ignored.\r
\r
@retval EFI_UNSUPPORTED\r
**/\r
/**\r
File style interface for console StdErr (Read).\r
\r
- @param[in] This Ignored.\r
- @param[in,out] BufferSize Ignored.\r
- @param[out] Buffer Ignored.\r
+ @param[in] This Ignored.\r
+ @param[in, out] BufferSize Ignored.\r
+ @param[out] Buffer Ignored.\r
\r
@retval EFI_UNSUPPORTED Always.\r
**/\r
/**\r
File style interface for NUL file (Read).\r
\r
- @param[in] This Ignored.\r
- @param[in,out] BufferSize Poiner to 0 upon return.\r
- @param[out] Buffer Ignored.\r
+ @param[in] This Ignored.\r
+ @param[in, out] BufferSize Poiner to 0 upon return.\r
+ @param[out] Buffer Ignored.\r
\r
@retval EFI_SUCCESS Always.\r
**/\r
/**\r
File style interface for NUL file (Write).\r
\r
- @param[in] This Ignored.\r
- @param[in,out] BufferSize Ignored.\r
- @param[in] Buffer Ignored.\r
+ @param[in] This Ignored.\r
+ @param[in, out] BufferSize Ignored.\r
+ @param[in] Buffer Ignored.\r
\r
@retval EFI_SUCCESS\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
- continue;\r
+\r
+ if (Status == EFI_NOT_READY)\r
+ continue;\r
+\r
+ ZeroMem (CurrentString, MaxStr * sizeof(CHAR16));\r
+ StringLen = 0;\r
+ break;\r
}\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
- StrCpy(TabStr, Cwd);\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
- } else {\r
- StrCpy(TabStr, L"");\r
- StrnCat(TabStr, CurrentString + TabPos, (StringLen - TabPos) * sizeof (CHAR16));\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
- StrCpy(TabStr, CurrentString + TabPos);\r
+ TabCurrent = (EFI_SHELL_FILE_INFO*) GetNextNode (&TabCompleteList->Link, &TabCurrent->Link);\r
}\r
- StrCat(TabStr, L"*");\r
- FoundFileList = NULL;\r
-// TabStr = PathCleanUpDirectories(TabStr);\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 EFI_SUCCESS;\r
+ return Status;\r
}\r
\r
//\r
IN EFI_FILE_PROTOCOL *This\r
)\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
+ // 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 = 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
+ 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 (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
+ }\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
/**\r
File style interface for Environment Variable (Read).\r
\r
- @param[in] This The pointer to the EFI_FILE_PROTOCOL object.\r
- @param[in,out] BufferSize Size in bytes of Buffer.\r
- @param[out] Buffer The pointer to the buffer to fill.\r
+ @param[in] This The pointer to the EFI_FILE_PROTOCOL object.\r
+ @param[in, out] BufferSize Size in bytes of Buffer.\r
+ @param[out] Buffer The pointer to the buffer to fill.\r
\r
@retval EFI_SUCCESS The data was read.\r
**/\r
/**\r
File style interface for Volatile Environment Variable (Write).\r
\r
- @param[in] This The pointer to the EFI_FILE_PROTOCOL object.\r
- @param[in,out] BufferSize Size in bytes of Buffer.\r
- @param[in] Buffer The pointer to the buffer to write.\r
+ @param[in] This The pointer to the EFI_FILE_PROTOCOL object.\r
+ @param[in, out] BufferSize Size in bytes of Buffer.\r
+ @param[in] Buffer The pointer to the buffer to write.\r
\r
@retval EFI_SUCCESS The data was read.\r
**/\r
/**\r
File style interface for Non Volatile Environment Variable (Write).\r
\r
- @param[in] This The pointer to the EFI_FILE_PROTOCOL object.\r
- @param[in,out] BufferSize Size in bytes of Buffer.\r
- @param[in] Buffer The pointer to the buffer to write.\r
+ @param[in] This The pointer to the EFI_FILE_PROTOCOL object.\r
+ @param[in, out] BufferSize Size in bytes of Buffer.\r
+ @param[in] Buffer The pointer to the buffer to write.\r
\r
@retval EFI_SUCCESS The data was read.\r
**/\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
- 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
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
//\r
- if (IsVolatileEnv(EnvName)) {\r
+ if (Volatile) {\r
EnvFileInterface->Write = FileInterfaceEnvVolWrite;\r
} else {\r
EnvFileInterface->Write = FileInterfaceEnvNonVolWrite;\r
Move the cursor position one character backward.\r
\r
@param[in] LineLength Length of a line. Get it by calling QueryMode\r
- @param[in,out] Column Current column of the cursor position\r
- @param[in,out] Row Current row of the cursor position\r
+ @param[in, out] Column Current column of the cursor position\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
\r
@param[in] LineLength Length of a line.\r
@param[in] TotalRow Total row of a screen\r
- @param[in,out] Column Current column of the cursor position\r
- @param[in,out] Row Current row of the cursor position\r
+ @param[in, out] Column Current column of the cursor position\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
/**\r
File style interface for Mem (Write).\r
\r
- @param[in] This The pointer to the EFI_FILE_PROTOCOL object.\r
- @param[in,out] BufferSize Size in bytes of Buffer.\r
- @param[in] Buffer The pointer to the buffer to write.\r
+ @param[in] This The pointer to the EFI_FILE_PROTOCOL object.\r
+ @param[in, out] BufferSize Size in bytes of Buffer.\r
+ @param[in] Buffer The pointer to the buffer to write.\r
\r
- @retval EFI_SUCCESS The data was written.\r
+ @retval EFI_OUT_OF_RESOURCES The operation failed due to lack of resources.\r
+ @retval EFI_SUCCESS The data was written.\r
**/\r
EFI_STATUS\r
EFIAPI\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
// Ascii\r
//\r
AsciiBuffer = AllocateZeroPool(*BufferSize);\r
+ if (AsciiBuffer == NULL) {\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
/**\r
File style interface for Mem (Read).\r
\r
- @param[in] This The pointer to the EFI_FILE_PROTOCOL object.\r
- @param[in,out] BufferSize Size in bytes of Buffer.\r
- @param[in] Buffer The pointer to the buffer to fill.\r
+ @param[in] This The pointer to the EFI_FILE_PROTOCOL object.\r
+ @param[in, out] BufferSize Size in bytes of Buffer.\r
+ @param[in] Buffer The pointer to the buffer to fill.\r
\r
@retval EFI_SUCCESS The data was read.\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
If the file was opened with ASCII mode the data will be processed through \r
AsciiSPrint before writing.\r
\r
- @param[in] This The pointer to the EFI_FILE_PROTOCOL object.\r
- @param[in,out] BufferSize Size in bytes of Buffer.\r
- @param[in] Buffer The pointer to the buffer to write.\r
+ @param[in] This The pointer to the EFI_FILE_PROTOCOL object.\r
+ @param[in, out] BufferSize Size in bytes of Buffer.\r
+ @param[in] Buffer The pointer to the buffer to write.\r
\r
@retval EFI_SUCCESS The data was written.\r
**/\r