This change returns the error code when they keyboard fails to read instead of potentially spinning endlessly. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jaben Carsey <jaben.carsey@intel.com> Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15135 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			1840 lines
		
	
	
		
			56 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1840 lines
		
	
	
		
			56 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  EFI_FILE_PROTOCOL wrappers for other items (Like Environment Variables,
 | 
						|
  StdIn, StdOut, StdErr, etc...).
 | 
						|
 | 
						|
  Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
 | 
						|
  Copyright (c) 2013, Hewlett-Packard Development Company, L.P.
 | 
						|
  This program and the accompanying materials
 | 
						|
  are licensed and made available under the terms and conditions of the BSD License
 | 
						|
  which accompanies this distribution.  The full text of the license may be found at
 | 
						|
  http://opensource.org/licenses/bsd-license.php
 | 
						|
 | 
						|
  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | 
						|
  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "Shell.h"
 | 
						|
#include "FileHandleInternal.h"
 | 
						|
 | 
						|
/**
 | 
						|
  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);
 | 
						|
  } else {
 | 
						|
    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);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  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               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               Index;
 | 
						|
  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 *FoundFileList;
 | 
						|
  EFI_SHELL_FILE_INFO *TabLinePos;
 | 
						|
  EFI_SHELL_FILE_INFO *TempPos;
 | 
						|
  CHAR16              *TabStr;
 | 
						|
  CHAR16              *TabOutputStr;
 | 
						|
  BOOLEAN             InQuotationMode;
 | 
						|
  CHAR16              *TempStr;
 | 
						|
  UINTN               TabPos;         // Start index of the string to search for TAB completion.
 | 
						|
  UINTN               TabUpdatePos;   // Start index of the string updated by TAB stroke
 | 
						|
//  UINTN               Count;
 | 
						|
  UINTN               EventIndex;
 | 
						|
  CONST CHAR16        *Cwd;
 | 
						|
 | 
						|
  //
 | 
						|
  // 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;
 | 
						|
  TabLinePos        = NULL;
 | 
						|
  FoundFileList     = NULL;
 | 
						|
  TempPos           = NULL;
 | 
						|
  TabPos            = 0;
 | 
						|
  TabUpdatePos      = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // Allocate buffers
 | 
						|
  //
 | 
						|
  TabStr            = AllocateZeroPool (*BufferSize);
 | 
						|
  if (TabStr == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
  TabOutputStr      = AllocateZeroPool (*BufferSize);
 | 
						|
  if (TabOutputStr == NULL) {
 | 
						|
    FreePool(TabStr);
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // 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 minimun 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)) {
 | 
						|
      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 (FoundFileList != NULL) {
 | 
						|
          ShellInfoObject.NewEfiShellProtocol->FreeFileList (&FoundFileList);
 | 
						|
          DEBUG_CODE(FoundFileList = 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:
 | 
						|
      //
 | 
						|
      // handle auto complete of file and directory names...
 | 
						|
      //
 | 
						|
      if (InTabScrolling) {
 | 
						|
        ASSERT(FoundFileList != NULL);
 | 
						|
        ASSERT(TabLinePos != NULL);
 | 
						|
        TabLinePos = (EFI_SHELL_FILE_INFO*)GetNextNode(&(FoundFileList->Link), &TabLinePos->Link);
 | 
						|
        if (IsNull(&(FoundFileList->Link), &TabLinePos->Link)) {
 | 
						|
          TabLinePos = (EFI_SHELL_FILE_INFO*)GetNextNode(&(FoundFileList->Link), &TabLinePos->Link);
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        TabPos          = 0;
 | 
						|
        TabUpdatePos    = 0;
 | 
						|
        InQuotationMode = FALSE;
 | 
						|
        for (Index = 0; Index < StringLen; Index++) {
 | 
						|
          if (CurrentString[Index] == L'\"') {
 | 
						|
            InQuotationMode = (BOOLEAN)(!InQuotationMode);
 | 
						|
          }
 | 
						|
          if (CurrentString[Index] == L' ' && !InQuotationMode) {
 | 
						|
            TabPos = Index + 1;
 | 
						|
            TabUpdatePos = Index + 1;
 | 
						|
          }
 | 
						|
          if (CurrentString[Index] == L'\\') {
 | 
						|
            TabUpdatePos = Index + 1;
 | 
						|
          }
 | 
						|
        }
 | 
						|
        if (StrStr(CurrentString + TabPos, L":") == NULL) {
 | 
						|
          Cwd = ShellInfoObject.NewEfiShellProtocol->GetCurDir(NULL);
 | 
						|
          if (Cwd != NULL) {
 | 
						|
            StrCpy(TabStr, Cwd);
 | 
						|
            if (TabStr[StrLen(TabStr)-1] == L'\\' && *(CurrentString + TabPos) == L'\\' ) {
 | 
						|
              TabStr[StrLen(TabStr)-1] = CHAR_NULL;
 | 
						|
            }
 | 
						|
            StrnCat(TabStr, CurrentString + TabPos, (StringLen - TabPos) * sizeof (CHAR16));
 | 
						|
          } else {
 | 
						|
            StrCpy(TabStr, L"");
 | 
						|
            StrnCat(TabStr, CurrentString + TabPos, (StringLen - TabPos) * sizeof (CHAR16));
 | 
						|
          }
 | 
						|
        } else {
 | 
						|
          StrCpy(TabStr, CurrentString + TabPos);
 | 
						|
        }
 | 
						|
        StrCat(TabStr, L"*");
 | 
						|
        FoundFileList = NULL;
 | 
						|
//        TabStr = PathCleanUpDirectories(TabStr);
 | 
						|
        Status  = ShellInfoObject.NewEfiShellProtocol->FindFiles(TabStr, &FoundFileList);
 | 
						|
        for ( TempStr = CurrentString
 | 
						|
            ; *TempStr == L' '
 | 
						|
            ; TempStr++); // note the ';'... empty for loop
 | 
						|
        //
 | 
						|
        // make sure we have a list before we do anything more...
 | 
						|
        //
 | 
						|
        if (EFI_ERROR (Status) || FoundFileList == NULL) {
 | 
						|
          InTabScrolling = FALSE;
 | 
						|
          TabLinePos = NULL;
 | 
						|
          continue;
 | 
						|
        } else {
 | 
						|
          //
 | 
						|
          // enumerate through the list of files
 | 
						|
          //
 | 
						|
          for ( TempPos = (EFI_SHELL_FILE_INFO*)GetFirstNode(&(FoundFileList->Link))
 | 
						|
              ; !IsNull(&FoundFileList->Link, &TempPos->Link)
 | 
						|
              ; TempPos = (EFI_SHELL_FILE_INFO*)GetNextNode(&(FoundFileList->Link), &(TempPos->Link))
 | 
						|
             ){
 | 
						|
            //
 | 
						|
            // If "cd" is typed, only directory name will be auto-complete filled
 | 
						|
            // in either case . and .. will be removed.
 | 
						|
            //
 | 
						|
            if ((((TempStr[0] == L'c' || TempStr[0] == L'C') &&
 | 
						|
                (TempStr[1] == L'd' || TempStr[1] == L'D')
 | 
						|
               ) && ((ShellIsDirectory(TempPos->FullName) != EFI_SUCCESS)
 | 
						|
                ||(StrCmp(TempPos->FileName, L".") == 0)
 | 
						|
                ||(StrCmp(TempPos->FileName, L"..") == 0)
 | 
						|
               )) || ((StrCmp(TempPos->FileName, L".") == 0)
 | 
						|
                ||(StrCmp(TempPos->FileName, L"..") == 0))){
 | 
						|
                TabLinePos = TempPos;
 | 
						|
                TempPos = (EFI_SHELL_FILE_INFO*)(RemoveEntryList(&(TempPos->Link))->BackLink);
 | 
						|
                InternalFreeShellFileInfoNode(TabLinePos);
 | 
						|
            }
 | 
						|
          }
 | 
						|
          if (FoundFileList != NULL && !IsListEmpty(&FoundFileList->Link)) {
 | 
						|
            TabLinePos = (EFI_SHELL_FILE_INFO*)GetFirstNode(&FoundFileList->Link);
 | 
						|
            InTabScrolling = TRUE;
 | 
						|
          } else {
 | 
						|
            FreePool(FoundFileList);
 | 
						|
            FoundFileList = NULL;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
      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) {
 | 
						|
      //
 | 
						|
      // 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 (TabLinePos->FileName);
 | 
						|
      //
 | 
						|
      // if the output string contains  blank space, quotation marks L'\"'
 | 
						|
      // should be added to the output.
 | 
						|
      //
 | 
						|
      if (StrStr(TabLinePos->FileName, L" ") != NULL){
 | 
						|
        TabOutputStr[0] = L'\"';
 | 
						|
        CopyMem (TabOutputStr + 1, TabLinePos->FileName, OutputLength * sizeof (CHAR16));
 | 
						|
        TabOutputStr[OutputLength + 1] = L'\"';
 | 
						|
        TabOutputStr[OutputLength + 2] = CHAR_NULL;
 | 
						|
      } else {
 | 
						|
        CopyMem (TabOutputStr, TabLinePos->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;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // 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)) {
 | 
						|
        //
 | 
						|
        // Calulate 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);
 | 
						|
  }
 | 
						|
 | 
						|
  FreePool (TabStr);
 | 
						|
  FreePool (TabOutputStr);
 | 
						|
  //
 | 
						|
  // Return the data to the caller
 | 
						|
  //
 | 
						|
  *BufferSize = StringLen * sizeof (CHAR16);
 | 
						|
 | 
						|
  //
 | 
						|
  // if this was used it should be deallocated by now...
 | 
						|
  // prevent memory leaks...
 | 
						|
  //
 | 
						|
  ASSERT(FoundFileList == NULL);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// FILE sytle 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;
 | 
						|
 | 
						|
  //
 | 
						|
  // 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;
 | 
						|
 | 
						|
  Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer);
 | 
						|
  if (Status == EFI_BUFFER_TOO_SMALL) {
 | 
						|
    NewBuffer = AllocateZeroPool(NewSize + sizeof(CHAR16));
 | 
						|
    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 (StrSize(NewBuffer) > 6)
 | 
						|
    {
 | 
						|
      if ((((CHAR16*)NewBuffer)[(StrSize(NewBuffer)/2) - 2] == CHAR_LINEFEED) 
 | 
						|
           && (((CHAR16*)NewBuffer)[(StrSize(NewBuffer)/2) - 3] == CHAR_CARRIAGE_RETURN)) {
 | 
						|
        ((CHAR16*)NewBuffer)[(StrSize(NewBuffer)/2) - 3] = CHAR_NULL;   
 | 
						|
      }
 | 
						|
    
 | 
						|
      if (IsVolatileEnv(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name)) {
 | 
						|
        Status = SHELL_SET_ENVIRONMENT_VARIABLE_V(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, StrSize(NewBuffer), NewBuffer);
 | 
						|
      } else {
 | 
						|
        Status = SHELL_SET_ENVIRONMENT_VARIABLE_NV(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, StrSize(NewBuffer), NewBuffer);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } 
 | 
						|
  
 | 
						|
  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
 | 
						|
  )
 | 
						|
{
 | 
						|
  return (SHELL_GET_ENVIRONMENT_VARIABLE(
 | 
						|
    ((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name,
 | 
						|
    BufferSize,
 | 
						|
    Buffer));
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  File style interface for Volatile Environment Variable (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_SUCCESS   The data was read.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
FileInterfaceEnvVolWrite(
 | 
						|
  IN EFI_FILE_PROTOCOL *This,
 | 
						|
  IN OUT UINTN *BufferSize,
 | 
						|
  IN VOID *Buffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  VOID*       NewBuffer;
 | 
						|
  UINTN       NewSize;
 | 
						|
  EFI_STATUS  Status;
 | 
						|
 | 
						|
  NewBuffer   = NULL;
 | 
						|
  NewSize     = 0;
 | 
						|
 | 
						|
  Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer);
 | 
						|
  if (Status == EFI_BUFFER_TOO_SMALL){
 | 
						|
    NewBuffer = AllocateZeroPool(NewSize + *BufferSize + sizeof(CHAR16));
 | 
						|
    Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer);
 | 
						|
  }
 | 
						|
  if (!EFI_ERROR(Status) && NewBuffer != NULL) {
 | 
						|
    while (((CHAR16*)NewBuffer)[NewSize/2] == CHAR_NULL) {
 | 
						|
      //
 | 
						|
      // We want to overwrite the CHAR_NULL
 | 
						|
      //
 | 
						|
      NewSize -= 2;
 | 
						|
    }
 | 
						|
    CopyMem((UINT8*)NewBuffer + NewSize + 2, Buffer, *BufferSize);
 | 
						|
    Status = SHELL_SET_ENVIRONMENT_VARIABLE_V(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, StrSize(NewBuffer), NewBuffer);
 | 
						|
    FreePool(NewBuffer);
 | 
						|
    return (Status);
 | 
						|
  } else {
 | 
						|
    SHELL_FREE_NON_NULL(NewBuffer);
 | 
						|
    return (SHELL_SET_ENVIRONMENT_VARIABLE_V(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, *BufferSize, Buffer));
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  File style interface for Non Volatile Environment Variable (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_SUCCESS   The data was read.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
FileInterfaceEnvNonVolWrite(
 | 
						|
  IN EFI_FILE_PROTOCOL *This,
 | 
						|
  IN OUT UINTN *BufferSize,
 | 
						|
  IN VOID *Buffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  VOID*       NewBuffer;
 | 
						|
  UINTN       NewSize;
 | 
						|
  EFI_STATUS  Status;
 | 
						|
 | 
						|
  NewBuffer   = NULL;
 | 
						|
  NewSize     = 0;
 | 
						|
 | 
						|
  Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer);
 | 
						|
  if (Status == EFI_BUFFER_TOO_SMALL){
 | 
						|
    NewBuffer = AllocateZeroPool(NewSize + *BufferSize);
 | 
						|
    Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer);
 | 
						|
  }
 | 
						|
  if (!EFI_ERROR(Status)) {
 | 
						|
    CopyMem((UINT8*)NewBuffer + NewSize, Buffer, *BufferSize);
 | 
						|
    return (SHELL_SET_ENVIRONMENT_VARIABLE_NV(
 | 
						|
    ((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name,
 | 
						|
    NewSize + *BufferSize,
 | 
						|
    NewBuffer));
 | 
						|
  } else {
 | 
						|
    return (SHELL_SET_ENVIRONMENT_VARIABLE_NV(
 | 
						|
    ((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name,
 | 
						|
    *BufferSize,
 | 
						|
    Buffer));
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  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*
 | 
						|
EFIAPI
 | 
						|
CreateFileInterfaceEnv(
 | 
						|
  IN CONST CHAR16 *EnvName
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_FILE_PROTOCOL_ENVIRONMENT  *EnvFileInterface;
 | 
						|
 | 
						|
  if (EnvName == NULL) {
 | 
						|
    return (NULL);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Get some memory
 | 
						|
  //
 | 
						|
  EnvFileInterface = AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_ENVIRONMENT)+StrSize(EnvName));
 | 
						|
  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;
 | 
						|
 | 
						|
  StrCpy(EnvFileInterface->Name, EnvName);
 | 
						|
 | 
						|
  //
 | 
						|
  // Assign the different members for Volatile and Non-Volatile variables
 | 
						|
  //
 | 
						|
  if (IsVolatileEnv(EnvName)) {
 | 
						|
    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
 | 
						|
EFIAPI
 | 
						|
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
 | 
						|
EFIAPI
 | 
						|
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
 | 
						|
EFIAPI
 | 
						|
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;
 | 
						|
} 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)->BufferSize) {
 | 
						|
    ((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 (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;
 | 
						|
  if (((EFI_FILE_PROTOCOL_MEM*)This)->Unicode) {
 | 
						|
    //
 | 
						|
    // Unicode
 | 
						|
    //
 | 
						|
    if ((UINTN)(((EFI_FILE_PROTOCOL_MEM*)This)->Position + (*BufferSize)) > (UINTN)(((EFI_FILE_PROTOCOL_MEM*)This)->BufferSize)) {
 | 
						|
      ((EFI_FILE_PROTOCOL_MEM*)This)->Buffer = ReallocatePool((UINTN)(((EFI_FILE_PROTOCOL_MEM*)This)->BufferSize), (UINTN)(((EFI_FILE_PROTOCOL_MEM*)This)->BufferSize) + (*BufferSize) + 10, ((EFI_FILE_PROTOCOL_MEM*)This)->Buffer);
 | 
						|
      ((EFI_FILE_PROTOCOL_MEM*)This)->BufferSize += (*BufferSize) + 10;
 | 
						|
    }
 | 
						|
    CopyMem(((UINT8*)((EFI_FILE_PROTOCOL_MEM*)This)->Buffer) + ((EFI_FILE_PROTOCOL_MEM*)This)->Position, Buffer, *BufferSize);
 | 
						|
    ((EFI_FILE_PROTOCOL_MEM*)This)->Position += (*BufferSize);
 | 
						|
    return (EFI_SUCCESS);
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // Ascii
 | 
						|
    //
 | 
						|
    AsciiBuffer = AllocateZeroPool(*BufferSize);
 | 
						|
    if (AsciiBuffer == NULL) {
 | 
						|
      return (EFI_OUT_OF_RESOURCES);
 | 
						|
    }
 | 
						|
    AsciiSPrint(AsciiBuffer, *BufferSize, "%S", Buffer);
 | 
						|
    if ((UINTN)(((EFI_FILE_PROTOCOL_MEM*)This)->Position + AsciiStrSize(AsciiBuffer)) > (UINTN)(((EFI_FILE_PROTOCOL_MEM*)This)->BufferSize)) {
 | 
						|
      ((EFI_FILE_PROTOCOL_MEM*)This)->Buffer = ReallocatePool((UINTN)(((EFI_FILE_PROTOCOL_MEM*)This)->BufferSize), (UINTN)(((EFI_FILE_PROTOCOL_MEM*)This)->BufferSize) + AsciiStrSize(AsciiBuffer) + 10, ((EFI_FILE_PROTOCOL_MEM*)This)->Buffer);
 | 
						|
      ((EFI_FILE_PROTOCOL_MEM*)This)->BufferSize += AsciiStrSize(AsciiBuffer) + 10;
 | 
						|
    }
 | 
						|
    CopyMem(((UINT8*)((EFI_FILE_PROTOCOL_MEM*)This)->Buffer) + ((EFI_FILE_PROTOCOL_MEM*)This)->Position, AsciiBuffer, AsciiStrSize(AsciiBuffer));
 | 
						|
    ((EFI_FILE_PROTOCOL_MEM*)This)->Position += AsciiStrSize(AsciiBuffer);
 | 
						|
    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
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (*BufferSize > (UINTN)((((EFI_FILE_PROTOCOL_MEM*)This)->BufferSize) - (UINTN)(((EFI_FILE_PROTOCOL_MEM*)This)->Position))) {
 | 
						|
    (*BufferSize) = (UINTN)((((EFI_FILE_PROTOCOL_MEM*)This)->BufferSize) - (UINTN)(((EFI_FILE_PROTOCOL_MEM*)This)->Position));
 | 
						|
  }
 | 
						|
  CopyMem(Buffer, ((UINT8*)((EFI_FILE_PROTOCOL_MEM*)This)->Buffer) + ((EFI_FILE_PROTOCOL_MEM*)This)->Position, (*BufferSize));
 | 
						|
  ((EFI_FILE_PROTOCOL_MEM*)This)->Position = ((EFI_FILE_PROTOCOL_MEM*)This)->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*
 | 
						|
EFIAPI
 | 
						|
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     = FileInterfaceNopGetInfo;
 | 
						|
  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);
 | 
						|
 | 
						|
  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
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR8       *AsciiBuffer;
 | 
						|
  UINTN       Size;
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  if (((EFI_FILE_PROTOCOL_FILE*)This)->Unicode) {
 | 
						|
    //
 | 
						|
    // Unicode
 | 
						|
    //
 | 
						|
    return (((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Read(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, BufferSize, Buffer));
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // Ascii
 | 
						|
    //
 | 
						|
    AsciiBuffer = AllocateZeroPool((Size = *BufferSize));
 | 
						|
    Status = (((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Read(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, &Size, AsciiBuffer));
 | 
						|
    UnicodeSPrint(Buffer, *BufferSize, L"%a", AsciiBuffer);
 | 
						|
    FreePool(AsciiBuffer);
 | 
						|
    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);
 | 
						|
}
 |