2.Code scrub. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@7269 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			1763 lines
		
	
	
		
			62 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1763 lines
		
	
	
		
			62 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Support for ConsoleControl protocol. Support for Graphics output 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.
 | 
						|
 | 
						|
Copyright (c) 2006 - 2008, Intel Corporation. <BR>
 | 
						|
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.
 | 
						|
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "ConSplitter.h"
 | 
						|
 | 
						|
 | 
						|
CHAR16 mCrLfString[3] = { CHAR_CARRIAGE_RETURN, CHAR_LINEFEED, CHAR_NULL };
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Return the current video mode information. Also returns info about existence
 | 
						|
  of Graphics Output devices or UGA Draw devices in system, and whether the Std
 | 
						|
  In device is locked. GopUgaExists and StdInLocked parameters are optional, and
 | 
						|
  only returned if a non NULL pointer is passed in.
 | 
						|
 | 
						|
  @param  This                    Protocol instance pointer.
 | 
						|
  @param  Mode                    Current video mode.
 | 
						|
  @param  GopUgaExists            TRUE if GOP Spliter has found a GOP/UGA device
 | 
						|
  @param  StdInLocked             TRUE if StdIn device is keyboard locked
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             Video mode information is returned.
 | 
						|
  @retval EFI_INVALID_PARAMETER   Invalid parameters if Mode == NULL.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ConSpliterConsoleControlGetMode (
 | 
						|
  IN  EFI_CONSOLE_CONTROL_PROTOCOL    *This,
 | 
						|
  OUT EFI_CONSOLE_CONTROL_SCREEN_MODE *Mode,
 | 
						|
  OUT BOOLEAN                         *GopUgaExists,
 | 
						|
  OUT BOOLEAN                         *StdInLocked
 | 
						|
  )
 | 
						|
{
 | 
						|
  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->ConsoleOutputMode;
 | 
						|
 | 
						|
  if (GopUgaExists != NULL) {
 | 
						|
    *GopUgaExists = FALSE;
 | 
						|
    for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
 | 
						|
      if ((Private->TextOutList[Index].GraphicsOutput != NULL) || (Private->TextOutList[Index].UgaDraw != NULL)) {
 | 
						|
        *GopUgaExists = TRUE;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (StdInLocked != NULL) {
 | 
						|
    *StdInLocked = ConSpliterConssoleControlStdInLocked ();
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Set the current video mode to either text or graphics. Graphics is
 | 
						|
  for Quiet Boot.
 | 
						|
 | 
						|
  @param  This                    Console Control Protocol instance pointer.
 | 
						|
  @param  Mode                    Video mode is to be set.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             Mode is set successfully.
 | 
						|
  @retval EFI_INVALID_PARAMETER   Mode is not the valid mode value.
 | 
						|
  @retval EFI_UNSUPPORTED         Mode is unsupported by console device.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ConSpliterConsoleControlSetMode (
 | 
						|
  IN  EFI_CONSOLE_CONTROL_PROTOCOL    *This,
 | 
						|
  IN  EFI_CONSOLE_CONTROL_SCREEN_MODE Mode
 | 
						|
  )
 | 
						|
{
 | 
						|
  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private;
 | 
						|
  UINTN                           Index;
 | 
						|
  TEXT_OUT_AND_GOP_DATA           *TextAndGop;
 | 
						|
  BOOLEAN                         Supported;
 | 
						|
 | 
						|
  Private = CONSOLE_CONTROL_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
 | 
						|
 | 
						|
  if (Mode >= EfiConsoleControlScreenMaxValue) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Judge current mode with wanted mode at first.
 | 
						|
  //
 | 
						|
  if (Private->ConsoleOutputMode == Mode) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  Supported   = FALSE;
 | 
						|
  TextAndGop  = &Private->TextOutList[0];
 | 
						|
  for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++, TextAndGop++) {
 | 
						|
    if ((TextAndGop->GraphicsOutput != NULL) || (TextAndGop->UgaDraw != NULL)) {
 | 
						|
      Supported = TRUE;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if ((!Supported) && (Mode == EfiConsoleControlScreenGraphics)) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  Private->ConsoleOutputMode  = Mode;
 | 
						|
 | 
						|
  TextAndGop = &Private->TextOutList[0];
 | 
						|
  for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++, TextAndGop++) {
 | 
						|
 | 
						|
    TextAndGop->TextOutEnabled = TRUE;
 | 
						|
    //
 | 
						|
    // If we are going into Graphics mode disable ConOut to any UGA device
 | 
						|
    //
 | 
						|
    if ((Mode == EfiConsoleControlScreenGraphics) &&((TextAndGop->GraphicsOutput != NULL) || (TextAndGop->UgaDraw != NULL))) {
 | 
						|
      TextAndGop->TextOutEnabled = FALSE;
 | 
						|
      if (FeaturePcdGet (PcdConOutGopSupport)) {
 | 
						|
        DevNullGopSync (Private, TextAndGop->GraphicsOutput, TextAndGop->UgaDraw);
 | 
						|
      } else if (FeaturePcdGet (PcdConOutUgaSupport)) {
 | 
						|
        DevNullUgaSync (Private, TextAndGop->GraphicsOutput, TextAndGop->UgaDraw);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (Mode == EfiConsoleControlScreenText) {
 | 
						|
    DevNullSyncStdOut (Private);
 | 
						|
  }
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Returns information for an available graphics mode that the graphics device
 | 
						|
  and the set of active video output devices supports.
 | 
						|
 | 
						|
  @param  This                  The EFI_GRAPHICS_OUTPUT_PROTOCOL instance.
 | 
						|
  @param  ModeNumber            The mode number to return information on.
 | 
						|
  @param  SizeOfInfo            A pointer to the size, in bytes, of the Info buffer.
 | 
						|
  @param  Info                  A pointer to callee allocated buffer that returns information about ModeNumber.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           Mode information returned.
 | 
						|
  @retval EFI_BUFFER_TOO_SMALL  The Info buffer was too small.
 | 
						|
  @retval EFI_DEVICE_ERROR      A hardware error occurred trying to retrieve the video mode.
 | 
						|
  @retval EFI_NOT_STARTED       Video display is not initialized. Call SetMode ()
 | 
						|
  @retval EFI_INVALID_PARAMETER One of the input args was NULL.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  No resource available.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ConSpliterGraphicsOutputQueryMode (
 | 
						|
  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL          *This,
 | 
						|
  IN  UINT32                                ModeNumber,
 | 
						|
  OUT UINTN                                 *SizeOfInfo,
 | 
						|
  OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  **Info
 | 
						|
  )
 | 
						|
{
 | 
						|
  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private;
 | 
						|
 | 
						|
  if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // retrieve private data
 | 
						|
  //
 | 
						|
  Private = GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
 | 
						|
 | 
						|
  if (Private->HardwareNeedsStarting) {
 | 
						|
    return EFI_NOT_STARTED;
 | 
						|
  }
 | 
						|
 | 
						|
  *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
 | 
						|
  if (*Info == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
 | 
						|
 | 
						|
  CopyMem (*Info, &Private->GraphicsOutputModeBuffer[ModeNumber], *SizeOfInfo);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Set the video device into the specified mode and clears the visible portions of
 | 
						|
  the output display to black.
 | 
						|
 | 
						|
  @param  This                  The EFI_GRAPHICS_OUTPUT_PROTOCOL instance.
 | 
						|
  @param  ModeNumber            Abstraction that defines the current video mode.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           The graphics mode specified by ModeNumber was selected.
 | 
						|
  @retval EFI_DEVICE_ERROR      The device had an error and could not complete the request.
 | 
						|
  @retval EFI_UNSUPPORTED       ModeNumber is not supported by this device.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  No resource available.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ConSpliterGraphicsOutputSetMode (
 | 
						|
  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL * This,
 | 
						|
  IN  UINT32                       ModeNumber
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                             Status;
 | 
						|
  TEXT_OUT_SPLITTER_PRIVATE_DATA         *Private;
 | 
						|
  UINTN                                  Index;
 | 
						|
  EFI_STATUS                             ReturnStatus;
 | 
						|
  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION   *Mode;
 | 
						|
  UINTN                                  Size;
 | 
						|
  EFI_GRAPHICS_OUTPUT_PROTOCOL           *GraphicsOutput;
 | 
						|
  UINTN                                  NumberIndex;
 | 
						|
  UINTN                                  SizeOfInfo;
 | 
						|
  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION   *Info;
 | 
						|
  EFI_UGA_DRAW_PROTOCOL                  *UgaDraw;
 | 
						|
 | 
						|
  if (ModeNumber >= This->Mode->MaxMode) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  if (ModeNumber == This->Mode->Mode) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  Private = GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
 | 
						|
 | 
						|
  ReturnStatus = EFI_SUCCESS;
 | 
						|
 | 
						|
  //
 | 
						|
  // Free the old version
 | 
						|
  //
 | 
						|
  if (Private->GraphicsOutputBlt != NULL) {
 | 
						|
    FreePool (Private->GraphicsOutputBlt);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Allocate the virtual Blt buffer
 | 
						|
  //
 | 
						|
  Mode = &Private->GraphicsOutputModeBuffer[ModeNumber];
 | 
						|
  Size = Mode->HorizontalResolution * Mode->VerticalResolution * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
 | 
						|
  Private->GraphicsOutputBlt = AllocateZeroPool (Size);
 | 
						|
 | 
						|
  if (Private->GraphicsOutputBlt == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // return the worst status met
 | 
						|
  //
 | 
						|
  for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
 | 
						|
    GraphicsOutput = Private->TextOutList[Index].GraphicsOutput;
 | 
						|
    if (GraphicsOutput != NULL) {
 | 
						|
      //
 | 
						|
      // Find corresponding ModeNumber of this GraphicsOutput instance
 | 
						|
      //
 | 
						|
      for (NumberIndex = 0; NumberIndex < GraphicsOutput->Mode->MaxMode; NumberIndex ++) {
 | 
						|
        Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) NumberIndex, &SizeOfInfo, &Info);
 | 
						|
        if (EFI_ERROR (Status)) {
 | 
						|
          return Status;
 | 
						|
        }
 | 
						|
        if ((Info->HorizontalResolution == Mode->HorizontalResolution) && (Info->VerticalResolution == Mode->VerticalResolution)) {
 | 
						|
          FreePool (Info);
 | 
						|
          break;
 | 
						|
        }
 | 
						|
        FreePool (Info);
 | 
						|
      }
 | 
						|
 | 
						|
      Status = GraphicsOutput->SetMode (GraphicsOutput, (UINT32) NumberIndex);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        ReturnStatus = Status;
 | 
						|
      }
 | 
						|
    } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
 | 
						|
      UgaDraw = Private->TextOutList[Index].UgaDraw;
 | 
						|
      if (UgaDraw != NULL) {
 | 
						|
        Status = UgaDraw->SetMode (
 | 
						|
                            UgaDraw,
 | 
						|
                            Mode->HorizontalResolution,
 | 
						|
                            Mode->VerticalResolution,
 | 
						|
                            32,
 | 
						|
                            60
 | 
						|
                            );
 | 
						|
        if (EFI_ERROR (Status)) {
 | 
						|
          ReturnStatus = Status;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  This->Mode->Mode = ModeNumber;
 | 
						|
 | 
						|
  CopyMem (This->Mode->Info, &Private->GraphicsOutputModeBuffer[ModeNumber], This->Mode->SizeOfInfo);
 | 
						|
 | 
						|
  //
 | 
						|
  // Information is not enough here, so the following items remain unchanged:
 | 
						|
  //  GraphicsOutputMode->Info->Version, GraphicsOutputMode->Info->PixelFormat
 | 
						|
  //  GraphicsOutputMode->SizeOfInfo, GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize
 | 
						|
  // These items will be initialized/updated when a new GOP device is added into ConsoleSplitter.
 | 
						|
  //
 | 
						|
 | 
						|
  Private->HardwareNeedsStarting = FALSE;
 | 
						|
 | 
						|
  return ReturnStatus;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  The following table defines actions for BltOperations.
 | 
						|
 | 
						|
  EfiBltVideoFill - 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.
 | 
						|
  EfiBltVideoToBltBuffer - 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.
 | 
						|
  EfiBltBufferToVideo - 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.
 | 
						|
  EfiBltVideoToVideo - 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.
 | 
						|
 | 
						|
  @param  Private                 Protocol instance pointer.
 | 
						|
  @param  BltBuffer               Buffer containing data to blit into video buffer.
 | 
						|
                                  This buffer has a size of
 | 
						|
                                  Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
 | 
						|
  @param  BltOperation            Operation to perform on BlitBuffer and video
 | 
						|
                                  memory
 | 
						|
  @param  SourceX                 X coordinate of source for the BltBuffer.
 | 
						|
  @param  SourceY                 Y coordinate of source for the BltBuffer.
 | 
						|
  @param  DestinationX            X coordinate of destination for the BltBuffer.
 | 
						|
  @param  DestinationY            Y coordinate of destination for the BltBuffer.
 | 
						|
  @param  Width                   Width of rectangle in BltBuffer in pixels.
 | 
						|
  @param  Height                  Hight of rectangle in BltBuffer in pixels.
 | 
						|
  @param  Delta                   OPTIONAL.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The Blt operation completed.
 | 
						|
  @retval EFI_INVALID_PARAMETER   BltOperation is not valid.
 | 
						|
  @retval EFI_DEVICE_ERROR        A hardware error occured writting to the video
 | 
						|
                                  buffer.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
DevNullGraphicsOutputBlt (
 | 
						|
  IN  TEXT_OUT_SPLITTER_PRIVATE_DATA                *Private,
 | 
						|
  IN  EFI_GRAPHICS_OUTPUT_BLT_PIXEL                 *BltBuffer, OPTIONAL
 | 
						|
  IN  EFI_GRAPHICS_OUTPUT_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;
 | 
						|
  BOOLEAN                       Forward;
 | 
						|
  UINTN                         Index;
 | 
						|
  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltPtr;
 | 
						|
  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *ScreenPtr;
 | 
						|
  UINTN                         HorizontalResolution;
 | 
						|
  UINTN                         VerticalResolution;
 | 
						|
 | 
						|
  if ((BltOperation < EfiBltVideoFill) || (BltOperation >= EfiGraphicsOutputBltOperationMax)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Width == 0 || Height == 0) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Delta == 0) {
 | 
						|
    Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
 | 
						|
  }
 | 
						|
 | 
						|
  HorizontalResolution  = Private->GraphicsOutput.Mode->Info->HorizontalResolution;
 | 
						|
  VerticalResolution    = Private->GraphicsOutput.Mode->Info->VerticalResolution;
 | 
						|
 | 
						|
  //
 | 
						|
  // We need to fill the Virtual Screen buffer with the blt data.
 | 
						|
  //
 | 
						|
  if (BltOperation == EfiBltVideoToBltBuffer) {
 | 
						|
    //
 | 
						|
    // 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_GRAPHICS_OUTPUT_BLT_PIXEL *) ((UINT8 *) BltBuffer + DestinationY * Delta + DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
 | 
						|
    ScreenPtr = &Private->GraphicsOutputBlt[SourceY * HorizontalResolution + SourceX];
 | 
						|
    while (Height > 0) {
 | 
						|
      CopyMem (BltPtr, ScreenPtr, Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
 | 
						|
      BltPtr = (EFI_GRAPHICS_OUTPUT_BLT_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;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((BltOperation == EfiBltVideoToVideo) && (DestinationY > SourceY)) {
 | 
						|
      //
 | 
						|
      // Copy backwards, only care the Video to Video Blt
 | 
						|
      //
 | 
						|
      ScreenPtr = &Private->GraphicsOutputBlt[(DestinationY + Height - 1) * HorizontalResolution + DestinationX];
 | 
						|
      SrcY      = SourceY + Height - 1;
 | 
						|
      Forward   = FALSE;
 | 
						|
    } else {
 | 
						|
      //
 | 
						|
      // Copy forwards, for other cases
 | 
						|
      //
 | 
						|
      ScreenPtr = &Private->GraphicsOutputBlt[DestinationY * HorizontalResolution + DestinationX];
 | 
						|
      SrcY      = SourceY;
 | 
						|
      Forward   = TRUE;
 | 
						|
    }
 | 
						|
 | 
						|
    while (Height != 0) {
 | 
						|
      if (BltOperation == EfiBltVideoFill) {
 | 
						|
        for (Index = 0; Index < Width; Index++) {
 | 
						|
          ScreenPtr[Index] = *BltBuffer;
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        if (BltOperation == EfiBltBufferToVideo) {
 | 
						|
          BltPtr = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) ((UINT8 *) BltBuffer + SrcY * Delta + SourceX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
 | 
						|
        } else {
 | 
						|
          BltPtr = &Private->GraphicsOutputBlt[SrcY * HorizontalResolution + SourceX];
 | 
						|
        }
 | 
						|
 | 
						|
        CopyMem (ScreenPtr, BltPtr, Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
 | 
						|
      }
 | 
						|
 | 
						|
      if (Forward) {
 | 
						|
        ScreenPtr += HorizontalResolution;
 | 
						|
        SrcY ++;
 | 
						|
      } else {
 | 
						|
        ScreenPtr -= HorizontalResolution;
 | 
						|
        SrcY --;
 | 
						|
      }
 | 
						|
      Height--;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  The following table defines actions for BltOperations.
 | 
						|
 | 
						|
  EfiBltVideoFill - 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.
 | 
						|
  EfiBltVideoToBltBuffer - 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.
 | 
						|
  EfiBltBufferToVideo - 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.
 | 
						|
  EfiBltVideoToVideo - 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.
 | 
						|
 | 
						|
  @param  This                    Protocol instance pointer.
 | 
						|
  @param  BltBuffer               Buffer containing data to blit into video buffer.
 | 
						|
                                  This buffer has a size of
 | 
						|
                                  Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
 | 
						|
  @param  BltOperation            Operation to perform on BlitBuffer and video
 | 
						|
                                  memory
 | 
						|
  @param  SourceX                 X coordinate of source for the BltBuffer.
 | 
						|
  @param  SourceY                 Y coordinate of source for the BltBuffer.
 | 
						|
  @param  DestinationX            X coordinate of destination for the BltBuffer.
 | 
						|
  @param  DestinationY            Y coordinate of destination for the BltBuffer.
 | 
						|
  @param  Width                   Width of rectangle in BltBuffer in pixels.
 | 
						|
  @param  Height                  Hight of rectangle in BltBuffer in pixels.
 | 
						|
  @param  Delta                   OPTIONAL.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The Blt operation completed.
 | 
						|
  @retval EFI_INVALID_PARAMETER   BltOperation is not valid.
 | 
						|
  @retval EFI_DEVICE_ERROR        A hardware error occured writting to the video
 | 
						|
                                  buffer.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ConSpliterGraphicsOutputBlt (
 | 
						|
  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL                  *This,
 | 
						|
  IN  EFI_GRAPHICS_OUTPUT_BLT_PIXEL                 *BltBuffer, OPTIONAL
 | 
						|
  IN  EFI_GRAPHICS_OUTPUT_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
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                      Status;
 | 
						|
  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private;
 | 
						|
  UINTN                           Index;
 | 
						|
  EFI_STATUS                      ReturnStatus;
 | 
						|
  EFI_GRAPHICS_OUTPUT_PROTOCOL    *GraphicsOutput;
 | 
						|
  EFI_UGA_DRAW_PROTOCOL           *UgaDraw;
 | 
						|
 | 
						|
  Private = GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
 | 
						|
 | 
						|
  //
 | 
						|
  // Sync up DevNull GOP device
 | 
						|
  //
 | 
						|
  ReturnStatus = DevNullGraphicsOutputBlt (
 | 
						|
                  Private,
 | 
						|
                  BltBuffer,
 | 
						|
                  BltOperation,
 | 
						|
                  SourceX,
 | 
						|
                  SourceY,
 | 
						|
                  DestinationX,
 | 
						|
                  DestinationY,
 | 
						|
                  Width,
 | 
						|
                  Height,
 | 
						|
                  Delta
 | 
						|
                  );
 | 
						|
 | 
						|
  if (Private->ConsoleOutputMode != EfiConsoleControlScreenGraphics) {
 | 
						|
    return ReturnStatus;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // return the worst status met
 | 
						|
  //
 | 
						|
  for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
 | 
						|
    GraphicsOutput = Private->TextOutList[Index].GraphicsOutput;
 | 
						|
    if (GraphicsOutput != NULL) {
 | 
						|
      Status = GraphicsOutput->Blt (
 | 
						|
                              GraphicsOutput,
 | 
						|
                              BltBuffer,
 | 
						|
                              BltOperation,
 | 
						|
                              SourceX,
 | 
						|
                              SourceY,
 | 
						|
                              DestinationX,
 | 
						|
                              DestinationY,
 | 
						|
                              Width,
 | 
						|
                              Height,
 | 
						|
                              Delta
 | 
						|
                              );
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        ReturnStatus = Status;
 | 
						|
      } else if (BltOperation == EfiBltVideoToBltBuffer) {
 | 
						|
        //
 | 
						|
        // Only need to read the data into buffer one time
 | 
						|
        //
 | 
						|
        return EFI_SUCCESS;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    UgaDraw = Private->TextOutList[Index].UgaDraw;
 | 
						|
    if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
 | 
						|
      Status = UgaDraw->Blt (
 | 
						|
                              UgaDraw,
 | 
						|
                              (EFI_UGA_PIXEL *) BltBuffer,
 | 
						|
                              (EFI_UGA_BLT_OPERATION) BltOperation,
 | 
						|
                              SourceX,
 | 
						|
                              SourceY,
 | 
						|
                              DestinationX,
 | 
						|
                              DestinationY,
 | 
						|
                              Width,
 | 
						|
                              Height,
 | 
						|
                              Delta
 | 
						|
                              );
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        ReturnStatus = Status;
 | 
						|
      } else if (BltOperation == EfiBltVideoToBltBuffer) {
 | 
						|
        //
 | 
						|
        // Only need to read the data into buffer one time
 | 
						|
        //
 | 
						|
        return EFI_SUCCESS;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return ReturnStatus;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Write data from the buffer to video display based on Graphics Output setting.
 | 
						|
 | 
						|
  @param  Private                 Consplitter Text Out pointer.
 | 
						|
  @param  GraphicsOutput          Graphics Output protocol pointer.
 | 
						|
  @param  UgaDraw                 UGA Draw protocol pointer.
 | 
						|
 | 
						|
  @retval EFI_UNSUPPORTED         No graphics devcie available .
 | 
						|
  @retval EFI_SUCCESS             The Blt operation completed.
 | 
						|
  @retval EFI_INVALID_PARAMETER   BltOperation is not valid.
 | 
						|
  @retval EFI_DEVICE_ERROR        A hardware error occured writting to the video buffer.
 | 
						|
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
DevNullGopSync (
 | 
						|
  IN  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private,
 | 
						|
  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL    *GraphicsOutput,
 | 
						|
  IN  EFI_UGA_DRAW_PROTOCOL           *UgaDraw
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (GraphicsOutput != NULL) {
 | 
						|
    return GraphicsOutput->Blt (
 | 
						|
                      GraphicsOutput,
 | 
						|
                      Private->GraphicsOutputBlt,
 | 
						|
                      EfiBltBufferToVideo,
 | 
						|
                      0,
 | 
						|
                      0,
 | 
						|
                      0,
 | 
						|
                      0,
 | 
						|
                      Private->GraphicsOutput.Mode->Info->HorizontalResolution,
 | 
						|
                      Private->GraphicsOutput.Mode->Info->VerticalResolution,
 | 
						|
                      0
 | 
						|
                      );
 | 
						|
  } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
 | 
						|
    return UgaDraw->Blt (
 | 
						|
                      UgaDraw,
 | 
						|
                      (EFI_UGA_PIXEL *) Private->GraphicsOutputBlt,
 | 
						|
                      EfiUgaBltBufferToVideo,
 | 
						|
                      0,
 | 
						|
                      0,
 | 
						|
                      0,
 | 
						|
                      0,
 | 
						|
                      Private->GraphicsOutput.Mode->Info->HorizontalResolution,
 | 
						|
                      Private->GraphicsOutput.Mode->Info->VerticalResolution,
 | 
						|
                      0
 | 
						|
                      );
 | 
						|
  } else {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Return the current video mode information.
 | 
						|
 | 
						|
  @param  This                  The EFI_UGA_DRAW_PROTOCOL instance.
 | 
						|
  @param  HorizontalResolution  The size of video screen in pixels in the X dimension.
 | 
						|
  @param  VerticalResolution    The size of video screen in pixels in the Y dimension.
 | 
						|
  @param  ColorDepth            Number of bits per pixel, currently defined to be 32.
 | 
						|
  @param  RefreshRate           The refresh rate of the monitor in Hertz.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           Mode information returned.
 | 
						|
  @retval EFI_NOT_STARTED       Video display is not initialized. Call SetMode ()
 | 
						|
  @retval EFI_INVALID_PARAMETER One of the input args was NULL.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ConSpliterUgaDrawGetMode (
 | 
						|
  IN  EFI_UGA_DRAW_PROTOCOL           *This,
 | 
						|
  OUT UINT32                          *HorizontalResolution,
 | 
						|
  OUT UINT32                          *VerticalResolution,
 | 
						|
  OUT UINT32                          *ColorDepth,
 | 
						|
  OUT UINT32                          *RefreshRate
 | 
						|
  )
 | 
						|
{
 | 
						|
  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private;
 | 
						|
 | 
						|
  if ((HorizontalResolution == NULL) ||
 | 
						|
      (VerticalResolution   == NULL) ||
 | 
						|
      (RefreshRate          == NULL) ||
 | 
						|
      (ColorDepth           == NULL)) {
 | 
						|
    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;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Set the current video mode information.
 | 
						|
 | 
						|
  @param  This                 The EFI_UGA_DRAW_PROTOCOL instance.
 | 
						|
  @param  HorizontalResolution The size of video screen in pixels in the X dimension.
 | 
						|
  @param  VerticalResolution   The size of video screen in pixels in the Y dimension.
 | 
						|
  @param  ColorDepth           Number of bits per pixel, currently defined to be 32.
 | 
						|
  @param  RefreshRate          The refresh rate of the monitor in Hertz.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS          Mode information returned.
 | 
						|
  @retval EFI_NOT_STARTED      Video display is not initialized. Call SetMode ()
 | 
						|
  @retval EFI_OUT_OF_RESOURCES Out of resources.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ConSpliterUgaDrawSetMode (
 | 
						|
  IN  EFI_UGA_DRAW_PROTOCOL           *This,
 | 
						|
  IN UINT32                           HorizontalResolution,
 | 
						|
  IN UINT32                           VerticalResolution,
 | 
						|
  IN UINT32                           ColorDepth,
 | 
						|
  IN UINT32                           RefreshRate
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                             Status;
 | 
						|
  TEXT_OUT_SPLITTER_PRIVATE_DATA         *Private;
 | 
						|
  UINTN                                  Index;
 | 
						|
  EFI_STATUS                             ReturnStatus;
 | 
						|
  UINTN                                  Size;
 | 
						|
  EFI_GRAPHICS_OUTPUT_PROTOCOL           *GraphicsOutput;
 | 
						|
  UINTN                                  NumberIndex;
 | 
						|
  UINTN                                  SizeOfInfo;
 | 
						|
  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION   *Info;
 | 
						|
  EFI_UGA_DRAW_PROTOCOL                  *UgaDraw;
 | 
						|
 | 
						|
  Private = UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
 | 
						|
 | 
						|
  //
 | 
						|
  // UgaDevNullSetMode ()
 | 
						|
  //
 | 
						|
  ReturnStatus = EFI_SUCCESS;
 | 
						|
 | 
						|
  //
 | 
						|
  // Free the old version
 | 
						|
  //
 | 
						|
  if (Private->UgaBlt != NULL) {
 | 
						|
    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->ConsoleOutputMode != EfiConsoleControlScreenGraphics) {
 | 
						|
    return ReturnStatus;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // return the worst status met
 | 
						|
  //
 | 
						|
  for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
 | 
						|
 | 
						|
    ReturnStatus = EFI_UNSUPPORTED;
 | 
						|
 | 
						|
    GraphicsOutput = Private->TextOutList[Index].GraphicsOutput;
 | 
						|
    if (GraphicsOutput != NULL) {
 | 
						|
      //
 | 
						|
      // Find corresponding ModeNumber of this GraphicsOutput instance
 | 
						|
      //
 | 
						|
      for (NumberIndex = 0; NumberIndex < GraphicsOutput->Mode->MaxMode; NumberIndex ++) {
 | 
						|
        Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) NumberIndex, &SizeOfInfo, &Info);
 | 
						|
        if (EFI_ERROR (Status)) {
 | 
						|
          return Status;
 | 
						|
        }
 | 
						|
        if ((Info->HorizontalResolution == HorizontalResolution) && (Info->VerticalResolution == VerticalResolution)) {
 | 
						|
          FreePool (Info);
 | 
						|
          break;
 | 
						|
        }
 | 
						|
        FreePool (Info);
 | 
						|
      }
 | 
						|
 | 
						|
      Status = GraphicsOutput->SetMode (GraphicsOutput, (UINT32) NumberIndex);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        ReturnStatus = Status;
 | 
						|
      }
 | 
						|
    } else if (FeaturePcdGet (PcdUgaConsumeSupport)){
 | 
						|
      UgaDraw = Private->TextOutList[Index].UgaDraw;
 | 
						|
      if (UgaDraw != NULL) {
 | 
						|
        Status = UgaDraw->SetMode (
 | 
						|
                          UgaDraw,
 | 
						|
                          HorizontalResolution,
 | 
						|
                          VerticalResolution,
 | 
						|
                          ColorDepth,
 | 
						|
                          RefreshRate
 | 
						|
                          );
 | 
						|
        if (EFI_ERROR (Status)) {
 | 
						|
          ReturnStatus = Status;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return ReturnStatus;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Blt a rectangle of pixels on the graphics screen.
 | 
						|
 | 
						|
  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.
 | 
						|
 | 
						|
  @param  Private                 Text Out Splitter pointer.
 | 
						|
  @param  BltBuffer               Buffer containing data to blit into video buffer.
 | 
						|
                                  This buffer has a size of
 | 
						|
                                  Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
 | 
						|
  @param  BltOperation            Operation to perform on BlitBuffer and video
 | 
						|
                                  memory
 | 
						|
  @param  SourceX                 X coordinate of source for the BltBuffer.
 | 
						|
  @param  SourceY                 Y coordinate of source for the BltBuffer.
 | 
						|
  @param  DestinationX            X coordinate of destination for the BltBuffer.
 | 
						|
  @param  DestinationY            Y coordinate of destination for the BltBuffer.
 | 
						|
  @param  Width                   Width of rectangle in BltBuffer in pixels.
 | 
						|
  @param  Height                  Hight of rectangle in BltBuffer in pixels.
 | 
						|
  @param  Delta                   OPTIONAL.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The Blt operation completed.
 | 
						|
  @retval EFI_INVALID_PARAMETER   BltOperation is not valid.
 | 
						|
  @retval EFI_DEVICE_ERROR        A hardware error occured writting to the video
 | 
						|
                                  buffer.
 | 
						|
 | 
						|
**/
 | 
						|
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;
 | 
						|
  BOOLEAN       Forward;
 | 
						|
  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 > 0) {
 | 
						|
      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;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((BltOperation == EfiUgaVideoToVideo) && (DestinationY > SourceY)) {
 | 
						|
      //
 | 
						|
      // Copy backwards, only care the Video to Video Blt
 | 
						|
      //
 | 
						|
      ScreenPtr = &Private->UgaBlt[(DestinationY + Height - 1) * HorizontalResolution + DestinationX];
 | 
						|
      SrcY      = SourceY + Height - 1;
 | 
						|
      Forward   = FALSE;
 | 
						|
    } else {
 | 
						|
      //
 | 
						|
      // Copy forwards, for other cases
 | 
						|
      //
 | 
						|
      ScreenPtr = &Private->UgaBlt[DestinationY * HorizontalResolution + DestinationX];
 | 
						|
      SrcY      = SourceY;
 | 
						|
      Forward   = TRUE;
 | 
						|
    }
 | 
						|
 | 
						|
    while (Height != 0) {
 | 
						|
      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));
 | 
						|
      }
 | 
						|
 | 
						|
      if (Forward) {
 | 
						|
        ScreenPtr += HorizontalResolution;
 | 
						|
        SrcY ++;
 | 
						|
      } else {
 | 
						|
        ScreenPtr -= HorizontalResolution;
 | 
						|
        SrcY --;
 | 
						|
      }
 | 
						|
      Height--;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Blt a rectangle of pixels on the graphics screen.
 | 
						|
 | 
						|
  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.
 | 
						|
 | 
						|
  @param  This           Protocol instance pointer.
 | 
						|
  @param  BltBuffer      Buffer containing data to blit into video buffer. This
 | 
						|
                         buffer has a size of Width*Height*sizeof(EFI_UGA_PIXEL)
 | 
						|
  @param  BltOperation   Operation to perform on BlitBuffer and video memory
 | 
						|
  @param  SourceX        X coordinate of source for the BltBuffer.
 | 
						|
  @param  SourceY        Y coordinate of source for the BltBuffer.
 | 
						|
  @param  DestinationX   X coordinate of destination for the BltBuffer.
 | 
						|
  @param  DestinationY   Y coordinate of destination for the BltBuffer.
 | 
						|
  @param  Width          Width of rectangle in BltBuffer in pixels.
 | 
						|
  @param  Height         Hight of rectangle in BltBuffer in pixels.
 | 
						|
  @param  Delta          OPTIONAL
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            The Blt operation completed.
 | 
						|
  @retval EFI_INVALID_PARAMETER  BltOperation is not valid.
 | 
						|
  @retval EFI_DEVICE_ERROR       A hardware error occured writting to the video buffer.
 | 
						|
 | 
						|
**/
 | 
						|
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
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                      Status;
 | 
						|
  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private;
 | 
						|
  UINTN                           Index;
 | 
						|
  EFI_STATUS                      ReturnStatus;
 | 
						|
  EFI_GRAPHICS_OUTPUT_PROTOCOL    *GraphicsOutput;
 | 
						|
 | 
						|
  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->ConsoleOutputMode != EfiConsoleControlScreenGraphics) {
 | 
						|
    return ReturnStatus;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // return the worst status met
 | 
						|
  //
 | 
						|
  for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
 | 
						|
    GraphicsOutput = Private->TextOutList[Index].GraphicsOutput;
 | 
						|
    if (GraphicsOutput != NULL) {
 | 
						|
      Status = GraphicsOutput->Blt (
 | 
						|
                              GraphicsOutput,
 | 
						|
                              (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltBuffer,
 | 
						|
                              (EFI_GRAPHICS_OUTPUT_BLT_OPERATION) BltOperation,
 | 
						|
                              SourceX,
 | 
						|
                              SourceY,
 | 
						|
                              DestinationX,
 | 
						|
                              DestinationY,
 | 
						|
                              Width,
 | 
						|
                              Height,
 | 
						|
                              Delta
 | 
						|
                              );
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        ReturnStatus = Status;
 | 
						|
      } else if (BltOperation == EfiBltVideoToBltBuffer) {
 | 
						|
        //
 | 
						|
        // Only need to read the data into buffer one time
 | 
						|
        //
 | 
						|
        return EFI_SUCCESS;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if (Private->TextOutList[Index].UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
 | 
						|
      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;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Write data from the buffer to video display based on UGA Draw setting.
 | 
						|
 | 
						|
  @param  Private                 Consplitter Text Out pointer.
 | 
						|
  @param  GraphicsOutput          Graphics Output protocol pointer.
 | 
						|
  @param  UgaDraw                 UGA Draw protocol pointer.
 | 
						|
 | 
						|
  @retval EFI_UNSUPPORTED         No graphics devcie available .
 | 
						|
  @retval EFI_SUCCESS             The Blt operation completed.
 | 
						|
  @retval EFI_INVALID_PARAMETER   BltOperation is not valid.
 | 
						|
  @retval EFI_DEVICE_ERROR        A hardware error occured writting to the video buffer.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
DevNullUgaSync (
 | 
						|
  IN  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private,
 | 
						|
  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL    *GraphicsOutput,
 | 
						|
  IN  EFI_UGA_DRAW_PROTOCOL           *UgaDraw
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (GraphicsOutput != NULL) {
 | 
						|
    return GraphicsOutput->Blt (
 | 
						|
                      GraphicsOutput,
 | 
						|
                      (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) Private->UgaBlt,
 | 
						|
                      EfiBltBufferToVideo,
 | 
						|
                      0,
 | 
						|
                      0,
 | 
						|
                      0,
 | 
						|
                      0,
 | 
						|
                      Private->UgaHorizontalResolution,
 | 
						|
                      Private->UgaVerticalResolution,
 | 
						|
                      0
 | 
						|
                      );
 | 
						|
  } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
 | 
						|
    return UgaDraw->Blt (
 | 
						|
                      UgaDraw,
 | 
						|
                      Private->UgaBlt,
 | 
						|
                      EfiUgaBltBufferToVideo,
 | 
						|
                      0,
 | 
						|
                      0,
 | 
						|
                      0,
 | 
						|
                      0,
 | 
						|
                      Private->UgaHorizontalResolution,
 | 
						|
                      Private->UgaVerticalResolution,
 | 
						|
                      Private->UgaHorizontalResolution * sizeof (EFI_UGA_PIXEL)
 | 
						|
                      );
 | 
						|
  } else {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Write a Unicode string to the output device.
 | 
						|
 | 
						|
  @param  Private                 Pointer to the console output splitter's private
 | 
						|
                                  data. It indicates the calling context.
 | 
						|
  @param  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
 | 
						|
DevNullTextOutOutputString (
 | 
						|
  IN  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private,
 | 
						|
  IN  CHAR16                          *WString
 | 
						|
  )
 | 
						|
{
 | 
						|
  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) != 0) {
 | 
						|
    CurrentWidth = 2;
 | 
						|
  } else {
 | 
						|
    CurrentWidth = 1;
 | 
						|
  }
 | 
						|
 | 
						|
  while (*WString != L'\0') {
 | 
						|
 | 
						|
    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 != L'\0') {
 | 
						|
            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     = L' ';
 | 
						|
          *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 == UNICODE_WIDE_CHAR || *WString == UNICODE_NARROW_CHAR) {
 | 
						|
          CurrentWidth = (*WString == UNICODE_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;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Sets the output device(s) to a specified mode.
 | 
						|
 | 
						|
  @param  Private                 Text Out Splitter pointer.
 | 
						|
  @param  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.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES    Out of resources.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
DevNullTextOutSetMode (
 | 
						|
  IN  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private,
 | 
						|
  IN  UINTN                           ModeNumber
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN                         Size;
 | 
						|
  INT32                         CurrentMode;
 | 
						|
  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.
 | 
						|
  // Row and Column should be fetched from intersection map.
 | 
						|
  //
 | 
						|
  if (Private->TextOutModeMap != NULL) {
 | 
						|
    CurrentMode = *(Private->TextOutModeMap + Private->TextOutListCount * ModeNumber);
 | 
						|
  } else {
 | 
						|
    CurrentMode = (INT32) (ModeNumber);
 | 
						|
  }
 | 
						|
  Mode    = &(Private->TextOutQueryData[CurrentMode]);
 | 
						|
  Row     = Mode->Rows;
 | 
						|
  Column  = Mode->Columns;
 | 
						|
 | 
						|
  if (Row == 0 || Column == 0) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Private->TextOutMode.Mode != (INT32) ModeNumber) {
 | 
						|
 | 
						|
    Private->TextOutMode.Mode = (INT32) ModeNumber;
 | 
						|
    Private->DevNullColumns   = Column;
 | 
						|
    Private->DevNullRows      = Row;
 | 
						|
 | 
						|
    if (Private->DevNullScreen != NULL) {
 | 
						|
      FreePool (Private->DevNullScreen);
 | 
						|
    }
 | 
						|
 | 
						|
    Size                    = (Row * (Column + 1)) * sizeof (CHAR16);
 | 
						|
    Private->DevNullScreen  = AllocateZeroPool (Size);
 | 
						|
    if (Private->DevNullScreen == NULL) {
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
 | 
						|
    if (Private->DevNullAttributes != NULL) {
 | 
						|
      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;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Clears the output device(s) display to the currently selected background
 | 
						|
  color.
 | 
						|
 | 
						|
  @param  Private                 Text Out Splitter 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
 | 
						|
DevNullTextOutClearScreen (
 | 
						|
  IN  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private
 | 
						|
  )
 | 
						|
{
 | 
						|
  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     = L' ';
 | 
						|
      *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);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Sets the current coordinates of the cursor position on NULL device.
 | 
						|
 | 
						|
  @param  Private                  Text Out Splitter pointer.
 | 
						|
  @param  Column                   The column position to set the cursor to. Must be
 | 
						|
                                   greater than or equal to zero and less than the
 | 
						|
                                   number of columns by QueryMode ().
 | 
						|
  @param  Row                      The row position to set the cursor to. Must be
 | 
						|
                                   greater than or equal to zero and less than the
 | 
						|
                                   number of rows by QueryMode ().
 | 
						|
 | 
						|
  @retval EFI_SUCCESS              Always returned.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
DevNullTextOutSetCursorPosition (
 | 
						|
  IN  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private,
 | 
						|
  IN  UINTN                           Column,
 | 
						|
  IN  UINTN                           Row
 | 
						|
  )
 | 
						|
{
 | 
						|
  //
 | 
						|
  // 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;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Set cursor visibility property on NULL device.
 | 
						|
 | 
						|
  @param  Private                 Text Out Splitter pointer.
 | 
						|
  @param  Visible                 If TRUE, the cursor is set to be visible, If
 | 
						|
                                  FALSE, the cursor is set to be invisible.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             Always returned.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
DevNullTextOutEnableCursor (
 | 
						|
  IN  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private,
 | 
						|
  IN  BOOLEAN                         Visible
 | 
						|
  )
 | 
						|
{
 | 
						|
  Private->TextOutMode.CursorVisible = Visible;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Take the DevNull TextOut device and update the Simple Text Out on every
 | 
						|
  UGA device.
 | 
						|
 | 
						|
  @param  Private                 Text Out Splitter pointer.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The request is valid.
 | 
						|
  @retval other                   Return status of TextOut->OutputString ()
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
DevNullSyncStdOut (
 | 
						|
  IN  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private
 | 
						|
  )
 | 
						|
{
 | 
						|
  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_OUTPUT_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 GOP/UGA devices
 | 
						|
    //
 | 
						|
    if ((Private->TextOutList[List].GraphicsOutput != NULL) || (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));
 | 
						|
  if (Buffer == NULL) {
 | 
						|
    return ReturnStatus;
 | 
						|
  }
 | 
						|
 | 
						|
  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] > 0) {
 | 
						|
        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) != 0) {
 | 
						|
            Str++;
 | 
						|
            Column++;
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        *BufferTail = 0;
 | 
						|
 | 
						|
        for (List = 0; List < Private->CurrentNumberOfConsoles; List++) {
 | 
						|
 | 
						|
          Sto = Private->TextOutList[List].TextOut;
 | 
						|
 | 
						|
          //
 | 
						|
          // Skip non GOP/UGA devices
 | 
						|
          //
 | 
						|
          if ((Private->TextOutList[List].GraphicsOutput != NULL) || (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 GOP/UGA devices
 | 
						|
    //
 | 
						|
    if ((Private->TextOutList[List].GraphicsOutput != NULL) || (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;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  FreePool (Buffer);
 | 
						|
 | 
						|
  return ReturnStatus;
 | 
						|
}
 |