Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jaben Carsey <jaben.carsey@intel.com> Reviewed-by: Erik Bjorge <erik.c.bjorge@intel.com> git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13939 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			1197 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1197 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Provides interface to shell console logger.
 | 
						|
 | 
						|
  Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
 | 
						|
  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"
 | 
						|
 | 
						|
STATIC CONST CHAR16                     mCrLfString[3] = { CHAR_CARRIAGE_RETURN, CHAR_LINEFEED, CHAR_NULL };
 | 
						|
 | 
						|
/**
 | 
						|
  Install our intermediate ConOut into the system table to
 | 
						|
  keep a log of all the info that is displayed to the user.
 | 
						|
 | 
						|
  @param[in] ScreensToSave  Sets how many screen-worths of data to save.
 | 
						|
  @param[out] ConsoleInfo   The object to pass into later functions.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS       The operation was successful.
 | 
						|
  @return other             The operation failed.
 | 
						|
 | 
						|
  @sa ConsoleLoggerResetBuffers
 | 
						|
  @sa InstallProtocolInterface
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ConsoleLoggerInstall(
 | 
						|
  IN CONST UINTN ScreensToSave,
 | 
						|
  OUT CONSOLE_LOGGER_PRIVATE_DATA **ConsoleInfo
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS Status;
 | 
						|
  ASSERT(ConsoleInfo != NULL);
 | 
						|
 | 
						|
  (*ConsoleInfo) = AllocateZeroPool(sizeof(CONSOLE_LOGGER_PRIVATE_DATA));
 | 
						|
  if ((*ConsoleInfo) == NULL) {
 | 
						|
    return (EFI_OUT_OF_RESOURCES);
 | 
						|
  }
 | 
						|
 | 
						|
  (*ConsoleInfo)->Signature                   = CONSOLE_LOGGER_PRIVATE_DATA_SIGNATURE;
 | 
						|
  (*ConsoleInfo)->OldConOut                   = gST->ConOut;
 | 
						|
  (*ConsoleInfo)->OldConHandle                = gST->ConsoleOutHandle;
 | 
						|
  (*ConsoleInfo)->Buffer                      = NULL;
 | 
						|
  (*ConsoleInfo)->BufferSize                  = 0;
 | 
						|
  (*ConsoleInfo)->OriginalStartRow            = 0;
 | 
						|
  (*ConsoleInfo)->CurrentStartRow             = 0;
 | 
						|
  (*ConsoleInfo)->RowsPerScreen               = 0;
 | 
						|
  (*ConsoleInfo)->ColsPerScreen               = 0;
 | 
						|
  (*ConsoleInfo)->Attributes                  = NULL;
 | 
						|
  (*ConsoleInfo)->AttribSize                  = 0;
 | 
						|
  (*ConsoleInfo)->ScreenCount                 = ScreensToSave;
 | 
						|
  (*ConsoleInfo)->HistoryMode.MaxMode         = 1;
 | 
						|
  (*ConsoleInfo)->HistoryMode.Mode            = 0;
 | 
						|
  (*ConsoleInfo)->HistoryMode.Attribute       = 0;
 | 
						|
  (*ConsoleInfo)->HistoryMode.CursorColumn    = 0;
 | 
						|
  (*ConsoleInfo)->HistoryMode.CursorRow       = 0;
 | 
						|
  (*ConsoleInfo)->HistoryMode.CursorVisible   = FALSE;
 | 
						|
  (*ConsoleInfo)->OurConOut.Reset             = ConsoleLoggerReset;
 | 
						|
  (*ConsoleInfo)->OurConOut.OutputString      = ConsoleLoggerOutputString;
 | 
						|
  (*ConsoleInfo)->OurConOut.TestString        = ConsoleLoggerTestString;
 | 
						|
  (*ConsoleInfo)->OurConOut.QueryMode         = ConsoleLoggerQueryMode;
 | 
						|
  (*ConsoleInfo)->OurConOut.SetMode           = ConsoleLoggerSetMode;
 | 
						|
  (*ConsoleInfo)->OurConOut.SetAttribute      = ConsoleLoggerSetAttribute;
 | 
						|
  (*ConsoleInfo)->OurConOut.ClearScreen       = ConsoleLoggerClearScreen;
 | 
						|
  (*ConsoleInfo)->OurConOut.SetCursorPosition = ConsoleLoggerSetCursorPosition;
 | 
						|
  (*ConsoleInfo)->OurConOut.EnableCursor      = ConsoleLoggerEnableCursor;
 | 
						|
  (*ConsoleInfo)->OurConOut.Mode              = gST->ConOut->Mode;
 | 
						|
  (*ConsoleInfo)->Enabled                     = TRUE;
 | 
						|
 | 
						|
  Status = ConsoleLoggerResetBuffers(*ConsoleInfo);
 | 
						|
  if (EFI_ERROR(Status)) {
 | 
						|
    SHELL_FREE_NON_NULL((*ConsoleInfo));
 | 
						|
    *ConsoleInfo = NULL;
 | 
						|
    return (Status);
 | 
						|
  }
 | 
						|
 | 
						|
  Status = gBS->InstallProtocolInterface(&gImageHandle, &gEfiSimpleTextOutProtocolGuid, EFI_NATIVE_INTERFACE, (VOID*)&((*ConsoleInfo)->OurConOut));
 | 
						|
  if (EFI_ERROR(Status)) {
 | 
						|
    SHELL_FREE_NON_NULL((*ConsoleInfo)->Buffer);
 | 
						|
    SHELL_FREE_NON_NULL((*ConsoleInfo)->Attributes);
 | 
						|
    SHELL_FREE_NON_NULL((*ConsoleInfo));
 | 
						|
    *ConsoleInfo = NULL;
 | 
						|
    return (Status);
 | 
						|
  }
 | 
						|
 | 
						|
  gST->ConsoleOutHandle = gImageHandle;
 | 
						|
  gST->ConOut           = &(*ConsoleInfo)->OurConOut;
 | 
						|
 | 
						|
  return (Status);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Return the system to the state it was before InstallConsoleLogger
 | 
						|
  was installed.
 | 
						|
 | 
						|
  @param[in] ConsoleInfo  The object from the install function.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS     The operation was successful
 | 
						|
  @return other           The operation failed.  This was from UninstallProtocolInterface.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ConsoleLoggerUninstall(
 | 
						|
  IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
 | 
						|
  )
 | 
						|
{
 | 
						|
  ASSERT(ConsoleInfo != NULL);
 | 
						|
  ASSERT(ConsoleInfo->OldConOut != NULL);
 | 
						|
 | 
						|
  if (ConsoleInfo->Buffer != NULL) {
 | 
						|
    FreePool(ConsoleInfo->Buffer);
 | 
						|
    DEBUG_CODE(ConsoleInfo->Buffer     = NULL;);
 | 
						|
    DEBUG_CODE(ConsoleInfo->BufferSize = 0;);
 | 
						|
  }
 | 
						|
  if (ConsoleInfo->Attributes != NULL) {
 | 
						|
    FreePool(ConsoleInfo->Attributes);
 | 
						|
    DEBUG_CODE(ConsoleInfo->Attributes = NULL;);
 | 
						|
    DEBUG_CODE(ConsoleInfo->AttribSize = 0;);
 | 
						|
  }
 | 
						|
 | 
						|
  gST->ConsoleOutHandle = ConsoleInfo->OldConHandle;
 | 
						|
  gST->ConOut = ConsoleInfo->OldConOut;
 | 
						|
 | 
						|
  return (gBS->UninstallProtocolInterface(gImageHandle, &gEfiSimpleTextOutProtocolGuid, (VOID*)&ConsoleInfo->OurConOut));
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Displays previously logged output back to the screen.
 | 
						|
 | 
						|
  This will scroll the screen forwards and backwards through the log of previous
 | 
						|
  output.  If Rows is 0 then the size of 1/2 the screen will be scrolled.  If Rows
 | 
						|
  is (UINTN)(-1) then the size of the screen will be scrolled.
 | 
						|
 | 
						|
  @param[in] Forward      If TRUE then the log will be displayed forwards (scroll to newer).
 | 
						|
                          If FALSE then the log will be displayed backwards (scroll to older).
 | 
						|
  @param[in] Rows         Determines how many rows the log should scroll.
 | 
						|
  @param[in] ConsoleInfo  The pointer to the instance of the console logger information.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ConsoleLoggerDisplayHistory(
 | 
						|
  IN CONST BOOLEAN  Forward,
 | 
						|
  IN CONST UINTN    Rows,
 | 
						|
  IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN   RowChange;
 | 
						|
 | 
						|
  ASSERT(ConsoleInfo != NULL);
 | 
						|
 | 
						|
  //
 | 
						|
  // Calculate the row number change
 | 
						|
  //
 | 
						|
  switch (Rows) {
 | 
						|
  case ((UINTN)(-1)):
 | 
						|
    RowChange = ConsoleInfo->RowsPerScreen;
 | 
						|
    break;
 | 
						|
  case (0):
 | 
						|
    RowChange = ConsoleInfo->RowsPerScreen / 2;
 | 
						|
    break;
 | 
						|
  default:
 | 
						|
    RowChange = Rows;
 | 
						|
    break;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Do the math for direction
 | 
						|
  //
 | 
						|
  if (Forward) {
 | 
						|
    if ((ConsoleInfo->OriginalStartRow - ConsoleInfo->CurrentStartRow) < RowChange) {
 | 
						|
      RowChange = ConsoleInfo->OriginalStartRow - ConsoleInfo->CurrentStartRow;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    if (ConsoleInfo->CurrentStartRow < RowChange) {
 | 
						|
      RowChange = ConsoleInfo->CurrentStartRow;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // If we are already at one end or the other
 | 
						|
  //
 | 
						|
  if (RowChange == 0) {
 | 
						|
    return (EFI_SUCCESS);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Clear the screen
 | 
						|
  //
 | 
						|
  ConsoleInfo->OldConOut->ClearScreen(ConsoleInfo->OldConOut);
 | 
						|
 | 
						|
  //
 | 
						|
  // Set the new start row
 | 
						|
  //
 | 
						|
  if (Forward) {
 | 
						|
    ConsoleInfo->CurrentStartRow += RowChange;
 | 
						|
  } else {
 | 
						|
    ConsoleInfo->CurrentStartRow -= RowChange;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Change the screen
 | 
						|
  //
 | 
						|
  return (UpdateDisplayFromHistory(ConsoleInfo));
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Function to return to normal output whent he scrolling is complete.
 | 
						|
  @param[in] ConsoleInfo  The pointer to the instance of the console logger information.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS   The operation was successful.
 | 
						|
  @return other         The operation failed.  See UpdateDisplayFromHistory.
 | 
						|
 | 
						|
  @sa UpdateDisplayFromHistory
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ConsoleLoggerStopHistory(
 | 
						|
  IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
 | 
						|
  )
 | 
						|
{
 | 
						|
  ASSERT(ConsoleInfo != NULL);
 | 
						|
  if (ConsoleInfo->CurrentStartRow == ConsoleInfo->OriginalStartRow) {
 | 
						|
    return (EFI_SUCCESS);
 | 
						|
  }
 | 
						|
  ConsoleInfo->CurrentStartRow = ConsoleInfo->OriginalStartRow;
 | 
						|
  return (UpdateDisplayFromHistory(ConsoleInfo));
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Updates the hidden ConOut to be displaying the correct stuff.
 | 
						|
  @param[in] ConsoleInfo  The pointer to the instance of the console logger information.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS     The operation was successful.
 | 
						|
  @return other           The operation failed.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
UpdateDisplayFromHistory(
 | 
						|
  IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS      Status;
 | 
						|
  EFI_STATUS      RetVal;
 | 
						|
  CHAR16          *Screen;
 | 
						|
  INT32           *Attributes;
 | 
						|
  UINTN           CurrentRow;
 | 
						|
  CHAR16          TempCharHolder;
 | 
						|
  UINTN           Column;
 | 
						|
  INT32           CurrentAttrib;
 | 
						|
  UINTN           CurrentColumn;
 | 
						|
  CHAR16          *StringSegment;
 | 
						|
  CHAR16          *StringSegmentEnd;
 | 
						|
  CHAR16          StringSegmentEndChar;
 | 
						|
  INT32           OrigAttribute;
 | 
						|
 | 
						|
  ASSERT(ConsoleInfo != NULL);
 | 
						|
  TempCharHolder = CHAR_NULL;
 | 
						|
  RetVal = EFI_SUCCESS;
 | 
						|
  OrigAttribute = ConsoleInfo->OldConOut->Mode->Attribute;
 | 
						|
 | 
						|
  //
 | 
						|
  // Disable cursor visibility and move it to the top left corner
 | 
						|
  //
 | 
						|
  ConsoleInfo->OldConOut->EnableCursor       (ConsoleInfo->OldConOut, FALSE);
 | 
						|
  ConsoleInfo->OldConOut->SetCursorPosition  (ConsoleInfo->OldConOut, 0, 0);
 | 
						|
 | 
						|
  Screen = &ConsoleInfo->Buffer[(ConsoleInfo->ColsPerScreen + 2) * ConsoleInfo->CurrentStartRow];
 | 
						|
  Attributes = &ConsoleInfo->Attributes[ConsoleInfo->ColsPerScreen * ConsoleInfo->CurrentStartRow];
 | 
						|
  for ( CurrentRow = 0
 | 
						|
      ; CurrentRow < ConsoleInfo->RowsPerScreen
 | 
						|
      ; CurrentRow++
 | 
						|
      , Screen += (ConsoleInfo->ColsPerScreen + 2)
 | 
						|
      , Attributes += ConsoleInfo->ColsPerScreen
 | 
						|
     ){
 | 
						|
    //
 | 
						|
    // dont use the last char - prevents screen scroll
 | 
						|
    //
 | 
						|
    if (CurrentRow == (ConsoleInfo->RowsPerScreen-1)){
 | 
						|
      TempCharHolder = Screen[ConsoleInfo->ColsPerScreen - 1];
 | 
						|
      Screen[ConsoleInfo->ColsPerScreen - 1] = CHAR_NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    for ( Column = 0
 | 
						|
        ; Column < ConsoleInfo->ColsPerScreen
 | 
						|
        ; Column++
 | 
						|
       ){
 | 
						|
      if (Screen[Column] != CHAR_NULL) {
 | 
						|
        CurrentAttrib = Attributes[Column];
 | 
						|
        CurrentColumn = Column;
 | 
						|
        StringSegment = &Screen[Column];
 | 
						|
 | 
						|
        //
 | 
						|
        // Find the first char with a different arrribute and make that temporarily NULL
 | 
						|
        // so we can do fewer printout statements.  (later) restore that one and we will
 | 
						|
        // start at that collumn on the next loop.
 | 
						|
        //
 | 
						|
        StringSegmentEndChar = CHAR_NULL;
 | 
						|
        for ( StringSegmentEnd = StringSegment
 | 
						|
            ; StringSegmentEnd != CHAR_NULL
 | 
						|
            ; StringSegmentEnd++
 | 
						|
            , Column++
 | 
						|
           ){
 | 
						|
          if (Attributes[Column] != CurrentAttrib) {
 | 
						|
            StringSegmentEndChar = *StringSegmentEnd;
 | 
						|
            *StringSegmentEnd    = CHAR_NULL;
 | 
						|
            break;
 | 
						|
          }
 | 
						|
        } // StringSegmentEnd loop
 | 
						|
 | 
						|
        //
 | 
						|
        // Now write out as much as had the same Attributes
 | 
						|
        //
 | 
						|
 | 
						|
        ConsoleInfo->OldConOut->SetAttribute(ConsoleInfo->OldConOut, CurrentAttrib);
 | 
						|
        ConsoleInfo->OldConOut->SetCursorPosition(ConsoleInfo->OldConOut, CurrentColumn, CurrentRow);
 | 
						|
        Status = ConsoleInfo->OldConOut->OutputString(ConsoleInfo->OldConOut, StringSegment);
 | 
						|
 | 
						|
        if (EFI_ERROR(Status)) {
 | 
						|
          ASSERT(FALSE);
 | 
						|
          RetVal = Status;
 | 
						|
        }
 | 
						|
 | 
						|
        //
 | 
						|
        // If we found a change in attribute put the character back and decrement the column
 | 
						|
        // so when it increments it will point at that character and we will start printing
 | 
						|
        // a segment with that new attribute
 | 
						|
        //
 | 
						|
        if (StringSegmentEndChar != CHAR_NULL) {
 | 
						|
          *StringSegmentEnd = StringSegmentEndChar;
 | 
						|
          StringSegmentEndChar = CHAR_NULL;
 | 
						|
          Column--;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    } // column for loop
 | 
						|
 | 
						|
    //
 | 
						|
    // If we removed the last char and this was the last row put it back
 | 
						|
    //
 | 
						|
    if (TempCharHolder != CHAR_NULL) {
 | 
						|
      Screen[ConsoleInfo->ColsPerScreen - 1] = TempCharHolder;
 | 
						|
      TempCharHolder = CHAR_NULL;
 | 
						|
    }
 | 
						|
  } // row for loop
 | 
						|
 | 
						|
  //
 | 
						|
  // If we are setting the screen back to original turn on the cursor and make it visible
 | 
						|
  // and set the attributes back to what they were
 | 
						|
  //
 | 
						|
  if (ConsoleInfo->CurrentStartRow == ConsoleInfo->OriginalStartRow) {
 | 
						|
    ConsoleInfo->OldConOut->SetAttribute (
 | 
						|
                                ConsoleInfo->OldConOut,
 | 
						|
                                ConsoleInfo->HistoryMode.Attribute
 | 
						|
                               );
 | 
						|
    ConsoleInfo->OldConOut->SetCursorPosition (
 | 
						|
                                ConsoleInfo->OldConOut,
 | 
						|
                                ConsoleInfo->HistoryMode.CursorColumn,
 | 
						|
                                ConsoleInfo->HistoryMode.CursorRow - ConsoleInfo->OriginalStartRow
 | 
						|
                               );
 | 
						|
 | 
						|
    Status = ConsoleInfo->OldConOut->EnableCursor (
 | 
						|
                                ConsoleInfo->OldConOut,
 | 
						|
                                ConsoleInfo->HistoryMode.CursorVisible
 | 
						|
                               );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      RetVal = Status;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    ConsoleInfo->OldConOut->SetAttribute (
 | 
						|
                                ConsoleInfo->OldConOut,
 | 
						|
                                OrigAttribute
 | 
						|
                               );
 | 
						|
  }
 | 
						|
 | 
						|
  return (RetVal);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Reset the text output device hardware and optionaly run diagnostics
 | 
						|
 | 
						|
  @param  This                pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
 | 
						|
  @param ExtendedVerification Indicates that a more extensive test may be performed
 | 
						|
 | 
						|
  @retval EFI_SUCCESS         The text output device was reset.
 | 
						|
  @retval EFI_DEVICE_ERROR    The text output device is not functioning correctly and
 | 
						|
                              could not be reset.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ConsoleLoggerReset (
 | 
						|
  IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
 | 
						|
  IN  BOOLEAN                         ExtendedVerification
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                  Status;
 | 
						|
  CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;
 | 
						|
  ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);
 | 
						|
 | 
						|
  //
 | 
						|
  // Forward the request to the original ConOut
 | 
						|
  //
 | 
						|
  Status = ConsoleInfo->OldConOut->Reset (ConsoleInfo->OldConOut, ExtendedVerification);
 | 
						|
 | 
						|
  //
 | 
						|
  // Check that the buffers are still correct for logging
 | 
						|
  //
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    ConsoleLoggerResetBuffers(ConsoleInfo);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Appends a string to the history buffer.  If the buffer is full then the oldest
 | 
						|
  information in the buffer will be dropped.  Information is added in a line by
 | 
						|
  line manner such that an empty line takes up just as much space as a full line.
 | 
						|
 | 
						|
  @param[in] String       String pointer to add.
 | 
						|
  @param[in] ConsoleInfo  The pointer to the instance of the console logger information.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
AppendStringToHistory(
 | 
						|
  IN CONST CHAR16 *String,
 | 
						|
  IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
 | 
						|
  )
 | 
						|
{
 | 
						|
  CONST CHAR16  *Walker;
 | 
						|
  UINTN         CopySize;
 | 
						|
  UINTN         PrintIndex;
 | 
						|
  UINTN         Index;
 | 
						|
 | 
						|
  ASSERT(ConsoleInfo != NULL);
 | 
						|
 | 
						|
  for ( Walker = String
 | 
						|
      ; Walker != NULL && *Walker != CHAR_NULL
 | 
						|
      ; Walker++
 | 
						|
     ){
 | 
						|
    switch (*Walker) {
 | 
						|
    case (CHAR_BACKSPACE):
 | 
						|
      if (ConsoleInfo->HistoryMode.CursorColumn > 0) {
 | 
						|
        ConsoleInfo->HistoryMode.CursorColumn--;
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case (CHAR_LINEFEED):
 | 
						|
      if (ConsoleInfo->HistoryMode.CursorRow >= (INT32)((ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount)-1)) {
 | 
						|
        //
 | 
						|
        // Should never be bigger
 | 
						|
        //
 | 
						|
        ASSERT(ConsoleInfo->HistoryMode.CursorRow == (INT32)((ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount)-1));
 | 
						|
 | 
						|
        //
 | 
						|
        // scroll history attributes 'up' 1 row and set the last row to default attribute
 | 
						|
        //
 | 
						|
        CopySize = ConsoleInfo->ColsPerScreen
 | 
						|
                 * ((ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount) - 1)
 | 
						|
                 * sizeof(ConsoleInfo->Attributes[0]);
 | 
						|
        ASSERT(CopySize < ConsoleInfo->AttribSize);
 | 
						|
        CopyMem(
 | 
						|
          ConsoleInfo->Attributes,
 | 
						|
          ConsoleInfo->Attributes + ConsoleInfo->ColsPerScreen,
 | 
						|
          CopySize
 | 
						|
         );
 | 
						|
 | 
						|
        for ( Index = 0
 | 
						|
            ; Index < ConsoleInfo->ColsPerScreen
 | 
						|
            ; Index++
 | 
						|
           ){
 | 
						|
          *(ConsoleInfo->Attributes + (CopySize/sizeof(ConsoleInfo->Attributes[0])) + Index) = ConsoleInfo->HistoryMode.Attribute;
 | 
						|
        }
 | 
						|
 | 
						|
        //
 | 
						|
        // scroll history buffer 'up' 1 row and set the last row to spaces (L' ')
 | 
						|
        //
 | 
						|
        CopySize = (ConsoleInfo->ColsPerScreen + 2)
 | 
						|
                 * ((ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount) - 1)
 | 
						|
                 * sizeof(ConsoleInfo->Buffer[0]);
 | 
						|
        ASSERT(CopySize < ConsoleInfo->BufferSize);
 | 
						|
        CopyMem(
 | 
						|
          ConsoleInfo->Buffer,
 | 
						|
          ConsoleInfo->Buffer + (ConsoleInfo->ColsPerScreen + 2),
 | 
						|
          CopySize
 | 
						|
         );
 | 
						|
 | 
						|
        //
 | 
						|
        // Set that last row of chars to spaces
 | 
						|
        //
 | 
						|
        SetMem16(((UINT8*)ConsoleInfo->Buffer)+CopySize, ConsoleInfo->ColsPerScreen*sizeof(CHAR16), L' ');
 | 
						|
      } else {
 | 
						|
        //
 | 
						|
        // we are not on the last row
 | 
						|
        //
 | 
						|
 | 
						|
        //
 | 
						|
        // We should not be scrolling history
 | 
						|
        //
 | 
						|
        ASSERT (ConsoleInfo->OriginalStartRow == ConsoleInfo->CurrentStartRow);
 | 
						|
        //
 | 
						|
        // are we at the end of a row?
 | 
						|
        //
 | 
						|
        if (ConsoleInfo->HistoryMode.CursorRow == (INT32) (ConsoleInfo->OriginalStartRow + ConsoleInfo->RowsPerScreen - 1)) {
 | 
						|
          ConsoleInfo->OriginalStartRow++;
 | 
						|
          ConsoleInfo->CurrentStartRow++;
 | 
						|
        }
 | 
						|
        ConsoleInfo->HistoryMode.CursorRow++;
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case (CHAR_CARRIAGE_RETURN):
 | 
						|
      //
 | 
						|
      // Move the cursor to the beginning of the current row.
 | 
						|
      //
 | 
						|
      ConsoleInfo->HistoryMode.CursorColumn = 0;
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      //
 | 
						|
      // Acrtually print characters into the history buffer
 | 
						|
      //
 | 
						|
 | 
						|
      PrintIndex = ConsoleInfo->HistoryMode.CursorRow * ConsoleInfo->ColsPerScreen + ConsoleInfo->HistoryMode.CursorColumn;
 | 
						|
 | 
						|
      for ( // no initializer needed
 | 
						|
          ; ConsoleInfo->HistoryMode.CursorColumn < (INT32) ConsoleInfo->ColsPerScreen
 | 
						|
          ; ConsoleInfo->HistoryMode.CursorColumn++
 | 
						|
          , PrintIndex++
 | 
						|
          , Walker++
 | 
						|
         ){
 | 
						|
        if (*Walker == CHAR_NULL
 | 
						|
          ||*Walker == CHAR_BACKSPACE
 | 
						|
          ||*Walker == CHAR_LINEFEED
 | 
						|
          ||*Walker == CHAR_CARRIAGE_RETURN
 | 
						|
         ){
 | 
						|
            Walker--;
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        //
 | 
						|
        // The buffer is 2*CursorRow more since it has that many \r\n characters at the end of each row.
 | 
						|
        //
 | 
						|
 | 
						|
        ASSERT(PrintIndex + ConsoleInfo->HistoryMode.CursorRow < ConsoleInfo->BufferSize);
 | 
						|
        ConsoleInfo->Buffer[PrintIndex + (2*ConsoleInfo->HistoryMode.CursorRow)] = *Walker;
 | 
						|
        ASSERT(PrintIndex < ConsoleInfo->AttribSize);
 | 
						|
        ConsoleInfo->Attributes[PrintIndex] = ConsoleInfo->HistoryMode.Attribute;
 | 
						|
      } // for loop
 | 
						|
 | 
						|
      //
 | 
						|
      // Add the carriage return and line feed at the end of the lines
 | 
						|
      //
 | 
						|
      if (ConsoleInfo->HistoryMode.CursorColumn >= (INT32)ConsoleInfo->ColsPerScreen) {
 | 
						|
        AppendStringToHistory(L"\r\n", ConsoleInfo);
 | 
						|
        Walker--;
 | 
						|
      }
 | 
						|
 | 
						|
      break;
 | 
						|
    } // switch for character
 | 
						|
  } // for loop
 | 
						|
 | 
						|
  return (EFI_SUCCESS);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Worker function to handle printing the output to the screen
 | 
						|
  and the history buffer
 | 
						|
 | 
						|
  @param[in] String               The string to output
 | 
						|
  @param[in] ConsoleInfo          The pointer to the instance of the console logger information.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The string was printed
 | 
						|
  @retval EFI_DEVICE_ERROR        The device reported an error while attempting to output
 | 
						|
                                  the text.
 | 
						|
  @retval EFI_UNSUPPORTED         The output device's mode is not currently in a
 | 
						|
                                  defined text mode.
 | 
						|
  @retval EFI_WARN_UNKNOWN_GLYPH  This warning code indicates that some of the
 | 
						|
                                  characters in the Unicode string could not be
 | 
						|
                                  rendered and were skipped.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ConsoleLoggerOutputStringSplit(
 | 
						|
  IN CONST CHAR16   *String,
 | 
						|
  IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS    Status;
 | 
						|
 | 
						|
  //
 | 
						|
  // Forward the request to the original ConOut
 | 
						|
  //
 | 
						|
  Status = ConsoleInfo->OldConOut->OutputString (ConsoleInfo->OldConOut, (CHAR16*)String);
 | 
						|
 | 
						|
  if (EFI_ERROR(Status)) {
 | 
						|
    return (Status);
 | 
						|
  }
 | 
						|
 | 
						|
  return (AppendStringToHistory(String, ConsoleInfo));
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Function to handle page break mode.
 | 
						|
 | 
						|
  This function will prompt for continue or break.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS   Continue was choosen
 | 
						|
  @return other         Break was choosen
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ConsoleLoggerDoPageBreak(
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  SHELL_PROMPT_RESPONSE *Resp;
 | 
						|
  EFI_STATUS            Status;
 | 
						|
 | 
						|
  Resp = NULL;
 | 
						|
  ASSERT(ShellInfoObject.PageBreakEnabled);
 | 
						|
  ShellInfoObject.PageBreakEnabled = FALSE;
 | 
						|
  Status = ShellPromptForResponseHii(ShellPromptResponseTypeQuitContinue, STRING_TOKEN(STR_SHELL_QUIT_CONT), ShellInfoObject.HiiHandle, (VOID**)&Resp);
 | 
						|
  ShellInfoObject.PageBreakEnabled = TRUE;
 | 
						|
  ASSERT(Resp != NULL);
 | 
						|
  if (Resp == NULL) {
 | 
						|
    return (EFI_NOT_FOUND);
 | 
						|
  }
 | 
						|
  if (EFI_ERROR(Status)) {
 | 
						|
    if (Resp != NULL) {
 | 
						|
      FreePool(Resp);
 | 
						|
    }
 | 
						|
    return (Status);
 | 
						|
  }
 | 
						|
  if (*Resp == ShellPromptResponseContinue) {
 | 
						|
    FreePool(Resp);
 | 
						|
    ShellInfoObject.ConsoleInfo->RowCounter                   = 0;
 | 
						|
//    ShellInfoObject.ConsoleInfo->OurConOut.Mode->CursorRow    = 0;
 | 
						|
//    ShellInfoObject.ConsoleInfo->OurConOut.Mode->CursorColumn = 0;
 | 
						|
 | 
						|
    return (EFI_SUCCESS);
 | 
						|
  } else if (*Resp == ShellPromptResponseQuit) {
 | 
						|
    FreePool(Resp);
 | 
						|
    ShellInfoObject.ConsoleInfo->Enabled = FALSE;
 | 
						|
    return (EFI_DEVICE_ERROR);
 | 
						|
  } else {
 | 
						|
    ASSERT(FALSE);
 | 
						|
  }
 | 
						|
  return (EFI_SUCCESS);
 | 
						|
}
 | 
						|
/**
 | 
						|
  Worker function to handle printing the output with page breaks.
 | 
						|
 | 
						|
  @param[in] String               The string to output
 | 
						|
  @param[in] ConsoleInfo          The pointer to the instance of the console logger information.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The string was printed
 | 
						|
  @retval EFI_DEVICE_ERROR        The device reported an error while attempting to output
 | 
						|
                                  the text.
 | 
						|
  @retval EFI_UNSUPPORTED         The output device's mode is not currently in a
 | 
						|
                                  defined text mode.
 | 
						|
  @retval EFI_WARN_UNKNOWN_GLYPH  This warning code indicates that some of the
 | 
						|
                                  characters in the Unicode string could not be
 | 
						|
                                  rendered and were skipped.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ConsoleLoggerPrintWithPageBreak(
 | 
						|
  IN CONST CHAR16   *String,
 | 
						|
  IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
 | 
						|
  )
 | 
						|
{
 | 
						|
  CONST CHAR16  *Walker;
 | 
						|
  CONST CHAR16  *LineStart;
 | 
						|
  CHAR16        *StringCopy;
 | 
						|
  CHAR16        TempChar;
 | 
						|
 | 
						|
  StringCopy = NULL;
 | 
						|
  StringCopy = StrnCatGrow(&StringCopy, NULL, String, 0);
 | 
						|
  if (StringCopy == NULL) {
 | 
						|
    return (EFI_OUT_OF_RESOURCES);
 | 
						|
  }
 | 
						|
 | 
						|
  for ( Walker = StringCopy
 | 
						|
      , LineStart = StringCopy
 | 
						|
      ; Walker != NULL && *Walker != CHAR_NULL
 | 
						|
      ; Walker++
 | 
						|
     ){
 | 
						|
    switch (*Walker) {
 | 
						|
    case (CHAR_BACKSPACE):
 | 
						|
      if (ConsoleInfo->OurConOut.Mode->CursorColumn > 0) {
 | 
						|
        ConsoleInfo->OurConOut.Mode->CursorColumn--;
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case (CHAR_LINEFEED):
 | 
						|
      //
 | 
						|
      // add a temp NULL terminator
 | 
						|
      //
 | 
						|
      TempChar = *(Walker + 1);
 | 
						|
      *((CHAR16*)(Walker+1)) = CHAR_NULL;
 | 
						|
 | 
						|
      //
 | 
						|
      // output the string
 | 
						|
      //
 | 
						|
      ConsoleLoggerOutputStringSplit (LineStart, ConsoleInfo);
 | 
						|
 | 
						|
      //
 | 
						|
      // restore the temp NULL terminator to it's original character
 | 
						|
      //
 | 
						|
      *((CHAR16*)(Walker+1)) = TempChar;
 | 
						|
 | 
						|
      //
 | 
						|
      // Update LineStart Variable
 | 
						|
      //
 | 
						|
      LineStart = Walker + 1;
 | 
						|
 | 
						|
      //
 | 
						|
      // increment row count
 | 
						|
      //
 | 
						|
      ShellInfoObject.ConsoleInfo->RowCounter++;
 | 
						|
      ConsoleInfo->OurConOut.Mode->CursorRow++;
 | 
						|
 | 
						|
      break;
 | 
						|
    case (CHAR_CARRIAGE_RETURN):
 | 
						|
      //
 | 
						|
      // Move the cursor to the beginning of the current row.
 | 
						|
      //
 | 
						|
      ConsoleInfo->OurConOut.Mode->CursorColumn = 0;
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      //
 | 
						|
      // increment column count
 | 
						|
      //
 | 
						|
      ConsoleInfo->OurConOut.Mode->CursorColumn++;
 | 
						|
      //
 | 
						|
      // check if that is the last column
 | 
						|
      //
 | 
						|
      if ((INTN)ConsoleInfo->ColsPerScreen == ConsoleInfo->OurConOut.Mode->CursorColumn + 1) {
 | 
						|
        //
 | 
						|
        // output a line similar to the linefeed character.
 | 
						|
        //
 | 
						|
 | 
						|
        //
 | 
						|
        // add a temp NULL terminator
 | 
						|
        //
 | 
						|
        TempChar = *(Walker + 1);
 | 
						|
        *((CHAR16*)(Walker+1)) = CHAR_NULL;
 | 
						|
 | 
						|
        //
 | 
						|
        // output the string
 | 
						|
        //
 | 
						|
        ConsoleLoggerOutputStringSplit (LineStart, ConsoleInfo);
 | 
						|
 | 
						|
        //
 | 
						|
        // restore the temp NULL terminator to it's original character
 | 
						|
        //
 | 
						|
        *((CHAR16*)(Walker+1)) = TempChar;
 | 
						|
 | 
						|
        //
 | 
						|
        // Update LineStart Variable
 | 
						|
        //
 | 
						|
        LineStart = Walker + 1;
 | 
						|
 | 
						|
        //
 | 
						|
        // increment row count and zero the column
 | 
						|
        //
 | 
						|
        ShellInfoObject.ConsoleInfo->RowCounter++;
 | 
						|
        ConsoleInfo->OurConOut.Mode->CursorRow++;
 | 
						|
        ConsoleInfo->OurConOut.Mode->CursorColumn = 0;
 | 
						|
      } // last column on line
 | 
						|
      break;
 | 
						|
    } // switch for character
 | 
						|
 | 
						|
    //
 | 
						|
    // check if that was the last printable row.  If yes handle PageBreak mode
 | 
						|
    //
 | 
						|
    if ((ConsoleInfo->RowsPerScreen) -1 == ShellInfoObject.ConsoleInfo->RowCounter) {
 | 
						|
      if (EFI_ERROR(ConsoleLoggerDoPageBreak())) {
 | 
						|
        //
 | 
						|
        // We got an error which means 'break' and halt the printing
 | 
						|
        //
 | 
						|
        SHELL_FREE_NON_NULL(StringCopy);
 | 
						|
        return (EFI_DEVICE_ERROR);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } // for loop
 | 
						|
 | 
						|
  if (LineStart != NULL && *LineStart != CHAR_NULL) {
 | 
						|
    ConsoleLoggerOutputStringSplit (LineStart, ConsoleInfo);
 | 
						|
  }
 | 
						|
 | 
						|
  SHELL_FREE_NON_NULL(StringCopy);
 | 
						|
  return (EFI_SUCCESS);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Write a Unicode string to the output device.
 | 
						|
 | 
						|
  @param[in] This                 Protocol instance pointer.
 | 
						|
  @param[in] WString              The NULL-terminated Unicode string to be displayed on the output
 | 
						|
                                  device(s). All output devices must also support the Unicode
 | 
						|
                                  drawing defined in this file.
 | 
						|
  @retval EFI_SUCCESS             The string was output to the device.
 | 
						|
  @retval EFI_DEVICE_ERROR        The device reported an error while attempting to output
 | 
						|
                                  the text.
 | 
						|
  @retval EFI_UNSUPPORTED         The output device's mode is not currently in a
 | 
						|
                                  defined text mode.
 | 
						|
  @retval EFI_WARN_UNKNOWN_GLYPH  This warning code indicates that some of the
 | 
						|
                                  characters in the Unicode string could not be
 | 
						|
                                  rendered and were skipped.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ConsoleLoggerOutputString (
 | 
						|
  IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
 | 
						|
  IN  CHAR16                          *WString
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_INPUT_KEY               Key;
 | 
						|
  UINTN                       EventIndex;
 | 
						|
  CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;
 | 
						|
  ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);
 | 
						|
  if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut) {
 | 
						|
    return (EFI_UNSUPPORTED);
 | 
						|
  }
 | 
						|
  ASSERT(ShellInfoObject.ConsoleInfo == ConsoleInfo);
 | 
						|
  if (ShellInfoObject.HaltOutput) {
 | 
						|
    //
 | 
						|
    // just get some key
 | 
						|
    //
 | 
						|
    gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);
 | 
						|
    gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
 | 
						|
    ShellInfoObject.HaltOutput = FALSE;
 | 
						|
  }
 | 
						|
  if (!ShellInfoObject.ConsoleInfo->Enabled) {
 | 
						|
    return (EFI_DEVICE_ERROR);
 | 
						|
  } else if (ShellInfoObject.PageBreakEnabled) {
 | 
						|
    return (ConsoleLoggerPrintWithPageBreak(WString, ConsoleInfo));
 | 
						|
  } else {
 | 
						|
    return (ConsoleLoggerOutputStringSplit(WString, ConsoleInfo));
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Verifies that all characters in a Unicode string can be output to the
 | 
						|
  target device.
 | 
						|
 | 
						|
  @param[in] This     Protocol instance pointer.
 | 
						|
  @param[in] WString  The NULL-terminated Unicode string to be examined for the output
 | 
						|
                      device(s).
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           The device(s) are capable of rendering the output string.
 | 
						|
  @retval EFI_UNSUPPORTED       Some of the characters in the Unicode string cannot be
 | 
						|
                                rendered by one or more of the output devices mapped
 | 
						|
                                by the EFI handle.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ConsoleLoggerTestString (
 | 
						|
  IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
 | 
						|
  IN  CHAR16                        *WString
 | 
						|
  )
 | 
						|
{
 | 
						|
  CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;
 | 
						|
  ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);
 | 
						|
  //
 | 
						|
  // Forward the request to the original ConOut
 | 
						|
  //
 | 
						|
  return (ConsoleInfo->OldConOut->TestString (ConsoleInfo->OldConOut, WString));
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Returns information for an available text mode that the output device(s)
 | 
						|
  supports.
 | 
						|
 | 
						|
  @param[in] This               Protocol instance pointer.
 | 
						|
  @param[in] ModeNumber         The mode number to return information on.
 | 
						|
  @param[out] Columns           Upon return, the number of columns in the selected geometry
 | 
						|
  @param[out] Rows              Upon return, the number of rows in the selected geometry
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           The requested mode information was returned.
 | 
						|
  @retval EFI_DEVICE_ERROR      The device had an error and could not
 | 
						|
                                complete the request.
 | 
						|
  @retval EFI_UNSUPPORTED       The mode number was not valid.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ConsoleLoggerQueryMode (
 | 
						|
  IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
 | 
						|
  IN  UINTN                         ModeNumber,
 | 
						|
  OUT UINTN                         *Columns,
 | 
						|
  OUT UINTN                         *Rows
 | 
						|
  )
 | 
						|
{
 | 
						|
  CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;
 | 
						|
  ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);
 | 
						|
  //
 | 
						|
  // Forward the request to the original ConOut
 | 
						|
  //
 | 
						|
  return (ConsoleInfo->OldConOut->QueryMode (
 | 
						|
    ConsoleInfo->OldConOut,
 | 
						|
    ModeNumber,
 | 
						|
    Columns,
 | 
						|
    Rows
 | 
						|
   ));
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Sets the output device(s) to a specified mode.
 | 
						|
 | 
						|
  @param[in] This               Protocol instance pointer.
 | 
						|
  @param[in] ModeNumber         The mode number to set.
 | 
						|
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           The requested text mode was set.
 | 
						|
  @retval EFI_DEVICE_ERROR      The device had an error and
 | 
						|
                                could not complete the request.
 | 
						|
  @retval EFI_UNSUPPORTED       The mode number was not valid.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ConsoleLoggerSetMode (
 | 
						|
  IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL   *This,
 | 
						|
  IN  UINTN                             ModeNumber
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                  Status;
 | 
						|
 | 
						|
  CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;
 | 
						|
  ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);
 | 
						|
 | 
						|
  //
 | 
						|
  // Forward the request to the original ConOut
 | 
						|
  //
 | 
						|
  Status = ConsoleInfo->OldConOut->SetMode (ConsoleInfo->OldConOut, ModeNumber);
 | 
						|
 | 
						|
  //
 | 
						|
  // Check that the buffers are still correct for logging
 | 
						|
  //
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    ConsoleInfo->OurConOut.Mode = gST->ConOut->Mode;
 | 
						|
    ConsoleLoggerResetBuffers(ConsoleInfo);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Sets the background and foreground colors for the OutputString () and
 | 
						|
  ClearScreen () functions.
 | 
						|
 | 
						|
  @param[in] This               Protocol instance pointer.
 | 
						|
  @param[in] Attribute          The attribute to set. Bits 0..3 are the foreground color, and
 | 
						|
                                bits 4..6 are the background color. All other bits are undefined
 | 
						|
                                and must be zero. The valid Attributes are defined in this file.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           The attribute was set.
 | 
						|
  @retval EFI_DEVICE_ERROR      The device had an error and
 | 
						|
                                could not complete the request.
 | 
						|
  @retval EFI_UNSUPPORTED       The attribute requested is not defined.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ConsoleLoggerSetAttribute (
 | 
						|
  IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
 | 
						|
  IN  UINTN                           Attribute
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                  Status;
 | 
						|
 | 
						|
  CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;
 | 
						|
  ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);
 | 
						|
 | 
						|
  //
 | 
						|
  // Forward the request to the original ConOut
 | 
						|
  //
 | 
						|
  Status = ConsoleInfo->OldConOut->SetAttribute (ConsoleInfo->OldConOut, Attribute);
 | 
						|
 | 
						|
  //
 | 
						|
  // Record console output history
 | 
						|
  //
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    ConsoleInfo->HistoryMode.Attribute = (INT32) Attribute;
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Clears the output device(s) display to the currently selected background
 | 
						|
  color.
 | 
						|
 | 
						|
  @param[in] This               Protocol instance pointer.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           The operation completed successfully.
 | 
						|
  @retval EFI_DEVICE_ERROR      The device had an error and
 | 
						|
                                could not complete the request.
 | 
						|
  @retval EFI_UNSUPPORTED       The output device is not in a valid text mode.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ConsoleLoggerClearScreen (
 | 
						|
  IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS        Status;
 | 
						|
  CHAR16            *Screen;
 | 
						|
  INT32             *Attributes;
 | 
						|
  UINTN             Row;
 | 
						|
  UINTN             Column;
 | 
						|
  CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;
 | 
						|
 | 
						|
  if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut) {
 | 
						|
    return (EFI_UNSUPPORTED);
 | 
						|
  }
 | 
						|
 | 
						|
  ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);
 | 
						|
 | 
						|
  //
 | 
						|
  // Forward the request to the original ConOut
 | 
						|
  //
 | 
						|
  Status = ConsoleInfo->OldConOut->ClearScreen (ConsoleInfo->OldConOut);
 | 
						|
 | 
						|
  //
 | 
						|
  // Record console output history
 | 
						|
  //
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    Screen = &ConsoleInfo->Buffer[(ConsoleInfo->ColsPerScreen + 2) * ConsoleInfo->CurrentStartRow];
 | 
						|
    Attributes = &ConsoleInfo->Attributes[ConsoleInfo->ColsPerScreen * ConsoleInfo->CurrentStartRow];
 | 
						|
    for ( Row = ConsoleInfo->OriginalStartRow
 | 
						|
        ; Row < (ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount)
 | 
						|
        ; Row++
 | 
						|
       ){
 | 
						|
      for ( Column = 0
 | 
						|
          ; Column < ConsoleInfo->ColsPerScreen
 | 
						|
          ; Column++
 | 
						|
          , Screen++
 | 
						|
          , Attributes++
 | 
						|
         ){
 | 
						|
        *Screen = L' ';
 | 
						|
        *Attributes = ConsoleInfo->OldConOut->Mode->Attribute;
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // Skip the NULL on each column end in text buffer only
 | 
						|
      //
 | 
						|
      Screen += 2;
 | 
						|
    }
 | 
						|
    ConsoleInfo->HistoryMode.CursorColumn = 0;
 | 
						|
    ConsoleInfo->HistoryMode.CursorRow    = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Sets the current coordinates of the cursor position
 | 
						|
 | 
						|
  @param[in] This               Protocol instance pointer.
 | 
						|
  @param[in] Column             Column to put the cursor in.  Must be between zero and Column returned from QueryMode
 | 
						|
  @param[in] Row                Row to put the cursor in.  Must be between zero and Row returned from QueryMode
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           The operation completed successfully.
 | 
						|
  @retval EFI_DEVICE_ERROR      The device had an error and
 | 
						|
                                could not complete the request.
 | 
						|
  @retval EFI_UNSUPPORTED       The output device is not in a valid text mode, or the
 | 
						|
                                cursor position is invalid for the current mode.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ConsoleLoggerSetCursorPosition (
 | 
						|
  IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
 | 
						|
  IN  UINTN                         Column,
 | 
						|
  IN  UINTN                         Row
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                  Status;
 | 
						|
  CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;
 | 
						|
 | 
						|
  if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut) {
 | 
						|
    return (EFI_UNSUPPORTED);
 | 
						|
  }
 | 
						|
 | 
						|
  ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);
 | 
						|
  //
 | 
						|
  // Forward the request to the original ConOut
 | 
						|
  //
 | 
						|
  Status = ConsoleInfo->OldConOut->SetCursorPosition (
 | 
						|
    ConsoleInfo->OldConOut,
 | 
						|
    Column,
 | 
						|
    Row
 | 
						|
   );
 | 
						|
 | 
						|
  //
 | 
						|
  // Record console output history
 | 
						|
  //
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    ConsoleInfo->HistoryMode.CursorColumn = (INT32)Column;
 | 
						|
    ConsoleInfo->HistoryMode.CursorRow    = (INT32)(ConsoleInfo->OriginalStartRow + Row);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Makes the cursor visible or invisible
 | 
						|
 | 
						|
  @param[in] This       Protocol instance pointer.
 | 
						|
  @param[in] Visible    If TRUE, the cursor is set to be visible. If FALSE, the cursor is
 | 
						|
                        set to be invisible.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           The operation completed successfully.
 | 
						|
  @retval EFI_DEVICE_ERROR      The device had an error and could not complete the
 | 
						|
                                request, or the device does not support changing
 | 
						|
                                the cursor mode.
 | 
						|
  @retval EFI_UNSUPPORTED       The output device is not in a valid text mode.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ConsoleLoggerEnableCursor (
 | 
						|
  IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
 | 
						|
  IN  BOOLEAN                       Visible
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                  Status;
 | 
						|
 | 
						|
  CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;
 | 
						|
  ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);
 | 
						|
  //
 | 
						|
  // Forward the request to the original ConOut
 | 
						|
  //
 | 
						|
  Status = ConsoleInfo->OldConOut->EnableCursor (ConsoleInfo->OldConOut, Visible);
 | 
						|
 | 
						|
  //
 | 
						|
  // Record console output history
 | 
						|
  //
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    ConsoleInfo->HistoryMode.CursorVisible = Visible;
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Function to update and verify that the current buffers are correct.
 | 
						|
 | 
						|
  @param[in] ConsoleInfo  The pointer to the instance of the console logger information.
 | 
						|
 | 
						|
  This will be used when a mode has changed or a reset ocurred to verify all
 | 
						|
  history buffers.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ConsoleLoggerResetBuffers(
 | 
						|
  IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS Status;
 | 
						|
 | 
						|
  if (ConsoleInfo->Buffer != NULL) {
 | 
						|
    FreePool(ConsoleInfo->Buffer);
 | 
						|
    ConsoleInfo->Buffer     = NULL;
 | 
						|
    ConsoleInfo->BufferSize = 0;
 | 
						|
  }
 | 
						|
  if (ConsoleInfo->Attributes != NULL) {
 | 
						|
    FreePool(ConsoleInfo->Attributes);
 | 
						|
    ConsoleInfo->Attributes = NULL;
 | 
						|
    ConsoleInfo->AttribSize = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &ConsoleInfo->ColsPerScreen, &ConsoleInfo->RowsPerScreen);
 | 
						|
  if (EFI_ERROR(Status)){
 | 
						|
    return (Status);
 | 
						|
  }
 | 
						|
 | 
						|
  ConsoleInfo->BufferSize = (ConsoleInfo->ColsPerScreen + 2) * ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount * sizeof(ConsoleInfo->Buffer[0]);
 | 
						|
  ConsoleInfo->AttribSize = ConsoleInfo->ColsPerScreen * ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount * sizeof(ConsoleInfo->Attributes[0]);
 | 
						|
 | 
						|
  ConsoleInfo->Buffer = (CHAR16*)AllocateZeroPool(ConsoleInfo->BufferSize);
 | 
						|
 | 
						|
  if (ConsoleInfo->Buffer == NULL) {
 | 
						|
    return (EFI_OUT_OF_RESOURCES);
 | 
						|
  }
 | 
						|
 | 
						|
  ConsoleInfo->Attributes = (INT32*)AllocateZeroPool(ConsoleInfo->AttribSize);
 | 
						|
  if (ConsoleInfo->Attributes == NULL) {
 | 
						|
    FreePool(ConsoleInfo->Buffer);
 | 
						|
    ConsoleInfo->Buffer     = NULL;
 | 
						|
    return (EFI_OUT_OF_RESOURCES);
 | 
						|
  }
 | 
						|
 | 
						|
  CopyMem (&ConsoleInfo->HistoryMode, ConsoleInfo->OldConOut->Mode, sizeof (EFI_SIMPLE_TEXT_OUTPUT_MODE));
 | 
						|
 | 
						|
  return (EFI_SUCCESS);
 | 
						|
}
 |