mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-11-04 05:25:45 +01:00 
			
		
		
		
	git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			1077 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1077 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*++
 | 
						|
 | 
						|
Copyright (c) 2006, Intel Corporation                                                         
 | 
						|
All rights reserved. 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.             
 | 
						|
 | 
						|
Module Name:
 | 
						|
  
 | 
						|
  ConSplitterGraphics.c
 | 
						|
 | 
						|
Abstract:
 | 
						|
 | 
						|
  Support for ConsoleControl protocol. Support for UGA Draw spliter.
 | 
						|
  Support for DevNull Console Out. This console uses memory buffers
 | 
						|
  to represnt the console. It allows a console to start very early and
 | 
						|
  when a new console is added it is synced up with the current console
 | 
						|
 | 
						|
--*/
 | 
						|
 | 
						|
 | 
						|
#include "ConSplitter.h"
 | 
						|
 | 
						|
static CHAR16 mCrLfString[3] = { CHAR_CARRIAGE_RETURN, CHAR_LINEFEED, CHAR_NULL };
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ConSpliterConsoleControlGetMode (
 | 
						|
  IN  EFI_CONSOLE_CONTROL_PROTOCOL    *This,
 | 
						|
  OUT EFI_CONSOLE_CONTROL_SCREEN_MODE *Mode,
 | 
						|
  OUT BOOLEAN                         *UgaExists,
 | 
						|
  OUT BOOLEAN                         *StdInLocked
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
  Routine Description:
 | 
						|
    Return the current video mode information. Also returns info about existence
 | 
						|
    of UGA Draw devices in system, and if the Std In device is locked. All the
 | 
						|
    arguments are optional and only returned if a non NULL pointer is passed in.
 | 
						|
 | 
						|
  Arguments:
 | 
						|
    This - Protocol instance pointer.
 | 
						|
    Mode        - Are we in text of grahics mode.
 | 
						|
    UgaExists   - TRUE if UGA Spliter has found a UGA device
 | 
						|
    StdInLocked - TRUE if StdIn device is keyboard locked
 | 
						|
 | 
						|
  Returns:
 | 
						|
    EFI_SUCCESS - Mode information returned.
 | 
						|
    EFI_INVALID_PARAMETER - Invalid parameters.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private;
 | 
						|
  UINTN                           Index;
 | 
						|
 | 
						|
  Private = CONSOLE_CONTROL_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
 | 
						|
 | 
						|
  if (Mode == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  *Mode = Private->UgaMode;
 | 
						|
 | 
						|
  if (UgaExists != NULL) {
 | 
						|
    *UgaExists = FALSE;
 | 
						|
    for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
 | 
						|
      if (Private->TextOutList[Index].UgaDraw != NULL) {
 | 
						|
        *UgaExists = TRUE;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (StdInLocked != NULL) {
 | 
						|
    *StdInLocked = ConSpliterConssoleControlStdInLocked ();
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ConSpliterConsoleControlSetMode (
 | 
						|
  IN  EFI_CONSOLE_CONTROL_PROTOCOL    *This,
 | 
						|
  IN  EFI_CONSOLE_CONTROL_SCREEN_MODE Mode
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
  Routine Description:
 | 
						|
    Set the current mode to either text or graphics. Graphics is
 | 
						|
    for Quiet Boot.
 | 
						|
 | 
						|
  Arguments:
 | 
						|
    This  - Protocol instance pointer.
 | 
						|
    Mode  - Mode to set the 
 | 
						|
 | 
						|
  Returns:
 | 
						|
    EFI_SUCCESS     - Mode information returned.
 | 
						|
    EFI_INVALID_PARAMETER - Invalid parameter.
 | 
						|
    EFI_UNSUPPORTED - Operation unsupported.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private;
 | 
						|
  UINTN                           Index;
 | 
						|
  TEXT_OUT_AND_UGA_DATA           *TextAndUga;
 | 
						|
  BOOLEAN                         Supported;
 | 
						|
 | 
						|
  Private = CONSOLE_CONTROL_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
 | 
						|
 | 
						|
  if (Mode >= EfiConsoleControlScreenMaxValue) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Supported   = FALSE;
 | 
						|
  TextAndUga  = &Private->TextOutList[0];
 | 
						|
  for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++, TextAndUga++) {
 | 
						|
    if (TextAndUga->UgaDraw != NULL) {
 | 
						|
      Supported = TRUE;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if ((!Supported) && (Mode == EfiConsoleControlScreenGraphics)) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  Private->UgaMode  = Mode;
 | 
						|
 | 
						|
  TextAndUga        = &Private->TextOutList[0];
 | 
						|
  for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++, TextAndUga++) {
 | 
						|
 | 
						|
    TextAndUga->TextOutEnabled = TRUE;
 | 
						|
    //
 | 
						|
    // If we are going into Graphics mode disable ConOut to any UGA device
 | 
						|
    //
 | 
						|
    if ((Mode == EfiConsoleControlScreenGraphics) && (TextAndUga->UgaDraw != NULL)) {
 | 
						|
      TextAndUga->TextOutEnabled = FALSE;
 | 
						|
      DevNullUgaSync (Private, TextAndUga->UgaDraw);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (Mode == EfiConsoleControlScreenText) {
 | 
						|
    DevNullSyncUgaStdOut (Private);
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ConSpliterUgaDrawGetMode (
 | 
						|
  IN  EFI_UGA_DRAW_PROTOCOL           *This,
 | 
						|
  OUT UINT32                          *HorizontalResolution,
 | 
						|
  OUT UINT32                          *VerticalResolution,
 | 
						|
  OUT UINT32                          *ColorDepth,
 | 
						|
  OUT UINT32                          *RefreshRate
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
  Routine Description:
 | 
						|
    Return the current video mode information.
 | 
						|
 | 
						|
  Arguments:
 | 
						|
    This                  - Protocol instance pointer.
 | 
						|
    HorizontalResolution  - Current video horizontal resolution in pixels
 | 
						|
    VerticalResolution    - Current video vertical resolution in pixels
 | 
						|
    ColorDepth            - Current video color depth in bits per pixel
 | 
						|
    RefreshRate           - Current video refresh rate in Hz.
 | 
						|
 | 
						|
  Returns:
 | 
						|
    EFI_SUCCESS           - Mode information returned.
 | 
						|
    EFI_NOT_STARTED       - Video display is not initialized. Call SetMode () 
 | 
						|
    EFI_INVALID_PARAMETER - One of the input args was NULL.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private;
 | 
						|
 | 
						|
  if (!(HorizontalResolution && VerticalResolution && RefreshRate && ColorDepth)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // retrieve private data
 | 
						|
  //
 | 
						|
  Private               = UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
 | 
						|
 | 
						|
  *HorizontalResolution = Private->UgaHorizontalResolution;
 | 
						|
  *VerticalResolution   = Private->UgaVerticalResolution;
 | 
						|
  *ColorDepth           = Private->UgaColorDepth;
 | 
						|
  *RefreshRate          = Private->UgaRefreshRate;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ConSpliterUgaDrawSetMode (
 | 
						|
  IN  EFI_UGA_DRAW_PROTOCOL           *This,
 | 
						|
  IN UINT32                           HorizontalResolution,
 | 
						|
  IN UINT32                           VerticalResolution,
 | 
						|
  IN UINT32                           ColorDepth,
 | 
						|
  IN UINT32                           RefreshRate
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
  Routine Description:
 | 
						|
    Return the current video mode information.
 | 
						|
 | 
						|
  Arguments:
 | 
						|
    This                  - Protocol instance pointer.
 | 
						|
    HorizontalResolution  - Current video horizontal resolution in pixels
 | 
						|
    VerticalResolution    - Current video vertical resolution in pixels
 | 
						|
    ColorDepth            - Current video color depth in bits per pixel
 | 
						|
    RefreshRate           - Current video refresh rate in Hz.
 | 
						|
 | 
						|
  Returns:
 | 
						|
    EFI_SUCCESS     - Mode information returned.
 | 
						|
    EFI_NOT_STARTED - Video display is not initialized. Call SetMode () 
 | 
						|
    EFI_OUT_OF_RESOURCES - Out of resources.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS                      Status;
 | 
						|
  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private;
 | 
						|
  UINTN                           Index;
 | 
						|
  EFI_STATUS                      ReturnStatus;
 | 
						|
  UINTN                           Size;
 | 
						|
 | 
						|
  Private = UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
 | 
						|
 | 
						|
  //
 | 
						|
  // UgaDevNullSetMode ()
 | 
						|
  //
 | 
						|
  ReturnStatus = EFI_SUCCESS;
 | 
						|
 | 
						|
  //
 | 
						|
  // Free the old version
 | 
						|
  //
 | 
						|
  gBS->FreePool (Private->UgaBlt);
 | 
						|
 | 
						|
  //
 | 
						|
  // Allocate the virtual Blt buffer
 | 
						|
  //
 | 
						|
  Size            = HorizontalResolution * VerticalResolution * sizeof (EFI_UGA_PIXEL);
 | 
						|
  Private->UgaBlt = AllocateZeroPool (Size);
 | 
						|
  if (Private->UgaBlt == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Update the Mode data
 | 
						|
  //
 | 
						|
  Private->UgaHorizontalResolution  = HorizontalResolution;
 | 
						|
  Private->UgaVerticalResolution    = VerticalResolution;
 | 
						|
  Private->UgaColorDepth            = ColorDepth;
 | 
						|
  Private->UgaRefreshRate           = RefreshRate;
 | 
						|
 | 
						|
  if (Private->UgaMode != EfiConsoleControlScreenGraphics) {
 | 
						|
    return ReturnStatus;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // return the worst status met
 | 
						|
  //
 | 
						|
  for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
 | 
						|
    if (Private->TextOutList[Index].UgaDraw != NULL) {
 | 
						|
      Status = Private->TextOutList[Index].UgaDraw->SetMode (
 | 
						|
                                                      Private->TextOutList[Index].UgaDraw,
 | 
						|
                                                      HorizontalResolution,
 | 
						|
                                                      VerticalResolution,
 | 
						|
                                                      ColorDepth,
 | 
						|
                                                      RefreshRate
 | 
						|
                                                      );
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        ReturnStatus = Status;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return ReturnStatus;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
DevNullUgaBlt (
 | 
						|
  IN  TEXT_OUT_SPLITTER_PRIVATE_DATA                *Private,
 | 
						|
  IN  EFI_UGA_PIXEL                                 *BltBuffer, OPTIONAL
 | 
						|
  IN  EFI_UGA_BLT_OPERATION                         BltOperation,
 | 
						|
  IN  UINTN                                         SourceX,
 | 
						|
  IN  UINTN                                         SourceY,
 | 
						|
  IN  UINTN                                         DestinationX,
 | 
						|
  IN  UINTN                                         DestinationY,
 | 
						|
  IN  UINTN                                         Width,
 | 
						|
  IN  UINTN                                         Height,
 | 
						|
  IN  UINTN                                         Delta         OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN         SrcY;
 | 
						|
  UINTN         Index;
 | 
						|
  EFI_UGA_PIXEL *BltPtr;
 | 
						|
  EFI_UGA_PIXEL *ScreenPtr;
 | 
						|
  UINT32        HorizontalResolution;
 | 
						|
  UINT32        VerticalResolution;
 | 
						|
 | 
						|
  if ((BltOperation < 0) || (BltOperation >= EfiUgaBltMax)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Width == 0 || Height == 0) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Delta == 0) {
 | 
						|
    Delta = Width * sizeof (EFI_UGA_PIXEL);
 | 
						|
  }
 | 
						|
 | 
						|
  HorizontalResolution  = Private->UgaHorizontalResolution;
 | 
						|
  VerticalResolution    = Private->UgaVerticalResolution;
 | 
						|
 | 
						|
  //
 | 
						|
  // We need to fill the Virtual Screen buffer with the blt data.
 | 
						|
  //
 | 
						|
  if (BltOperation == EfiUgaVideoToBltBuffer) {
 | 
						|
    //
 | 
						|
    // Video to BltBuffer: Source is Video, destination is BltBuffer
 | 
						|
    //
 | 
						|
    if ((SourceY + Height) > VerticalResolution) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((SourceX + Width) > HorizontalResolution) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    BltPtr    = (EFI_UGA_PIXEL *) ((UINT8 *) BltBuffer + DestinationY * Delta + DestinationX * sizeof (EFI_UGA_PIXEL));
 | 
						|
    ScreenPtr = &Private->UgaBlt[SourceY * HorizontalResolution + SourceX];
 | 
						|
    while (Height) {
 | 
						|
      CopyMem (BltPtr, ScreenPtr, Width * sizeof (EFI_UGA_PIXEL));
 | 
						|
      BltPtr = (EFI_UGA_PIXEL *) ((UINT8 *) BltPtr + Delta);
 | 
						|
      ScreenPtr += HorizontalResolution;
 | 
						|
      Height--;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // BltBuffer to Video: Source is BltBuffer, destination is Video
 | 
						|
    //
 | 
						|
    if (DestinationY + Height > VerticalResolution) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    if (DestinationX + Width > HorizontalResolution) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    ScreenPtr = &Private->UgaBlt[DestinationY * HorizontalResolution + DestinationX];
 | 
						|
    SrcY      = SourceY;
 | 
						|
    while (Height) {
 | 
						|
      if (BltOperation == EfiUgaVideoFill) {
 | 
						|
        for (Index = 0; Index < Width; Index++) {
 | 
						|
          ScreenPtr[Index] = *BltBuffer;
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        if (BltOperation == EfiUgaBltBufferToVideo) {
 | 
						|
          BltPtr = (EFI_UGA_PIXEL *) ((UINT8 *) BltBuffer + SrcY * Delta + SourceX * sizeof (EFI_UGA_PIXEL));
 | 
						|
        } else {
 | 
						|
          BltPtr = &Private->UgaBlt[SrcY * HorizontalResolution + SourceX];
 | 
						|
        }
 | 
						|
 | 
						|
        CopyMem (ScreenPtr, BltPtr, Width * sizeof (EFI_UGA_PIXEL));
 | 
						|
      }
 | 
						|
 | 
						|
      ScreenPtr += HorizontalResolution;
 | 
						|
      SrcY++;
 | 
						|
      Height--;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ConSpliterUgaDrawBlt (
 | 
						|
  IN  EFI_UGA_DRAW_PROTOCOL                         *This,
 | 
						|
  IN  EFI_UGA_PIXEL                                 *BltBuffer, OPTIONAL
 | 
						|
  IN  EFI_UGA_BLT_OPERATION                         BltOperation,
 | 
						|
  IN  UINTN                                         SourceX,
 | 
						|
  IN  UINTN                                         SourceY,
 | 
						|
  IN  UINTN                                         DestinationX,
 | 
						|
  IN  UINTN                                         DestinationY,
 | 
						|
  IN  UINTN                                         Width,
 | 
						|
  IN  UINTN                                         Height,
 | 
						|
  IN  UINTN                                         Delta         OPTIONAL
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
  Routine Description:
 | 
						|
    The following table defines actions for BltOperations:
 | 
						|
    EfiUgaVideoFill - Write data from the  BltBuffer pixel (SourceX, SourceY) 
 | 
						|
      directly to every pixel of the video display rectangle 
 | 
						|
      (DestinationX, DestinationY) 
 | 
						|
      (DestinationX + Width, DestinationY + Height).
 | 
						|
      Only one pixel will be used from the BltBuffer. Delta is NOT used.
 | 
						|
    EfiUgaVideoToBltBuffer - Read data from the video display rectangle 
 | 
						|
      (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in 
 | 
						|
      the BltBuffer rectangle (DestinationX, DestinationY ) 
 | 
						|
      (DestinationX + Width, DestinationY + Height). If DestinationX or 
 | 
						|
      DestinationY is not zero then Delta must be set to the length in bytes 
 | 
						|
      of a row in the BltBuffer.
 | 
						|
    EfiUgaBltBufferToVideo - Write data from the  BltBuffer rectangle 
 | 
						|
      (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the 
 | 
						|
      video display rectangle (DestinationX, DestinationY) 
 | 
						|
      (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is 
 | 
						|
      not zero then Delta must be set to the length in bytes of a row in the 
 | 
						|
      BltBuffer.
 | 
						|
    EfiUgaVideoToVideo - Copy from the video display rectangle 
 | 
						|
      (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
 | 
						|
      to the video display rectangle (DestinationX, DestinationY) 
 | 
						|
      (DestinationX + Width, DestinationY + Height). 
 | 
						|
     The BltBuffer and Delta  are not used in this mode.
 | 
						|
 | 
						|
  Arguments:
 | 
						|
    This          - Protocol instance pointer.
 | 
						|
    BltBuffer     - Buffer containing data to blit into video buffer. This 
 | 
						|
                    buffer has a size of Width*Height*sizeof(EFI_UGA_PIXEL)
 | 
						|
    BltOperation  - Operation to perform on BlitBuffer and video memory
 | 
						|
    SourceX       - X coordinate of source for the BltBuffer.
 | 
						|
    SourceY       - Y coordinate of source for the BltBuffer.
 | 
						|
    DestinationX  - X coordinate of destination for the BltBuffer.
 | 
						|
    DestinationY  - Y coordinate of destination for the BltBuffer.
 | 
						|
    Width         - Width of rectangle in BltBuffer in pixels.
 | 
						|
    Height        - Hight of rectangle in BltBuffer in pixels.
 | 
						|
    Delta         -
 | 
						|
  
 | 
						|
  Returns:
 | 
						|
    EFI_SUCCESS           - The Blt operation completed.
 | 
						|
    EFI_INVALID_PARAMETER - BltOperation is not valid.
 | 
						|
    EFI_DEVICE_ERROR      - A hardware error occured writting to the video 
 | 
						|
                             buffer.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS                      Status;
 | 
						|
  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private;
 | 
						|
  UINTN                           Index;
 | 
						|
  EFI_STATUS                      ReturnStatus;
 | 
						|
 | 
						|
  Private = UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
 | 
						|
 | 
						|
  //
 | 
						|
  // Sync up DevNull UGA device
 | 
						|
  //
 | 
						|
  ReturnStatus = DevNullUgaBlt (
 | 
						|
                  Private,
 | 
						|
                  BltBuffer,
 | 
						|
                  BltOperation,
 | 
						|
                  SourceX,
 | 
						|
                  SourceY,
 | 
						|
                  DestinationX,
 | 
						|
                  DestinationY,
 | 
						|
                  Width,
 | 
						|
                  Height,
 | 
						|
                  Delta
 | 
						|
                  );
 | 
						|
  if (Private->UgaMode != EfiConsoleControlScreenGraphics) {
 | 
						|
    return ReturnStatus;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // return the worst status met
 | 
						|
  //
 | 
						|
  for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
 | 
						|
    if (Private->TextOutList[Index].UgaDraw != NULL) {
 | 
						|
      Status = Private->TextOutList[Index].UgaDraw->Blt (
 | 
						|
                                                      Private->TextOutList[Index].UgaDraw,
 | 
						|
                                                      BltBuffer,
 | 
						|
                                                      BltOperation,
 | 
						|
                                                      SourceX,
 | 
						|
                                                      SourceY,
 | 
						|
                                                      DestinationX,
 | 
						|
                                                      DestinationY,
 | 
						|
                                                      Width,
 | 
						|
                                                      Height,
 | 
						|
                                                      Delta
 | 
						|
                                                      );
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        ReturnStatus = Status;
 | 
						|
      } else if (BltOperation == EfiUgaVideoToBltBuffer) {
 | 
						|
        //
 | 
						|
        // Only need to read the data into buffer one time
 | 
						|
        //
 | 
						|
        return EFI_SUCCESS;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return ReturnStatus;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
DevNullUgaSync (
 | 
						|
  IN  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private,
 | 
						|
  IN  EFI_UGA_DRAW_PROTOCOL           *UgaDraw
 | 
						|
  )
 | 
						|
{
 | 
						|
  return UgaDraw->Blt (
 | 
						|
                    UgaDraw,
 | 
						|
                    Private->UgaBlt,
 | 
						|
                    EfiUgaBltBufferToVideo,
 | 
						|
                    0,
 | 
						|
                    0,
 | 
						|
                    0,
 | 
						|
                    0,
 | 
						|
                    Private->UgaHorizontalResolution,
 | 
						|
                    Private->UgaVerticalResolution,
 | 
						|
                    Private->UgaHorizontalResolution * sizeof (EFI_UGA_PIXEL)
 | 
						|
                    );
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
DevNullTextOutOutputString (
 | 
						|
  IN  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private,
 | 
						|
  IN  CHAR16                          *WString
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
  Routine Description:
 | 
						|
    Write a Unicode string to the output device.
 | 
						|
 | 
						|
  Arguments:
 | 
						|
    Private - Pointer to the console output splitter's private data. It
 | 
						|
              indicates the calling context.
 | 
						|
    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.
 | 
						|
 | 
						|
  Returns:
 | 
						|
    EFI_SUCCESS            - The string was output to the device.
 | 
						|
    EFI_DEVICE_ERROR       - The device reported an error while attempting to 
 | 
						|
                              output the text.
 | 
						|
    EFI_UNSUPPORTED        - The output device's mode is not currently in a 
 | 
						|
                              defined text mode.
 | 
						|
    EFI_WARN_UNKNOWN_GLYPH - This warning code indicates that some of the 
 | 
						|
                              characters in the Unicode string could not be 
 | 
						|
                              rendered and were skipped.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  UINTN                       SizeScreen;
 | 
						|
  UINTN                       SizeAttribute;
 | 
						|
  UINTN                       Index;
 | 
						|
  EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode;
 | 
						|
  CHAR16                      *Screen;
 | 
						|
  CHAR16                      *NullScreen;
 | 
						|
  CHAR16                      InsertChar;
 | 
						|
  CHAR16                      TempChar;
 | 
						|
  CHAR16                      *PStr;
 | 
						|
  INT32                       *Attribute;
 | 
						|
  INT32                       *NullAttributes;
 | 
						|
  INT32                       CurrentWidth;
 | 
						|
  UINTN                       LastRow;
 | 
						|
  UINTN                       MaxColumn;
 | 
						|
 | 
						|
  Mode            = &Private->TextOutMode;
 | 
						|
  NullScreen      = Private->DevNullScreen;
 | 
						|
  NullAttributes  = Private->DevNullAttributes;
 | 
						|
  LastRow         = Private->DevNullRows - 1;
 | 
						|
  MaxColumn       = Private->DevNullColumns;
 | 
						|
 | 
						|
  if (Mode->Attribute & EFI_WIDE_ATTRIBUTE) {
 | 
						|
    CurrentWidth = 2;
 | 
						|
  } else {
 | 
						|
    CurrentWidth = 1;
 | 
						|
  }
 | 
						|
 | 
						|
  while (*WString) {
 | 
						|
 | 
						|
    if (*WString == CHAR_BACKSPACE) {
 | 
						|
      //
 | 
						|
      // If the cursor is at the left edge of the display, then move the cursor
 | 
						|
      // one row up.
 | 
						|
      //
 | 
						|
      if (Mode->CursorColumn == 0 && Mode->CursorRow > 0) {
 | 
						|
        Mode->CursorRow--;
 | 
						|
        Mode->CursorColumn = (INT32) MaxColumn;
 | 
						|
      }
 | 
						|
 | 
						|
      //
 | 
						|
      // If the cursor is not at the left edge of the display,
 | 
						|
      // then move the cursor left one column.
 | 
						|
      //
 | 
						|
      if (Mode->CursorColumn > 0) {
 | 
						|
        Mode->CursorColumn--;
 | 
						|
        if (Mode->CursorColumn > 0 &&
 | 
						|
            NullAttributes[Mode->CursorRow * MaxColumn + Mode->CursorColumn - 1] & EFI_WIDE_ATTRIBUTE
 | 
						|
            ) {
 | 
						|
          Mode->CursorColumn--;
 | 
						|
 | 
						|
          //
 | 
						|
          // Insert an extra backspace
 | 
						|
          //
 | 
						|
          InsertChar  = CHAR_BACKSPACE;
 | 
						|
          PStr        = WString + 1;
 | 
						|
          while (*PStr) {
 | 
						|
            TempChar    = *PStr;
 | 
						|
            *PStr       = InsertChar;
 | 
						|
            InsertChar  = TempChar;
 | 
						|
            PStr++;
 | 
						|
          }
 | 
						|
 | 
						|
          *PStr     = InsertChar;
 | 
						|
          *(++PStr) = 0;
 | 
						|
 | 
						|
          WString++;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      WString++;
 | 
						|
 | 
						|
    } else if (*WString == CHAR_LINEFEED) {
 | 
						|
      //
 | 
						|
      // If the cursor is at the bottom of the display,
 | 
						|
      // then scroll the display one row, and do not update
 | 
						|
      // the cursor position. Otherwise, move the cursor down one row.
 | 
						|
      //
 | 
						|
      if (Mode->CursorRow == (INT32) (LastRow)) {
 | 
						|
        //
 | 
						|
        // Scroll Screen Up One Row
 | 
						|
        //
 | 
						|
        SizeAttribute = LastRow * MaxColumn;
 | 
						|
        CopyMem (
 | 
						|
          NullAttributes,
 | 
						|
          NullAttributes + MaxColumn,
 | 
						|
          SizeAttribute * sizeof (INT32)
 | 
						|
          );
 | 
						|
 | 
						|
        //
 | 
						|
        // Each row has an ending CHAR_NULL. So one more character each line
 | 
						|
        // for DevNullScreen than DevNullAttributes
 | 
						|
        //
 | 
						|
        SizeScreen = SizeAttribute + LastRow;
 | 
						|
        CopyMem (
 | 
						|
          NullScreen,
 | 
						|
          NullScreen + (MaxColumn + 1),
 | 
						|
          SizeScreen * sizeof (CHAR16)
 | 
						|
          );
 | 
						|
 | 
						|
        //
 | 
						|
        // Print Blank Line at last line
 | 
						|
        //
 | 
						|
        Screen    = NullScreen + SizeScreen;
 | 
						|
        Attribute = NullAttributes + SizeAttribute;
 | 
						|
 | 
						|
        for (Index = 0; Index < MaxColumn; Index++, Screen++, Attribute++) {
 | 
						|
          *Screen     = ' ';
 | 
						|
          *Attribute  = Mode->Attribute;
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        Mode->CursorRow++;
 | 
						|
      }
 | 
						|
 | 
						|
      WString++;
 | 
						|
    } else if (*WString == CHAR_CARRIAGE_RETURN) {
 | 
						|
      //
 | 
						|
      // Move the cursor to the beginning of the current row.
 | 
						|
      //
 | 
						|
      Mode->CursorColumn = 0;
 | 
						|
      WString++;
 | 
						|
    } else {
 | 
						|
      //
 | 
						|
      // Print the character at the current cursor position and
 | 
						|
      // move the cursor right one column. If this moves the cursor
 | 
						|
      // past the right edge of the display, then the line should wrap to
 | 
						|
      // the beginning of the next line. This is equivalent to inserting
 | 
						|
      // a CR and an LF. Note that if the cursor is at the bottom of the
 | 
						|
      // display, and the line wraps, then the display will be scrolled
 | 
						|
      // one line.
 | 
						|
      //
 | 
						|
      Index = Mode->CursorRow * MaxColumn + Mode->CursorColumn;
 | 
						|
 | 
						|
      while (Mode->CursorColumn < (INT32) MaxColumn) {
 | 
						|
        if (*WString == CHAR_NULL) {
 | 
						|
          break;
 | 
						|
        }
 | 
						|
 | 
						|
        if (*WString == CHAR_BACKSPACE) {
 | 
						|
          break;
 | 
						|
        }
 | 
						|
 | 
						|
        if (*WString == CHAR_LINEFEED) {
 | 
						|
          break;
 | 
						|
        }
 | 
						|
 | 
						|
        if (*WString == CHAR_CARRIAGE_RETURN) {
 | 
						|
          break;
 | 
						|
        }
 | 
						|
 | 
						|
        if (*WString == WIDE_CHAR || *WString == NARROW_CHAR) {
 | 
						|
          CurrentWidth = (*WString == WIDE_CHAR) ? 2 : 1;
 | 
						|
          WString++;
 | 
						|
          continue;
 | 
						|
        }
 | 
						|
 | 
						|
        if (Mode->CursorColumn + CurrentWidth > (INT32) MaxColumn) {
 | 
						|
          //
 | 
						|
          // If a wide char is at the rightmost column, then move the char
 | 
						|
          // to the beginning of the next row
 | 
						|
          //
 | 
						|
          NullScreen[Index + Mode->CursorRow] = L' ';
 | 
						|
          NullAttributes[Index]               = Mode->Attribute | (UINT32) EFI_WIDE_ATTRIBUTE;
 | 
						|
          Index++;
 | 
						|
          Mode->CursorColumn++;
 | 
						|
        } else {
 | 
						|
          NullScreen[Index + Mode->CursorRow] = *WString;
 | 
						|
          NullAttributes[Index]               = Mode->Attribute;
 | 
						|
          if (CurrentWidth == 1) {
 | 
						|
            NullAttributes[Index] &= (~ (UINT32) EFI_WIDE_ATTRIBUTE);
 | 
						|
          } else {
 | 
						|
            NullAttributes[Index] |= (UINT32) EFI_WIDE_ATTRIBUTE;
 | 
						|
            NullAttributes[Index + 1] &= (~ (UINT32) EFI_WIDE_ATTRIBUTE);
 | 
						|
          }
 | 
						|
 | 
						|
          Index += CurrentWidth;
 | 
						|
          WString++;
 | 
						|
          Mode->CursorColumn += CurrentWidth;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // At the end of line, output carriage return and line feed
 | 
						|
      //
 | 
						|
      if (Mode->CursorColumn >= (INT32) MaxColumn) {
 | 
						|
        DevNullTextOutOutputString (Private, mCrLfString);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
DevNullTextOutSetMode (
 | 
						|
  IN  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private,
 | 
						|
  IN  UINTN                           ModeNumber
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
  Routine Description:
 | 
						|
    Sets the output device(s) to a specified mode.
 | 
						|
 | 
						|
  Arguments:
 | 
						|
    Private    - Private data structure pointer.
 | 
						|
    ModeNumber - The mode number to set.
 | 
						|
 | 
						|
  Returns:
 | 
						|
    EFI_SUCCESS      - The requested text mode was set.
 | 
						|
    EFI_DEVICE_ERROR - The device had an error and 
 | 
						|
                       could not complete the request.
 | 
						|
    EFI_UNSUPPORTED - The mode number was not valid.
 | 
						|
    EFI_OUT_OF_RESOURCES - Out of resources.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  UINTN                         Size;
 | 
						|
  UINTN                         Row;
 | 
						|
  UINTN                         Column;
 | 
						|
  TEXT_OUT_SPLITTER_QUERY_DATA  *Mode;
 | 
						|
 | 
						|
  //
 | 
						|
  // No extra check for ModeNumber here, as it has been checked in
 | 
						|
  // ConSplitterTextOutSetMode. And mode 0 should always be supported.
 | 
						|
  //
 | 
						|
  Mode    = &(Private->TextOutQueryData[ModeNumber]);
 | 
						|
  Row     = Mode->Rows;
 | 
						|
  Column  = Mode->Columns;
 | 
						|
 | 
						|
  if (Row <= 0 && Column <= 0) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Private->DevNullColumns != Column || Private->DevNullRows != Row) {
 | 
						|
 | 
						|
    Private->TextOutMode.Mode = (INT32) ModeNumber;
 | 
						|
    Private->DevNullColumns   = Column;
 | 
						|
    Private->DevNullRows      = Row;
 | 
						|
 | 
						|
    gBS->FreePool (Private->DevNullScreen);
 | 
						|
 | 
						|
    Size                    = (Row * (Column + 1)) * sizeof (CHAR16);
 | 
						|
    Private->DevNullScreen  = AllocateZeroPool (Size);
 | 
						|
    if (Private->DevNullScreen == NULL) {
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
 | 
						|
    gBS->FreePool (Private->DevNullAttributes);
 | 
						|
 | 
						|
    Size                        = Row * Column * sizeof (INT32);
 | 
						|
    Private->DevNullAttributes  = AllocateZeroPool (Size);
 | 
						|
    if (Private->DevNullAttributes == NULL) {
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  DevNullTextOutClearScreen (Private);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
DevNullTextOutClearScreen (
 | 
						|
  IN  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
  Routine Description:
 | 
						|
    Clears the output device(s) display to the currently selected background 
 | 
						|
    color.
 | 
						|
 | 
						|
  Arguments:
 | 
						|
    Private     - Protocol instance pointer.
 | 
						|
 | 
						|
  Returns:
 | 
						|
    EFI_SUCCESS      - The operation completed successfully.
 | 
						|
    EFI_DEVICE_ERROR - The device had an error and 
 | 
						|
                       could not complete the request.
 | 
						|
    EFI_UNSUPPORTED - The output device is not in a valid text mode.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  UINTN   Row;
 | 
						|
  UINTN   Column;
 | 
						|
  CHAR16  *Screen;
 | 
						|
  INT32   *Attributes;
 | 
						|
  INT32   CurrentAttribute;
 | 
						|
 | 
						|
  //
 | 
						|
  // Clear the DevNull Text Out Buffers.
 | 
						|
  // The screen is filled with spaces.
 | 
						|
  // The attributes are all synced with the current Simple Text Out Attribute
 | 
						|
  //
 | 
						|
  Screen            = Private->DevNullScreen;
 | 
						|
  Attributes        = Private->DevNullAttributes;
 | 
						|
  CurrentAttribute  = Private->TextOutMode.Attribute;
 | 
						|
 | 
						|
  for (Row = 0; Row < Private->DevNullRows; Row++) {
 | 
						|
    for (Column = 0; Column < Private->DevNullColumns; Column++, Screen++, Attributes++) {
 | 
						|
      *Screen     = ' ';
 | 
						|
      *Attributes = CurrentAttribute;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Each line of the screen has a NULL on the end so we must skip over it
 | 
						|
    //
 | 
						|
    Screen++;
 | 
						|
  }
 | 
						|
 | 
						|
  DevNullTextOutSetCursorPosition (Private, 0, 0);
 | 
						|
 | 
						|
  return DevNullTextOutEnableCursor (Private, TRUE);
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
DevNullTextOutSetCursorPosition (
 | 
						|
  IN  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private,
 | 
						|
  IN  UINTN                           Column,
 | 
						|
  IN  UINTN                           Row
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
  Routine Description:
 | 
						|
    Sets the current coordinates of the cursor position
 | 
						|
 | 
						|
  Arguments:
 | 
						|
    Private       - Protocol instance pointer.
 | 
						|
    Column, Row - the position to set the cursor to. Must be greater than or
 | 
						|
                  equal to zero and less than the number of columns and rows
 | 
						|
                  by QueryMode ().
 | 
						|
 | 
						|
  Returns:
 | 
						|
    EFI_SUCCESS      - The operation completed successfully.
 | 
						|
    EFI_DEVICE_ERROR - The device had an error and 
 | 
						|
                       could not complete the request.
 | 
						|
    EFI_UNSUPPORTED - The output device is not in a valid text mode, or the 
 | 
						|
                       cursor position is invalid for the current mode.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  //
 | 
						|
  // No need to do extra check here as whether (Column, Row) is valid has
 | 
						|
  // been checked in ConSplitterTextOutSetCursorPosition. And (0, 0) should
 | 
						|
  // always be supported.
 | 
						|
  //
 | 
						|
  Private->TextOutMode.CursorColumn = (INT32) Column;
 | 
						|
  Private->TextOutMode.CursorRow    = (INT32) Row;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
DevNullTextOutEnableCursor (
 | 
						|
  IN  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private,
 | 
						|
  IN  BOOLEAN                         Visible
 | 
						|
  )
 | 
						|
/*++
 | 
						|
  Routine Description:
 | 
						|
  
 | 
						|
    Implements SIMPLE_TEXT_OUTPUT.EnableCursor().
 | 
						|
    In this driver, the cursor cannot be hidden.        
 | 
						|
  
 | 
						|
  Arguments:
 | 
						|
  
 | 
						|
    Private - Indicates the calling context.
 | 
						|
        
 | 
						|
    Visible - If TRUE, the cursor is set to be visible, If FALSE, the cursor 
 | 
						|
              is set to be invisible.        
 | 
						|
 | 
						|
  Returns:
 | 
						|
  
 | 
						|
    EFI_SUCCESS - The request is valid.
 | 
						|
       
 | 
						|
               
 | 
						|
--*/
 | 
						|
{
 | 
						|
  Private->TextOutMode.CursorVisible = Visible;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
DevNullSyncUgaStdOut (
 | 
						|
  IN  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private
 | 
						|
  )
 | 
						|
/*++
 | 
						|
  Routine Description:
 | 
						|
    Take the DevNull TextOut device and update the Simple Text Out on every
 | 
						|
    UGA device. 
 | 
						|
 
 | 
						|
  Arguments:
 | 
						|
    Private - Indicates the calling context.
 | 
						|
 | 
						|
  Returns:
 | 
						|
    EFI_SUCCESS - The request is valid.
 | 
						|
    other       - Return status of TextOut->OutputString ()
 | 
						|
               
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS                    Status;
 | 
						|
  EFI_STATUS                    ReturnStatus;
 | 
						|
  UINTN                         Row;
 | 
						|
  UINTN                         Column;
 | 
						|
  UINTN                         List;
 | 
						|
  UINTN                         MaxColumn;
 | 
						|
  UINTN                         CurrentColumn;
 | 
						|
  UINTN                         StartRow;
 | 
						|
  UINTN                         StartColumn;
 | 
						|
  INT32                         StartAttribute;
 | 
						|
  BOOLEAN                       StartCursorState;
 | 
						|
  CHAR16                        *Screen;
 | 
						|
  CHAR16                        *Str;
 | 
						|
  CHAR16                        *Buffer;
 | 
						|
  CHAR16                        *BufferTail;
 | 
						|
  CHAR16                        *ScreenStart;
 | 
						|
  INT32                         CurrentAttribute;
 | 
						|
  INT32                         *Attributes;
 | 
						|
  EFI_SIMPLE_TEXT_OUT_PROTOCOL  *Sto;
 | 
						|
 | 
						|
  //
 | 
						|
  // Save the devices Attributes, Cursor enable state and location
 | 
						|
  //
 | 
						|
  StartColumn       = Private->TextOutMode.CursorColumn;
 | 
						|
  StartRow          = Private->TextOutMode.CursorRow;
 | 
						|
  StartAttribute    = Private->TextOutMode.Attribute;
 | 
						|
  StartCursorState  = Private->TextOutMode.CursorVisible;
 | 
						|
 | 
						|
  for (List = 0; List < Private->CurrentNumberOfConsoles; List++) {
 | 
						|
 | 
						|
    Sto = Private->TextOutList[List].TextOut;
 | 
						|
 | 
						|
    //
 | 
						|
    // Skip non UGA devices
 | 
						|
    //
 | 
						|
    if (Private->TextOutList[List].UgaDraw != NULL) {
 | 
						|
      Sto->EnableCursor (Sto, FALSE);
 | 
						|
      Sto->ClearScreen (Sto);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  ReturnStatus  = EFI_SUCCESS;
 | 
						|
  Screen        = Private->DevNullScreen;
 | 
						|
  Attributes    = Private->DevNullAttributes;
 | 
						|
  MaxColumn     = Private->DevNullColumns;
 | 
						|
 | 
						|
  Buffer        = AllocateZeroPool ((MaxColumn + 1) * sizeof (CHAR16));
 | 
						|
 | 
						|
  for (Row = 0; Row < Private->DevNullRows; Row++, Screen += (MaxColumn + 1), Attributes += MaxColumn) {
 | 
						|
 | 
						|
    if (Row == (Private->DevNullRows - 1)) {
 | 
						|
      //
 | 
						|
      // Don't ever sync the last character as it will scroll the screen
 | 
						|
      //
 | 
						|
      Screen[MaxColumn - 1] = 0x00;
 | 
						|
    }
 | 
						|
 | 
						|
    Column = 0;
 | 
						|
    while (Column < MaxColumn) {
 | 
						|
      if (Screen[Column]) {
 | 
						|
        CurrentAttribute  = Attributes[Column];
 | 
						|
        CurrentColumn     = Column;
 | 
						|
        ScreenStart       = &Screen[Column];
 | 
						|
 | 
						|
        //
 | 
						|
        // the line end is alway 0x0. So Column should be less than MaxColumn
 | 
						|
        // It should be still in the same row
 | 
						|
        //
 | 
						|
        for (Str = ScreenStart, BufferTail = Buffer; *Str != 0; Str++, Column++) {
 | 
						|
 | 
						|
          if (Attributes[Column] != CurrentAttribute) {
 | 
						|
            Column--;
 | 
						|
            break;
 | 
						|
          }
 | 
						|
 | 
						|
          *BufferTail = *Str;
 | 
						|
          BufferTail++;
 | 
						|
          if (Attributes[Column] & EFI_WIDE_ATTRIBUTE) {
 | 
						|
            Str++;
 | 
						|
            Column++;
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        *BufferTail = 0;
 | 
						|
 | 
						|
        for (List = 0; List < Private->CurrentNumberOfConsoles; List++) {
 | 
						|
 | 
						|
          Sto = Private->TextOutList[List].TextOut;
 | 
						|
 | 
						|
          //
 | 
						|
          // Skip non UGA devices
 | 
						|
          //
 | 
						|
          if (Private->TextOutList[List].UgaDraw != NULL) {
 | 
						|
            Sto->SetAttribute (Sto, CurrentAttribute);
 | 
						|
            Sto->SetCursorPosition (Sto, CurrentColumn, Row);
 | 
						|
            Status = Sto->OutputString (Sto, Buffer);
 | 
						|
            if (EFI_ERROR (Status)) {
 | 
						|
              ReturnStatus = Status;
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
      }
 | 
						|
 | 
						|
      Column++;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Restore the devices Attributes, Cursor enable state and location
 | 
						|
  //
 | 
						|
  for (List = 0; List < Private->CurrentNumberOfConsoles; List++) {
 | 
						|
    Sto = Private->TextOutList[List].TextOut;
 | 
						|
 | 
						|
    //
 | 
						|
    // Skip non UGA devices
 | 
						|
    //
 | 
						|
    if (Private->TextOutList[List].UgaDraw != NULL) {
 | 
						|
      Sto->SetAttribute (Sto, StartAttribute);
 | 
						|
      Sto->SetCursorPosition (Sto, StartColumn, StartRow);
 | 
						|
      Status = Sto->EnableCursor (Sto, StartCursorState);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        ReturnStatus = Status;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  gBS->FreePool (Buffer);
 | 
						|
 | 
						|
  return ReturnStatus;
 | 
						|
}
 |