diff options
Diffstat (limited to 'ShellPkg/Application/Shell/FileHandleWrappers.c')
| -rw-r--r-- | ShellPkg/Application/Shell/FileHandleWrappers.c | 4388 |
1 files changed, 2194 insertions, 2194 deletions
diff --git a/ShellPkg/Application/Shell/FileHandleWrappers.c b/ShellPkg/Application/Shell/FileHandleWrappers.c index 2ba9b3401a..ed1bcecb7b 100644 --- a/ShellPkg/Application/Shell/FileHandleWrappers.c +++ b/ShellPkg/Application/Shell/FileHandleWrappers.c @@ -1,2194 +1,2194 @@ -/** @file
- EFI_FILE_PROTOCOL wrappers for other items (Like Environment Variables,
- StdIn, StdOut, StdErr, etc...).
-
- Copyright 2016 Dell Inc.
- Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
- (C) Copyright 2013 Hewlett-Packard Development Company, L.P.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "Shell.h"
-#include "FileHandleInternal.h"
-
-#define MEM_WRITE_REALLOC_OVERHEAD 1024
-
-/**
- File style interface for console (Open).
-
- @param[in] This Ignored.
- @param[out] NewHandle Ignored.
- @param[in] FileName Ignored.
- @param[in] OpenMode Ignored.
- @param[in] Attributes Ignored.
-
- @retval EFI_NOT_FOUND
-**/
-EFI_STATUS
-EFIAPI
-FileInterfaceOpenNotFound (
- IN EFI_FILE_PROTOCOL *This,
- OUT EFI_FILE_PROTOCOL **NewHandle,
- IN CHAR16 *FileName,
- IN UINT64 OpenMode,
- IN UINT64 Attributes
- )
-{
- return (EFI_NOT_FOUND);
-}
-
-/**
- File style interface for console (Close, Delete, & Flush)
-
- @param[in] This Ignored.
-
- @retval EFI_SUCCESS
-**/
-EFI_STATUS
-EFIAPI
-FileInterfaceNopGeneric (
- IN EFI_FILE_PROTOCOL *This
- )
-{
- return (EFI_SUCCESS);
-}
-
-/**
- File style interface for console (GetPosition).
-
- @param[in] This Ignored.
- @param[out] Position Ignored.
-
- @retval EFI_UNSUPPORTED
-**/
-EFI_STATUS
-EFIAPI
-FileInterfaceNopGetPosition (
- IN EFI_FILE_PROTOCOL *This,
- OUT UINT64 *Position
- )
-{
- return (EFI_UNSUPPORTED);
-}
-
-/**
- File style interface for console (SetPosition).
-
- @param[in] This Ignored.
- @param[in] Position Ignored.
-
- @retval EFI_UNSUPPORTED
-**/
-EFI_STATUS
-EFIAPI
-FileInterfaceNopSetPosition (
- IN EFI_FILE_PROTOCOL *This,
- IN UINT64 Position
- )
-{
- return (EFI_UNSUPPORTED);
-}
-
-/**
- File style interface for console (GetInfo).
-
- @param[in] This Ignored.
- @param[in] InformationType Ignored.
- @param[in, out] BufferSize Ignored.
- @param[out] Buffer Ignored.
-
- @retval EFI_UNSUPPORTED
-**/
-EFI_STATUS
-EFIAPI
-FileInterfaceNopGetInfo (
- IN EFI_FILE_PROTOCOL *This,
- IN EFI_GUID *InformationType,
- IN OUT UINTN *BufferSize,
- OUT VOID *Buffer
- )
-{
- return (EFI_UNSUPPORTED);
-}
-
-/**
- File style interface for console (SetInfo).
-
- @param[in] This Ignored.
- @param[in] InformationType Ignored.
- @param[in] BufferSize Ignored.
- @param[in] Buffer Ignored.
-
- @retval EFI_UNSUPPORTED
-**/
-EFI_STATUS
-EFIAPI
-FileInterfaceNopSetInfo (
- IN EFI_FILE_PROTOCOL *This,
- IN EFI_GUID *InformationType,
- IN UINTN BufferSize,
- IN VOID *Buffer
- )
-{
- return (EFI_UNSUPPORTED);
-}
-
-/**
- File style interface for StdOut (Write).
-
- Writes data to the screen.
-
- @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
- @param[in, out] BufferSize Size in bytes of Buffer.
- @param[in] Buffer The pointer to the buffer to write.
-
- @retval EFI_UNSUPPORTED No output console is supported.
- @return A return value from gST->ConOut->OutputString.
-**/
-EFI_STATUS
-EFIAPI
-FileInterfaceStdOutWrite (
- IN EFI_FILE_PROTOCOL *This,
- IN OUT UINTN *BufferSize,
- IN VOID *Buffer
- )
-{
- if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut) {
- return (EFI_UNSUPPORTED);
- }
-
- if (*((CHAR16 *)Buffer) == gUnicodeFileTag) {
- return (gST->ConOut->OutputString (gST->ConOut, (CHAR16 *)Buffer + 1));
- }
-
- return (gST->ConOut->OutputString (gST->ConOut, Buffer));
-}
-
-/**
- File style interface for StdIn (Write).
-
- @param[in] This Ignored.
- @param[in, out] BufferSize Ignored.
- @param[in] Buffer Ignored.
-
- @retval EFI_UNSUPPORTED
-**/
-EFI_STATUS
-EFIAPI
-FileInterfaceStdInWrite (
- IN EFI_FILE_PROTOCOL *This,
- IN OUT UINTN *BufferSize,
- IN VOID *Buffer
- )
-{
- return (EFI_UNSUPPORTED);
-}
-
-/**
- File style interface for console StdErr (Write).
-
- Writes error to the error output.
-
- @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
- @param[in, out] BufferSize Size in bytes of Buffer.
- @param[in] Buffer The pointer to the buffer to write.
-
- @return A return value from gST->StdErr->OutputString.
-**/
-EFI_STATUS
-EFIAPI
-FileInterfaceStdErrWrite (
- IN EFI_FILE_PROTOCOL *This,
- IN OUT UINTN *BufferSize,
- IN VOID *Buffer
- )
-{
- return (gST->StdErr->OutputString (gST->StdErr, Buffer));
-}
-
-/**
- File style interface for console StdOut (Read).
-
- @param[in] This Ignored.
- @param[in, out] BufferSize Ignored.
- @param[out] Buffer Ignored.
-
- @retval EFI_UNSUPPORTED
-**/
-EFI_STATUS
-EFIAPI
-FileInterfaceStdOutRead (
- IN EFI_FILE_PROTOCOL *This,
- IN OUT UINTN *BufferSize,
- OUT VOID *Buffer
- )
-{
- return (EFI_UNSUPPORTED);
-}
-
-/**
- File style interface for console StdErr (Read).
-
- @param[in] This Ignored.
- @param[in, out] BufferSize Ignored.
- @param[out] Buffer Ignored.
-
- @retval EFI_UNSUPPORTED Always.
-**/
-EFI_STATUS
-EFIAPI
-FileInterfaceStdErrRead (
- IN EFI_FILE_PROTOCOL *This,
- IN OUT UINTN *BufferSize,
- OUT VOID *Buffer
- )
-{
- return (EFI_UNSUPPORTED);
-}
-
-/**
- File style interface for NUL file (Read).
-
- @param[in] This Ignored.
- @param[in, out] BufferSize Poiner to 0 upon return.
- @param[out] Buffer Ignored.
-
- @retval EFI_SUCCESS Always.
-**/
-EFI_STATUS
-EFIAPI
-FileInterfaceNulRead (
- IN EFI_FILE_PROTOCOL *This,
- IN OUT UINTN *BufferSize,
- OUT VOID *Buffer
- )
-{
- *BufferSize = 0;
- return (EFI_SUCCESS);
-}
-
-/**
- File style interface for NUL file (Write).
-
- @param[in] This Ignored.
- @param[in, out] BufferSize Ignored.
- @param[in] Buffer Ignored.
-
- @retval EFI_SUCCESS
-**/
-EFI_STATUS
-EFIAPI
-FileInterfaceNulWrite (
- IN EFI_FILE_PROTOCOL *This,
- IN OUT UINTN *BufferSize,
- IN VOID *Buffer
- )
-{
- return (EFI_SUCCESS);
-}
-
-/**
- Create the TAB completion list.
-
- @param[in] InputString The command line to expand.
- @param[in] StringLen Length of the command line.
- @param[in] BufferSize Buffer size.
- @param[in, out] TabCompletionList Return the TAB completion list.
- @param[in, out] TabUpdatePos Return the TAB update position.
-**/
-EFI_STATUS
-CreateTabCompletionList (
- IN CONST CHAR16 *InputString,
- IN CONST UINTN StringLen,
- IN CONST UINTN BufferSize,
- IN OUT EFI_SHELL_FILE_INFO **TabCompletionList,
- IN OUT UINTN *TabUpdatePos
- )
-{
- BOOLEAN InQuotation;
- UINTN TabPos;
- UINTN Index;
- CONST CHAR16 *Cwd;
- EFI_STATUS Status;
- CHAR16 *TabStr;
- EFI_SHELL_FILE_INFO *FileList;
- EFI_SHELL_FILE_INFO *FileInfo;
- EFI_SHELL_FILE_INFO *TempFileInfo;
-
- //
- // Allocate buffers
- //
- TabStr = AllocateZeroPool (BufferSize);
- if (TabStr == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // handle auto complete of file and directory names...
- // E.g.: cd fs0:\EFI\Bo<TAB>
- // ^ ^
- // TabPos TabUpdatePos
- //
- TabPos = 0;
- *TabUpdatePos = 0;
- FileList = NULL;
- InQuotation = FALSE;
- for (Index = 0; Index < StringLen; Index++) {
- switch (InputString[Index]) {
- case L'\"':
- InQuotation = (BOOLEAN)(!InQuotation);
- break;
-
- case L' ':
- if (!InQuotation) {
- TabPos = Index + 1;
- *TabUpdatePos = TabPos;
- }
-
- break;
-
- case L':':
- //
- // handle the case "fs0:<TAB>"
- // Update the TabUpdatePos as well.
- //
- case L'\\':
- *TabUpdatePos = Index + 1;
- break;
-
- default:
- break;
- }
- }
-
- if (StrStr (InputString + TabPos, L":") == NULL) {
- //
- // If file path doesn't contain ":", ...
- //
- Cwd = ShellInfoObject.NewEfiShellProtocol->GetCurDir (NULL);
- if (Cwd != NULL) {
- if (InputString[TabPos] != L'\\') {
- //
- // and it doesn't begin with "\\", it's a path relative to current directory.
- // TabStr = "<cwd>\\"
- //
- StrnCpyS (TabStr, BufferSize / sizeof (CHAR16), Cwd, (BufferSize) / sizeof (CHAR16) - 1);
- StrCatS (TabStr, (BufferSize) / sizeof (CHAR16), L"\\");
- } else {
- //
- // and it begins with "\\", it's a path pointing to root directory of current map.
- // TabStr = "fsx:"
- //
- Index = StrStr (Cwd, L":") - Cwd + 1;
- StrnCpyS (TabStr, BufferSize / sizeof (CHAR16), Cwd, Index);
- }
- }
- }
-
- StrnCatS (TabStr, (BufferSize) / sizeof (CHAR16), InputString + TabPos, StringLen - TabPos);
- StrnCatS (TabStr, (BufferSize) / sizeof (CHAR16), L"*", (BufferSize) / sizeof (CHAR16) - 1 - StrLen (TabStr));
- Status = ShellInfoObject.NewEfiShellProtocol->FindFiles (TabStr, &FileList);
-
- //
- // Filter out the non-directory for "CD" command
- // Filter "." and ".." for all
- //
- if (!EFI_ERROR (Status) && (FileList != NULL)) {
- //
- // Skip the spaces in the beginning
- //
- while (*InputString == L' ') {
- InputString++;
- }
-
- for (FileInfo = (EFI_SHELL_FILE_INFO *)GetFirstNode (&FileList->Link); !IsNull (&FileList->Link, &FileInfo->Link); ) {
- if (((StrCmp (FileInfo->FileName, L".") == 0) || (StrCmp (FileInfo->FileName, L"..") == 0)) ||
- ((((InputString[0] == L'c') || (InputString[0] == L'C')) && ((InputString[1] == L'd') || (InputString[1] == L'D'))) &&
- (ShellIsDirectory (FileInfo->FullName) != EFI_SUCCESS)))
- {
- TempFileInfo = FileInfo;
- FileInfo = (EFI_SHELL_FILE_INFO *)RemoveEntryList (&FileInfo->Link);
- InternalFreeShellFileInfoNode (TempFileInfo);
- } else {
- FileInfo = (EFI_SHELL_FILE_INFO *)GetNextNode (&FileList->Link, &FileInfo->Link);
- }
- }
- }
-
- if ((FileList != NULL) && !IsListEmpty (&FileList->Link)) {
- Status = EFI_SUCCESS;
- } else {
- ShellInfoObject.NewEfiShellProtocol->FreeFileList (&FileList);
- Status = EFI_NOT_FOUND;
- }
-
- FreePool (TabStr);
-
- *TabCompletionList = FileList;
- return Status;
-}
-
-/**
- File style interface for console (Read).
-
- This will return a single line of input from the console.
-
- @param This A pointer to the EFI_FILE_PROTOCOL instance that is the
- file handle to read data from. Not used.
- @param BufferSize On input, the size of the Buffer. On output, the amount
- of data returned in Buffer. In both cases, the size is
- measured in bytes.
- @param Buffer The buffer into which the data is read.
-
-
- @retval EFI_SUCCESS The data was read.
- @retval EFI_NO_MEDIA The device has no medium.
- @retval EFI_DEVICE_ERROR The device reported an error.
- @retval EFI_DEVICE_ERROR An attempt was made to read from a deleted file.
- @retval EFI_DEVICE_ERROR On entry, the current file position is beyond the end of the file.
- @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
- @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory
- entry. BufferSize has been updated with the size
- needed to complete the request.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
-**/
-EFI_STATUS
-EFIAPI
-FileInterfaceStdInRead (
- IN EFI_FILE_PROTOCOL *This,
- IN OUT UINTN *BufferSize,
- OUT VOID *Buffer
- )
-{
- CHAR16 *CurrentString;
- BOOLEAN Done;
- UINTN TabUpdatePos; // Start index of the string updated by TAB stroke
- UINTN Column; // Column of current cursor
- UINTN Row; // Row of current cursor
- UINTN StartColumn; // Column at the beginning of the line
- UINTN Update; // Line index for update
- UINTN Delete; // Num of chars to delete from console after update
- UINTN StringLen; // Total length of the line
- UINTN StringCurPos; // Line index corresponding to the cursor
- UINTN MaxStr; // Maximum possible line length
- UINTN TotalColumn; // Num of columns in the console
- UINTN TotalRow; // Num of rows in the console
- UINTN SkipLength;
- UINTN OutputLength; // Length of the update string
- UINTN TailRow; // Row of end of line
- UINTN TailColumn; // Column of end of line
- EFI_INPUT_KEY Key;
-
- BUFFER_LIST *LinePos;
- BUFFER_LIST *NewPos;
- BOOLEAN InScrolling;
- EFI_STATUS Status;
- BOOLEAN InTabScrolling; // Whether in TAB-completion state
- EFI_SHELL_FILE_INFO *TabCompleteList;
- EFI_SHELL_FILE_INFO *TabCurrent;
- UINTN EventIndex;
- CHAR16 *TabOutputStr;
-
- //
- // If buffer is not large enough to hold a CHAR16, return minimum buffer size
- //
- if (*BufferSize < sizeof (CHAR16) * 2) {
- *BufferSize = sizeof (CHAR16) * 2;
- return (EFI_BUFFER_TOO_SMALL);
- }
-
- Done = FALSE;
- CurrentString = Buffer;
- StringLen = 0;
- StringCurPos = 0;
- OutputLength = 0;
- Update = 0;
- Delete = 0;
- LinePos = NewPos = (BUFFER_LIST *)(&ShellInfoObject.ViewingSettings.CommandHistory);
- InScrolling = FALSE;
- InTabScrolling = FALSE;
- Status = EFI_SUCCESS;
- TabOutputStr = NULL;
- TabUpdatePos = 0;
- TabCompleteList = NULL;
- TabCurrent = NULL;
-
- //
- // Get the screen setting and the current cursor location
- //
- Column = StartColumn = gST->ConOut->Mode->CursorColumn;
- Row = gST->ConOut->Mode->CursorRow;
- gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &TotalColumn, &TotalRow);
-
- //
- // Limit the line length to the buffer size or the minimum size of the
- // screen. (The smaller takes effect)
- //
- MaxStr = TotalColumn * (TotalRow - 1) - StartColumn;
- if (MaxStr > *BufferSize / sizeof (CHAR16)) {
- MaxStr = *BufferSize / sizeof (CHAR16);
- }
-
- ZeroMem (CurrentString, MaxStr * sizeof (CHAR16));
- do {
- //
- // Read a key
- //
- gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);
- Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
- if (EFI_ERROR (Status)) {
- if (Status == EFI_NOT_READY) {
- continue;
- }
-
- ZeroMem (CurrentString, MaxStr * sizeof (CHAR16));
- StringLen = 0;
- break;
- }
-
- //
- // Press PageUp or PageDown to scroll the history screen up or down.
- // Press any other key to quit scrolling.
- //
- if ((Key.UnicodeChar == 0) && ((Key.ScanCode == SCAN_PAGE_UP) || (Key.ScanCode == SCAN_PAGE_DOWN))) {
- if (Key.ScanCode == SCAN_PAGE_UP) {
- ConsoleLoggerDisplayHistory (FALSE, 0, ShellInfoObject.ConsoleInfo);
- } else if (Key.ScanCode == SCAN_PAGE_DOWN) {
- ConsoleLoggerDisplayHistory (TRUE, 0, ShellInfoObject.ConsoleInfo);
- }
-
- InScrolling = TRUE;
- } else {
- if (InScrolling) {
- ConsoleLoggerStopHistory (ShellInfoObject.ConsoleInfo);
- InScrolling = FALSE;
- }
- }
-
- //
- // If we are quitting TAB scrolling...
- //
- if (InTabScrolling && (Key.UnicodeChar != CHAR_TAB)) {
- if (TabCompleteList != NULL) {
- ShellInfoObject.NewEfiShellProtocol->FreeFileList (&TabCompleteList);
- DEBUG_CODE (
- TabCompleteList = NULL;
- );
- }
-
- InTabScrolling = FALSE;
- }
-
- switch (Key.UnicodeChar) {
- case CHAR_CARRIAGE_RETURN:
- //
- // All done, print a newline at the end of the string
- //
- TailRow = Row + (StringLen - StringCurPos + Column) / TotalColumn;
- TailColumn = (StringLen - StringCurPos + Column) % TotalColumn;
- ShellPrintEx ((INT32)TailColumn, (INT32)TailRow, L"%N\n");
- Done = TRUE;
- break;
-
- case CHAR_BACKSPACE:
- if (StringCurPos != 0) {
- //
- // If not move back beyond string beginning, move all characters behind
- // the current position one character forward
- //
- StringCurPos--;
- Update = StringCurPos;
- Delete = 1;
- CopyMem (CurrentString + StringCurPos, CurrentString + StringCurPos + 1, sizeof (CHAR16) * (StringLen - StringCurPos));
-
- //
- // Adjust the current column and row
- //
- MoveCursorBackward (TotalColumn, &Column, &Row);
- }
-
- break;
-
- case CHAR_TAB:
- if (!InTabScrolling) {
- TabCurrent = NULL;
- //
- // Initialize a tab complete operation.
- //
- Status = CreateTabCompletionList (CurrentString, StringLen, *BufferSize, &TabCompleteList, &TabUpdatePos);
- if (!EFI_ERROR (Status)) {
- InTabScrolling = TRUE;
- }
-
- //
- // We do not set up the replacement.
- // The next section will do that.
- //
- }
-
- if (InTabScrolling) {
- //
- // We are in a tab complete operation.
- // set up the next replacement.
- //
- ASSERT (TabCompleteList != NULL);
- if (TabCurrent == NULL) {
- TabCurrent = (EFI_SHELL_FILE_INFO *)GetFirstNode (&TabCompleteList->Link);
- } else {
- TabCurrent = (EFI_SHELL_FILE_INFO *)GetNextNode (&TabCompleteList->Link, &TabCurrent->Link);
- }
-
- //
- // Skip over the empty list beginning node
- //
- if (IsNull (&TabCompleteList->Link, &TabCurrent->Link)) {
- TabCurrent = (EFI_SHELL_FILE_INFO *)GetNextNode (&TabCompleteList->Link, &TabCurrent->Link);
- }
- }
-
- break;
-
- default:
- if (Key.UnicodeChar >= ' ') {
- //
- // If we are at the buffer's end, drop the key
- //
- if ((StringLen == MaxStr - 1) && (ShellInfoObject.ViewingSettings.InsertMode || (StringCurPos == StringLen))) {
- break;
- }
-
- //
- // If in insert mode, make space by moving each other character 1
- // space higher in the array
- //
- if (ShellInfoObject.ViewingSettings.InsertMode) {
- CopyMem (CurrentString + StringCurPos + 1, CurrentString + StringCurPos, (StringLen - StringCurPos)*sizeof (CurrentString[0]));
- }
-
- CurrentString[StringCurPos] = Key.UnicodeChar;
- Update = StringCurPos;
-
- StringCurPos += 1;
- OutputLength = 1;
- }
-
- break;
-
- case 0:
- switch (Key.ScanCode) {
- case SCAN_DELETE:
- //
- // Move characters behind current position one character forward
- //
- if (StringLen != 0) {
- Update = StringCurPos;
- Delete = 1;
- CopyMem (CurrentString + StringCurPos, CurrentString + StringCurPos + 1, sizeof (CHAR16) * (StringLen - StringCurPos));
- }
-
- break;
-
- case SCAN_UP:
- //
- // Prepare to print the previous command
- //
- NewPos = (BUFFER_LIST *)GetPreviousNode (&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link);
- if (IsNull (&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link)) {
- NewPos = (BUFFER_LIST *)GetPreviousNode (&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link);
- }
-
- break;
-
- case SCAN_DOWN:
- //
- // Prepare to print the next command
- //
- NewPos = (BUFFER_LIST *)GetNextNode (&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link);
- if (NewPos == (BUFFER_LIST *)(&ShellInfoObject.ViewingSettings.CommandHistory)) {
- NewPos = (BUFFER_LIST *)GetNextNode (&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link);
- }
-
- break;
-
- case SCAN_LEFT:
- //
- // Adjust current cursor position
- //
- if (StringCurPos != 0) {
- --StringCurPos;
- MoveCursorBackward (TotalColumn, &Column, &Row);
- }
-
- break;
-
- case SCAN_RIGHT:
- //
- // Adjust current cursor position
- //
- if (StringCurPos < StringLen) {
- ++StringCurPos;
- MoveCursorForward (TotalColumn, TotalRow, &Column, &Row);
- }
-
- break;
-
- case SCAN_HOME:
- //
- // Move current cursor position to the beginning of the command line
- //
- Row -= (StringCurPos + StartColumn) / TotalColumn;
- Column = StartColumn;
- StringCurPos = 0;
- break;
-
- case SCAN_END:
- //
- // Move current cursor position to the end of the command line
- //
- TailRow = Row + (StringLen - StringCurPos + Column) / TotalColumn;
- TailColumn = (StringLen - StringCurPos + Column) % TotalColumn;
- Row = TailRow;
- Column = TailColumn;
- StringCurPos = StringLen;
- break;
-
- case SCAN_ESC:
- //
- // Prepare to clear the current command line
- //
- CurrentString[0] = 0;
- Update = 0;
- Delete = StringLen;
- Row -= (StringCurPos + StartColumn) / TotalColumn;
- Column = StartColumn;
- OutputLength = 0;
- break;
-
- case SCAN_INSERT:
- //
- // Toggle the SEnvInsertMode flag
- //
- ShellInfoObject.ViewingSettings.InsertMode = (BOOLEAN) !ShellInfoObject.ViewingSettings.InsertMode;
- break;
-
- case SCAN_F7:
- //
- // Print command history
- //
- PrintCommandHistory (TotalColumn, TotalRow, 4);
- *CurrentString = CHAR_NULL;
- Done = TRUE;
- break;
- }
- }
-
- if (Done) {
- break;
- }
-
- //
- // If we are in auto-complete mode, we are preparing to print
- // the next file or directory name
- //
- if (InTabScrolling) {
- TabOutputStr = AllocateZeroPool (*BufferSize);
- if (TabOutputStr == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- }
- }
-
- if (InTabScrolling && (TabOutputStr != NULL)) {
- //
- // Adjust the column and row to the start of TAB-completion string.
- //
- Column = (StartColumn + TabUpdatePos) % TotalColumn;
- Row -= (StartColumn + StringCurPos) / TotalColumn - (StartColumn + TabUpdatePos) / TotalColumn;
- OutputLength = StrLen (TabCurrent->FileName);
- //
- // if the output string contains blank space, quotation marks L'\"'
- // should be added to the output.
- //
- if (StrStr (TabCurrent->FileName, L" ") != NULL) {
- TabOutputStr[0] = L'\"';
- CopyMem (TabOutputStr + 1, TabCurrent->FileName, OutputLength * sizeof (CHAR16));
- TabOutputStr[OutputLength + 1] = L'\"';
- TabOutputStr[OutputLength + 2] = CHAR_NULL;
- } else {
- CopyMem (TabOutputStr, TabCurrent->FileName, OutputLength * sizeof (CHAR16));
- TabOutputStr[OutputLength] = CHAR_NULL;
- }
-
- OutputLength = StrLen (TabOutputStr) < MaxStr - 1 ? StrLen (TabOutputStr) : MaxStr - 1;
- CopyMem (CurrentString + TabUpdatePos, TabOutputStr, OutputLength * sizeof (CHAR16));
- CurrentString[TabUpdatePos + OutputLength] = CHAR_NULL;
- StringCurPos = TabUpdatePos + OutputLength;
- Update = TabUpdatePos;
- if (StringLen > TabUpdatePos + OutputLength) {
- Delete = StringLen - TabUpdatePos - OutputLength;
- }
-
- FreePool (TabOutputStr);
- }
-
- //
- // If we have a new position, we are preparing to print a previous or
- // next command.
- //
- if (NewPos != (BUFFER_LIST *)(&ShellInfoObject.ViewingSettings.CommandHistory)) {
- Column = StartColumn;
- Row -= (StringCurPos + StartColumn) / TotalColumn;
-
- LinePos = NewPos;
- NewPos = (BUFFER_LIST *)(&ShellInfoObject.ViewingSettings.CommandHistory);
-
- OutputLength = StrLen (LinePos->Buffer) < MaxStr - 1 ? StrLen (LinePos->Buffer) : MaxStr - 1;
- CopyMem (CurrentString, LinePos->Buffer, OutputLength * sizeof (CHAR16));
- CurrentString[OutputLength] = CHAR_NULL;
-
- StringCurPos = OutputLength;
-
- //
- // Draw new input string
- //
- Update = 0;
- if (StringLen > OutputLength) {
- //
- // If old string was longer, blank its tail
- //
- Delete = StringLen - OutputLength;
- }
- }
-
- //
- // If we need to update the output do so now
- //
- if (Update != (UINTN)-1) {
- ShellPrintEx ((INT32)Column, (INT32)Row, L"%s%.*s", CurrentString + Update, Delete, L"");
- StringLen = StrLen (CurrentString);
-
- if (Delete != 0) {
- SetMem (CurrentString + StringLen, Delete * sizeof (CHAR16), CHAR_NULL);
- }
-
- if (StringCurPos > StringLen) {
- StringCurPos = StringLen;
- }
-
- Update = (UINTN)-1;
-
- //
- // After using print to reflect newly updates, if we're not using
- // BACKSPACE and DELETE, we need to move the cursor position forward,
- // so adjust row and column here.
- //
- if ((Key.UnicodeChar != CHAR_BACKSPACE) && !((Key.UnicodeChar == 0) && (Key.ScanCode == SCAN_DELETE))) {
- //
- // Calculate row and column of the tail of current string
- //
- TailRow = Row + (StringLen - StringCurPos + Column + OutputLength) / TotalColumn;
- TailColumn = (StringLen - StringCurPos + Column + OutputLength) % TotalColumn;
-
- //
- // If the tail of string reaches screen end, screen rolls up, so if
- // Row does not equal TailRow, Row should be decremented
- //
- // (if we are recalling commands using UPPER and DOWN key, and if the
- // old command is too long to fit the screen, TailColumn must be 79.
- //
- if ((TailColumn == 0) && (TailRow >= TotalRow) && (Row != TailRow)) {
- Row--;
- }
-
- //
- // Calculate the cursor position after current operation. If cursor
- // reaches line end, update both row and column, otherwise, only
- // column will be changed.
- //
- if (Column + OutputLength >= TotalColumn) {
- SkipLength = OutputLength - (TotalColumn - Column);
-
- Row += SkipLength / TotalColumn + 1;
- if (Row > TotalRow - 1) {
- Row = TotalRow - 1;
- }
-
- Column = SkipLength % TotalColumn;
- } else {
- Column += OutputLength;
- }
- }
-
- Delete = 0;
- }
-
- //
- // Set the cursor position for this key
- //
- gST->ConOut->SetCursorPosition (gST->ConOut, Column, Row);
- } while (!Done);
-
- if ((CurrentString != NULL) && (StrLen (CurrentString) > 0)) {
- //
- // add the line to the history buffer
- //
- AddLineToCommandHistory (CurrentString);
- }
-
- //
- // Return the data to the caller
- //
- *BufferSize = StringLen * sizeof (CHAR16);
-
- //
- // if this was used it should be deallocated by now...
- // prevent memory leaks...
- //
- if (TabCompleteList != NULL) {
- ShellInfoObject.NewEfiShellProtocol->FreeFileList (&TabCompleteList);
- }
-
- ASSERT (TabCompleteList == NULL);
-
- return Status;
-}
-
-//
-// FILE style interfaces for StdIn/StdOut/StdErr
-//
-EFI_FILE_PROTOCOL FileInterfaceStdIn = {
- EFI_FILE_REVISION,
- FileInterfaceOpenNotFound,
- FileInterfaceNopGeneric,
- FileInterfaceNopGeneric,
- FileInterfaceStdInRead,
- FileInterfaceStdInWrite,
- FileInterfaceNopGetPosition,
- FileInterfaceNopSetPosition,
- FileInterfaceNopGetInfo,
- FileInterfaceNopSetInfo,
- FileInterfaceNopGeneric
-};
-
-EFI_FILE_PROTOCOL FileInterfaceStdOut = {
- EFI_FILE_REVISION,
- FileInterfaceOpenNotFound,
- FileInterfaceNopGeneric,
- FileInterfaceNopGeneric,
- FileInterfaceStdOutRead,
- FileInterfaceStdOutWrite,
- FileInterfaceNopGetPosition,
- FileInterfaceNopSetPosition,
- FileInterfaceNopGetInfo,
- FileInterfaceNopSetInfo,
- FileInterfaceNopGeneric
-};
-
-EFI_FILE_PROTOCOL FileInterfaceStdErr = {
- EFI_FILE_REVISION,
- FileInterfaceOpenNotFound,
- FileInterfaceNopGeneric,
- FileInterfaceNopGeneric,
- FileInterfaceStdErrRead,
- FileInterfaceStdErrWrite,
- FileInterfaceNopGetPosition,
- FileInterfaceNopSetPosition,
- FileInterfaceNopGetInfo,
- FileInterfaceNopSetInfo,
- FileInterfaceNopGeneric
-};
-
-EFI_FILE_PROTOCOL FileInterfaceNulFile = {
- EFI_FILE_REVISION,
- FileInterfaceOpenNotFound,
- FileInterfaceNopGeneric,
- FileInterfaceNopGeneric,
- FileInterfaceNulRead,
- FileInterfaceNulWrite,
- FileInterfaceNopGetPosition,
- FileInterfaceNopSetPosition,
- FileInterfaceNopGetInfo,
- FileInterfaceNopSetInfo,
- FileInterfaceNopGeneric
-};
-
-//
-// This is identical to EFI_FILE_PROTOCOL except for the additional member
-// for the name.
-//
-
-typedef struct {
- UINT64 Revision;
- EFI_FILE_OPEN Open;
- EFI_FILE_CLOSE Close;
- EFI_FILE_DELETE Delete;
- EFI_FILE_READ Read;
- EFI_FILE_WRITE Write;
- EFI_FILE_GET_POSITION GetPosition;
- EFI_FILE_SET_POSITION SetPosition;
- EFI_FILE_GET_INFO GetInfo;
- EFI_FILE_SET_INFO SetInfo;
- EFI_FILE_FLUSH Flush;
- CHAR16 Name[1];
-} EFI_FILE_PROTOCOL_ENVIRONMENT;
-// ANSI compliance helper to get size of the struct.
-#define SIZE_OF_EFI_FILE_PROTOCOL_ENVIRONMENT EFI_FIELD_OFFSET (EFI_FILE_PROTOCOL_ENVIRONMENT, Name)
-
-/**
- File style interface for Environment Variable (Close).
-
- Frees the memory for this object.
-
- @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
-
- @retval EFI_SUCCESS
-**/
-EFI_STATUS
-EFIAPI
-FileInterfaceEnvClose (
- IN EFI_FILE_PROTOCOL *This
- )
-{
- VOID *NewBuffer;
- UINTN NewSize;
- EFI_STATUS Status;
- BOOLEAN Volatile;
- UINTN TotalSize;
-
- //
- // Most if not all UEFI commands will have an '\r\n' at the end of any output.
- // Since the output was redirected to a variable, it does not make sense to
- // keep this. So, before closing, strip the trailing '\r\n' from the variable
- // if it exists.
- //
- NewBuffer = NULL;
- NewSize = 0;
- TotalSize = 0;
-
- Status = IsVolatileEnv (((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name, &Volatile);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Status = SHELL_GET_ENVIRONMENT_VARIABLE (((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name, &NewSize, NewBuffer);
- if (Status == EFI_BUFFER_TOO_SMALL) {
- TotalSize = NewSize + sizeof (CHAR16);
- NewBuffer = AllocateZeroPool (TotalSize);
- if (NewBuffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- Status = SHELL_GET_ENVIRONMENT_VARIABLE (((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name, &NewSize, NewBuffer);
- }
-
- if (!EFI_ERROR (Status) && (NewBuffer != NULL)) {
- if (TotalSize / sizeof (CHAR16) >= 3) {
- if ((((CHAR16 *)NewBuffer)[TotalSize / sizeof (CHAR16) - 2] == CHAR_LINEFEED) &&
- (((CHAR16 *)NewBuffer)[TotalSize / sizeof (CHAR16) - 3] == CHAR_CARRIAGE_RETURN)
- )
- {
- ((CHAR16 *)NewBuffer)[TotalSize / sizeof (CHAR16) - 3] = CHAR_NULL;
- //
- // If the NewBuffer end with \r\n\0, We will replace '\r' by '\0' and then update TotalSize.
- //
- TotalSize -= sizeof (CHAR16) * 2;
- }
-
- if (Volatile) {
- Status = SHELL_SET_ENVIRONMENT_VARIABLE_V (
- ((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name,
- TotalSize - sizeof (CHAR16),
- NewBuffer
- );
-
- if (!EFI_ERROR (Status)) {
- Status = ShellAddEnvVarToList (
- ((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name,
- NewBuffer,
- TotalSize,
- EFI_VARIABLE_BOOTSERVICE_ACCESS
- );
- }
- } else {
- Status = SHELL_SET_ENVIRONMENT_VARIABLE_NV (
- ((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name,
- TotalSize - sizeof (CHAR16),
- NewBuffer
- );
-
- if (!EFI_ERROR (Status)) {
- Status = ShellAddEnvVarToList (
- ((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name,
- NewBuffer,
- TotalSize,
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS
- );
- }
- }
- }
- }
-
- SHELL_FREE_NON_NULL (NewBuffer);
- FreePool ((EFI_FILE_PROTOCOL_ENVIRONMENT *)This);
- return (Status);
-}
-
-/**
- File style interface for Environment Variable (Delete).
-
- @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
-
- @retval The return value from FileInterfaceEnvClose().
-**/
-EFI_STATUS
-EFIAPI
-FileInterfaceEnvDelete (
- IN EFI_FILE_PROTOCOL *This
- )
-{
- SHELL_DELETE_ENVIRONMENT_VARIABLE (((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name);
- return (FileInterfaceEnvClose (This));
-}
-
-/**
- File style interface for Environment Variable (Read).
-
- @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
- @param[in, out] BufferSize Size in bytes of Buffer.
- @param[out] Buffer The pointer to the buffer to fill.
-
- @retval EFI_SUCCESS The data was read.
-**/
-EFI_STATUS
-EFIAPI
-FileInterfaceEnvRead (
- IN EFI_FILE_PROTOCOL *This,
- IN OUT UINTN *BufferSize,
- OUT VOID *Buffer
- )
-{
- EFI_STATUS Status;
-
- *BufferSize = *BufferSize / sizeof (CHAR16) * sizeof (CHAR16);
- if (*BufferSize != 0) {
- //
- // Make sure the first unicode character is \xFEFF
- //
- *(CHAR16 *)Buffer = gUnicodeFileTag;
- Buffer = (CHAR16 *)Buffer + 1;
- *BufferSize -= sizeof (gUnicodeFileTag);
- }
-
- Status = SHELL_GET_ENVIRONMENT_VARIABLE (
- ((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name,
- BufferSize,
- Buffer
- );
- if (!EFI_ERROR (Status) || (Status == EFI_BUFFER_TOO_SMALL)) {
- //
- // BufferSize is valid and needs update when Status is Success or BufferTooSmall.
- //
- *BufferSize += sizeof (gUnicodeFileTag);
- }
-
- return Status;
-}
-
-/**
- File style interface for Volatile Environment Variable (Write).
- This function also caches the environment variable into gShellEnvVarList.
-
- @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
- @param[in, out] BufferSize Size in bytes of Buffer.
- @param[in] Buffer The pointer to the buffer to write.
-
- @retval EFI_SUCCESS The data was successfully write to variable.
- @retval SHELL_OUT_OF_RESOURCES A memory allocation failed.
-**/
-EFI_STATUS
-EFIAPI
-FileInterfaceEnvVolWrite (
- IN EFI_FILE_PROTOCOL *This,
- IN OUT UINTN *BufferSize,
- IN VOID *Buffer
- )
-{
- VOID *NewBuffer;
- UINTN NewSize;
- EFI_STATUS Status;
- UINTN TotalSize;
-
- NewBuffer = NULL;
- NewSize = 0;
- TotalSize = 0;
-
- Status = SHELL_GET_ENVIRONMENT_VARIABLE (((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name, &NewSize, NewBuffer);
- if (Status == EFI_BUFFER_TOO_SMALL) {
- TotalSize = NewSize + *BufferSize + sizeof (CHAR16);
- } else if (Status == EFI_NOT_FOUND) {
- TotalSize = *BufferSize + sizeof (CHAR16);
- } else {
- return Status;
- }
-
- NewBuffer = AllocateZeroPool (TotalSize);
- if (NewBuffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- if (Status == EFI_BUFFER_TOO_SMALL) {
- Status = SHELL_GET_ENVIRONMENT_VARIABLE (((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name, &NewSize, NewBuffer);
- }
-
- if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
- FreePool (NewBuffer);
- return Status;
- }
-
- CopyMem ((UINT8 *)NewBuffer + NewSize, Buffer, *BufferSize);
- Status = ShellAddEnvVarToList (
- ((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name,
- NewBuffer,
- TotalSize,
- EFI_VARIABLE_BOOTSERVICE_ACCESS
- );
- if (EFI_ERROR (Status)) {
- FreePool (NewBuffer);
- return Status;
- }
-
- Status = SHELL_SET_ENVIRONMENT_VARIABLE_V (
- ((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name,
- TotalSize - sizeof (CHAR16),
- NewBuffer
- );
- if (EFI_ERROR (Status)) {
- ShellRemvoeEnvVarFromList (((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name);
- }
-
- FreePool (NewBuffer);
- return Status;
-}
-
-/**
- File style interface for Non Volatile Environment Variable (Write).
- This function also caches the environment variable into gShellEnvVarList.
-
- @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
- @param[in, out] BufferSize Size in bytes of Buffer.
- @param[in] Buffer The pointer to the buffer to write.
-
- @retval EFI_SUCCESS The data was successfully write to variable.
- @retval SHELL_OUT_OF_RESOURCES A memory allocation failed.
-**/
-EFI_STATUS
-EFIAPI
-FileInterfaceEnvNonVolWrite (
- IN EFI_FILE_PROTOCOL *This,
- IN OUT UINTN *BufferSize,
- IN VOID *Buffer
- )
-{
- VOID *NewBuffer;
- UINTN NewSize;
- EFI_STATUS Status;
- UINTN TotalSize;
-
- NewBuffer = NULL;
- NewSize = 0;
- TotalSize = 0;
-
- Status = SHELL_GET_ENVIRONMENT_VARIABLE (((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name, &NewSize, NewBuffer);
- if (Status == EFI_BUFFER_TOO_SMALL) {
- TotalSize = NewSize + *BufferSize + sizeof (CHAR16);
- } else if (Status == EFI_NOT_FOUND) {
- TotalSize = *BufferSize + sizeof (CHAR16);
- } else {
- return Status;
- }
-
- NewBuffer = AllocateZeroPool (TotalSize);
- if (NewBuffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- if (Status == EFI_BUFFER_TOO_SMALL) {
- Status = SHELL_GET_ENVIRONMENT_VARIABLE (((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name, &NewSize, NewBuffer);
- }
-
- if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
- FreePool (NewBuffer);
- return Status;
- }
-
- CopyMem ((UINT8 *)NewBuffer + NewSize, Buffer, *BufferSize);
- Status = ShellAddEnvVarToList (
- ((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name,
- NewBuffer,
- TotalSize,
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS
- );
- if (EFI_ERROR (Status)) {
- FreePool (NewBuffer);
- return Status;
- }
-
- Status = SHELL_SET_ENVIRONMENT_VARIABLE_NV (
- ((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name,
- TotalSize - sizeof (CHAR16),
- NewBuffer
- );
- if (EFI_ERROR (Status)) {
- ShellRemvoeEnvVarFromList (((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name);
- }
-
- FreePool (NewBuffer);
- return Status;
-}
-
-/**
- Creates a EFI_FILE_PROTOCOL (almost) object for using to access
- environment variables through file operations.
-
- @param EnvName The name of the Environment Variable to be operated on.
-
- @retval NULL Memory could not be allocated.
- @return other a pointer to an EFI_FILE_PROTOCOL structure
-**/
-EFI_FILE_PROTOCOL *
-CreateFileInterfaceEnv (
- IN CONST CHAR16 *EnvName
- )
-{
- EFI_STATUS Status;
- EFI_FILE_PROTOCOL_ENVIRONMENT *EnvFileInterface;
- UINTN EnvNameSize;
- BOOLEAN Volatile;
-
- if (EnvName == NULL) {
- return (NULL);
- }
-
- Status = IsVolatileEnv (EnvName, &Volatile);
- if (EFI_ERROR (Status)) {
- return NULL;
- }
-
- //
- // Get some memory
- //
- EnvNameSize = StrSize (EnvName);
- EnvFileInterface = AllocateZeroPool (sizeof (EFI_FILE_PROTOCOL_ENVIRONMENT)+EnvNameSize);
- if (EnvFileInterface == NULL) {
- return (NULL);
- }
-
- //
- // Assign the generic members
- //
- EnvFileInterface->Revision = EFI_FILE_REVISION;
- EnvFileInterface->Open = FileInterfaceOpenNotFound;
- EnvFileInterface->Close = FileInterfaceEnvClose;
- EnvFileInterface->GetPosition = FileInterfaceNopGetPosition;
- EnvFileInterface->SetPosition = FileInterfaceNopSetPosition;
- EnvFileInterface->GetInfo = FileInterfaceNopGetInfo;
- EnvFileInterface->SetInfo = FileInterfaceNopSetInfo;
- EnvFileInterface->Flush = FileInterfaceNopGeneric;
- EnvFileInterface->Delete = FileInterfaceEnvDelete;
- EnvFileInterface->Read = FileInterfaceEnvRead;
-
- CopyMem (EnvFileInterface->Name, EnvName, EnvNameSize);
-
- //
- // Assign the different members for Volatile and Non-Volatile variables
- //
- if (Volatile) {
- EnvFileInterface->Write = FileInterfaceEnvVolWrite;
- } else {
- EnvFileInterface->Write = FileInterfaceEnvNonVolWrite;
- }
-
- return ((EFI_FILE_PROTOCOL *)EnvFileInterface);
-}
-
-/**
- Move the cursor position one character backward.
-
- @param[in] LineLength Length of a line. Get it by calling QueryMode
- @param[in, out] Column Current column of the cursor position
- @param[in, out] Row Current row of the cursor position
-**/
-VOID
-MoveCursorBackward (
- IN UINTN LineLength,
- IN OUT UINTN *Column,
- IN OUT UINTN *Row
- )
-{
- //
- // If current column is 0, move to the last column of the previous line,
- // otherwise, just decrement column.
- //
- if (*Column == 0) {
- *Column = LineLength - 1;
- if (*Row > 0) {
- (*Row)--;
- }
-
- return;
- }
-
- (*Column)--;
-}
-
-/**
- Move the cursor position one character forward.
-
- @param[in] LineLength Length of a line.
- @param[in] TotalRow Total row of a screen
- @param[in, out] Column Current column of the cursor position
- @param[in, out] Row Current row of the cursor position
-**/
-VOID
-MoveCursorForward (
- IN UINTN LineLength,
- IN UINTN TotalRow,
- IN OUT UINTN *Column,
- IN OUT UINTN *Row
- )
-{
- //
- // Increment Column.
- // If this puts column past the end of the line, move to first column
- // of the next row.
- //
- (*Column)++;
- if (*Column >= LineLength) {
- (*Column) = 0;
- if ((*Row) < TotalRow - 1) {
- (*Row)++;
- }
- }
-}
-
-/**
- Prints out each previously typed command in the command list history log.
-
- When each screen is full it will pause for a key before continuing.
-
- @param[in] TotalCols How many columns are on the screen
- @param[in] TotalRows How many rows are on the screen
- @param[in] StartColumn which column to start at
-**/
-VOID
-PrintCommandHistory (
- IN CONST UINTN TotalCols,
- IN CONST UINTN TotalRows,
- IN CONST UINTN StartColumn
- )
-{
- BUFFER_LIST *Node;
- UINTN Index;
- UINTN LineNumber;
- UINTN LineCount;
-
- ShellPrintEx (-1, -1, L"\n");
- Index = 0;
- LineNumber = 0;
- //
- // go through history list...
- //
- for ( Node = (BUFFER_LIST *)GetFirstNode (&ShellInfoObject.ViewingSettings.CommandHistory.Link)
- ; !IsNull (&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Node->Link)
- ; Node = (BUFFER_LIST *)GetNextNode (&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Node->Link)
- )
- {
- Index++;
- LineCount = ((StrLen (Node->Buffer) + StartColumn + 1) / TotalCols) + 1;
-
- if (LineNumber + LineCount >= TotalRows) {
- ShellPromptForResponseHii (
- ShellPromptResponseTypeEnterContinue,
- STRING_TOKEN (STR_SHELL_ENTER_TO_CONT),
- ShellInfoObject.HiiHandle,
- NULL
- );
- LineNumber = 0;
- }
-
- ShellPrintEx (-1, -1, L"%2d. %s\n", Index, Node->Buffer);
- LineNumber += LineCount;
- }
-}
-
-//
-// This is identical to EFI_FILE_PROTOCOL except for the additional members
-// for the buffer, size, and position.
-//
-
-typedef struct {
- UINT64 Revision;
- EFI_FILE_OPEN Open;
- EFI_FILE_CLOSE Close;
- EFI_FILE_DELETE Delete;
- EFI_FILE_READ Read;
- EFI_FILE_WRITE Write;
- EFI_FILE_GET_POSITION GetPosition;
- EFI_FILE_SET_POSITION SetPosition;
- EFI_FILE_GET_INFO GetInfo;
- EFI_FILE_SET_INFO SetInfo;
- EFI_FILE_FLUSH Flush;
- VOID *Buffer;
- UINT64 Position;
- UINT64 BufferSize;
- BOOLEAN Unicode;
- UINT64 FileSize;
-} EFI_FILE_PROTOCOL_MEM;
-
-/**
- File style interface for Mem (SetPosition).
-
- @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
- @param[out] Position The position to set.
-
- @retval EFI_SUCCESS The position was successfully changed.
- @retval EFI_INVALID_PARAMETER The Position was invalid.
-**/
-EFI_STATUS
-EFIAPI
-FileInterfaceMemSetPosition (
- IN EFI_FILE_PROTOCOL *This,
- OUT UINT64 Position
- )
-{
- if (Position <= ((EFI_FILE_PROTOCOL_MEM *)This)->FileSize) {
- ((EFI_FILE_PROTOCOL_MEM *)This)->Position = Position;
- return (EFI_SUCCESS);
- } else {
- return (EFI_INVALID_PARAMETER);
- }
-}
-
-/**
- File style interface for Mem (GetPosition).
-
- @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
- @param[out] Position The pointer to the position.
-
- @retval EFI_SUCCESS The position was retrieved.
-**/
-EFI_STATUS
-EFIAPI
-FileInterfaceMemGetPosition (
- IN EFI_FILE_PROTOCOL *This,
- OUT UINT64 *Position
- )
-{
- *Position = ((EFI_FILE_PROTOCOL_MEM *)This)->Position;
- return (EFI_SUCCESS);
-}
-
-/**
- File style interface for Mem (GetInfo).
-
- @param This Protocol instance pointer.
- @param InformationType Type of information to return in Buffer.
- @param BufferSize On input size of buffer, on output amount of data in buffer.
- @param Buffer The buffer to return data.
-
- @retval EFI_SUCCESS Data was returned.
- @retval EFI_UNSUPPORT InformationType is not supported.
- @retval EFI_NO_MEDIA The device has no media.
- @retval EFI_DEVICE_ERROR The device reported an error.
- @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
- @retval EFI_WRITE_PROTECTED The device is write protected.
- @retval EFI_ACCESS_DENIED The file was open for read only.
- @retval EFI_BUFFER_TOO_SMALL Buffer was too small; required size returned in BufferSize.
-
-**/
-EFI_STATUS
-EFIAPI
-FileInterfaceMemGetInfo (
- IN EFI_FILE_PROTOCOL *This,
- IN EFI_GUID *InformationType,
- IN OUT UINTN *BufferSize,
- OUT VOID *Buffer
- )
-{
- EFI_FILE_INFO *FileInfo;
-
- if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {
- if (*BufferSize < sizeof (EFI_FILE_INFO)) {
- *BufferSize = sizeof (EFI_FILE_INFO);
- return EFI_BUFFER_TOO_SMALL;
- }
-
- if (Buffer == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- FileInfo = (EFI_FILE_INFO *)Buffer;
- FileInfo->Size = sizeof (*FileInfo);
- ZeroMem (FileInfo, sizeof (*FileInfo));
- FileInfo->FileSize = ((EFI_FILE_PROTOCOL_MEM *)This)->FileSize;
- FileInfo->PhysicalSize = FileInfo->FileSize;
- return EFI_SUCCESS;
- }
-
- return EFI_UNSUPPORTED;
-}
-
-/**
- File style interface for Mem (Write).
-
- @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
- @param[in, out] BufferSize Size in bytes of Buffer.
- @param[in] Buffer The pointer to the buffer to write.
-
- @retval EFI_OUT_OF_RESOURCES The operation failed due to lack of resources.
- @retval EFI_SUCCESS The data was written.
-**/
-EFI_STATUS
-EFIAPI
-FileInterfaceMemWrite (
- IN EFI_FILE_PROTOCOL *This,
- IN OUT UINTN *BufferSize,
- IN VOID *Buffer
- )
-{
- CHAR8 *AsciiBuffer;
- EFI_FILE_PROTOCOL_MEM *MemFile;
-
- MemFile = (EFI_FILE_PROTOCOL_MEM *)This;
- if (MemFile->Unicode) {
- //
- // Unicode
- //
- if ((UINTN)(MemFile->Position + (*BufferSize)) > (UINTN)(MemFile->BufferSize)) {
- MemFile->Buffer = ReallocatePool ((UINTN)(MemFile->BufferSize), (UINTN)(MemFile->BufferSize) + (*BufferSize) + MEM_WRITE_REALLOC_OVERHEAD, MemFile->Buffer);
- if (MemFile->Buffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- MemFile->BufferSize += (*BufferSize) + MEM_WRITE_REALLOC_OVERHEAD;
- }
-
- CopyMem (((UINT8 *)MemFile->Buffer) + MemFile->Position, Buffer, *BufferSize);
- MemFile->Position += (*BufferSize);
- MemFile->FileSize = MemFile->Position;
- return (EFI_SUCCESS);
- } else {
- //
- // Ascii
- //
- AsciiBuffer = AllocateZeroPool (*BufferSize);
- if (AsciiBuffer == NULL) {
- return (EFI_OUT_OF_RESOURCES);
- }
-
- AsciiSPrint (AsciiBuffer, *BufferSize, "%S", Buffer);
- if ((UINTN)(MemFile->Position + AsciiStrSize (AsciiBuffer)) > (UINTN)(MemFile->BufferSize)) {
- MemFile->Buffer = ReallocatePool ((UINTN)(MemFile->BufferSize), (UINTN)(MemFile->BufferSize) + AsciiStrSize (AsciiBuffer) + MEM_WRITE_REALLOC_OVERHEAD, MemFile->Buffer);
- if (MemFile->Buffer == NULL) {
- FreePool (AsciiBuffer);
- return EFI_OUT_OF_RESOURCES;
- }
-
- MemFile->BufferSize += AsciiStrSize (AsciiBuffer) + MEM_WRITE_REALLOC_OVERHEAD;
- }
-
- CopyMem (((UINT8 *)MemFile->Buffer) + MemFile->Position, AsciiBuffer, AsciiStrSize (AsciiBuffer));
- MemFile->Position += (*BufferSize / sizeof (CHAR16));
- MemFile->FileSize = MemFile->Position;
- FreePool (AsciiBuffer);
- return (EFI_SUCCESS);
- }
-}
-
-/**
- File style interface for Mem (Read).
-
- @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
- @param[in, out] BufferSize Size in bytes of Buffer.
- @param[in] Buffer The pointer to the buffer to fill.
-
- @retval EFI_SUCCESS The data was read.
-**/
-EFI_STATUS
-EFIAPI
-FileInterfaceMemRead (
- IN EFI_FILE_PROTOCOL *This,
- IN OUT UINTN *BufferSize,
- IN VOID *Buffer
- )
-{
- EFI_FILE_PROTOCOL_MEM *MemFile;
-
- MemFile = (EFI_FILE_PROTOCOL_MEM *)This;
- if (*BufferSize > (UINTN)((MemFile->FileSize) - (UINTN)(MemFile->Position))) {
- (*BufferSize) = (UINTN)((MemFile->FileSize) - (UINTN)(MemFile->Position));
- }
-
- CopyMem (Buffer, ((UINT8 *)MemFile->Buffer) + MemFile->Position, (*BufferSize));
- MemFile->Position = MemFile->Position + (*BufferSize);
- return (EFI_SUCCESS);
-}
-
-/**
- File style interface for Mem (Close).
-
- Frees all memory associated with this object.
-
- @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
-
- @retval EFI_SUCCESS The 'file' was closed.
-**/
-EFI_STATUS
-EFIAPI
-FileInterfaceMemClose (
- IN EFI_FILE_PROTOCOL *This
- )
-{
- SHELL_FREE_NON_NULL (((EFI_FILE_PROTOCOL_MEM *)This)->Buffer);
- SHELL_FREE_NON_NULL (This);
- return (EFI_SUCCESS);
-}
-
-/**
- Creates a EFI_FILE_PROTOCOL (almost) object for using to access
- a file entirely in memory through file operations.
-
- @param[in] Unicode Boolean value with TRUE for Unicode and FALSE for Ascii.
-
- @retval NULL Memory could not be allocated.
- @return other A pointer to an EFI_FILE_PROTOCOL structure.
-**/
-EFI_FILE_PROTOCOL *
-CreateFileInterfaceMem (
- IN CONST BOOLEAN Unicode
- )
-{
- EFI_FILE_PROTOCOL_MEM *FileInterface;
-
- //
- // Get some memory
- //
- FileInterface = AllocateZeroPool (sizeof (EFI_FILE_PROTOCOL_MEM));
- if (FileInterface == NULL) {
- return (NULL);
- }
-
- //
- // Assign the generic members
- //
- FileInterface->Revision = EFI_FILE_REVISION;
- FileInterface->Open = FileInterfaceOpenNotFound;
- FileInterface->Close = FileInterfaceMemClose;
- FileInterface->GetPosition = FileInterfaceMemGetPosition;
- FileInterface->SetPosition = FileInterfaceMemSetPosition;
- FileInterface->GetInfo = FileInterfaceMemGetInfo;
- FileInterface->SetInfo = FileInterfaceNopSetInfo;
- FileInterface->Flush = FileInterfaceNopGeneric;
- FileInterface->Delete = FileInterfaceNopGeneric;
- FileInterface->Read = FileInterfaceMemRead;
- FileInterface->Write = FileInterfaceMemWrite;
- FileInterface->Unicode = Unicode;
-
- ASSERT (FileInterface->Buffer == NULL);
- ASSERT (FileInterface->BufferSize == 0);
- ASSERT (FileInterface->Position == 0);
-
- if (Unicode) {
- FileInterface->Buffer = AllocateZeroPool (sizeof (gUnicodeFileTag));
- if (FileInterface->Buffer == NULL) {
- FreePool (FileInterface);
- return NULL;
- }
-
- *((CHAR16 *)(FileInterface->Buffer)) = EFI_UNICODE_BYTE_ORDER_MARK;
- FileInterface->BufferSize = 2;
- FileInterface->Position = 2;
- }
-
- return ((EFI_FILE_PROTOCOL *)FileInterface);
-}
-
-typedef struct {
- UINT64 Revision;
- EFI_FILE_OPEN Open;
- EFI_FILE_CLOSE Close;
- EFI_FILE_DELETE Delete;
- EFI_FILE_READ Read;
- EFI_FILE_WRITE Write;
- EFI_FILE_GET_POSITION GetPosition;
- EFI_FILE_SET_POSITION SetPosition;
- EFI_FILE_GET_INFO GetInfo;
- EFI_FILE_SET_INFO SetInfo;
- EFI_FILE_FLUSH Flush;
- BOOLEAN Unicode;
- EFI_FILE_PROTOCOL *Orig;
-} EFI_FILE_PROTOCOL_FILE;
-
-/**
- Set a files current position
-
- @param This Protocol instance pointer.
- @param Position Byte position from the start of the file.
-
- @retval EFI_SUCCESS Data was written.
- @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open.
-
-**/
-EFI_STATUS
-EFIAPI
-FileInterfaceFileSetPosition (
- IN EFI_FILE_PROTOCOL *This,
- IN UINT64 Position
- )
-{
- return ((EFI_FILE_PROTOCOL_FILE *)This)->Orig->SetPosition (((EFI_FILE_PROTOCOL_FILE *)This)->Orig, Position);
-}
-
-/**
- Get a file's current position
-
- @param This Protocol instance pointer.
- @param Position Byte position from the start of the file.
-
- @retval EFI_SUCCESS Data was written.
- @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open..
-
-**/
-EFI_STATUS
-EFIAPI
-FileInterfaceFileGetPosition (
- IN EFI_FILE_PROTOCOL *This,
- OUT UINT64 *Position
- )
-{
- return ((EFI_FILE_PROTOCOL_FILE *)This)->Orig->GetPosition (((EFI_FILE_PROTOCOL_FILE *)This)->Orig, Position);
-}
-
-/**
- Get information about a file.
-
- @param This Protocol instance pointer.
- @param InformationType Type of information to return in Buffer.
- @param BufferSize On input size of buffer, on output amount of data in buffer.
- @param Buffer The buffer to return data.
-
- @retval EFI_SUCCESS Data was returned.
- @retval EFI_UNSUPPORT InformationType is not supported.
- @retval EFI_NO_MEDIA The device has no media.
- @retval EFI_DEVICE_ERROR The device reported an error.
- @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
- @retval EFI_WRITE_PROTECTED The device is write protected.
- @retval EFI_ACCESS_DENIED The file was open for read only.
- @retval EFI_BUFFER_TOO_SMALL Buffer was too small; required size returned in BufferSize.
-
-**/
-EFI_STATUS
-EFIAPI
-FileInterfaceFileGetInfo (
- IN EFI_FILE_PROTOCOL *This,
- IN EFI_GUID *InformationType,
- IN OUT UINTN *BufferSize,
- OUT VOID *Buffer
- )
-{
- return ((EFI_FILE_PROTOCOL_FILE *)This)->Orig->GetInfo (((EFI_FILE_PROTOCOL_FILE *)This)->Orig, InformationType, BufferSize, Buffer);
-}
-
-/**
- Set information about a file
-
- @param This Protocol instance pointer.
- @param InformationType Type of information in Buffer.
- @param BufferSize Size of buffer.
- @param Buffer The data to write.
-
- @retval EFI_SUCCESS Data was returned.
- @retval EFI_UNSUPPORT InformationType is not supported.
- @retval EFI_NO_MEDIA The device has no media.
- @retval EFI_DEVICE_ERROR The device reported an error.
- @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
- @retval EFI_WRITE_PROTECTED The device is write protected.
- @retval EFI_ACCESS_DENIED The file was open for read only.
-
-**/
-EFI_STATUS
-EFIAPI
-FileInterfaceFileSetInfo (
- IN EFI_FILE_PROTOCOL *This,
- IN EFI_GUID *InformationType,
- IN UINTN BufferSize,
- IN VOID *Buffer
- )
-{
- return ((EFI_FILE_PROTOCOL_FILE *)This)->Orig->SetInfo (((EFI_FILE_PROTOCOL_FILE *)This)->Orig, InformationType, BufferSize, Buffer);
-}
-
-/**
- Flush data back for the file handle.
-
- @param This Protocol instance pointer.
-
- @retval EFI_SUCCESS Data was written.
- @retval EFI_UNSUPPORT Writes to Open directory are not supported.
- @retval EFI_NO_MEDIA The device has no media.
- @retval EFI_DEVICE_ERROR The device reported an error.
- @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
- @retval EFI_WRITE_PROTECTED The device is write protected.
- @retval EFI_ACCESS_DENIED The file was open for read only.
- @retval EFI_VOLUME_FULL The volume is full.
-
-**/
-EFI_STATUS
-EFIAPI
-FileInterfaceFileFlush (
- IN EFI_FILE_PROTOCOL *This
- )
-{
- return ((EFI_FILE_PROTOCOL_FILE *)This)->Orig->Flush (((EFI_FILE_PROTOCOL_FILE *)This)->Orig);
-}
-
-/**
- Read data from the file.
-
- @param This Protocol instance pointer.
- @param BufferSize On input size of buffer, on output amount of data in buffer.
- @param Buffer The buffer in which data is read.
-
- @retval EFI_SUCCESS Data was read.
- @retval EFI_NO_MEDIA The device has no media.
- @retval EFI_DEVICE_ERROR The device reported an error.
- @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
- @retval EFI_BUFFER_TO_SMALL BufferSize is too small. BufferSize contains required size.
-
-**/
-EFI_STATUS
-EFIAPI
-FileInterfaceFileRead (
- IN EFI_FILE_PROTOCOL *This,
- IN OUT UINTN *BufferSize,
- OUT VOID *Buffer
- )
-{
- EFI_STATUS Status;
- UINT64 Position;
- CHAR8 *AsciiStrBuffer;
- CHAR16 *UscStrBuffer;
- UINTN Size;
-
- if (((EFI_FILE_PROTOCOL_FILE *)This)->Unicode) {
- //
- // Unicode
- // There might be different file tag for the Unicode file. We cannot unconditionally insert the \xFEFF.
- // So we choose to leave the file content as is.
- //
- return (((EFI_FILE_PROTOCOL_FILE *)This)->Orig->Read (((EFI_FILE_PROTOCOL_FILE *)This)->Orig, BufferSize, Buffer));
- } else {
- //
- // Ascii
- //
- *BufferSize = *BufferSize / sizeof (CHAR16) * sizeof (CHAR16);
- if (*BufferSize == 0) {
- return EFI_SUCCESS;
- }
-
- Status = ((EFI_FILE_PROTOCOL_FILE *)This)->Orig->GetPosition (((EFI_FILE_PROTOCOL_FILE *)This)->Orig, &Position);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- if (Position == 0) {
- //
- // First two bytes in Buffer is for the Unicode file tag.
- //
- *(CHAR16 *)Buffer = gUnicodeFileTag;
- Buffer = (CHAR16 *)Buffer + 1;
- Size = *BufferSize / sizeof (CHAR16) - 1;
- } else {
- Size = *BufferSize / sizeof (CHAR16);
- }
-
- AsciiStrBuffer = AllocateZeroPool (Size + 1);
- if (AsciiStrBuffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- UscStrBuffer = AllocateZeroPool ((Size + 1) * sizeof (CHAR16));
- if (UscStrBuffer == NULL) {
- SHELL_FREE_NON_NULL (AsciiStrBuffer);
- return EFI_OUT_OF_RESOURCES;
- }
-
- Status = ((EFI_FILE_PROTOCOL_FILE *)This)->Orig->Read (((EFI_FILE_PROTOCOL_FILE *)This)->Orig, &Size, AsciiStrBuffer);
- if (!EFI_ERROR (Status)) {
- AsciiStrToUnicodeStrS (AsciiStrBuffer, UscStrBuffer, Size + 1);
- *BufferSize = Size * sizeof (CHAR16);
- CopyMem (Buffer, UscStrBuffer, *BufferSize);
- }
-
- SHELL_FREE_NON_NULL (AsciiStrBuffer);
- SHELL_FREE_NON_NULL (UscStrBuffer);
- return Status;
- }
-}
-
-/**
- Opens a new file relative to the source file's location.
-
- @param[in] This The protocol instance pointer.
- @param[out] NewHandle Returns File Handle for FileName.
- @param[in] FileName Null terminated string. "\", ".", and ".." are supported.
- @param[in] OpenMode Open mode for file.
- @param[in] Attributes Only used for EFI_FILE_MODE_CREATE.
-
- @retval EFI_SUCCESS The device was opened.
- @retval EFI_NOT_FOUND The specified file could not be found on the device.
- @retval EFI_NO_MEDIA The device has no media.
- @retval EFI_MEDIA_CHANGED The media has changed.
- @retval EFI_DEVICE_ERROR The device reported an error.
- @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
- @retval EFI_ACCESS_DENIED The service denied access to the file.
- @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources.
- @retval EFI_VOLUME_FULL The volume is full.
-**/
-EFI_STATUS
-EFIAPI
-FileInterfaceFileOpen (
- IN EFI_FILE_PROTOCOL *This,
- OUT EFI_FILE_PROTOCOL **NewHandle,
- IN CHAR16 *FileName,
- IN UINT64 OpenMode,
- IN UINT64 Attributes
- )
-{
- return ((EFI_FILE_PROTOCOL_FILE *)This)->Orig->Open (((EFI_FILE_PROTOCOL_FILE *)This)->Orig, NewHandle, FileName, OpenMode, Attributes);
-}
-
-/**
- Close and delete the file handle.
-
- @param This Protocol instance pointer.
-
- @retval EFI_SUCCESS The device was opened.
- @retval EFI_WARN_DELETE_FAILURE The handle was closed but the file was not deleted.
-
-**/
-EFI_STATUS
-EFIAPI
-FileInterfaceFileDelete (
- IN EFI_FILE_PROTOCOL *This
- )
-{
- EFI_STATUS Status;
-
- Status = ((EFI_FILE_PROTOCOL_FILE *)This)->Orig->Delete (((EFI_FILE_PROTOCOL_FILE *)This)->Orig);
- FreePool (This);
- return (Status);
-}
-
-/**
- File style interface for File (Close).
-
- @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
-
- @retval EFI_SUCCESS The file was closed.
-**/
-EFI_STATUS
-EFIAPI
-FileInterfaceFileClose (
- IN EFI_FILE_PROTOCOL *This
- )
-{
- EFI_STATUS Status;
-
- Status = ((EFI_FILE_PROTOCOL_FILE *)This)->Orig->Close (((EFI_FILE_PROTOCOL_FILE *)This)->Orig);
- FreePool (This);
- return (Status);
-}
-
-/**
- File style interface for File (Write).
-
- If the file was opened with ASCII mode the data will be processed through
- AsciiSPrint before writing.
-
- @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
- @param[in, out] BufferSize Size in bytes of Buffer.
- @param[in] Buffer The pointer to the buffer to write.
-
- @retval EFI_SUCCESS The data was written.
-**/
-EFI_STATUS
-EFIAPI
-FileInterfaceFileWrite (
- IN EFI_FILE_PROTOCOL *This,
- IN OUT UINTN *BufferSize,
- IN VOID *Buffer
- )
-{
- CHAR8 *AsciiBuffer;
- UINTN Size;
- EFI_STATUS Status;
-
- if (((EFI_FILE_PROTOCOL_FILE *)This)->Unicode) {
- //
- // Unicode
- //
- return (((EFI_FILE_PROTOCOL_FILE *)This)->Orig->Write (((EFI_FILE_PROTOCOL_FILE *)This)->Orig, BufferSize, Buffer));
- } else {
- //
- // Ascii
- //
- AsciiBuffer = AllocateZeroPool (*BufferSize);
- AsciiSPrint (AsciiBuffer, *BufferSize, "%S", Buffer);
- Size = AsciiStrSize (AsciiBuffer) - 1; // (we dont need the null terminator)
- Status = (((EFI_FILE_PROTOCOL_FILE *)This)->Orig->Write (((EFI_FILE_PROTOCOL_FILE *)This)->Orig, &Size, AsciiBuffer));
- FreePool (AsciiBuffer);
- return (Status);
- }
-}
-
-/**
- Create a file interface with unicode information.
-
- This will create a new EFI_FILE_PROTOCOL identical to the Templace
- except that the new one has Unicode and Ascii knowledge.
-
- @param[in] Template A pointer to the EFI_FILE_PROTOCOL object.
- @param[in] Unicode TRUE for UCS-2, FALSE for ASCII.
-
- @return a new EFI_FILE_PROTOCOL object to be used instead of the template.
-**/
-EFI_FILE_PROTOCOL *
-CreateFileInterfaceFile (
- IN CONST EFI_FILE_PROTOCOL *Template,
- IN CONST BOOLEAN Unicode
- )
-{
- EFI_FILE_PROTOCOL_FILE *NewOne;
-
- NewOne = AllocateZeroPool (sizeof (EFI_FILE_PROTOCOL_FILE));
- if (NewOne == NULL) {
- return (NULL);
- }
-
- CopyMem (NewOne, Template, sizeof (EFI_FILE_PROTOCOL_FILE));
- NewOne->Orig = (EFI_FILE_PROTOCOL *)Template;
- NewOne->Unicode = Unicode;
- NewOne->Open = FileInterfaceFileOpen;
- NewOne->Close = FileInterfaceFileClose;
- NewOne->Delete = FileInterfaceFileDelete;
- NewOne->Read = FileInterfaceFileRead;
- NewOne->Write = FileInterfaceFileWrite;
- NewOne->GetPosition = FileInterfaceFileGetPosition;
- NewOne->SetPosition = FileInterfaceFileSetPosition;
- NewOne->GetInfo = FileInterfaceFileGetInfo;
- NewOne->SetInfo = FileInterfaceFileSetInfo;
- NewOne->Flush = FileInterfaceFileFlush;
-
- return ((EFI_FILE_PROTOCOL *)NewOne);
-}
+/** @file + EFI_FILE_PROTOCOL wrappers for other items (Like Environment Variables, + StdIn, StdOut, StdErr, etc...). + + Copyright 2016 Dell Inc. + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR> + (C) Copyright 2013 Hewlett-Packard Development Company, L.P.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "Shell.h" +#include "FileHandleInternal.h" + +#define MEM_WRITE_REALLOC_OVERHEAD 1024 + +/** + File style interface for console (Open). + + @param[in] This Ignored. + @param[out] NewHandle Ignored. + @param[in] FileName Ignored. + @param[in] OpenMode Ignored. + @param[in] Attributes Ignored. + + @retval EFI_NOT_FOUND +**/ +EFI_STATUS +EFIAPI +FileInterfaceOpenNotFound ( + IN EFI_FILE_PROTOCOL *This, + OUT EFI_FILE_PROTOCOL **NewHandle, + IN CHAR16 *FileName, + IN UINT64 OpenMode, + IN UINT64 Attributes + ) +{ + return (EFI_NOT_FOUND); +} + +/** + File style interface for console (Close, Delete, & Flush) + + @param[in] This Ignored. + + @retval EFI_SUCCESS +**/ +EFI_STATUS +EFIAPI +FileInterfaceNopGeneric ( + IN EFI_FILE_PROTOCOL *This + ) +{ + return (EFI_SUCCESS); +} + +/** + File style interface for console (GetPosition). + + @param[in] This Ignored. + @param[out] Position Ignored. + + @retval EFI_UNSUPPORTED +**/ +EFI_STATUS +EFIAPI +FileInterfaceNopGetPosition ( + IN EFI_FILE_PROTOCOL *This, + OUT UINT64 *Position + ) +{ + return (EFI_UNSUPPORTED); +} + +/** + File style interface for console (SetPosition). + + @param[in] This Ignored. + @param[in] Position Ignored. + + @retval EFI_UNSUPPORTED +**/ +EFI_STATUS +EFIAPI +FileInterfaceNopSetPosition ( + IN EFI_FILE_PROTOCOL *This, + IN UINT64 Position + ) +{ + return (EFI_UNSUPPORTED); +} + +/** + File style interface for console (GetInfo). + + @param[in] This Ignored. + @param[in] InformationType Ignored. + @param[in, out] BufferSize Ignored. + @param[out] Buffer Ignored. + + @retval EFI_UNSUPPORTED +**/ +EFI_STATUS +EFIAPI +FileInterfaceNopGetInfo ( + IN EFI_FILE_PROTOCOL *This, + IN EFI_GUID *InformationType, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + return (EFI_UNSUPPORTED); +} + +/** + File style interface for console (SetInfo). + + @param[in] This Ignored. + @param[in] InformationType Ignored. + @param[in] BufferSize Ignored. + @param[in] Buffer Ignored. + + @retval EFI_UNSUPPORTED +**/ +EFI_STATUS +EFIAPI +FileInterfaceNopSetInfo ( + IN EFI_FILE_PROTOCOL *This, + IN EFI_GUID *InformationType, + IN UINTN BufferSize, + IN VOID *Buffer + ) +{ + return (EFI_UNSUPPORTED); +} + +/** + File style interface for StdOut (Write). + + Writes data to the screen. + + @param[in] This The pointer to the EFI_FILE_PROTOCOL object. + @param[in, out] BufferSize Size in bytes of Buffer. + @param[in] Buffer The pointer to the buffer to write. + + @retval EFI_UNSUPPORTED No output console is supported. + @return A return value from gST->ConOut->OutputString. +**/ +EFI_STATUS +EFIAPI +FileInterfaceStdOutWrite ( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +{ + if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut) { + return (EFI_UNSUPPORTED); + } + + if (*((CHAR16 *)Buffer) == gUnicodeFileTag) { + return (gST->ConOut->OutputString (gST->ConOut, (CHAR16 *)Buffer + 1)); + } + + return (gST->ConOut->OutputString (gST->ConOut, Buffer)); +} + +/** + File style interface for StdIn (Write). + + @param[in] This Ignored. + @param[in, out] BufferSize Ignored. + @param[in] Buffer Ignored. + + @retval EFI_UNSUPPORTED +**/ +EFI_STATUS +EFIAPI +FileInterfaceStdInWrite ( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +{ + return (EFI_UNSUPPORTED); +} + +/** + File style interface for console StdErr (Write). + + Writes error to the error output. + + @param[in] This The pointer to the EFI_FILE_PROTOCOL object. + @param[in, out] BufferSize Size in bytes of Buffer. + @param[in] Buffer The pointer to the buffer to write. + + @return A return value from gST->StdErr->OutputString. +**/ +EFI_STATUS +EFIAPI +FileInterfaceStdErrWrite ( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +{ + return (gST->StdErr->OutputString (gST->StdErr, Buffer)); +} + +/** + File style interface for console StdOut (Read). + + @param[in] This Ignored. + @param[in, out] BufferSize Ignored. + @param[out] Buffer Ignored. + + @retval EFI_UNSUPPORTED +**/ +EFI_STATUS +EFIAPI +FileInterfaceStdOutRead ( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + return (EFI_UNSUPPORTED); +} + +/** + File style interface for console StdErr (Read). + + @param[in] This Ignored. + @param[in, out] BufferSize Ignored. + @param[out] Buffer Ignored. + + @retval EFI_UNSUPPORTED Always. +**/ +EFI_STATUS +EFIAPI +FileInterfaceStdErrRead ( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + return (EFI_UNSUPPORTED); +} + +/** + File style interface for NUL file (Read). + + @param[in] This Ignored. + @param[in, out] BufferSize Poiner to 0 upon return. + @param[out] Buffer Ignored. + + @retval EFI_SUCCESS Always. +**/ +EFI_STATUS +EFIAPI +FileInterfaceNulRead ( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + *BufferSize = 0; + return (EFI_SUCCESS); +} + +/** + File style interface for NUL file (Write). + + @param[in] This Ignored. + @param[in, out] BufferSize Ignored. + @param[in] Buffer Ignored. + + @retval EFI_SUCCESS +**/ +EFI_STATUS +EFIAPI +FileInterfaceNulWrite ( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +{ + return (EFI_SUCCESS); +} + +/** + Create the TAB completion list. + + @param[in] InputString The command line to expand. + @param[in] StringLen Length of the command line. + @param[in] BufferSize Buffer size. + @param[in, out] TabCompletionList Return the TAB completion list. + @param[in, out] TabUpdatePos Return the TAB update position. +**/ +EFI_STATUS +CreateTabCompletionList ( + IN CONST CHAR16 *InputString, + IN CONST UINTN StringLen, + IN CONST UINTN BufferSize, + IN OUT EFI_SHELL_FILE_INFO **TabCompletionList, + IN OUT UINTN *TabUpdatePos + ) +{ + BOOLEAN InQuotation; + UINTN TabPos; + UINTN Index; + CONST CHAR16 *Cwd; + EFI_STATUS Status; + CHAR16 *TabStr; + EFI_SHELL_FILE_INFO *FileList; + EFI_SHELL_FILE_INFO *FileInfo; + EFI_SHELL_FILE_INFO *TempFileInfo; + + // + // Allocate buffers + // + TabStr = AllocateZeroPool (BufferSize); + if (TabStr == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // handle auto complete of file and directory names... + // E.g.: cd fs0:\EFI\Bo<TAB> + // ^ ^ + // TabPos TabUpdatePos + // + TabPos = 0; + *TabUpdatePos = 0; + FileList = NULL; + InQuotation = FALSE; + for (Index = 0; Index < StringLen; Index++) { + switch (InputString[Index]) { + case L'\"': + InQuotation = (BOOLEAN)(!InQuotation); + break; + + case L' ': + if (!InQuotation) { + TabPos = Index + 1; + *TabUpdatePos = TabPos; + } + + break; + + case L':': + // + // handle the case "fs0:<TAB>" + // Update the TabUpdatePos as well. + // + case L'\\': + *TabUpdatePos = Index + 1; + break; + + default: + break; + } + } + + if (StrStr (InputString + TabPos, L":") == NULL) { + // + // If file path doesn't contain ":", ... + // + Cwd = ShellInfoObject.NewEfiShellProtocol->GetCurDir (NULL); + if (Cwd != NULL) { + if (InputString[TabPos] != L'\\') { + // + // and it doesn't begin with "\\", it's a path relative to current directory. + // TabStr = "<cwd>\\" + // + StrnCpyS (TabStr, BufferSize / sizeof (CHAR16), Cwd, (BufferSize) / sizeof (CHAR16) - 1); + StrCatS (TabStr, (BufferSize) / sizeof (CHAR16), L"\\"); + } else { + // + // and it begins with "\\", it's a path pointing to root directory of current map. + // TabStr = "fsx:" + // + Index = StrStr (Cwd, L":") - Cwd + 1; + StrnCpyS (TabStr, BufferSize / sizeof (CHAR16), Cwd, Index); + } + } + } + + StrnCatS (TabStr, (BufferSize) / sizeof (CHAR16), InputString + TabPos, StringLen - TabPos); + StrnCatS (TabStr, (BufferSize) / sizeof (CHAR16), L"*", (BufferSize) / sizeof (CHAR16) - 1 - StrLen (TabStr)); + Status = ShellInfoObject.NewEfiShellProtocol->FindFiles (TabStr, &FileList); + + // + // Filter out the non-directory for "CD" command + // Filter "." and ".." for all + // + if (!EFI_ERROR (Status) && (FileList != NULL)) { + // + // Skip the spaces in the beginning + // + while (*InputString == L' ') { + InputString++; + } + + for (FileInfo = (EFI_SHELL_FILE_INFO *)GetFirstNode (&FileList->Link); !IsNull (&FileList->Link, &FileInfo->Link); ) { + if (((StrCmp (FileInfo->FileName, L".") == 0) || (StrCmp (FileInfo->FileName, L"..") == 0)) || + ((((InputString[0] == L'c') || (InputString[0] == L'C')) && ((InputString[1] == L'd') || (InputString[1] == L'D'))) && + (ShellIsDirectory (FileInfo->FullName) != EFI_SUCCESS))) + { + TempFileInfo = FileInfo; + FileInfo = (EFI_SHELL_FILE_INFO *)RemoveEntryList (&FileInfo->Link); + InternalFreeShellFileInfoNode (TempFileInfo); + } else { + FileInfo = (EFI_SHELL_FILE_INFO *)GetNextNode (&FileList->Link, &FileInfo->Link); + } + } + } + + if ((FileList != NULL) && !IsListEmpty (&FileList->Link)) { + Status = EFI_SUCCESS; + } else { + ShellInfoObject.NewEfiShellProtocol->FreeFileList (&FileList); + Status = EFI_NOT_FOUND; + } + + FreePool (TabStr); + + *TabCompletionList = FileList; + return Status; +} + +/** + File style interface for console (Read). + + This will return a single line of input from the console. + + @param This A pointer to the EFI_FILE_PROTOCOL instance that is the + file handle to read data from. Not used. + @param BufferSize On input, the size of the Buffer. On output, the amount + of data returned in Buffer. In both cases, the size is + measured in bytes. + @param Buffer The buffer into which the data is read. + + + @retval EFI_SUCCESS The data was read. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_DEVICE_ERROR An attempt was made to read from a deleted file. + @retval EFI_DEVICE_ERROR On entry, the current file position is beyond the end of the file. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory + entry. BufferSize has been updated with the size + needed to complete the request. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +EFIAPI +FileInterfaceStdInRead ( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + CHAR16 *CurrentString; + BOOLEAN Done; + UINTN TabUpdatePos; // Start index of the string updated by TAB stroke + UINTN Column; // Column of current cursor + UINTN Row; // Row of current cursor + UINTN StartColumn; // Column at the beginning of the line + UINTN Update; // Line index for update + UINTN Delete; // Num of chars to delete from console after update + UINTN StringLen; // Total length of the line + UINTN StringCurPos; // Line index corresponding to the cursor + UINTN MaxStr; // Maximum possible line length + UINTN TotalColumn; // Num of columns in the console + UINTN TotalRow; // Num of rows in the console + UINTN SkipLength; + UINTN OutputLength; // Length of the update string + UINTN TailRow; // Row of end of line + UINTN TailColumn; // Column of end of line + EFI_INPUT_KEY Key; + + BUFFER_LIST *LinePos; + BUFFER_LIST *NewPos; + BOOLEAN InScrolling; + EFI_STATUS Status; + BOOLEAN InTabScrolling; // Whether in TAB-completion state + EFI_SHELL_FILE_INFO *TabCompleteList; + EFI_SHELL_FILE_INFO *TabCurrent; + UINTN EventIndex; + CHAR16 *TabOutputStr; + + // + // If buffer is not large enough to hold a CHAR16, return minimum buffer size + // + if (*BufferSize < sizeof (CHAR16) * 2) { + *BufferSize = sizeof (CHAR16) * 2; + return (EFI_BUFFER_TOO_SMALL); + } + + Done = FALSE; + CurrentString = Buffer; + StringLen = 0; + StringCurPos = 0; + OutputLength = 0; + Update = 0; + Delete = 0; + LinePos = NewPos = (BUFFER_LIST *)(&ShellInfoObject.ViewingSettings.CommandHistory); + InScrolling = FALSE; + InTabScrolling = FALSE; + Status = EFI_SUCCESS; + TabOutputStr = NULL; + TabUpdatePos = 0; + TabCompleteList = NULL; + TabCurrent = NULL; + + // + // Get the screen setting and the current cursor location + // + Column = StartColumn = gST->ConOut->Mode->CursorColumn; + Row = gST->ConOut->Mode->CursorRow; + gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &TotalColumn, &TotalRow); + + // + // Limit the line length to the buffer size or the minimum size of the + // screen. (The smaller takes effect) + // + MaxStr = TotalColumn * (TotalRow - 1) - StartColumn; + if (MaxStr > *BufferSize / sizeof (CHAR16)) { + MaxStr = *BufferSize / sizeof (CHAR16); + } + + ZeroMem (CurrentString, MaxStr * sizeof (CHAR16)); + do { + // + // Read a key + // + gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex); + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + if (EFI_ERROR (Status)) { + if (Status == EFI_NOT_READY) { + continue; + } + + ZeroMem (CurrentString, MaxStr * sizeof (CHAR16)); + StringLen = 0; + break; + } + + // + // Press PageUp or PageDown to scroll the history screen up or down. + // Press any other key to quit scrolling. + // + if ((Key.UnicodeChar == 0) && ((Key.ScanCode == SCAN_PAGE_UP) || (Key.ScanCode == SCAN_PAGE_DOWN))) { + if (Key.ScanCode == SCAN_PAGE_UP) { + ConsoleLoggerDisplayHistory (FALSE, 0, ShellInfoObject.ConsoleInfo); + } else if (Key.ScanCode == SCAN_PAGE_DOWN) { + ConsoleLoggerDisplayHistory (TRUE, 0, ShellInfoObject.ConsoleInfo); + } + + InScrolling = TRUE; + } else { + if (InScrolling) { + ConsoleLoggerStopHistory (ShellInfoObject.ConsoleInfo); + InScrolling = FALSE; + } + } + + // + // If we are quitting TAB scrolling... + // + if (InTabScrolling && (Key.UnicodeChar != CHAR_TAB)) { + if (TabCompleteList != NULL) { + ShellInfoObject.NewEfiShellProtocol->FreeFileList (&TabCompleteList); + DEBUG_CODE ( + TabCompleteList = NULL; + ); + } + + InTabScrolling = FALSE; + } + + switch (Key.UnicodeChar) { + case CHAR_CARRIAGE_RETURN: + // + // All done, print a newline at the end of the string + // + TailRow = Row + (StringLen - StringCurPos + Column) / TotalColumn; + TailColumn = (StringLen - StringCurPos + Column) % TotalColumn; + ShellPrintEx ((INT32)TailColumn, (INT32)TailRow, L"%N\n"); + Done = TRUE; + break; + + case CHAR_BACKSPACE: + if (StringCurPos != 0) { + // + // If not move back beyond string beginning, move all characters behind + // the current position one character forward + // + StringCurPos--; + Update = StringCurPos; + Delete = 1; + CopyMem (CurrentString + StringCurPos, CurrentString + StringCurPos + 1, sizeof (CHAR16) * (StringLen - StringCurPos)); + + // + // Adjust the current column and row + // + MoveCursorBackward (TotalColumn, &Column, &Row); + } + + break; + + case CHAR_TAB: + if (!InTabScrolling) { + TabCurrent = NULL; + // + // Initialize a tab complete operation. + // + Status = CreateTabCompletionList (CurrentString, StringLen, *BufferSize, &TabCompleteList, &TabUpdatePos); + if (!EFI_ERROR (Status)) { + InTabScrolling = TRUE; + } + + // + // We do not set up the replacement. + // The next section will do that. + // + } + + if (InTabScrolling) { + // + // We are in a tab complete operation. + // set up the next replacement. + // + ASSERT (TabCompleteList != NULL); + if (TabCurrent == NULL) { + TabCurrent = (EFI_SHELL_FILE_INFO *)GetFirstNode (&TabCompleteList->Link); + } else { + TabCurrent = (EFI_SHELL_FILE_INFO *)GetNextNode (&TabCompleteList->Link, &TabCurrent->Link); + } + + // + // Skip over the empty list beginning node + // + if (IsNull (&TabCompleteList->Link, &TabCurrent->Link)) { + TabCurrent = (EFI_SHELL_FILE_INFO *)GetNextNode (&TabCompleteList->Link, &TabCurrent->Link); + } + } + + break; + + default: + if (Key.UnicodeChar >= ' ') { + // + // If we are at the buffer's end, drop the key + // + if ((StringLen == MaxStr - 1) && (ShellInfoObject.ViewingSettings.InsertMode || (StringCurPos == StringLen))) { + break; + } + + // + // If in insert mode, make space by moving each other character 1 + // space higher in the array + // + if (ShellInfoObject.ViewingSettings.InsertMode) { + CopyMem (CurrentString + StringCurPos + 1, CurrentString + StringCurPos, (StringLen - StringCurPos)*sizeof (CurrentString[0])); + } + + CurrentString[StringCurPos] = Key.UnicodeChar; + Update = StringCurPos; + + StringCurPos += 1; + OutputLength = 1; + } + + break; + + case 0: + switch (Key.ScanCode) { + case SCAN_DELETE: + // + // Move characters behind current position one character forward + // + if (StringLen != 0) { + Update = StringCurPos; + Delete = 1; + CopyMem (CurrentString + StringCurPos, CurrentString + StringCurPos + 1, sizeof (CHAR16) * (StringLen - StringCurPos)); + } + + break; + + case SCAN_UP: + // + // Prepare to print the previous command + // + NewPos = (BUFFER_LIST *)GetPreviousNode (&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link); + if (IsNull (&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link)) { + NewPos = (BUFFER_LIST *)GetPreviousNode (&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link); + } + + break; + + case SCAN_DOWN: + // + // Prepare to print the next command + // + NewPos = (BUFFER_LIST *)GetNextNode (&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link); + if (NewPos == (BUFFER_LIST *)(&ShellInfoObject.ViewingSettings.CommandHistory)) { + NewPos = (BUFFER_LIST *)GetNextNode (&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link); + } + + break; + + case SCAN_LEFT: + // + // Adjust current cursor position + // + if (StringCurPos != 0) { + --StringCurPos; + MoveCursorBackward (TotalColumn, &Column, &Row); + } + + break; + + case SCAN_RIGHT: + // + // Adjust current cursor position + // + if (StringCurPos < StringLen) { + ++StringCurPos; + MoveCursorForward (TotalColumn, TotalRow, &Column, &Row); + } + + break; + + case SCAN_HOME: + // + // Move current cursor position to the beginning of the command line + // + Row -= (StringCurPos + StartColumn) / TotalColumn; + Column = StartColumn; + StringCurPos = 0; + break; + + case SCAN_END: + // + // Move current cursor position to the end of the command line + // + TailRow = Row + (StringLen - StringCurPos + Column) / TotalColumn; + TailColumn = (StringLen - StringCurPos + Column) % TotalColumn; + Row = TailRow; + Column = TailColumn; + StringCurPos = StringLen; + break; + + case SCAN_ESC: + // + // Prepare to clear the current command line + // + CurrentString[0] = 0; + Update = 0; + Delete = StringLen; + Row -= (StringCurPos + StartColumn) / TotalColumn; + Column = StartColumn; + OutputLength = 0; + break; + + case SCAN_INSERT: + // + // Toggle the SEnvInsertMode flag + // + ShellInfoObject.ViewingSettings.InsertMode = (BOOLEAN) !ShellInfoObject.ViewingSettings.InsertMode; + break; + + case SCAN_F7: + // + // Print command history + // + PrintCommandHistory (TotalColumn, TotalRow, 4); + *CurrentString = CHAR_NULL; + Done = TRUE; + break; + } + } + + if (Done) { + break; + } + + // + // If we are in auto-complete mode, we are preparing to print + // the next file or directory name + // + if (InTabScrolling) { + TabOutputStr = AllocateZeroPool (*BufferSize); + if (TabOutputStr == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } + } + + if (InTabScrolling && (TabOutputStr != NULL)) { + // + // Adjust the column and row to the start of TAB-completion string. + // + Column = (StartColumn + TabUpdatePos) % TotalColumn; + Row -= (StartColumn + StringCurPos) / TotalColumn - (StartColumn + TabUpdatePos) / TotalColumn; + OutputLength = StrLen (TabCurrent->FileName); + // + // if the output string contains blank space, quotation marks L'\"' + // should be added to the output. + // + if (StrStr (TabCurrent->FileName, L" ") != NULL) { + TabOutputStr[0] = L'\"'; + CopyMem (TabOutputStr + 1, TabCurrent->FileName, OutputLength * sizeof (CHAR16)); + TabOutputStr[OutputLength + 1] = L'\"'; + TabOutputStr[OutputLength + 2] = CHAR_NULL; + } else { + CopyMem (TabOutputStr, TabCurrent->FileName, OutputLength * sizeof (CHAR16)); + TabOutputStr[OutputLength] = CHAR_NULL; + } + + OutputLength = StrLen (TabOutputStr) < MaxStr - 1 ? StrLen (TabOutputStr) : MaxStr - 1; + CopyMem (CurrentString + TabUpdatePos, TabOutputStr, OutputLength * sizeof (CHAR16)); + CurrentString[TabUpdatePos + OutputLength] = CHAR_NULL; + StringCurPos = TabUpdatePos + OutputLength; + Update = TabUpdatePos; + if (StringLen > TabUpdatePos + OutputLength) { + Delete = StringLen - TabUpdatePos - OutputLength; + } + + FreePool (TabOutputStr); + } + + // + // If we have a new position, we are preparing to print a previous or + // next command. + // + if (NewPos != (BUFFER_LIST *)(&ShellInfoObject.ViewingSettings.CommandHistory)) { + Column = StartColumn; + Row -= (StringCurPos + StartColumn) / TotalColumn; + + LinePos = NewPos; + NewPos = (BUFFER_LIST *)(&ShellInfoObject.ViewingSettings.CommandHistory); + + OutputLength = StrLen (LinePos->Buffer) < MaxStr - 1 ? StrLen (LinePos->Buffer) : MaxStr - 1; + CopyMem (CurrentString, LinePos->Buffer, OutputLength * sizeof (CHAR16)); + CurrentString[OutputLength] = CHAR_NULL; + + StringCurPos = OutputLength; + + // + // Draw new input string + // + Update = 0; + if (StringLen > OutputLength) { + // + // If old string was longer, blank its tail + // + Delete = StringLen - OutputLength; + } + } + + // + // If we need to update the output do so now + // + if (Update != (UINTN)-1) { + ShellPrintEx ((INT32)Column, (INT32)Row, L"%s%.*s", CurrentString + Update, Delete, L""); + StringLen = StrLen (CurrentString); + + if (Delete != 0) { + SetMem (CurrentString + StringLen, Delete * sizeof (CHAR16), CHAR_NULL); + } + + if (StringCurPos > StringLen) { + StringCurPos = StringLen; + } + + Update = (UINTN)-1; + + // + // After using print to reflect newly updates, if we're not using + // BACKSPACE and DELETE, we need to move the cursor position forward, + // so adjust row and column here. + // + if ((Key.UnicodeChar != CHAR_BACKSPACE) && !((Key.UnicodeChar == 0) && (Key.ScanCode == SCAN_DELETE))) { + // + // Calculate row and column of the tail of current string + // + TailRow = Row + (StringLen - StringCurPos + Column + OutputLength) / TotalColumn; + TailColumn = (StringLen - StringCurPos + Column + OutputLength) % TotalColumn; + + // + // If the tail of string reaches screen end, screen rolls up, so if + // Row does not equal TailRow, Row should be decremented + // + // (if we are recalling commands using UPPER and DOWN key, and if the + // old command is too long to fit the screen, TailColumn must be 79. + // + if ((TailColumn == 0) && (TailRow >= TotalRow) && (Row != TailRow)) { + Row--; + } + + // + // Calculate the cursor position after current operation. If cursor + // reaches line end, update both row and column, otherwise, only + // column will be changed. + // + if (Column + OutputLength >= TotalColumn) { + SkipLength = OutputLength - (TotalColumn - Column); + + Row += SkipLength / TotalColumn + 1; + if (Row > TotalRow - 1) { + Row = TotalRow - 1; + } + + Column = SkipLength % TotalColumn; + } else { + Column += OutputLength; + } + } + + Delete = 0; + } + + // + // Set the cursor position for this key + // + gST->ConOut->SetCursorPosition (gST->ConOut, Column, Row); + } while (!Done); + + if ((CurrentString != NULL) && (StrLen (CurrentString) > 0)) { + // + // add the line to the history buffer + // + AddLineToCommandHistory (CurrentString); + } + + // + // Return the data to the caller + // + *BufferSize = StringLen * sizeof (CHAR16); + + // + // if this was used it should be deallocated by now... + // prevent memory leaks... + // + if (TabCompleteList != NULL) { + ShellInfoObject.NewEfiShellProtocol->FreeFileList (&TabCompleteList); + } + + ASSERT (TabCompleteList == NULL); + + return Status; +} + +// +// FILE style interfaces for StdIn/StdOut/StdErr +// +EFI_FILE_PROTOCOL FileInterfaceStdIn = { + EFI_FILE_REVISION, + FileInterfaceOpenNotFound, + FileInterfaceNopGeneric, + FileInterfaceNopGeneric, + FileInterfaceStdInRead, + FileInterfaceStdInWrite, + FileInterfaceNopGetPosition, + FileInterfaceNopSetPosition, + FileInterfaceNopGetInfo, + FileInterfaceNopSetInfo, + FileInterfaceNopGeneric +}; + +EFI_FILE_PROTOCOL FileInterfaceStdOut = { + EFI_FILE_REVISION, + FileInterfaceOpenNotFound, + FileInterfaceNopGeneric, + FileInterfaceNopGeneric, + FileInterfaceStdOutRead, + FileInterfaceStdOutWrite, + FileInterfaceNopGetPosition, + FileInterfaceNopSetPosition, + FileInterfaceNopGetInfo, + FileInterfaceNopSetInfo, + FileInterfaceNopGeneric +}; + +EFI_FILE_PROTOCOL FileInterfaceStdErr = { + EFI_FILE_REVISION, + FileInterfaceOpenNotFound, + FileInterfaceNopGeneric, + FileInterfaceNopGeneric, + FileInterfaceStdErrRead, + FileInterfaceStdErrWrite, + FileInterfaceNopGetPosition, + FileInterfaceNopSetPosition, + FileInterfaceNopGetInfo, + FileInterfaceNopSetInfo, + FileInterfaceNopGeneric +}; + +EFI_FILE_PROTOCOL FileInterfaceNulFile = { + EFI_FILE_REVISION, + FileInterfaceOpenNotFound, + FileInterfaceNopGeneric, + FileInterfaceNopGeneric, + FileInterfaceNulRead, + FileInterfaceNulWrite, + FileInterfaceNopGetPosition, + FileInterfaceNopSetPosition, + FileInterfaceNopGetInfo, + FileInterfaceNopSetInfo, + FileInterfaceNopGeneric +}; + +// +// This is identical to EFI_FILE_PROTOCOL except for the additional member +// for the name. +// + +typedef struct { + UINT64 Revision; + EFI_FILE_OPEN Open; + EFI_FILE_CLOSE Close; + EFI_FILE_DELETE Delete; + EFI_FILE_READ Read; + EFI_FILE_WRITE Write; + EFI_FILE_GET_POSITION GetPosition; + EFI_FILE_SET_POSITION SetPosition; + EFI_FILE_GET_INFO GetInfo; + EFI_FILE_SET_INFO SetInfo; + EFI_FILE_FLUSH Flush; + CHAR16 Name[1]; +} EFI_FILE_PROTOCOL_ENVIRONMENT; +// ANSI compliance helper to get size of the struct. +#define SIZE_OF_EFI_FILE_PROTOCOL_ENVIRONMENT EFI_FIELD_OFFSET (EFI_FILE_PROTOCOL_ENVIRONMENT, Name) + +/** + File style interface for Environment Variable (Close). + + Frees the memory for this object. + + @param[in] This The pointer to the EFI_FILE_PROTOCOL object. + + @retval EFI_SUCCESS +**/ +EFI_STATUS +EFIAPI +FileInterfaceEnvClose ( + IN EFI_FILE_PROTOCOL *This + ) +{ + VOID *NewBuffer; + UINTN NewSize; + EFI_STATUS Status; + BOOLEAN Volatile; + UINTN TotalSize; + + // + // Most if not all UEFI commands will have an '\r\n' at the end of any output. + // Since the output was redirected to a variable, it does not make sense to + // keep this. So, before closing, strip the trailing '\r\n' from the variable + // if it exists. + // + NewBuffer = NULL; + NewSize = 0; + TotalSize = 0; + + Status = IsVolatileEnv (((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name, &Volatile); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = SHELL_GET_ENVIRONMENT_VARIABLE (((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name, &NewSize, NewBuffer); + if (Status == EFI_BUFFER_TOO_SMALL) { + TotalSize = NewSize + sizeof (CHAR16); + NewBuffer = AllocateZeroPool (TotalSize); + if (NewBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = SHELL_GET_ENVIRONMENT_VARIABLE (((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name, &NewSize, NewBuffer); + } + + if (!EFI_ERROR (Status) && (NewBuffer != NULL)) { + if (TotalSize / sizeof (CHAR16) >= 3) { + if ((((CHAR16 *)NewBuffer)[TotalSize / sizeof (CHAR16) - 2] == CHAR_LINEFEED) && + (((CHAR16 *)NewBuffer)[TotalSize / sizeof (CHAR16) - 3] == CHAR_CARRIAGE_RETURN) + ) + { + ((CHAR16 *)NewBuffer)[TotalSize / sizeof (CHAR16) - 3] = CHAR_NULL; + // + // If the NewBuffer end with \r\n\0, We will replace '\r' by '\0' and then update TotalSize. + // + TotalSize -= sizeof (CHAR16) * 2; + } + + if (Volatile) { + Status = SHELL_SET_ENVIRONMENT_VARIABLE_V ( + ((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name, + TotalSize - sizeof (CHAR16), + NewBuffer + ); + + if (!EFI_ERROR (Status)) { + Status = ShellAddEnvVarToList ( + ((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name, + NewBuffer, + TotalSize, + EFI_VARIABLE_BOOTSERVICE_ACCESS + ); + } + } else { + Status = SHELL_SET_ENVIRONMENT_VARIABLE_NV ( + ((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name, + TotalSize - sizeof (CHAR16), + NewBuffer + ); + + if (!EFI_ERROR (Status)) { + Status = ShellAddEnvVarToList ( + ((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name, + NewBuffer, + TotalSize, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS + ); + } + } + } + } + + SHELL_FREE_NON_NULL (NewBuffer); + FreePool ((EFI_FILE_PROTOCOL_ENVIRONMENT *)This); + return (Status); +} + +/** + File style interface for Environment Variable (Delete). + + @param[in] This The pointer to the EFI_FILE_PROTOCOL object. + + @retval The return value from FileInterfaceEnvClose(). +**/ +EFI_STATUS +EFIAPI +FileInterfaceEnvDelete ( + IN EFI_FILE_PROTOCOL *This + ) +{ + SHELL_DELETE_ENVIRONMENT_VARIABLE (((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name); + return (FileInterfaceEnvClose (This)); +} + +/** + File style interface for Environment Variable (Read). + + @param[in] This The pointer to the EFI_FILE_PROTOCOL object. + @param[in, out] BufferSize Size in bytes of Buffer. + @param[out] Buffer The pointer to the buffer to fill. + + @retval EFI_SUCCESS The data was read. +**/ +EFI_STATUS +EFIAPI +FileInterfaceEnvRead ( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + + *BufferSize = *BufferSize / sizeof (CHAR16) * sizeof (CHAR16); + if (*BufferSize != 0) { + // + // Make sure the first unicode character is \xFEFF + // + *(CHAR16 *)Buffer = gUnicodeFileTag; + Buffer = (CHAR16 *)Buffer + 1; + *BufferSize -= sizeof (gUnicodeFileTag); + } + + Status = SHELL_GET_ENVIRONMENT_VARIABLE ( + ((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name, + BufferSize, + Buffer + ); + if (!EFI_ERROR (Status) || (Status == EFI_BUFFER_TOO_SMALL)) { + // + // BufferSize is valid and needs update when Status is Success or BufferTooSmall. + // + *BufferSize += sizeof (gUnicodeFileTag); + } + + return Status; +} + +/** + File style interface for Volatile Environment Variable (Write). + This function also caches the environment variable into gShellEnvVarList. + + @param[in] This The pointer to the EFI_FILE_PROTOCOL object. + @param[in, out] BufferSize Size in bytes of Buffer. + @param[in] Buffer The pointer to the buffer to write. + + @retval EFI_SUCCESS The data was successfully write to variable. + @retval SHELL_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +EFIAPI +FileInterfaceEnvVolWrite ( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +{ + VOID *NewBuffer; + UINTN NewSize; + EFI_STATUS Status; + UINTN TotalSize; + + NewBuffer = NULL; + NewSize = 0; + TotalSize = 0; + + Status = SHELL_GET_ENVIRONMENT_VARIABLE (((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name, &NewSize, NewBuffer); + if (Status == EFI_BUFFER_TOO_SMALL) { + TotalSize = NewSize + *BufferSize + sizeof (CHAR16); + } else if (Status == EFI_NOT_FOUND) { + TotalSize = *BufferSize + sizeof (CHAR16); + } else { + return Status; + } + + NewBuffer = AllocateZeroPool (TotalSize); + if (NewBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + if (Status == EFI_BUFFER_TOO_SMALL) { + Status = SHELL_GET_ENVIRONMENT_VARIABLE (((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name, &NewSize, NewBuffer); + } + + if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { + FreePool (NewBuffer); + return Status; + } + + CopyMem ((UINT8 *)NewBuffer + NewSize, Buffer, *BufferSize); + Status = ShellAddEnvVarToList ( + ((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name, + NewBuffer, + TotalSize, + EFI_VARIABLE_BOOTSERVICE_ACCESS + ); + if (EFI_ERROR (Status)) { + FreePool (NewBuffer); + return Status; + } + + Status = SHELL_SET_ENVIRONMENT_VARIABLE_V ( + ((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name, + TotalSize - sizeof (CHAR16), + NewBuffer + ); + if (EFI_ERROR (Status)) { + ShellRemvoeEnvVarFromList (((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name); + } + + FreePool (NewBuffer); + return Status; +} + +/** + File style interface for Non Volatile Environment Variable (Write). + This function also caches the environment variable into gShellEnvVarList. + + @param[in] This The pointer to the EFI_FILE_PROTOCOL object. + @param[in, out] BufferSize Size in bytes of Buffer. + @param[in] Buffer The pointer to the buffer to write. + + @retval EFI_SUCCESS The data was successfully write to variable. + @retval SHELL_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +EFIAPI +FileInterfaceEnvNonVolWrite ( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +{ + VOID *NewBuffer; + UINTN NewSize; + EFI_STATUS Status; + UINTN TotalSize; + + NewBuffer = NULL; + NewSize = 0; + TotalSize = 0; + + Status = SHELL_GET_ENVIRONMENT_VARIABLE (((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name, &NewSize, NewBuffer); + if (Status == EFI_BUFFER_TOO_SMALL) { + TotalSize = NewSize + *BufferSize + sizeof (CHAR16); + } else if (Status == EFI_NOT_FOUND) { + TotalSize = *BufferSize + sizeof (CHAR16); + } else { + return Status; + } + + NewBuffer = AllocateZeroPool (TotalSize); + if (NewBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + if (Status == EFI_BUFFER_TOO_SMALL) { + Status = SHELL_GET_ENVIRONMENT_VARIABLE (((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name, &NewSize, NewBuffer); + } + + if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { + FreePool (NewBuffer); + return Status; + } + + CopyMem ((UINT8 *)NewBuffer + NewSize, Buffer, *BufferSize); + Status = ShellAddEnvVarToList ( + ((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name, + NewBuffer, + TotalSize, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS + ); + if (EFI_ERROR (Status)) { + FreePool (NewBuffer); + return Status; + } + + Status = SHELL_SET_ENVIRONMENT_VARIABLE_NV ( + ((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name, + TotalSize - sizeof (CHAR16), + NewBuffer + ); + if (EFI_ERROR (Status)) { + ShellRemvoeEnvVarFromList (((EFI_FILE_PROTOCOL_ENVIRONMENT *)This)->Name); + } + + FreePool (NewBuffer); + return Status; +} + +/** + Creates a EFI_FILE_PROTOCOL (almost) object for using to access + environment variables through file operations. + + @param EnvName The name of the Environment Variable to be operated on. + + @retval NULL Memory could not be allocated. + @return other a pointer to an EFI_FILE_PROTOCOL structure +**/ +EFI_FILE_PROTOCOL * +CreateFileInterfaceEnv ( + IN CONST CHAR16 *EnvName + ) +{ + EFI_STATUS Status; + EFI_FILE_PROTOCOL_ENVIRONMENT *EnvFileInterface; + UINTN EnvNameSize; + BOOLEAN Volatile; + + if (EnvName == NULL) { + return (NULL); + } + + Status = IsVolatileEnv (EnvName, &Volatile); + if (EFI_ERROR (Status)) { + return NULL; + } + + // + // Get some memory + // + EnvNameSize = StrSize (EnvName); + EnvFileInterface = AllocateZeroPool (sizeof (EFI_FILE_PROTOCOL_ENVIRONMENT)+EnvNameSize); + if (EnvFileInterface == NULL) { + return (NULL); + } + + // + // Assign the generic members + // + EnvFileInterface->Revision = EFI_FILE_REVISION; + EnvFileInterface->Open = FileInterfaceOpenNotFound; + EnvFileInterface->Close = FileInterfaceEnvClose; + EnvFileInterface->GetPosition = FileInterfaceNopGetPosition; + EnvFileInterface->SetPosition = FileInterfaceNopSetPosition; + EnvFileInterface->GetInfo = FileInterfaceNopGetInfo; + EnvFileInterface->SetInfo = FileInterfaceNopSetInfo; + EnvFileInterface->Flush = FileInterfaceNopGeneric; + EnvFileInterface->Delete = FileInterfaceEnvDelete; + EnvFileInterface->Read = FileInterfaceEnvRead; + + CopyMem (EnvFileInterface->Name, EnvName, EnvNameSize); + + // + // Assign the different members for Volatile and Non-Volatile variables + // + if (Volatile) { + EnvFileInterface->Write = FileInterfaceEnvVolWrite; + } else { + EnvFileInterface->Write = FileInterfaceEnvNonVolWrite; + } + + return ((EFI_FILE_PROTOCOL *)EnvFileInterface); +} + +/** + Move the cursor position one character backward. + + @param[in] LineLength Length of a line. Get it by calling QueryMode + @param[in, out] Column Current column of the cursor position + @param[in, out] Row Current row of the cursor position +**/ +VOID +MoveCursorBackward ( + IN UINTN LineLength, + IN OUT UINTN *Column, + IN OUT UINTN *Row + ) +{ + // + // If current column is 0, move to the last column of the previous line, + // otherwise, just decrement column. + // + if (*Column == 0) { + *Column = LineLength - 1; + if (*Row > 0) { + (*Row)--; + } + + return; + } + + (*Column)--; +} + +/** + Move the cursor position one character forward. + + @param[in] LineLength Length of a line. + @param[in] TotalRow Total row of a screen + @param[in, out] Column Current column of the cursor position + @param[in, out] Row Current row of the cursor position +**/ +VOID +MoveCursorForward ( + IN UINTN LineLength, + IN UINTN TotalRow, + IN OUT UINTN *Column, + IN OUT UINTN *Row + ) +{ + // + // Increment Column. + // If this puts column past the end of the line, move to first column + // of the next row. + // + (*Column)++; + if (*Column >= LineLength) { + (*Column) = 0; + if ((*Row) < TotalRow - 1) { + (*Row)++; + } + } +} + +/** + Prints out each previously typed command in the command list history log. + + When each screen is full it will pause for a key before continuing. + + @param[in] TotalCols How many columns are on the screen + @param[in] TotalRows How many rows are on the screen + @param[in] StartColumn which column to start at +**/ +VOID +PrintCommandHistory ( + IN CONST UINTN TotalCols, + IN CONST UINTN TotalRows, + IN CONST UINTN StartColumn + ) +{ + BUFFER_LIST *Node; + UINTN Index; + UINTN LineNumber; + UINTN LineCount; + + ShellPrintEx (-1, -1, L"\n"); + Index = 0; + LineNumber = 0; + // + // go through history list... + // + for ( Node = (BUFFER_LIST *)GetFirstNode (&ShellInfoObject.ViewingSettings.CommandHistory.Link) + ; !IsNull (&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Node->Link) + ; Node = (BUFFER_LIST *)GetNextNode (&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Node->Link) + ) + { + Index++; + LineCount = ((StrLen (Node->Buffer) + StartColumn + 1) / TotalCols) + 1; + + if (LineNumber + LineCount >= TotalRows) { + ShellPromptForResponseHii ( + ShellPromptResponseTypeEnterContinue, + STRING_TOKEN (STR_SHELL_ENTER_TO_CONT), + ShellInfoObject.HiiHandle, + NULL + ); + LineNumber = 0; + } + + ShellPrintEx (-1, -1, L"%2d. %s\n", Index, Node->Buffer); + LineNumber += LineCount; + } +} + +// +// This is identical to EFI_FILE_PROTOCOL except for the additional members +// for the buffer, size, and position. +// + +typedef struct { + UINT64 Revision; + EFI_FILE_OPEN Open; + EFI_FILE_CLOSE Close; + EFI_FILE_DELETE Delete; + EFI_FILE_READ Read; + EFI_FILE_WRITE Write; + EFI_FILE_GET_POSITION GetPosition; + EFI_FILE_SET_POSITION SetPosition; + EFI_FILE_GET_INFO GetInfo; + EFI_FILE_SET_INFO SetInfo; + EFI_FILE_FLUSH Flush; + VOID *Buffer; + UINT64 Position; + UINT64 BufferSize; + BOOLEAN Unicode; + UINT64 FileSize; +} EFI_FILE_PROTOCOL_MEM; + +/** + File style interface for Mem (SetPosition). + + @param[in] This The pointer to the EFI_FILE_PROTOCOL object. + @param[out] Position The position to set. + + @retval EFI_SUCCESS The position was successfully changed. + @retval EFI_INVALID_PARAMETER The Position was invalid. +**/ +EFI_STATUS +EFIAPI +FileInterfaceMemSetPosition ( + IN EFI_FILE_PROTOCOL *This, + OUT UINT64 Position + ) +{ + if (Position <= ((EFI_FILE_PROTOCOL_MEM *)This)->FileSize) { + ((EFI_FILE_PROTOCOL_MEM *)This)->Position = Position; + return (EFI_SUCCESS); + } else { + return (EFI_INVALID_PARAMETER); + } +} + +/** + File style interface for Mem (GetPosition). + + @param[in] This The pointer to the EFI_FILE_PROTOCOL object. + @param[out] Position The pointer to the position. + + @retval EFI_SUCCESS The position was retrieved. +**/ +EFI_STATUS +EFIAPI +FileInterfaceMemGetPosition ( + IN EFI_FILE_PROTOCOL *This, + OUT UINT64 *Position + ) +{ + *Position = ((EFI_FILE_PROTOCOL_MEM *)This)->Position; + return (EFI_SUCCESS); +} + +/** + File style interface for Mem (GetInfo). + + @param This Protocol instance pointer. + @param InformationType Type of information to return in Buffer. + @param BufferSize On input size of buffer, on output amount of data in buffer. + @param Buffer The buffer to return data. + + @retval EFI_SUCCESS Data was returned. + @retval EFI_UNSUPPORT InformationType is not supported. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED The device is write protected. + @retval EFI_ACCESS_DENIED The file was open for read only. + @retval EFI_BUFFER_TOO_SMALL Buffer was too small; required size returned in BufferSize. + +**/ +EFI_STATUS +EFIAPI +FileInterfaceMemGetInfo ( + IN EFI_FILE_PROTOCOL *This, + IN EFI_GUID *InformationType, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + EFI_FILE_INFO *FileInfo; + + if (CompareGuid (InformationType, &gEfiFileInfoGuid)) { + if (*BufferSize < sizeof (EFI_FILE_INFO)) { + *BufferSize = sizeof (EFI_FILE_INFO); + return EFI_BUFFER_TOO_SMALL; + } + + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + FileInfo = (EFI_FILE_INFO *)Buffer; + FileInfo->Size = sizeof (*FileInfo); + ZeroMem (FileInfo, sizeof (*FileInfo)); + FileInfo->FileSize = ((EFI_FILE_PROTOCOL_MEM *)This)->FileSize; + FileInfo->PhysicalSize = FileInfo->FileSize; + return EFI_SUCCESS; + } + + return EFI_UNSUPPORTED; +} + +/** + File style interface for Mem (Write). + + @param[in] This The pointer to the EFI_FILE_PROTOCOL object. + @param[in, out] BufferSize Size in bytes of Buffer. + @param[in] Buffer The pointer to the buffer to write. + + @retval EFI_OUT_OF_RESOURCES The operation failed due to lack of resources. + @retval EFI_SUCCESS The data was written. +**/ +EFI_STATUS +EFIAPI +FileInterfaceMemWrite ( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +{ + CHAR8 *AsciiBuffer; + EFI_FILE_PROTOCOL_MEM *MemFile; + + MemFile = (EFI_FILE_PROTOCOL_MEM *)This; + if (MemFile->Unicode) { + // + // Unicode + // + if ((UINTN)(MemFile->Position + (*BufferSize)) > (UINTN)(MemFile->BufferSize)) { + MemFile->Buffer = ReallocatePool ((UINTN)(MemFile->BufferSize), (UINTN)(MemFile->BufferSize) + (*BufferSize) + MEM_WRITE_REALLOC_OVERHEAD, MemFile->Buffer); + if (MemFile->Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + MemFile->BufferSize += (*BufferSize) + MEM_WRITE_REALLOC_OVERHEAD; + } + + CopyMem (((UINT8 *)MemFile->Buffer) + MemFile->Position, Buffer, *BufferSize); + MemFile->Position += (*BufferSize); + MemFile->FileSize = MemFile->Position; + return (EFI_SUCCESS); + } else { + // + // Ascii + // + AsciiBuffer = AllocateZeroPool (*BufferSize); + if (AsciiBuffer == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + + AsciiSPrint (AsciiBuffer, *BufferSize, "%S", Buffer); + if ((UINTN)(MemFile->Position + AsciiStrSize (AsciiBuffer)) > (UINTN)(MemFile->BufferSize)) { + MemFile->Buffer = ReallocatePool ((UINTN)(MemFile->BufferSize), (UINTN)(MemFile->BufferSize) + AsciiStrSize (AsciiBuffer) + MEM_WRITE_REALLOC_OVERHEAD, MemFile->Buffer); + if (MemFile->Buffer == NULL) { + FreePool (AsciiBuffer); + return EFI_OUT_OF_RESOURCES; + } + + MemFile->BufferSize += AsciiStrSize (AsciiBuffer) + MEM_WRITE_REALLOC_OVERHEAD; + } + + CopyMem (((UINT8 *)MemFile->Buffer) + MemFile->Position, AsciiBuffer, AsciiStrSize (AsciiBuffer)); + MemFile->Position += (*BufferSize / sizeof (CHAR16)); + MemFile->FileSize = MemFile->Position; + FreePool (AsciiBuffer); + return (EFI_SUCCESS); + } +} + +/** + File style interface for Mem (Read). + + @param[in] This The pointer to the EFI_FILE_PROTOCOL object. + @param[in, out] BufferSize Size in bytes of Buffer. + @param[in] Buffer The pointer to the buffer to fill. + + @retval EFI_SUCCESS The data was read. +**/ +EFI_STATUS +EFIAPI +FileInterfaceMemRead ( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +{ + EFI_FILE_PROTOCOL_MEM *MemFile; + + MemFile = (EFI_FILE_PROTOCOL_MEM *)This; + if (*BufferSize > (UINTN)((MemFile->FileSize) - (UINTN)(MemFile->Position))) { + (*BufferSize) = (UINTN)((MemFile->FileSize) - (UINTN)(MemFile->Position)); + } + + CopyMem (Buffer, ((UINT8 *)MemFile->Buffer) + MemFile->Position, (*BufferSize)); + MemFile->Position = MemFile->Position + (*BufferSize); + return (EFI_SUCCESS); +} + +/** + File style interface for Mem (Close). + + Frees all memory associated with this object. + + @param[in] This The pointer to the EFI_FILE_PROTOCOL object. + + @retval EFI_SUCCESS The 'file' was closed. +**/ +EFI_STATUS +EFIAPI +FileInterfaceMemClose ( + IN EFI_FILE_PROTOCOL *This + ) +{ + SHELL_FREE_NON_NULL (((EFI_FILE_PROTOCOL_MEM *)This)->Buffer); + SHELL_FREE_NON_NULL (This); + return (EFI_SUCCESS); +} + +/** + Creates a EFI_FILE_PROTOCOL (almost) object for using to access + a file entirely in memory through file operations. + + @param[in] Unicode Boolean value with TRUE for Unicode and FALSE for Ascii. + + @retval NULL Memory could not be allocated. + @return other A pointer to an EFI_FILE_PROTOCOL structure. +**/ +EFI_FILE_PROTOCOL * +CreateFileInterfaceMem ( + IN CONST BOOLEAN Unicode + ) +{ + EFI_FILE_PROTOCOL_MEM *FileInterface; + + // + // Get some memory + // + FileInterface = AllocateZeroPool (sizeof (EFI_FILE_PROTOCOL_MEM)); + if (FileInterface == NULL) { + return (NULL); + } + + // + // Assign the generic members + // + FileInterface->Revision = EFI_FILE_REVISION; + FileInterface->Open = FileInterfaceOpenNotFound; + FileInterface->Close = FileInterfaceMemClose; + FileInterface->GetPosition = FileInterfaceMemGetPosition; + FileInterface->SetPosition = FileInterfaceMemSetPosition; + FileInterface->GetInfo = FileInterfaceMemGetInfo; + FileInterface->SetInfo = FileInterfaceNopSetInfo; + FileInterface->Flush = FileInterfaceNopGeneric; + FileInterface->Delete = FileInterfaceNopGeneric; + FileInterface->Read = FileInterfaceMemRead; + FileInterface->Write = FileInterfaceMemWrite; + FileInterface->Unicode = Unicode; + + ASSERT (FileInterface->Buffer == NULL); + ASSERT (FileInterface->BufferSize == 0); + ASSERT (FileInterface->Position == 0); + + if (Unicode) { + FileInterface->Buffer = AllocateZeroPool (sizeof (gUnicodeFileTag)); + if (FileInterface->Buffer == NULL) { + FreePool (FileInterface); + return NULL; + } + + *((CHAR16 *)(FileInterface->Buffer)) = EFI_UNICODE_BYTE_ORDER_MARK; + FileInterface->BufferSize = 2; + FileInterface->Position = 2; + } + + return ((EFI_FILE_PROTOCOL *)FileInterface); +} + +typedef struct { + UINT64 Revision; + EFI_FILE_OPEN Open; + EFI_FILE_CLOSE Close; + EFI_FILE_DELETE Delete; + EFI_FILE_READ Read; + EFI_FILE_WRITE Write; + EFI_FILE_GET_POSITION GetPosition; + EFI_FILE_SET_POSITION SetPosition; + EFI_FILE_GET_INFO GetInfo; + EFI_FILE_SET_INFO SetInfo; + EFI_FILE_FLUSH Flush; + BOOLEAN Unicode; + EFI_FILE_PROTOCOL *Orig; +} EFI_FILE_PROTOCOL_FILE; + +/** + Set a files current position + + @param This Protocol instance pointer. + @param Position Byte position from the start of the file. + + @retval EFI_SUCCESS Data was written. + @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open. + +**/ +EFI_STATUS +EFIAPI +FileInterfaceFileSetPosition ( + IN EFI_FILE_PROTOCOL *This, + IN UINT64 Position + ) +{ + return ((EFI_FILE_PROTOCOL_FILE *)This)->Orig->SetPosition (((EFI_FILE_PROTOCOL_FILE *)This)->Orig, Position); +} + +/** + Get a file's current position + + @param This Protocol instance pointer. + @param Position Byte position from the start of the file. + + @retval EFI_SUCCESS Data was written. + @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open.. + +**/ +EFI_STATUS +EFIAPI +FileInterfaceFileGetPosition ( + IN EFI_FILE_PROTOCOL *This, + OUT UINT64 *Position + ) +{ + return ((EFI_FILE_PROTOCOL_FILE *)This)->Orig->GetPosition (((EFI_FILE_PROTOCOL_FILE *)This)->Orig, Position); +} + +/** + Get information about a file. + + @param This Protocol instance pointer. + @param InformationType Type of information to return in Buffer. + @param BufferSize On input size of buffer, on output amount of data in buffer. + @param Buffer The buffer to return data. + + @retval EFI_SUCCESS Data was returned. + @retval EFI_UNSUPPORT InformationType is not supported. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED The device is write protected. + @retval EFI_ACCESS_DENIED The file was open for read only. + @retval EFI_BUFFER_TOO_SMALL Buffer was too small; required size returned in BufferSize. + +**/ +EFI_STATUS +EFIAPI +FileInterfaceFileGetInfo ( + IN EFI_FILE_PROTOCOL *This, + IN EFI_GUID *InformationType, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + return ((EFI_FILE_PROTOCOL_FILE *)This)->Orig->GetInfo (((EFI_FILE_PROTOCOL_FILE *)This)->Orig, InformationType, BufferSize, Buffer); +} + +/** + Set information about a file + + @param This Protocol instance pointer. + @param InformationType Type of information in Buffer. + @param BufferSize Size of buffer. + @param Buffer The data to write. + + @retval EFI_SUCCESS Data was returned. + @retval EFI_UNSUPPORT InformationType is not supported. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED The device is write protected. + @retval EFI_ACCESS_DENIED The file was open for read only. + +**/ +EFI_STATUS +EFIAPI +FileInterfaceFileSetInfo ( + IN EFI_FILE_PROTOCOL *This, + IN EFI_GUID *InformationType, + IN UINTN BufferSize, + IN VOID *Buffer + ) +{ + return ((EFI_FILE_PROTOCOL_FILE *)This)->Orig->SetInfo (((EFI_FILE_PROTOCOL_FILE *)This)->Orig, InformationType, BufferSize, Buffer); +} + +/** + Flush data back for the file handle. + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS Data was written. + @retval EFI_UNSUPPORT Writes to Open directory are not supported. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED The device is write protected. + @retval EFI_ACCESS_DENIED The file was open for read only. + @retval EFI_VOLUME_FULL The volume is full. + +**/ +EFI_STATUS +EFIAPI +FileInterfaceFileFlush ( + IN EFI_FILE_PROTOCOL *This + ) +{ + return ((EFI_FILE_PROTOCOL_FILE *)This)->Orig->Flush (((EFI_FILE_PROTOCOL_FILE *)This)->Orig); +} + +/** + Read data from the file. + + @param This Protocol instance pointer. + @param BufferSize On input size of buffer, on output amount of data in buffer. + @param Buffer The buffer in which data is read. + + @retval EFI_SUCCESS Data was read. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_BUFFER_TO_SMALL BufferSize is too small. BufferSize contains required size. + +**/ +EFI_STATUS +EFIAPI +FileInterfaceFileRead ( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + UINT64 Position; + CHAR8 *AsciiStrBuffer; + CHAR16 *UscStrBuffer; + UINTN Size; + + if (((EFI_FILE_PROTOCOL_FILE *)This)->Unicode) { + // + // Unicode + // There might be different file tag for the Unicode file. We cannot unconditionally insert the \xFEFF. + // So we choose to leave the file content as is. + // + return (((EFI_FILE_PROTOCOL_FILE *)This)->Orig->Read (((EFI_FILE_PROTOCOL_FILE *)This)->Orig, BufferSize, Buffer)); + } else { + // + // Ascii + // + *BufferSize = *BufferSize / sizeof (CHAR16) * sizeof (CHAR16); + if (*BufferSize == 0) { + return EFI_SUCCESS; + } + + Status = ((EFI_FILE_PROTOCOL_FILE *)This)->Orig->GetPosition (((EFI_FILE_PROTOCOL_FILE *)This)->Orig, &Position); + if (EFI_ERROR (Status)) { + return Status; + } + + if (Position == 0) { + // + // First two bytes in Buffer is for the Unicode file tag. + // + *(CHAR16 *)Buffer = gUnicodeFileTag; + Buffer = (CHAR16 *)Buffer + 1; + Size = *BufferSize / sizeof (CHAR16) - 1; + } else { + Size = *BufferSize / sizeof (CHAR16); + } + + AsciiStrBuffer = AllocateZeroPool (Size + 1); + if (AsciiStrBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + UscStrBuffer = AllocateZeroPool ((Size + 1) * sizeof (CHAR16)); + if (UscStrBuffer == NULL) { + SHELL_FREE_NON_NULL (AsciiStrBuffer); + return EFI_OUT_OF_RESOURCES; + } + + Status = ((EFI_FILE_PROTOCOL_FILE *)This)->Orig->Read (((EFI_FILE_PROTOCOL_FILE *)This)->Orig, &Size, AsciiStrBuffer); + if (!EFI_ERROR (Status)) { + AsciiStrToUnicodeStrS (AsciiStrBuffer, UscStrBuffer, Size + 1); + *BufferSize = Size * sizeof (CHAR16); + CopyMem (Buffer, UscStrBuffer, *BufferSize); + } + + SHELL_FREE_NON_NULL (AsciiStrBuffer); + SHELL_FREE_NON_NULL (UscStrBuffer); + return Status; + } +} + +/** + Opens a new file relative to the source file's location. + + @param[in] This The protocol instance pointer. + @param[out] NewHandle Returns File Handle for FileName. + @param[in] FileName Null terminated string. "\", ".", and ".." are supported. + @param[in] OpenMode Open mode for file. + @param[in] Attributes Only used for EFI_FILE_MODE_CREATE. + + @retval EFI_SUCCESS The device was opened. + @retval EFI_NOT_FOUND The specified file could not be found on the device. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_MEDIA_CHANGED The media has changed. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_ACCESS_DENIED The service denied access to the file. + @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources. + @retval EFI_VOLUME_FULL The volume is full. +**/ +EFI_STATUS +EFIAPI +FileInterfaceFileOpen ( + IN EFI_FILE_PROTOCOL *This, + OUT EFI_FILE_PROTOCOL **NewHandle, + IN CHAR16 *FileName, + IN UINT64 OpenMode, + IN UINT64 Attributes + ) +{ + return ((EFI_FILE_PROTOCOL_FILE *)This)->Orig->Open (((EFI_FILE_PROTOCOL_FILE *)This)->Orig, NewHandle, FileName, OpenMode, Attributes); +} + +/** + Close and delete the file handle. + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS The device was opened. + @retval EFI_WARN_DELETE_FAILURE The handle was closed but the file was not deleted. + +**/ +EFI_STATUS +EFIAPI +FileInterfaceFileDelete ( + IN EFI_FILE_PROTOCOL *This + ) +{ + EFI_STATUS Status; + + Status = ((EFI_FILE_PROTOCOL_FILE *)This)->Orig->Delete (((EFI_FILE_PROTOCOL_FILE *)This)->Orig); + FreePool (This); + return (Status); +} + +/** + File style interface for File (Close). + + @param[in] This The pointer to the EFI_FILE_PROTOCOL object. + + @retval EFI_SUCCESS The file was closed. +**/ +EFI_STATUS +EFIAPI +FileInterfaceFileClose ( + IN EFI_FILE_PROTOCOL *This + ) +{ + EFI_STATUS Status; + + Status = ((EFI_FILE_PROTOCOL_FILE *)This)->Orig->Close (((EFI_FILE_PROTOCOL_FILE *)This)->Orig); + FreePool (This); + return (Status); +} + +/** + File style interface for File (Write). + + If the file was opened with ASCII mode the data will be processed through + AsciiSPrint before writing. + + @param[in] This The pointer to the EFI_FILE_PROTOCOL object. + @param[in, out] BufferSize Size in bytes of Buffer. + @param[in] Buffer The pointer to the buffer to write. + + @retval EFI_SUCCESS The data was written. +**/ +EFI_STATUS +EFIAPI +FileInterfaceFileWrite ( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +{ + CHAR8 *AsciiBuffer; + UINTN Size; + EFI_STATUS Status; + + if (((EFI_FILE_PROTOCOL_FILE *)This)->Unicode) { + // + // Unicode + // + return (((EFI_FILE_PROTOCOL_FILE *)This)->Orig->Write (((EFI_FILE_PROTOCOL_FILE *)This)->Orig, BufferSize, Buffer)); + } else { + // + // Ascii + // + AsciiBuffer = AllocateZeroPool (*BufferSize); + AsciiSPrint (AsciiBuffer, *BufferSize, "%S", Buffer); + Size = AsciiStrSize (AsciiBuffer) - 1; // (we dont need the null terminator) + Status = (((EFI_FILE_PROTOCOL_FILE *)This)->Orig->Write (((EFI_FILE_PROTOCOL_FILE *)This)->Orig, &Size, AsciiBuffer)); + FreePool (AsciiBuffer); + return (Status); + } +} + +/** + Create a file interface with unicode information. + + This will create a new EFI_FILE_PROTOCOL identical to the Templace + except that the new one has Unicode and Ascii knowledge. + + @param[in] Template A pointer to the EFI_FILE_PROTOCOL object. + @param[in] Unicode TRUE for UCS-2, FALSE for ASCII. + + @return a new EFI_FILE_PROTOCOL object to be used instead of the template. +**/ +EFI_FILE_PROTOCOL * +CreateFileInterfaceFile ( + IN CONST EFI_FILE_PROTOCOL *Template, + IN CONST BOOLEAN Unicode + ) +{ + EFI_FILE_PROTOCOL_FILE *NewOne; + + NewOne = AllocateZeroPool (sizeof (EFI_FILE_PROTOCOL_FILE)); + if (NewOne == NULL) { + return (NULL); + } + + CopyMem (NewOne, Template, sizeof (EFI_FILE_PROTOCOL_FILE)); + NewOne->Orig = (EFI_FILE_PROTOCOL *)Template; + NewOne->Unicode = Unicode; + NewOne->Open = FileInterfaceFileOpen; + NewOne->Close = FileInterfaceFileClose; + NewOne->Delete = FileInterfaceFileDelete; + NewOne->Read = FileInterfaceFileRead; + NewOne->Write = FileInterfaceFileWrite; + NewOne->GetPosition = FileInterfaceFileGetPosition; + NewOne->SetPosition = FileInterfaceFileSetPosition; + NewOne->GetInfo = FileInterfaceFileGetInfo; + NewOne->SetInfo = FileInterfaceFileSetInfo; + NewOne->Flush = FileInterfaceFileFlush; + + return ((EFI_FILE_PROTOCOL *)NewOne); +} |
