mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-11-04 05:25:45 +01:00 
			
		
		
		
	There are cases that the operands of an expression are all with rank less
than UINT64/INT64 and the result of the expression is explicitly cast to
UINT64/INT64 to fit the target size.
An example will be:
UINT32 a,b;
// a and b can be any unsigned int type with rank less than UINT64, like
// UINT8, UINT16, etc.
UINT64 c;
c = (UINT64) (a + b);
Some static code checkers may warn that the expression result might
overflow within the rank of "int" (integer promotions) and the result is
then cast to a bigger size.
The commit refines codes by the following rules:
1). When the expression is possible to overflow the range of unsigned int/
int:
c = (UINT64)a + b;
2). When the expression will not overflow within the rank of "int", remove
the explicit type casts:
c = a + b;
3). When the expression will be cast to pointer of possible greater size:
UINT32 a,b;
VOID *c;
c = (VOID *)(UINTN)(a + b); --> c = (VOID *)((UINTN)a + b);
4). When one side of a comparison expression contains only operands with
rank less than UINT32:
UINT8 a;
UINT16 b;
UINTN c;
if ((UINTN)(a + b) > c) {...} --> if (((UINT32)a + b) > c) {...}
For rule 4), if we remove the 'UINTN' type cast like:
if (a + b > c) {...}
The VS compiler will complain with warning C4018 (signed/unsigned
mismatch, level 3 warning) due to promoting 'a + b' to type 'int'.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Hao Wu <hao.a.wu@intel.com>
Reviewed-by: Jeff Fan <jeff.fan@intel.com>
		
	
			
		
			
				
	
	
		
			3297 lines
		
	
	
		
			107 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			3297 lines
		
	
	
		
			107 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  ConsoleOut Routines that speak VGA.
 | 
						|
 | 
						|
Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.<BR>
 | 
						|
 | 
						|
This program and the accompanying materials
 | 
						|
are licensed and made available under the terms and conditions
 | 
						|
of the BSD License which accompanies this distribution.  The
 | 
						|
full text of the license may be found at
 | 
						|
http://opensource.org/licenses/bsd-license.php
 | 
						|
 | 
						|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | 
						|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "BiosVideo.h"
 | 
						|
 | 
						|
//
 | 
						|
// EFI Driver Binding Protocol Instance
 | 
						|
//
 | 
						|
EFI_DRIVER_BINDING_PROTOCOL gBiosVideoDriverBinding = {
 | 
						|
  BiosVideoDriverBindingSupported,
 | 
						|
  BiosVideoDriverBindingStart,
 | 
						|
  BiosVideoDriverBindingStop,
 | 
						|
  0x3,
 | 
						|
  NULL,
 | 
						|
  NULL
 | 
						|
};
 | 
						|
 | 
						|
//
 | 
						|
// Global lookup tables for VGA graphics modes
 | 
						|
//
 | 
						|
UINT8                          mVgaLeftMaskTable[]   = { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01 };
 | 
						|
 | 
						|
UINT8                          mVgaRightMaskTable[]  = { 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
 | 
						|
 | 
						|
UINT8                          mVgaBitMaskTable[]    = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
 | 
						|
 | 
						|
//
 | 
						|
// Save controller attributes during first start
 | 
						|
//
 | 
						|
UINT64                         mOriginalPciAttributes;
 | 
						|
BOOLEAN                        mPciAttributesSaved = FALSE;
 | 
						|
 | 
						|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL  mVgaColorToGraphicsOutputColor[] = {
 | 
						|
  { 0x00, 0x00, 0x00, 0x00 },
 | 
						|
  { 0x98, 0x00, 0x00, 0x00 },
 | 
						|
  { 0x00, 0x98, 0x00, 0x00 },
 | 
						|
  { 0x98, 0x98, 0x00, 0x00 },
 | 
						|
  { 0x00, 0x00, 0x98, 0x00 },
 | 
						|
  { 0x98, 0x00, 0x98, 0x00 },
 | 
						|
  { 0x00, 0x98, 0x98, 0x00 },
 | 
						|
  { 0x98, 0x98, 0x98, 0x00 },
 | 
						|
  { 0x10, 0x10, 0x10, 0x00 },
 | 
						|
  { 0xff, 0x10, 0x10, 0x00 },
 | 
						|
  { 0x10, 0xff, 0x10, 0x00 },
 | 
						|
  { 0xff, 0xff, 0x10, 0x00 },
 | 
						|
  { 0x10, 0x10, 0xff, 0x00 },
 | 
						|
  { 0xf0, 0x10, 0xff, 0x00 },
 | 
						|
  { 0x10, 0xff, 0xff, 0x00 },
 | 
						|
  { 0xff, 0xff, 0xff, 0x00 }
 | 
						|
};
 | 
						|
 | 
						|
//
 | 
						|
// Standard timing defined by VESA EDID
 | 
						|
//
 | 
						|
VESA_BIOS_EXTENSIONS_EDID_TIMING mEstablishedEdidTiming[] = {
 | 
						|
  //
 | 
						|
  // Established Timing I
 | 
						|
  //
 | 
						|
  {800, 600, 60},
 | 
						|
  {800, 600, 56},
 | 
						|
  {640, 480, 75},
 | 
						|
  {640, 480, 72},
 | 
						|
  {640, 480, 67},
 | 
						|
  {640, 480, 60},
 | 
						|
  {720, 400, 88},
 | 
						|
  {720, 400, 70},
 | 
						|
  //
 | 
						|
  // Established Timing II
 | 
						|
  //
 | 
						|
  {1280, 1024, 75},
 | 
						|
  {1024,  768, 75},
 | 
						|
  {1024,  768, 70},
 | 
						|
  {1024,  768, 60},
 | 
						|
  {1024,  768, 87},
 | 
						|
  {832,   624, 75},
 | 
						|
  {800,   600, 75},
 | 
						|
  {800,   600, 72},
 | 
						|
  //
 | 
						|
  // Established Timing III
 | 
						|
  //
 | 
						|
  {1152, 870, 75}
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
  Supported.
 | 
						|
 | 
						|
  @param  This                   Pointer to driver binding protocol
 | 
						|
  @param  Controller             Controller handle to connect
 | 
						|
  @param  RemainingDevicePath    A pointer to the remaining portion of a device
 | 
						|
                                 path
 | 
						|
 | 
						|
  @retval EFI_STATUS             EFI_SUCCESS:This controller can be managed by this
 | 
						|
                                 driver, Otherwise, this controller cannot be
 | 
						|
                                 managed by this driver
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
BiosVideoDriverBindingSupported (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
 | 
						|
  IN EFI_HANDLE                   Controller,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                Status;
 | 
						|
  EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;
 | 
						|
  EFI_PCI_IO_PROTOCOL       *PciIo;
 | 
						|
  PCI_TYPE00                Pci;
 | 
						|
  EFI_DEV_PATH              *Node;
 | 
						|
 | 
						|
  //
 | 
						|
  // See if the Legacy BIOS Protocol is available
 | 
						|
  //
 | 
						|
  Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Open the IO Abstraction(s) needed to perform the supported test
 | 
						|
  //
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Controller,
 | 
						|
                  &gEfiPciIoProtocolGuid,
 | 
						|
                  (VOID **) &PciIo,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  Controller,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_DRIVER
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Status == EFI_ALREADY_STARTED) {
 | 
						|
    //
 | 
						|
    // If VgaMiniPort protocol is installed, EFI_ALREADY_STARTED indicates failure,
 | 
						|
    // because VgaMiniPort protocol is installed on controller handle directly.
 | 
						|
    //
 | 
						|
    Status = gBS->OpenProtocol (
 | 
						|
                    Controller,
 | 
						|
                    &gEfiVgaMiniPortProtocolGuid,
 | 
						|
                    NULL,
 | 
						|
                    NULL,
 | 
						|
                    NULL,
 | 
						|
                    EFI_OPEN_PROTOCOL_TEST_PROTOCOL
 | 
						|
                    );
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      return EFI_ALREADY_STARTED;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // See if this is a PCI Graphics Controller by looking at the Command register and
 | 
						|
  // Class Code Register
 | 
						|
  //
 | 
						|
  Status = PciIo->Pci.Read (
 | 
						|
                        PciIo,
 | 
						|
                        EfiPciIoWidthUint32,
 | 
						|
                        0,
 | 
						|
                        sizeof (Pci) / sizeof (UINT32),
 | 
						|
                        &Pci
 | 
						|
                        );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_UNSUPPORTED;
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = EFI_UNSUPPORTED;
 | 
						|
  if (Pci.Hdr.ClassCode[2] == 0x03 || (Pci.Hdr.ClassCode[2] == 0x00 && Pci.Hdr.ClassCode[1] == 0x01)) {
 | 
						|
 | 
						|
    Status = EFI_SUCCESS;
 | 
						|
    //
 | 
						|
    // If this is a graphics controller,
 | 
						|
    // go further check RemainingDevicePath validation
 | 
						|
    //
 | 
						|
    if (RemainingDevicePath != NULL) {
 | 
						|
      Node = (EFI_DEV_PATH *) RemainingDevicePath;
 | 
						|
      //
 | 
						|
      // Check if RemainingDevicePath is the End of Device Path Node, 
 | 
						|
      // if yes, return EFI_SUCCESS
 | 
						|
      //
 | 
						|
      if (!IsDevicePathEnd (Node)) {
 | 
						|
        //
 | 
						|
        // If RemainingDevicePath isn't the End of Device Path Node,
 | 
						|
        // check its validation
 | 
						|
        //
 | 
						|
        if (Node->DevPath.Type != ACPI_DEVICE_PATH ||
 | 
						|
            Node->DevPath.SubType != ACPI_ADR_DP ||
 | 
						|
            DevicePathNodeLength(&Node->DevPath) < sizeof(ACPI_ADR_DEVICE_PATH)) {
 | 
						|
          Status = EFI_UNSUPPORTED;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
Done:
 | 
						|
  gBS->CloseProtocol (
 | 
						|
         Controller,
 | 
						|
         &gEfiPciIoProtocolGuid,
 | 
						|
         This->DriverBindingHandle,
 | 
						|
         Controller
 | 
						|
         );
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Install Graphics Output Protocol onto VGA device handles.
 | 
						|
 | 
						|
  @param  This                   Pointer to driver binding protocol
 | 
						|
  @param  Controller             Controller handle to connect
 | 
						|
  @param  RemainingDevicePath    A pointer to the remaining portion of a device
 | 
						|
                                 path
 | 
						|
 | 
						|
  @return EFI_STATUS
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
BiosVideoDriverBindingStart (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
 | 
						|
  IN EFI_HANDLE                   Controller,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                Status;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath;
 | 
						|
  EFI_PCI_IO_PROTOCOL       *PciIo;
 | 
						|
  EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;
 | 
						|
  UINTN                     Flags;
 | 
						|
  UINT64                    Supports;
 | 
						|
 | 
						|
  //
 | 
						|
  // Initialize local variables
 | 
						|
  //
 | 
						|
  PciIo            = NULL;
 | 
						|
  ParentDevicePath = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  //
 | 
						|
  // See if the Legacy BIOS Protocol is available
 | 
						|
  //
 | 
						|
  Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Prepare for status code
 | 
						|
  //
 | 
						|
  Status = gBS->HandleProtocol (
 | 
						|
                  Controller,
 | 
						|
                  &gEfiDevicePathProtocolGuid,
 | 
						|
                  (VOID **) &ParentDevicePath
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Open the IO Abstraction(s) needed
 | 
						|
  //
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Controller,
 | 
						|
                  &gEfiPciIoProtocolGuid,
 | 
						|
                  (VOID **) &PciIo,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  Controller,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_DRIVER
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Save original PCI attributes
 | 
						|
  //
 | 
						|
  if (!mPciAttributesSaved) {
 | 
						|
    Status = PciIo->Attributes (
 | 
						|
                      PciIo,
 | 
						|
                      EfiPciIoAttributeOperationGet,
 | 
						|
                      0,
 | 
						|
                      &mOriginalPciAttributes
 | 
						|
                      );
 | 
						|
    
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
    mPciAttributesSaved = TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Get supported PCI attributes
 | 
						|
  //
 | 
						|
  Status = PciIo->Attributes (
 | 
						|
                    PciIo,
 | 
						|
                    EfiPciIoAttributeOperationSupported,
 | 
						|
                    0,
 | 
						|
                    &Supports
 | 
						|
                    );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  Supports &= (UINT64)(EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16);
 | 
						|
  if (Supports == 0 || Supports == (EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) {
 | 
						|
    Status = EFI_UNSUPPORTED;
 | 
						|
    goto Done;
 | 
						|
  }  
 | 
						|
 | 
						|
  REPORT_STATUS_CODE_WITH_DEVICE_PATH (
 | 
						|
    EFI_PROGRESS_CODE,
 | 
						|
    EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_ENABLE,
 | 
						|
    ParentDevicePath
 | 
						|
    );
 | 
						|
  //
 | 
						|
  // Enable the device and make sure VGA cycles are being forwarded to this VGA device
 | 
						|
  //
 | 
						|
  Status = PciIo->Attributes (
 | 
						|
             PciIo,
 | 
						|
             EfiPciIoAttributeOperationEnable,
 | 
						|
             EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | Supports,
 | 
						|
             NULL
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    REPORT_STATUS_CODE_WITH_DEVICE_PATH (
 | 
						|
      EFI_ERROR_CODE | EFI_ERROR_MINOR,
 | 
						|
      EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_RESOURCE_CONFLICT,
 | 
						|
      ParentDevicePath
 | 
						|
      );
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Check to see if there is a legacy option ROM image associated with this PCI device
 | 
						|
  //
 | 
						|
  Status = LegacyBios->CheckPciRom (
 | 
						|
                         LegacyBios,
 | 
						|
                         Controller,
 | 
						|
                         NULL,
 | 
						|
                         NULL,
 | 
						|
                         &Flags
 | 
						|
                         );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Post the legacy option ROM if it is available.
 | 
						|
  //
 | 
						|
  REPORT_STATUS_CODE_WITH_DEVICE_PATH (
 | 
						|
    EFI_PROGRESS_CODE,
 | 
						|
    EFI_P_PC_RESET,
 | 
						|
    ParentDevicePath
 | 
						|
    );
 | 
						|
  Status = LegacyBios->InstallPciRom (
 | 
						|
                         LegacyBios,
 | 
						|
                         Controller,
 | 
						|
                         NULL,
 | 
						|
                         &Flags,
 | 
						|
                         NULL,
 | 
						|
                         NULL,
 | 
						|
                         NULL,
 | 
						|
                         NULL
 | 
						|
                         );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    REPORT_STATUS_CODE_WITH_DEVICE_PATH (
 | 
						|
      EFI_ERROR_CODE | EFI_ERROR_MINOR,
 | 
						|
      EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR,
 | 
						|
      ParentDevicePath
 | 
						|
      );
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  if (RemainingDevicePath != NULL) {
 | 
						|
    if (IsDevicePathEnd (RemainingDevicePath) && 
 | 
						|
        (FeaturePcdGet (PcdBiosVideoCheckVbeEnable) || FeaturePcdGet (PcdBiosVideoCheckVgaEnable))) {
 | 
						|
      //
 | 
						|
      // If RemainingDevicePath is the End of Device Path Node,
 | 
						|
      // don't create any child device and return EFI_SUCESS
 | 
						|
      Status = EFI_SUCCESS;
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Create child handle and install GraphicsOutputProtocol on it
 | 
						|
  //
 | 
						|
  Status = BiosVideoChildHandleInstall (
 | 
						|
             This,
 | 
						|
             Controller,
 | 
						|
             PciIo,
 | 
						|
             LegacyBios,
 | 
						|
             ParentDevicePath,
 | 
						|
             RemainingDevicePath
 | 
						|
             );
 | 
						|
 | 
						|
Done:
 | 
						|
  if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {
 | 
						|
    REPORT_STATUS_CODE_WITH_DEVICE_PATH (
 | 
						|
      EFI_PROGRESS_CODE,
 | 
						|
      EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_DISABLE,
 | 
						|
      ParentDevicePath
 | 
						|
      );
 | 
						|
 | 
						|
    REPORT_STATUS_CODE_WITH_DEVICE_PATH (
 | 
						|
      EFI_PROGRESS_CODE,
 | 
						|
      EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_NOT_DETECTED,
 | 
						|
      ParentDevicePath
 | 
						|
      );
 | 
						|
    if (!HasChildHandle (Controller)) {
 | 
						|
      if (mPciAttributesSaved) {
 | 
						|
        //
 | 
						|
        // Restore original PCI attributes
 | 
						|
        //
 | 
						|
        PciIo->Attributes (
 | 
						|
                        PciIo,
 | 
						|
                        EfiPciIoAttributeOperationSet,
 | 
						|
                        mOriginalPciAttributes,
 | 
						|
                        NULL
 | 
						|
                        );
 | 
						|
      }
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Release PCI I/O Protocols on the controller handle.
 | 
						|
    //
 | 
						|
    gBS->CloseProtocol (
 | 
						|
           Controller,
 | 
						|
           &gEfiPciIoProtocolGuid,
 | 
						|
           This->DriverBindingHandle,
 | 
						|
           Controller
 | 
						|
           );
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Stop.
 | 
						|
 | 
						|
  @param  This                   Pointer to driver binding protocol
 | 
						|
  @param  Controller             Controller handle to connect
 | 
						|
  @param  NumberOfChildren       Number of children handle created by this driver
 | 
						|
  @param  ChildHandleBuffer      Buffer containing child handle created
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            Driver disconnected successfully from controller
 | 
						|
  @retval EFI_UNSUPPORTED        Cannot find BIOS_VIDEO_DEV structure
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
BiosVideoDriverBindingStop (
 | 
						|
  IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
 | 
						|
  IN  EFI_HANDLE                      Controller,
 | 
						|
  IN  UINTN                           NumberOfChildren,
 | 
						|
  IN  EFI_HANDLE                      *ChildHandleBuffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                   Status;
 | 
						|
  BOOLEAN                      AllChildrenStopped;
 | 
						|
  UINTN                        Index;
 | 
						|
  EFI_PCI_IO_PROTOCOL          *PciIo;
 | 
						|
 | 
						|
  AllChildrenStopped = TRUE;
 | 
						|
 | 
						|
  if (NumberOfChildren == 0) {
 | 
						|
    //
 | 
						|
    // Close PCI I/O protocol on the controller handle
 | 
						|
    //
 | 
						|
    gBS->CloseProtocol (
 | 
						|
           Controller,
 | 
						|
           &gEfiPciIoProtocolGuid,
 | 
						|
           This->DriverBindingHandle,
 | 
						|
           Controller
 | 
						|
           );
 | 
						|
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  for (Index = 0; Index < NumberOfChildren; Index++) {
 | 
						|
    Status = BiosVideoChildHandleUninstall (This, Controller, ChildHandleBuffer[Index]);
 | 
						|
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      AllChildrenStopped = FALSE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (!AllChildrenStopped) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!HasChildHandle (Controller)) {
 | 
						|
    if (mPciAttributesSaved) {
 | 
						|
      Status = gBS->HandleProtocol (
 | 
						|
                      Controller,
 | 
						|
                      &gEfiPciIoProtocolGuid,
 | 
						|
                      (VOID **) &PciIo
 | 
						|
                      );
 | 
						|
      ASSERT_EFI_ERROR (Status);
 | 
						|
      
 | 
						|
      //
 | 
						|
      // Restore original PCI attributes
 | 
						|
      //
 | 
						|
      Status = PciIo->Attributes (
 | 
						|
                        PciIo,
 | 
						|
                        EfiPciIoAttributeOperationSet,
 | 
						|
                        mOriginalPciAttributes,
 | 
						|
                        NULL
 | 
						|
                        );
 | 
						|
      ASSERT_EFI_ERROR (Status);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Install child handles if the Handle supports MBR format.
 | 
						|
 | 
						|
  @param  This                   Calling context.
 | 
						|
  @param  ParentHandle           Parent Handle
 | 
						|
  @param  ParentPciIo            Parent PciIo interface
 | 
						|
  @param  ParentLegacyBios       Parent LegacyBios interface
 | 
						|
  @param  ParentDevicePath       Parent Device Path
 | 
						|
  @param  RemainingDevicePath    Remaining Device Path
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            If a child handle was added
 | 
						|
  @retval other                  A child handle was not added
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
BiosVideoChildHandleInstall (
 | 
						|
  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
 | 
						|
  IN  EFI_HANDLE                   ParentHandle,
 | 
						|
  IN  EFI_PCI_IO_PROTOCOL          *ParentPciIo,
 | 
						|
  IN  EFI_LEGACY_BIOS_PROTOCOL     *ParentLegacyBios,
 | 
						|
  IN  EFI_DEVICE_PATH_PROTOCOL     *ParentDevicePath,
 | 
						|
  IN  EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS               Status;
 | 
						|
  BIOS_VIDEO_DEV           *BiosVideoPrivate;
 | 
						|
  PCI_TYPE00               Pci;
 | 
						|
  ACPI_ADR_DEVICE_PATH     AcpiDeviceNode;
 | 
						|
  BOOLEAN                  ProtocolInstalled;
 | 
						|
 | 
						|
  //
 | 
						|
  // Allocate the private device structure for video device
 | 
						|
  //
 | 
						|
  BiosVideoPrivate = (BIOS_VIDEO_DEV *) AllocateZeroPool (
 | 
						|
																					sizeof (BIOS_VIDEO_DEV)
 | 
						|
																					);
 | 
						|
  if (NULL == BiosVideoPrivate) {
 | 
						|
		Status = EFI_OUT_OF_RESOURCES;
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // See if this is a VGA compatible controller or not
 | 
						|
  //
 | 
						|
  Status = ParentPciIo->Pci.Read (
 | 
						|
                          ParentPciIo,
 | 
						|
                          EfiPciIoWidthUint32,
 | 
						|
                          0,
 | 
						|
                          sizeof (Pci) / sizeof (UINT32),
 | 
						|
                          &Pci
 | 
						|
                          );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    REPORT_STATUS_CODE_WITH_DEVICE_PATH (
 | 
						|
      EFI_ERROR_CODE | EFI_ERROR_MINOR,
 | 
						|
      EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR,
 | 
						|
      ParentDevicePath
 | 
						|
      );
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
  BiosVideoPrivate->VgaCompatible = FALSE;
 | 
						|
  if (Pci.Hdr.ClassCode[2] == 0x00 && Pci.Hdr.ClassCode[1] == 0x01) {
 | 
						|
    BiosVideoPrivate->VgaCompatible = TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Pci.Hdr.ClassCode[2] == 0x03 && Pci.Hdr.ClassCode[1] == 0x00 && Pci.Hdr.ClassCode[0] == 0x00) {
 | 
						|
    BiosVideoPrivate->VgaCompatible = TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
 if (PcdGetBool (PcdBiosVideoSetTextVgaModeEnable)) {
 | 
						|
    //
 | 
						|
    // Create EXIT_BOOT_SERIVES Event
 | 
						|
    //
 | 
						|
    Status = gBS->CreateEventEx (
 | 
						|
                    EVT_NOTIFY_SIGNAL,
 | 
						|
                    TPL_NOTIFY,
 | 
						|
                    BiosVideoNotifyExitBootServices,
 | 
						|
                    BiosVideoPrivate,
 | 
						|
                    &gEfiEventExitBootServicesGuid,
 | 
						|
                    &BiosVideoPrivate->ExitBootServicesEvent
 | 
						|
                    );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Initialize the child private structure
 | 
						|
  //
 | 
						|
  BiosVideoPrivate->Signature = BIOS_VIDEO_DEV_SIGNATURE;
 | 
						|
 | 
						|
  //
 | 
						|
  // Fill in Graphics Output specific mode structures
 | 
						|
  //
 | 
						|
  BiosVideoPrivate->HardwareNeedsStarting = TRUE;
 | 
						|
  BiosVideoPrivate->ModeData              = NULL;
 | 
						|
  BiosVideoPrivate->LineBuffer            = NULL;
 | 
						|
  BiosVideoPrivate->VgaFrameBuffer        = NULL;
 | 
						|
  BiosVideoPrivate->VbeFrameBuffer        = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // Fill in the Graphics Output Protocol
 | 
						|
  //
 | 
						|
  BiosVideoPrivate->GraphicsOutput.QueryMode = BiosVideoGraphicsOutputQueryMode;
 | 
						|
  BiosVideoPrivate->GraphicsOutput.SetMode   = BiosVideoGraphicsOutputSetMode;
 | 
						|
 | 
						|
 | 
						|
  //
 | 
						|
  // Allocate buffer for Graphics Output Protocol mode information
 | 
						|
  //
 | 
						|
  BiosVideoPrivate->GraphicsOutput.Mode = (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *) AllocatePool (
 | 
						|
                                             sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE)
 | 
						|
                                             );
 | 
						|
  if (NULL == BiosVideoPrivate->GraphicsOutput.Mode) {
 | 
						|
    Status = EFI_OUT_OF_RESOURCES;
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  BiosVideoPrivate->GraphicsOutput.Mode->Info = (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) AllocatePool (
 | 
						|
                                             sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)
 | 
						|
                                             );
 | 
						|
  if (NULL ==  BiosVideoPrivate->GraphicsOutput.Mode->Info) {
 | 
						|
    Status = EFI_OUT_OF_RESOURCES;
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Assume that Graphics Output Protocol will be produced until proven otherwise
 | 
						|
  //
 | 
						|
  BiosVideoPrivate->ProduceGraphicsOutput = TRUE;
 | 
						|
 | 
						|
  //
 | 
						|
  // Set Gop Device Path, here RemainingDevicePath will not be one End of Device Path Node.
 | 
						|
  //
 | 
						|
  if ((RemainingDevicePath == NULL) || (!IsDevicePathEnd (RemainingDevicePath))) {
 | 
						|
    if (RemainingDevicePath == NULL) {
 | 
						|
      ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));
 | 
						|
      AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;
 | 
						|
      AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;
 | 
						|
      AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0);
 | 
						|
      SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH));
 | 
						|
    
 | 
						|
      BiosVideoPrivate->GopDevicePath = AppendDevicePathNode (
 | 
						|
                                          ParentDevicePath,
 | 
						|
                                          (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode
 | 
						|
                                          );
 | 
						|
    } else {
 | 
						|
      BiosVideoPrivate->GopDevicePath = AppendDevicePathNode (ParentDevicePath, RemainingDevicePath);
 | 
						|
    }
 | 
						|
    
 | 
						|
    //
 | 
						|
    // Creat child handle and device path protocol firstly
 | 
						|
    //
 | 
						|
    BiosVideoPrivate->Handle = NULL;
 | 
						|
    Status = gBS->InstallMultipleProtocolInterfaces (
 | 
						|
                    &BiosVideoPrivate->Handle,
 | 
						|
                    &gEfiDevicePathProtocolGuid,
 | 
						|
                    BiosVideoPrivate->GopDevicePath,
 | 
						|
                    NULL
 | 
						|
                    );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Fill in the VGA Mini Port Protocol fields
 | 
						|
  //
 | 
						|
  BiosVideoPrivate->VgaMiniPort.SetMode                   = BiosVideoVgaMiniPortSetMode;
 | 
						|
  BiosVideoPrivate->VgaMiniPort.VgaMemoryOffset           = 0xb8000;
 | 
						|
  BiosVideoPrivate->VgaMiniPort.CrtcAddressRegisterOffset = 0x3d4;
 | 
						|
  BiosVideoPrivate->VgaMiniPort.CrtcDataRegisterOffset    = 0x3d5;
 | 
						|
  BiosVideoPrivate->VgaMiniPort.VgaMemoryBar              = EFI_PCI_IO_PASS_THROUGH_BAR;
 | 
						|
  BiosVideoPrivate->VgaMiniPort.CrtcAddressRegisterBar    = EFI_PCI_IO_PASS_THROUGH_BAR;
 | 
						|
  BiosVideoPrivate->VgaMiniPort.CrtcDataRegisterBar       = EFI_PCI_IO_PASS_THROUGH_BAR;
 | 
						|
 | 
						|
  //
 | 
						|
  // Child handle need to consume the Legacy Bios protocol
 | 
						|
  //
 | 
						|
  BiosVideoPrivate->LegacyBios = ParentLegacyBios;
 | 
						|
 | 
						|
  //
 | 
						|
  // When check for VBE, PCI I/O protocol is needed, so use parent's protocol interface temporally
 | 
						|
  //
 | 
						|
  BiosVideoPrivate->PciIo                 = ParentPciIo;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check for VESA BIOS Extensions for modes that are compatible with Graphics Output
 | 
						|
  //
 | 
						|
  if (FeaturePcdGet (PcdBiosVideoCheckVbeEnable)) {
 | 
						|
    Status = BiosVideoCheckForVbe (BiosVideoPrivate);
 | 
						|
    DEBUG ((EFI_D_INFO, "BiosVideoCheckForVbe - %r\n", Status));
 | 
						|
  } else {
 | 
						|
    Status = EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    //
 | 
						|
    // The VESA BIOS Extensions are not compatible with Graphics Output, so check for support
 | 
						|
    // for the standard 640x480 16 color VGA mode
 | 
						|
    //
 | 
						|
    DEBUG ((EFI_D_INFO, "VgaCompatible - %x\n", BiosVideoPrivate->VgaCompatible));
 | 
						|
    if (BiosVideoPrivate->VgaCompatible) {
 | 
						|
      if (FeaturePcdGet (PcdBiosVideoCheckVgaEnable)) {
 | 
						|
        Status = BiosVideoCheckForVga (BiosVideoPrivate);
 | 
						|
        DEBUG ((EFI_D_INFO, "BiosVideoCheckForVga - %r\n", Status));
 | 
						|
      } else {
 | 
						|
        Status = EFI_UNSUPPORTED;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      //
 | 
						|
      // Free GOP mode structure if it is not freed before
 | 
						|
      // VgaMiniPort does not need this structure any more
 | 
						|
      //
 | 
						|
      if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) {
 | 
						|
        if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) {
 | 
						|
          FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info);
 | 
						|
          BiosVideoPrivate->GraphicsOutput.Mode->Info = NULL;
 | 
						|
        }
 | 
						|
        FreePool (BiosVideoPrivate->GraphicsOutput.Mode);
 | 
						|
        BiosVideoPrivate->GraphicsOutput.Mode = NULL;
 | 
						|
      }
 | 
						|
 | 
						|
      //
 | 
						|
      // Neither VBE nor the standard 640x480 16 color VGA mode are supported, so do
 | 
						|
      // not produce the Graphics Output protocol.  Instead, produce the VGA MiniPort Protocol.
 | 
						|
      //
 | 
						|
      BiosVideoPrivate->ProduceGraphicsOutput = FALSE;
 | 
						|
 | 
						|
      //
 | 
						|
      // INT services are available, so on the 80x25 and 80x50 text mode are supported
 | 
						|
      //
 | 
						|
      BiosVideoPrivate->VgaMiniPort.MaxMode = 2;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  ProtocolInstalled = FALSE;
 | 
						|
 | 
						|
  if (BiosVideoPrivate->ProduceGraphicsOutput) {
 | 
						|
    //
 | 
						|
    // Creat child handle and install Graphics Output Protocol,EDID Discovered/Active Protocol
 | 
						|
    //
 | 
						|
    Status = gBS->InstallMultipleProtocolInterfaces (
 | 
						|
                    &BiosVideoPrivate->Handle,
 | 
						|
                    &gEfiGraphicsOutputProtocolGuid,
 | 
						|
                    &BiosVideoPrivate->GraphicsOutput,
 | 
						|
                    &gEfiEdidDiscoveredProtocolGuid,
 | 
						|
                    &BiosVideoPrivate->EdidDiscovered,
 | 
						|
                    &gEfiEdidActiveProtocolGuid,
 | 
						|
                    &BiosVideoPrivate->EdidActive,
 | 
						|
                    NULL
 | 
						|
                    );
 | 
						|
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      //
 | 
						|
      // Open the Parent Handle for the child
 | 
						|
      //
 | 
						|
      Status = gBS->OpenProtocol (
 | 
						|
                      ParentHandle,
 | 
						|
                      &gEfiPciIoProtocolGuid,
 | 
						|
                      (VOID **) &BiosVideoPrivate->PciIo,
 | 
						|
                      This->DriverBindingHandle,
 | 
						|
                      BiosVideoPrivate->Handle,
 | 
						|
                      EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
 | 
						|
                      );
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        goto Done;
 | 
						|
      }
 | 
						|
      ProtocolInstalled = TRUE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (!ProtocolInstalled) {
 | 
						|
    //
 | 
						|
    // Install VGA Mini Port Protocol
 | 
						|
    //
 | 
						|
    Status = gBS->InstallMultipleProtocolInterfaces (
 | 
						|
                    &ParentHandle,
 | 
						|
                    &gEfiVgaMiniPortProtocolGuid,
 | 
						|
                    &BiosVideoPrivate->VgaMiniPort,
 | 
						|
                    NULL
 | 
						|
                    );
 | 
						|
  }
 | 
						|
 | 
						|
Done:
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    if ((BiosVideoPrivate != NULL) && (BiosVideoPrivate->ExitBootServicesEvent != NULL)) {
 | 
						|
      gBS->CloseEvent (BiosVideoPrivate->ExitBootServicesEvent);
 | 
						|
    }  
 | 
						|
    //
 | 
						|
    // Free private data structure
 | 
						|
    //
 | 
						|
    BiosVideoDeviceReleaseResource (BiosVideoPrivate);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Deregister an video child handle and free resources.
 | 
						|
 | 
						|
  @param  This                   Protocol instance pointer.
 | 
						|
  @param  Controller             Video controller handle
 | 
						|
  @param  Handle                 Video child handle
 | 
						|
 | 
						|
  @return EFI_STATUS
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
BiosVideoChildHandleUninstall (
 | 
						|
  EFI_DRIVER_BINDING_PROTOCOL    *This,
 | 
						|
  EFI_HANDLE                     Controller,
 | 
						|
  EFI_HANDLE                     Handle
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                   Status;
 | 
						|
  EFI_IA32_REGISTER_SET        Regs;
 | 
						|
  EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
 | 
						|
  EFI_VGA_MINI_PORT_PROTOCOL   *VgaMiniPort;
 | 
						|
  BIOS_VIDEO_DEV               *BiosVideoPrivate;
 | 
						|
  EFI_PCI_IO_PROTOCOL          *PciIo;
 | 
						|
 | 
						|
  BiosVideoPrivate = NULL;
 | 
						|
  GraphicsOutput   = NULL;
 | 
						|
  PciIo            = NULL;
 | 
						|
  Status           = EFI_UNSUPPORTED;
 | 
						|
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Handle,
 | 
						|
                  &gEfiGraphicsOutputProtocolGuid,
 | 
						|
                  (VOID **) &GraphicsOutput,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  Handle,
 | 
						|
                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | 
						|
                  );
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
      BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput);
 | 
						|
  }
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = gBS->OpenProtocol (
 | 
						|
                   Handle,
 | 
						|
                   &gEfiVgaMiniPortProtocolGuid,
 | 
						|
                   (VOID **) &VgaMiniPort,
 | 
						|
                   This->DriverBindingHandle,
 | 
						|
                   Handle,
 | 
						|
                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | 
						|
                   );
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (VgaMiniPort);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (BiosVideoPrivate == NULL) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Set the 80x25 Text VGA Mode
 | 
						|
  //
 | 
						|
  Regs.H.AH = 0x00;
 | 
						|
  Regs.H.AL = 0x03;
 | 
						|
  BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
 | 
						|
 | 
						|
  Regs.H.AH = 0x11;
 | 
						|
  Regs.H.AL = 0x14;
 | 
						|
  Regs.H.BL = 0;
 | 
						|
  BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
 | 
						|
 | 
						|
  //
 | 
						|
  // Close PCI I/O protocol that opened by child handle
 | 
						|
  //
 | 
						|
  Status = gBS->CloseProtocol (
 | 
						|
                  Controller,
 | 
						|
                  &gEfiPciIoProtocolGuid,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  Handle
 | 
						|
                  );
 | 
						|
 | 
						|
  //
 | 
						|
  // Uninstall protocols on child handle
 | 
						|
  //
 | 
						|
  if (BiosVideoPrivate->ProduceGraphicsOutput) {
 | 
						|
    Status = gBS->UninstallMultipleProtocolInterfaces (
 | 
						|
                    BiosVideoPrivate->Handle,
 | 
						|
                    &gEfiDevicePathProtocolGuid,
 | 
						|
                    BiosVideoPrivate->GopDevicePath,
 | 
						|
                    &gEfiGraphicsOutputProtocolGuid,
 | 
						|
                    &BiosVideoPrivate->GraphicsOutput,
 | 
						|
                    &gEfiEdidDiscoveredProtocolGuid,
 | 
						|
                    &BiosVideoPrivate->EdidDiscovered,
 | 
						|
                    &gEfiEdidActiveProtocolGuid,
 | 
						|
                    &BiosVideoPrivate->EdidActive,
 | 
						|
                    NULL
 | 
						|
                    );
 | 
						|
  }
 | 
						|
  if (!BiosVideoPrivate->ProduceGraphicsOutput) {
 | 
						|
    Status = gBS->UninstallMultipleProtocolInterfaces (
 | 
						|
                    Controller,
 | 
						|
                    &gEfiVgaMiniPortProtocolGuid,
 | 
						|
                    &BiosVideoPrivate->VgaMiniPort,
 | 
						|
                    NULL
 | 
						|
                    );
 | 
						|
  }
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    gBS->OpenProtocol (
 | 
						|
           Controller,
 | 
						|
           &gEfiPciIoProtocolGuid,
 | 
						|
           (VOID **) &PciIo,
 | 
						|
           This->DriverBindingHandle,
 | 
						|
           Handle,
 | 
						|
           EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
 | 
						|
           );
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  if (PcdGetBool (PcdBiosVideoSetTextVgaModeEnable)) {
 | 
						|
    //
 | 
						|
    // Close EXIT_BOOT_SERIVES Event
 | 
						|
    //
 | 
						|
    gBS->CloseEvent (BiosVideoPrivate->ExitBootServicesEvent);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Release all allocated resources
 | 
						|
  //
 | 
						|
  BiosVideoDeviceReleaseResource (BiosVideoPrivate);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Release resource for biso video instance.
 | 
						|
 | 
						|
  @param  BiosVideoPrivate       Video child device private data structure
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
BiosVideoDeviceReleaseResource (
 | 
						|
  BIOS_VIDEO_DEV  *BiosVideoPrivate
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (BiosVideoPrivate == NULL) {
 | 
						|
    return ;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Release all the resourses occupied by the BIOS_VIDEO_DEV
 | 
						|
  //
 | 
						|
 | 
						|
  //
 | 
						|
  // Free VGA Frame Buffer
 | 
						|
  //
 | 
						|
  if (BiosVideoPrivate->VgaFrameBuffer != NULL) {
 | 
						|
    FreePool (BiosVideoPrivate->VgaFrameBuffer);
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Free VBE Frame Buffer
 | 
						|
  //
 | 
						|
  if (BiosVideoPrivate->VbeFrameBuffer != NULL) {
 | 
						|
    FreePool (BiosVideoPrivate->VbeFrameBuffer);
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Free line buffer
 | 
						|
  //
 | 
						|
  if (BiosVideoPrivate->LineBuffer != NULL) {
 | 
						|
    FreePool (BiosVideoPrivate->LineBuffer);
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Free mode data
 | 
						|
  //
 | 
						|
  if (BiosVideoPrivate->ModeData != NULL) {
 | 
						|
    FreePool (BiosVideoPrivate->ModeData);
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Free memory allocated below 1MB
 | 
						|
  //
 | 
						|
  if (BiosVideoPrivate->PagesBelow1MB != 0) {
 | 
						|
    gBS->FreePages (BiosVideoPrivate->PagesBelow1MB, BiosVideoPrivate->NumberOfPagesBelow1MB);
 | 
						|
  }
 | 
						|
 | 
						|
  if (BiosVideoPrivate->VbeSaveRestorePages != 0) {
 | 
						|
    gBS->FreePages (BiosVideoPrivate->VbeSaveRestoreBuffer, BiosVideoPrivate->VbeSaveRestorePages);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Free graphics output protocol occupied resource
 | 
						|
  //
 | 
						|
  if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) {
 | 
						|
    if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) {
 | 
						|
        FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info);
 | 
						|
        BiosVideoPrivate->GraphicsOutput.Mode->Info = NULL;
 | 
						|
    }
 | 
						|
    FreePool (BiosVideoPrivate->GraphicsOutput.Mode);
 | 
						|
    BiosVideoPrivate->GraphicsOutput.Mode = NULL;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Free EDID discovered protocol occupied resource
 | 
						|
  //
 | 
						|
  if (BiosVideoPrivate->EdidDiscovered.Edid != NULL) {
 | 
						|
    FreePool (BiosVideoPrivate->EdidDiscovered.Edid);
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Free EDID active protocol occupied resource
 | 
						|
  //
 | 
						|
  if (BiosVideoPrivate->EdidActive.Edid != NULL) {
 | 
						|
    FreePool (BiosVideoPrivate->EdidActive.Edid);
 | 
						|
  }
 | 
						|
 | 
						|
  if (BiosVideoPrivate->GopDevicePath!= NULL) {
 | 
						|
    FreePool (BiosVideoPrivate->GopDevicePath);
 | 
						|
  }
 | 
						|
 | 
						|
  FreePool (BiosVideoPrivate);
 | 
						|
 | 
						|
  return ;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Generate a search key for a specified timing data.
 | 
						|
 | 
						|
  @param  EdidTiming             Pointer to EDID timing
 | 
						|
 | 
						|
  @return The 32 bit unique key for search.
 | 
						|
 | 
						|
**/
 | 
						|
UINT32
 | 
						|
CalculateEdidKey (
 | 
						|
  VESA_BIOS_EXTENSIONS_EDID_TIMING       *EdidTiming
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32 Key;
 | 
						|
 | 
						|
  //
 | 
						|
  // Be sure no conflicts for all standard timing defined by VESA.
 | 
						|
  //
 | 
						|
  Key = (EdidTiming->HorizontalResolution * 2) + EdidTiming->VerticalResolution;
 | 
						|
  return Key;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Parse the Established Timing and Standard Timing in EDID data block.
 | 
						|
 | 
						|
  @param  EdidBuffer             Pointer to EDID data block
 | 
						|
  @param  ValidEdidTiming        Valid EDID timing information
 | 
						|
 | 
						|
  @retval TRUE                   The EDID data is valid.
 | 
						|
  @retval FALSE                  The EDID data is invalid.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
ParseEdidData (
 | 
						|
  UINT8                                      *EdidBuffer,
 | 
						|
  VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING     *ValidEdidTiming
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8  CheckSum;
 | 
						|
  UINT32 Index;
 | 
						|
  UINT32 ValidNumber;
 | 
						|
  UINT32 TimingBits;
 | 
						|
  UINT8  *BufferIndex;
 | 
						|
  UINT16 HorizontalResolution;
 | 
						|
  UINT16 VerticalResolution;
 | 
						|
  UINT8  AspectRatio;
 | 
						|
  UINT8  RefreshRate;
 | 
						|
  VESA_BIOS_EXTENSIONS_EDID_TIMING     TempTiming;
 | 
						|
  VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *EdidDataBlock;
 | 
						|
 | 
						|
  EdidDataBlock = (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *) EdidBuffer;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check the checksum of EDID data
 | 
						|
  //
 | 
						|
  CheckSum = 0;
 | 
						|
  for (Index = 0; Index < VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE; Index ++) {
 | 
						|
    CheckSum = (UINT8) (CheckSum + EdidBuffer[Index]);
 | 
						|
  }
 | 
						|
  if (CheckSum != 0) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  ValidNumber = 0;
 | 
						|
  gBS->SetMem (ValidEdidTiming, sizeof (VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING), 0);
 | 
						|
 | 
						|
  if ((EdidDataBlock->EstablishedTimings[0] != 0) ||
 | 
						|
      (EdidDataBlock->EstablishedTimings[1] != 0) ||
 | 
						|
      (EdidDataBlock->EstablishedTimings[2] != 0)
 | 
						|
      ) {
 | 
						|
    //
 | 
						|
    // Established timing data
 | 
						|
    //
 | 
						|
    TimingBits = EdidDataBlock->EstablishedTimings[0] |
 | 
						|
                 (EdidDataBlock->EstablishedTimings[1] << 8) |
 | 
						|
                 ((EdidDataBlock->EstablishedTimings[2] & 0x80) << 9) ;
 | 
						|
    for (Index = 0; Index < VESA_BIOS_EXTENSIONS_EDID_ESTABLISHED_TIMING_MAX_NUMBER; Index ++) {
 | 
						|
      if ((TimingBits & 0x1) != 0) {
 | 
						|
        DEBUG ((EFI_D_INFO, "Established Timing: %d x %d\n",
 | 
						|
        mEstablishedEdidTiming[Index].HorizontalResolution, mEstablishedEdidTiming[Index].VerticalResolution));
 | 
						|
        ValidEdidTiming->Key[ValidNumber] = CalculateEdidKey (&mEstablishedEdidTiming[Index]);
 | 
						|
        ValidNumber ++;
 | 
						|
      }
 | 
						|
      TimingBits = TimingBits >> 1;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Parse the standard timing data
 | 
						|
  //
 | 
						|
  BufferIndex = &EdidDataBlock->StandardTimingIdentification[0];
 | 
						|
  for (Index = 0; Index < 8; Index ++) {
 | 
						|
    //
 | 
						|
    // Check if this is a valid Standard Timing entry
 | 
						|
    // VESA documents unused fields should be set to 01h
 | 
						|
    //
 | 
						|
    if ((BufferIndex[0] != 0x1) && (BufferIndex[1] != 0x1)){
 | 
						|
      //
 | 
						|
      // A valid Standard Timing
 | 
						|
      //
 | 
						|
      HorizontalResolution = (UINT16) (BufferIndex[0] * 8 + 248);
 | 
						|
      AspectRatio = (UINT8) (BufferIndex[1] >> 6);
 | 
						|
      switch (AspectRatio) {
 | 
						|
        case 0:
 | 
						|
          VerticalResolution = (UINT16) (HorizontalResolution / 16 * 10);
 | 
						|
          break;
 | 
						|
        case 1:
 | 
						|
          VerticalResolution = (UINT16) (HorizontalResolution / 4 * 3);
 | 
						|
          break;
 | 
						|
        case 2:
 | 
						|
          VerticalResolution = (UINT16) (HorizontalResolution / 5 * 4);
 | 
						|
          break;
 | 
						|
        case 3:
 | 
						|
          VerticalResolution = (UINT16) (HorizontalResolution / 16 * 9);
 | 
						|
          break;
 | 
						|
        default:
 | 
						|
          VerticalResolution = (UINT16) (HorizontalResolution / 4 * 3);
 | 
						|
          break;
 | 
						|
      }
 | 
						|
      RefreshRate = (UINT8) ((BufferIndex[1] & 0x1f) + 60);
 | 
						|
      DEBUG ((EFI_D_INFO, "Standard Timing: %d x %d\n", HorizontalResolution, VerticalResolution));
 | 
						|
      TempTiming.HorizontalResolution = HorizontalResolution;
 | 
						|
      TempTiming.VerticalResolution = VerticalResolution;
 | 
						|
      TempTiming.RefreshRate = RefreshRate;
 | 
						|
      ValidEdidTiming->Key[ValidNumber] = CalculateEdidKey (&TempTiming);
 | 
						|
      ValidNumber ++;
 | 
						|
    }
 | 
						|
    BufferIndex += 2;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Parse the Detailed Timing data
 | 
						|
  //
 | 
						|
  BufferIndex = &EdidDataBlock->DetailedTimingDescriptions[0];
 | 
						|
  for (Index = 0; Index < 4; Index ++, BufferIndex += VESA_BIOS_EXTENSIONS_DETAILED_TIMING_EACH_DESCRIPTOR_SIZE) {
 | 
						|
    if ((BufferIndex[0] == 0x0) && (BufferIndex[1] == 0x0)) {
 | 
						|
      //
 | 
						|
      // Check if this is a valid Detailed Timing Descriptor
 | 
						|
      // If first 2 bytes are zero, it is monitor descriptor other than detailed timing descriptor
 | 
						|
      //
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Calculate Horizontal and Vertical resolution
 | 
						|
    //
 | 
						|
    TempTiming.HorizontalResolution = ((UINT16)(BufferIndex[4] & 0xF0) << 4) | (BufferIndex[2]);
 | 
						|
    TempTiming.VerticalResolution = ((UINT16)(BufferIndex[7] & 0xF0) << 4) | (BufferIndex[5]);
 | 
						|
    DEBUG ((EFI_D_INFO, "Detailed Timing %d: %d x %d\n",
 | 
						|
            Index, TempTiming.HorizontalResolution, TempTiming.VerticalResolution));
 | 
						|
    ValidEdidTiming->Key[ValidNumber] = CalculateEdidKey (&TempTiming);
 | 
						|
    ValidNumber ++;
 | 
						|
  }
 | 
						|
 | 
						|
  ValidEdidTiming->ValidNumber = ValidNumber;
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Search a specified Timing in all the valid EDID timings.
 | 
						|
 | 
						|
  @param  ValidEdidTiming        All valid EDID timing information.
 | 
						|
  @param  EdidTiming             The Timing to search for.
 | 
						|
 | 
						|
  @retval TRUE                   Found.
 | 
						|
  @retval FALSE                  Not found.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
SearchEdidTiming (
 | 
						|
  VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING *ValidEdidTiming,
 | 
						|
  VESA_BIOS_EXTENSIONS_EDID_TIMING       *EdidTiming
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32 Index;
 | 
						|
  UINT32 Key;
 | 
						|
 | 
						|
  Key = CalculateEdidKey (EdidTiming);
 | 
						|
 | 
						|
  for (Index = 0; Index < ValidEdidTiming->ValidNumber; Index ++) {
 | 
						|
    if (Key == ValidEdidTiming->Key[Index]) {
 | 
						|
      return TRUE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Check if all video child handles have been uninstalled.
 | 
						|
 | 
						|
  @param  Controller             Video controller handle
 | 
						|
 | 
						|
  @return TRUE                   Child handles exist.
 | 
						|
  @return FALSE                  All video child handles have been uninstalled.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
HasChildHandle (
 | 
						|
  IN EFI_HANDLE  Controller
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN                                Index;
 | 
						|
  EFI_OPEN_PROTOCOL_INFORMATION_ENTRY  *OpenInfoBuffer;
 | 
						|
  UINTN                                EntryCount;
 | 
						|
  BOOLEAN                              HasChild;
 | 
						|
 | 
						|
  EntryCount = 0;
 | 
						|
  HasChild   = FALSE;
 | 
						|
  gBS->OpenProtocolInformation (
 | 
						|
         Controller,
 | 
						|
         &gEfiPciIoProtocolGuid,
 | 
						|
         &OpenInfoBuffer,
 | 
						|
         &EntryCount
 | 
						|
         );
 | 
						|
  for (Index = 0; Index < EntryCount; Index++) {
 | 
						|
    if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
 | 
						|
      HasChild = TRUE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  
 | 
						|
  return HasChild;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Check for VBE device.
 | 
						|
 | 
						|
  @param  BiosVideoPrivate       Pointer to BIOS_VIDEO_DEV structure
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            VBE device found
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
BiosVideoCheckForVbe (
 | 
						|
  IN OUT BIOS_VIDEO_DEV  *BiosVideoPrivate
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                             Status;
 | 
						|
  EFI_IA32_REGISTER_SET                  Regs;
 | 
						|
  UINT16                                 *ModeNumberPtr;
 | 
						|
  UINT16                                 VbeModeNumber;
 | 
						|
  BOOLEAN                                ModeFound;
 | 
						|
  BOOLEAN                                EdidFound;
 | 
						|
  BIOS_VIDEO_MODE_DATA                   *ModeBuffer;
 | 
						|
  BIOS_VIDEO_MODE_DATA                   *CurrentModeData;
 | 
						|
  UINTN                                  PreferMode;
 | 
						|
  UINTN                                  ModeNumber;
 | 
						|
  VESA_BIOS_EXTENSIONS_EDID_TIMING       Timing;
 | 
						|
  VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING ValidEdidTiming;
 | 
						|
  EFI_EDID_OVERRIDE_PROTOCOL             *EdidOverride;
 | 
						|
  UINT32                                 EdidAttributes;
 | 
						|
  BOOLEAN                                EdidOverrideFound;
 | 
						|
  UINTN                                  EdidOverrideDataSize;
 | 
						|
  UINT8                                  *EdidOverrideDataBlock;
 | 
						|
  UINTN                                  EdidActiveDataSize;
 | 
						|
  UINT8                                  *EdidActiveDataBlock;
 | 
						|
  UINT32                                 HighestHorizontalResolution;
 | 
						|
  UINT32                                 HighestVerticalResolution;
 | 
						|
  UINTN                                  HighestResolutionMode;
 | 
						|
 | 
						|
  EdidFound             = TRUE;
 | 
						|
  EdidOverrideFound     = FALSE;
 | 
						|
  EdidOverrideDataBlock = NULL;
 | 
						|
  EdidActiveDataSize    = 0;
 | 
						|
  EdidActiveDataBlock   = NULL;
 | 
						|
  HighestHorizontalResolution = 0;
 | 
						|
  HighestVerticalResolution   = 0;
 | 
						|
  HighestResolutionMode       = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // Allocate buffer under 1MB for VBE data structures
 | 
						|
  //
 | 
						|
  BiosVideoPrivate->NumberOfPagesBelow1MB = EFI_SIZE_TO_PAGES (
 | 
						|
                                              sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK) +
 | 
						|
                                              sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK) +
 | 
						|
                                              sizeof (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK) +
 | 
						|
                                              sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK)
 | 
						|
                                              );
 | 
						|
 | 
						|
  BiosVideoPrivate->PagesBelow1MB = 0x00100000 - 1;
 | 
						|
 | 
						|
  Status = gBS->AllocatePages (
 | 
						|
                  AllocateMaxAddress,
 | 
						|
                  EfiBootServicesData,
 | 
						|
                  BiosVideoPrivate->NumberOfPagesBelow1MB,
 | 
						|
                  &BiosVideoPrivate->PagesBelow1MB
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  ZeroMem (&ValidEdidTiming, sizeof (VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING));
 | 
						|
  	
 | 
						|
  //
 | 
						|
  // Fill in the VBE related data structures
 | 
						|
  //
 | 
						|
  BiosVideoPrivate->VbeInformationBlock = (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK *) (UINTN) (BiosVideoPrivate->PagesBelow1MB);
 | 
						|
  BiosVideoPrivate->VbeModeInformationBlock = (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK *) (BiosVideoPrivate->VbeInformationBlock + 1);
 | 
						|
  BiosVideoPrivate->VbeEdidDataBlock = (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *) (BiosVideoPrivate->VbeModeInformationBlock + 1);
 | 
						|
  BiosVideoPrivate->VbeCrtcInformationBlock = (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK *) (BiosVideoPrivate->VbeEdidDataBlock + 1);
 | 
						|
  BiosVideoPrivate->VbeSaveRestorePages   = 0;
 | 
						|
  BiosVideoPrivate->VbeSaveRestoreBuffer  = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // Test to see if the Video Adapter is compliant with VBE 3.0
 | 
						|
  //
 | 
						|
  gBS->SetMem (&Regs, sizeof (Regs), 0);
 | 
						|
  Regs.X.AX = VESA_BIOS_EXTENSIONS_RETURN_CONTROLLER_INFORMATION;
 | 
						|
  gBS->SetMem (BiosVideoPrivate->VbeInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK), 0);
 | 
						|
  BiosVideoPrivate->VbeInformationBlock->VESASignature  = VESA_BIOS_EXTENSIONS_VBE2_SIGNATURE;
 | 
						|
  Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeInformationBlock);
 | 
						|
  Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeInformationBlock);
 | 
						|
 | 
						|
  BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
 | 
						|
 | 
						|
  Status = EFI_DEVICE_ERROR;
 | 
						|
 | 
						|
  //
 | 
						|
  // See if the VESA call succeeded
 | 
						|
  //
 | 
						|
  if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Check for 'VESA' signature
 | 
						|
  //
 | 
						|
  if (BiosVideoPrivate->VbeInformationBlock->VESASignature != VESA_BIOS_EXTENSIONS_VESA_SIGNATURE) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Check to see if this is VBE 2.0 or higher
 | 
						|
  //
 | 
						|
  if (BiosVideoPrivate->VbeInformationBlock->VESAVersion < VESA_BIOS_EXTENSIONS_VERSION_2_0) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  EdidFound            = FALSE;
 | 
						|
  EdidAttributes       = 0xff;
 | 
						|
  EdidOverrideDataSize = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // Find EDID Override protocol firstly, this protocol is installed by platform if needed.
 | 
						|
  //
 | 
						|
  Status = gBS->LocateProtocol (
 | 
						|
                   &gEfiEdidOverrideProtocolGuid,
 | 
						|
                   NULL,
 | 
						|
                   (VOID **) &EdidOverride
 | 
						|
                   );
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    //
 | 
						|
    // Allocate double size of VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE to avoid overflow
 | 
						|
    //
 | 
						|
    EdidOverrideDataBlock = AllocatePool (VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE * 2);
 | 
						|
    if (NULL == EdidOverrideDataBlock) {
 | 
						|
  		Status = EFI_OUT_OF_RESOURCES;
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = EdidOverride->GetEdid (
 | 
						|
                             EdidOverride,
 | 
						|
                             BiosVideoPrivate->Handle,
 | 
						|
                             &EdidAttributes,
 | 
						|
                             &EdidOverrideDataSize,
 | 
						|
                             (UINT8 **) &EdidOverrideDataBlock
 | 
						|
                             );
 | 
						|
    if (!EFI_ERROR (Status)  &&
 | 
						|
         EdidAttributes == 0 &&
 | 
						|
         EdidOverrideDataSize != 0) {
 | 
						|
      //
 | 
						|
      // Succeeded to get EDID Override Data
 | 
						|
      //
 | 
						|
      EdidOverrideFound = TRUE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (!EdidOverrideFound || EdidAttributes == EFI_EDID_OVERRIDE_DONT_OVERRIDE) {
 | 
						|
    //
 | 
						|
    // If EDID Override data doesn't exist or EFI_EDID_OVERRIDE_DONT_OVERRIDE returned,
 | 
						|
    // read EDID information through INT10 call
 | 
						|
    //
 | 
						|
 | 
						|
    gBS->SetMem (&Regs, sizeof (Regs), 0);
 | 
						|
    Regs.X.AX = VESA_BIOS_EXTENSIONS_EDID;
 | 
						|
    Regs.X.BX = 1;
 | 
						|
    Regs.X.CX = 0;
 | 
						|
    Regs.X.DX = 0;
 | 
						|
    Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeEdidDataBlock);
 | 
						|
    Regs.X.DI = EFI_OFFSET  ((UINTN) BiosVideoPrivate->VbeEdidDataBlock);
 | 
						|
 | 
						|
    BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
 | 
						|
    //
 | 
						|
    // See if the VESA call succeeded
 | 
						|
    //
 | 
						|
    if (Regs.X.AX == VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {
 | 
						|
      //
 | 
						|
      // Set EDID Discovered Data
 | 
						|
      //
 | 
						|
      BiosVideoPrivate->EdidDiscovered.SizeOfEdid = VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE;
 | 
						|
 		  BiosVideoPrivate->EdidDiscovered.Edid = (UINT8 *) AllocateCopyPool (
 | 
						|
                                                          VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE,
 | 
						|
                                                          BiosVideoPrivate->VbeEdidDataBlock
 | 
						|
 																												  );
 | 
						|
 | 
						|
      if (NULL == BiosVideoPrivate->EdidDiscovered.Edid) {
 | 
						|
 			  Status = EFI_OUT_OF_RESOURCES;
 | 
						|
        goto Done;
 | 
						|
      }
 | 
						|
 | 
						|
      EdidFound = TRUE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (EdidFound) {
 | 
						|
    EdidActiveDataSize  = VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE;
 | 
						|
    EdidActiveDataBlock = BiosVideoPrivate->EdidDiscovered.Edid;
 | 
						|
  } else if (EdidOverrideFound) {
 | 
						|
    EdidActiveDataSize  = EdidOverrideDataSize;
 | 
						|
    EdidActiveDataBlock = EdidOverrideDataBlock;
 | 
						|
    EdidFound = TRUE;
 | 
						|
 	}
 | 
						|
 | 
						|
 	if (EdidFound) {
 | 
						|
    //
 | 
						|
    // Parse EDID data structure to retrieve modes supported by monitor
 | 
						|
    //
 | 
						|
    if (ParseEdidData ((UINT8 *) EdidActiveDataBlock, &ValidEdidTiming)) {
 | 
						|
      //
 | 
						|
      // Copy EDID Override Data to EDID Active Data
 | 
						|
      //
 | 
						|
      BiosVideoPrivate->EdidActive.SizeOfEdid = (UINT32) EdidActiveDataSize;
 | 
						|
      BiosVideoPrivate->EdidActive.Edid = (UINT8 *) AllocateCopyPool (
 | 
						|
                                                      EdidActiveDataSize,
 | 
						|
                                                      EdidActiveDataBlock
 | 
						|
                                                      );
 | 
						|
      if (NULL ==  BiosVideoPrivate->EdidActive.Edid) {
 | 
						|
   		  Status = EFI_OUT_OF_RESOURCES;
 | 
						|
        goto Done;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    BiosVideoPrivate->EdidActive.SizeOfEdid = 0;
 | 
						|
    BiosVideoPrivate->EdidActive.Edid = NULL;
 | 
						|
    EdidFound = FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Walk through the mode list to see if there is at least one mode the is compatible with the EDID mode
 | 
						|
  //
 | 
						|
  ModeNumberPtr = (UINT16 *)
 | 
						|
    (
 | 
						|
      (((UINTN) BiosVideoPrivate->VbeInformationBlock->VideoModePtr & 0xffff0000) >> 12) |
 | 
						|
        ((UINTN) BiosVideoPrivate->VbeInformationBlock->VideoModePtr & 0x0000ffff)
 | 
						|
    );
 | 
						|
 | 
						|
  PreferMode = 0;
 | 
						|
  ModeNumber = 0;
 | 
						|
  
 | 
						|
  //
 | 
						|
  // ModeNumberPtr may be not 16-byte aligned, so ReadUnaligned16 is used to access the buffer pointed by ModeNumberPtr.
 | 
						|
  //
 | 
						|
  for (VbeModeNumber = ReadUnaligned16 (ModeNumberPtr);
 | 
						|
       VbeModeNumber != VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST;
 | 
						|
       VbeModeNumber = ReadUnaligned16 (++ModeNumberPtr)) {
 | 
						|
    //
 | 
						|
    // Make sure this is a mode number defined by the VESA VBE specification.  If it isn'tm then skip this mode number.
 | 
						|
    //
 | 
						|
    if ((VbeModeNumber & VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA) == 0) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Get the information about the mode
 | 
						|
    //
 | 
						|
    gBS->SetMem (&Regs, sizeof (Regs), 0);
 | 
						|
    Regs.X.AX = VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION;
 | 
						|
    Regs.X.CX = VbeModeNumber;
 | 
						|
    gBS->SetMem (BiosVideoPrivate->VbeModeInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK), 0);
 | 
						|
    Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeModeInformationBlock);
 | 
						|
    Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeModeInformationBlock);
 | 
						|
 | 
						|
    BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
 | 
						|
 | 
						|
    //
 | 
						|
    // See if the call succeeded.  If it didn't, then try the next mode.
 | 
						|
    //
 | 
						|
    if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // See if the mode supports color.  If it doesn't then try the next mode.
 | 
						|
    //
 | 
						|
    if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_COLOR) == 0) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // See if the mode supports graphics.  If it doesn't then try the next mode.
 | 
						|
    //
 | 
						|
    if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_GRAPHICS) == 0) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // See if the mode supports a linear frame buffer.  If it doesn't then try the next mode.
 | 
						|
    //
 | 
						|
    if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER) == 0) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // See if the mode supports 32 bit color.  If it doesn't then try the next mode.
 | 
						|
    // 32 bit mode can be implemented by 24 Bits Per Pixels. Also make sure the
 | 
						|
    // number of bits per pixel is a multiple of 8 or more than 32 bits per pixel
 | 
						|
    //
 | 
						|
    if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel < 24) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel > 32) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel % 8) != 0) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // See if the physical base pointer for the linear mode is valid.  If it isn't then try the next mode.
 | 
						|
    //
 | 
						|
    if (BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr == 0) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    DEBUG ((EFI_D_INFO, "Video Controller Mode 0x%x: %d x %d\n",
 | 
						|
            VbeModeNumber, BiosVideoPrivate->VbeModeInformationBlock->XResolution, BiosVideoPrivate->VbeModeInformationBlock->YResolution));
 | 
						|
 | 
						|
    if (EdidFound && (ValidEdidTiming.ValidNumber > 0)) {
 | 
						|
      //
 | 
						|
      // EDID exist, check whether this mode match with any mode in EDID
 | 
						|
      //
 | 
						|
      Timing.HorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution;
 | 
						|
      Timing.VerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution;
 | 
						|
      if (!SearchEdidTiming (&ValidEdidTiming, &Timing)) {
 | 
						|
        //
 | 
						|
        // When EDID comes from INT10 call, EDID does not include 800x600, 640x480 and 1024x768,
 | 
						|
        // but INT10 can support these modes, we add them into GOP mode.
 | 
						|
        //
 | 
						|
        if ((BiosVideoPrivate->EdidDiscovered.SizeOfEdid != 0) &&
 | 
						|
            !((Timing.HorizontalResolution) == 1024 && (Timing.VerticalResolution == 768)) &&
 | 
						|
            !((Timing.HorizontalResolution) == 800 && (Timing.VerticalResolution == 600)) &&
 | 
						|
            !((Timing.HorizontalResolution) == 640 && (Timing.VerticalResolution == 480))) {
 | 
						|
        continue;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Select a reasonable mode to be set for current display mode
 | 
						|
    //
 | 
						|
    ModeFound = FALSE;
 | 
						|
 | 
						|
    if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 1024 &&
 | 
						|
        BiosVideoPrivate->VbeModeInformationBlock->YResolution == 768
 | 
						|
        ) {
 | 
						|
      ModeFound = TRUE;
 | 
						|
    }
 | 
						|
    if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 800 &&
 | 
						|
        BiosVideoPrivate->VbeModeInformationBlock->YResolution == 600
 | 
						|
        ) {
 | 
						|
      ModeFound = TRUE;
 | 
						|
      PreferMode = ModeNumber;
 | 
						|
    }
 | 
						|
    if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 640 &&
 | 
						|
        BiosVideoPrivate->VbeModeInformationBlock->YResolution == 480
 | 
						|
        ) {
 | 
						|
      ModeFound = TRUE;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((!EdidFound) && (!ModeFound)) {
 | 
						|
      //
 | 
						|
      // When no EDID exist, only select three possible resolutions, i.e. 1024x768, 800x600, 640x480
 | 
						|
      //
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Record the highest resolution mode to set later
 | 
						|
    //
 | 
						|
    if ((BiosVideoPrivate->VbeModeInformationBlock->XResolution > HighestHorizontalResolution) ||
 | 
						|
        ((BiosVideoPrivate->VbeModeInformationBlock->XResolution == HighestHorizontalResolution) && 
 | 
						|
         (BiosVideoPrivate->VbeModeInformationBlock->YResolution > HighestVerticalResolution))) {
 | 
						|
      HighestHorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution;
 | 
						|
      HighestVerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution;
 | 
						|
      HighestResolutionMode = ModeNumber;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Add mode to the list of available modes
 | 
						|
    //
 | 
						|
    ModeNumber ++;
 | 
						|
    ModeBuffer = (BIOS_VIDEO_MODE_DATA *) AllocatePool (
 | 
						|
																						ModeNumber * sizeof (BIOS_VIDEO_MODE_DATA)
 | 
						|
																						);
 | 
						|
    if (NULL == ModeBuffer) {
 | 
						|
			Status = EFI_OUT_OF_RESOURCES;
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
 | 
						|
    if (ModeNumber > 1) {
 | 
						|
      CopyMem (
 | 
						|
        ModeBuffer,
 | 
						|
        BiosVideoPrivate->ModeData,
 | 
						|
        (ModeNumber - 1) * sizeof (BIOS_VIDEO_MODE_DATA)
 | 
						|
        );
 | 
						|
    }
 | 
						|
 | 
						|
    if (BiosVideoPrivate->ModeData != NULL) {
 | 
						|
      FreePool (BiosVideoPrivate->ModeData);
 | 
						|
    }
 | 
						|
 | 
						|
    CurrentModeData = &ModeBuffer[ModeNumber - 1];
 | 
						|
    CurrentModeData->VbeModeNumber = VbeModeNumber;
 | 
						|
    if (BiosVideoPrivate->VbeInformationBlock->VESAVersion >= VESA_BIOS_EXTENSIONS_VERSION_3_0) {
 | 
						|
      CurrentModeData->BytesPerScanLine = BiosVideoPrivate->VbeModeInformationBlock->LinBytesPerScanLine;
 | 
						|
      CurrentModeData->Red.Position = BiosVideoPrivate->VbeModeInformationBlock->LinRedFieldPosition;
 | 
						|
      CurrentModeData->Red.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinRedMaskSize) - 1);
 | 
						|
      CurrentModeData->Blue.Position = BiosVideoPrivate->VbeModeInformationBlock->LinBlueFieldPosition;
 | 
						|
      CurrentModeData->Blue.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinBlueMaskSize) - 1);
 | 
						|
      CurrentModeData->Green.Position = BiosVideoPrivate->VbeModeInformationBlock->LinGreenFieldPosition;
 | 
						|
      CurrentModeData->Green.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinGreenMaskSize) - 1);
 | 
						|
      CurrentModeData->Reserved.Position = BiosVideoPrivate->VbeModeInformationBlock->LinRsvdFieldPosition;
 | 
						|
      CurrentModeData->Reserved.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinRsvdMaskSize) - 1);
 | 
						|
    } else {
 | 
						|
      CurrentModeData->BytesPerScanLine = BiosVideoPrivate->VbeModeInformationBlock->BytesPerScanLine;
 | 
						|
      CurrentModeData->Red.Position = BiosVideoPrivate->VbeModeInformationBlock->RedFieldPosition;
 | 
						|
      CurrentModeData->Red.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->RedMaskSize) - 1);
 | 
						|
      CurrentModeData->Blue.Position = BiosVideoPrivate->VbeModeInformationBlock->BlueFieldPosition;
 | 
						|
      CurrentModeData->Blue.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->BlueMaskSize) - 1);
 | 
						|
      CurrentModeData->Green.Position = BiosVideoPrivate->VbeModeInformationBlock->GreenFieldPosition;
 | 
						|
      CurrentModeData->Green.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->GreenMaskSize) - 1);
 | 
						|
      CurrentModeData->Reserved.Position = BiosVideoPrivate->VbeModeInformationBlock->RsvdFieldPosition;
 | 
						|
      CurrentModeData->Reserved.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->RsvdMaskSize) - 1);
 | 
						|
    }
 | 
						|
 | 
						|
    CurrentModeData->PixelFormat = PixelBitMask;
 | 
						|
    if ((BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel == 32) &&
 | 
						|
        (CurrentModeData->Red.Mask == 0xff) && (CurrentModeData->Green.Mask == 0xff) && (CurrentModeData->Blue.Mask == 0xff)) {
 | 
						|
      if ((CurrentModeData->Red.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Blue.Position == 16)) {
 | 
						|
        CurrentModeData->PixelFormat = PixelRedGreenBlueReserved8BitPerColor;
 | 
						|
      } else if ((CurrentModeData->Blue.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Red.Position == 16)) {
 | 
						|
        CurrentModeData->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    CurrentModeData->PixelBitMask.RedMask = ((UINT32) CurrentModeData->Red.Mask) << CurrentModeData->Red.Position;
 | 
						|
    CurrentModeData->PixelBitMask.GreenMask = ((UINT32) CurrentModeData->Green.Mask) << CurrentModeData->Green.Position;
 | 
						|
    CurrentModeData->PixelBitMask.BlueMask = ((UINT32) CurrentModeData->Blue.Mask) << CurrentModeData->Blue.Position;
 | 
						|
    CurrentModeData->PixelBitMask.ReservedMask = ((UINT32) CurrentModeData->Reserved.Mask) << CurrentModeData->Reserved.Position;
 | 
						|
 | 
						|
    CurrentModeData->LinearFrameBuffer = (VOID *) (UINTN)BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr;
 | 
						|
    CurrentModeData->HorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution;
 | 
						|
    CurrentModeData->VerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution;
 | 
						|
 | 
						|
    CurrentModeData->BitsPerPixel  = BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel;
 | 
						|
    CurrentModeData->FrameBufferSize = CurrentModeData->BytesPerScanLine * CurrentModeData->VerticalResolution;
 | 
						|
    //
 | 
						|
    // Make sure the FrameBufferSize does not exceed the max available frame buffer size reported by VEB.
 | 
						|
    //
 | 
						|
    ASSERT (CurrentModeData->FrameBufferSize <= ((UINT32)BiosVideoPrivate->VbeInformationBlock->TotalMemory * 64 * 1024));
 | 
						|
    
 | 
						|
    BiosVideoPrivate->ModeData = ModeBuffer;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Check to see if we found any modes that are compatible with GRAPHICS OUTPUT
 | 
						|
  //
 | 
						|
  if (ModeNumber == 0) {
 | 
						|
    Status = EFI_DEVICE_ERROR;
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Assign Gop's Blt function
 | 
						|
  //
 | 
						|
  BiosVideoPrivate->GraphicsOutput.Blt     = BiosVideoGraphicsOutputVbeBlt;
 | 
						|
 | 
						|
  BiosVideoPrivate->GraphicsOutput.Mode->MaxMode = (UINT32) ModeNumber;
 | 
						|
  //
 | 
						|
  // Current mode is unknow till now, set it to an invalid mode.
 | 
						|
  //
 | 
						|
  BiosVideoPrivate->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;
 | 
						|
 | 
						|
  //
 | 
						|
  // Find the best mode to initialize
 | 
						|
  //
 | 
						|
  if ((PcdGet32 (PcdVideoHorizontalResolution) == 0x0) || (PcdGet32 (PcdVideoVerticalResolution) == 0x0)) {
 | 
						|
    DEBUG_CODE (
 | 
						|
      BIOS_VIDEO_MODE_DATA    *ModeData;
 | 
						|
      ModeData = &BiosVideoPrivate->ModeData[HighestResolutionMode];
 | 
						|
      DEBUG ((EFI_D_INFO, "BiosVideo set highest resolution %d x %d\n",
 | 
						|
              ModeData->HorizontalResolution, ModeData->VerticalResolution));
 | 
						|
    );
 | 
						|
    PreferMode = HighestResolutionMode;
 | 
						|
  }
 | 
						|
  Status = BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate->GraphicsOutput, (UINT32) PreferMode);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    for (PreferMode = 0; PreferMode < ModeNumber; PreferMode ++) {
 | 
						|
      Status = BiosVideoGraphicsOutputSetMode (
 | 
						|
                &BiosVideoPrivate->GraphicsOutput,
 | 
						|
                (UINT32) PreferMode
 | 
						|
                );
 | 
						|
      if (!EFI_ERROR (Status)) {
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    if (PreferMode == ModeNumber) {
 | 
						|
      //
 | 
						|
      // None mode is set successfully.
 | 
						|
      //
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
Done:
 | 
						|
  //
 | 
						|
  // If there was an error, then free the mode structure
 | 
						|
  //
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    if (BiosVideoPrivate->ModeData != NULL) {
 | 
						|
      FreePool (BiosVideoPrivate->ModeData);
 | 
						|
      BiosVideoPrivate->ModeData  = NULL;
 | 
						|
      BiosVideoPrivate->MaxMode   = 0;
 | 
						|
    }
 | 
						|
    if (EdidOverrideDataBlock != NULL) {
 | 
						|
      FreePool (EdidOverrideDataBlock);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Check for VGA device.
 | 
						|
 | 
						|
  @param  BiosVideoPrivate       Pointer to BIOS_VIDEO_DEV structure
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            Standard VGA device found
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
BiosVideoCheckForVga (
 | 
						|
  IN OUT BIOS_VIDEO_DEV  *BiosVideoPrivate
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS            Status;
 | 
						|
  BIOS_VIDEO_MODE_DATA  *ModeBuffer;
 | 
						|
 | 
						|
  Status = EFI_UNSUPPORTED;
 | 
						|
 | 
						|
  //
 | 
						|
  // Assign Gop's Blt function
 | 
						|
  //
 | 
						|
  BiosVideoPrivate->GraphicsOutput.Blt     = BiosVideoGraphicsOutputVgaBlt;
 | 
						|
 | 
						|
  //
 | 
						|
  // Add mode to the list of available modes
 | 
						|
  // caller should guarantee that Mode has been allocated.
 | 
						|
  //
 | 
						|
  ASSERT (BiosVideoPrivate->GraphicsOutput.Mode != NULL);
 | 
						|
  BiosVideoPrivate->GraphicsOutput.Mode->MaxMode = 1;
 | 
						|
 | 
						|
  ModeBuffer = (BIOS_VIDEO_MODE_DATA *) AllocatePool (
 | 
						|
                                          sizeof (BIOS_VIDEO_MODE_DATA)
 | 
						|
                                          );
 | 
						|
  if (NULL == ModeBuffer) {
 | 
						|
		Status = EFI_OUT_OF_RESOURCES;
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  ModeBuffer->VbeModeNumber         = 0x0012;
 | 
						|
  ModeBuffer->BytesPerScanLine      = 640;
 | 
						|
  ModeBuffer->LinearFrameBuffer     = (VOID *) (UINTN) (0xa0000);
 | 
						|
  ModeBuffer->HorizontalResolution  = 640;
 | 
						|
  ModeBuffer->VerticalResolution    = 480;
 | 
						|
  ModeBuffer->PixelFormat           = PixelBltOnly;
 | 
						|
  ModeBuffer->BitsPerPixel          = 8;
 | 
						|
  ModeBuffer->ColorDepth            = 32;
 | 
						|
  ModeBuffer->RefreshRate           = 60;
 | 
						|
 | 
						|
  BiosVideoPrivate->ModeData = ModeBuffer;
 | 
						|
 | 
						|
  //
 | 
						|
  // Test to see if the Video Adapter support the 640x480 16 color mode
 | 
						|
  //
 | 
						|
  BiosVideoPrivate->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;
 | 
						|
  Status = BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate->GraphicsOutput, 0);
 | 
						|
 | 
						|
Done:
 | 
						|
  //
 | 
						|
  // If there was an error, then free the mode structure
 | 
						|
  //
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    if (BiosVideoPrivate->ModeData != NULL) {
 | 
						|
      FreePool (BiosVideoPrivate->ModeData);
 | 
						|
      BiosVideoPrivate->ModeData = NULL;
 | 
						|
    }
 | 
						|
    if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) {
 | 
						|
      if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) {
 | 
						|
        FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info);
 | 
						|
        BiosVideoPrivate->GraphicsOutput.Mode->Info = NULL;
 | 
						|
      }
 | 
						|
      FreePool (BiosVideoPrivate->GraphicsOutput.Mode);
 | 
						|
      BiosVideoPrivate->GraphicsOutput.Mode = NULL;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// Graphics Output Protocol Member Functions for VESA BIOS Extensions
 | 
						|
//
 | 
						|
 | 
						|
/**
 | 
						|
  Graphics Output protocol interface to get video mode.
 | 
						|
 | 
						|
  @param  This                   Protocol instance pointer.
 | 
						|
  @param  ModeNumber             The mode number to return information on.
 | 
						|
  @param  SizeOfInfo             A pointer to the size, in bytes, of the Info
 | 
						|
                                 buffer.
 | 
						|
  @param  Info                   Caller allocated buffer that returns information
 | 
						|
                                 about ModeNumber.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            Mode information returned.
 | 
						|
  @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.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
BiosVideoGraphicsOutputQueryMode (
 | 
						|
  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL          *This,
 | 
						|
  IN  UINT32                                ModeNumber,
 | 
						|
  OUT UINTN                                 *SizeOfInfo,
 | 
						|
  OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  **Info
 | 
						|
  )
 | 
						|
{
 | 
						|
  BIOS_VIDEO_DEV        *BiosVideoPrivate;
 | 
						|
  BIOS_VIDEO_MODE_DATA  *ModeData;
 | 
						|
 | 
						|
  BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);
 | 
						|
 | 
						|
  if (BiosVideoPrivate->HardwareNeedsStarting) {
 | 
						|
    REPORT_STATUS_CODE_WITH_DEVICE_PATH (
 | 
						|
      EFI_ERROR_CODE | EFI_ERROR_MINOR,
 | 
						|
      EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_OUTPUT_ERROR,
 | 
						|
      BiosVideoPrivate->GopDevicePath
 | 
						|
      );
 | 
						|
    return EFI_NOT_STARTED;
 | 
						|
  }
 | 
						|
 | 
						|
  if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  *Info = (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) AllocatePool (
 | 
						|
																										sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)
 | 
						|
																										);
 | 
						|
  if (NULL == *Info) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
 | 
						|
 | 
						|
  ModeData = &BiosVideoPrivate->ModeData[ModeNumber];
 | 
						|
  (*Info)->Version = 0;
 | 
						|
  (*Info)->HorizontalResolution = ModeData->HorizontalResolution;
 | 
						|
  (*Info)->VerticalResolution   = ModeData->VerticalResolution;
 | 
						|
  (*Info)->PixelFormat = ModeData->PixelFormat;
 | 
						|
  CopyMem (&((*Info)->PixelInformation), &(ModeData->PixelBitMask), sizeof(ModeData->PixelBitMask));
 | 
						|
 | 
						|
  (*Info)->PixelsPerScanLine =  (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Worker function to set video mode.
 | 
						|
 | 
						|
  @param  BiosVideoPrivate       Instance of BIOS_VIDEO_DEV.
 | 
						|
  @param  ModeData               The mode data to be set.
 | 
						|
  @param  DevicePath             Pointer to Device Path Protocol.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            Graphics mode was changed.
 | 
						|
  @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.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
BiosVideoSetModeWorker (
 | 
						|
  IN  BIOS_VIDEO_DEV               *BiosVideoPrivate,
 | 
						|
  IN  BIOS_VIDEO_MODE_DATA         *ModeData,
 | 
						|
  IN  EFI_DEVICE_PATH_PROTOCOL     *DevicePath
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS              Status;
 | 
						|
  EFI_IA32_REGISTER_SET   Regs;
 | 
						|
 | 
						|
  if (BiosVideoPrivate->LineBuffer != NULL) {
 | 
						|
    FreePool (BiosVideoPrivate->LineBuffer);
 | 
						|
  }
 | 
						|
 | 
						|
  if (BiosVideoPrivate->VgaFrameBuffer != NULL) {
 | 
						|
    FreePool (BiosVideoPrivate->VgaFrameBuffer);
 | 
						|
  }
 | 
						|
 | 
						|
  if (BiosVideoPrivate->VbeFrameBuffer != NULL) {
 | 
						|
    FreePool (BiosVideoPrivate->VbeFrameBuffer);
 | 
						|
  }
 | 
						|
 | 
						|
  BiosVideoPrivate->LineBuffer = (UINT8 *) AllocatePool (
 | 
						|
																					   ModeData->BytesPerScanLine
 | 
						|
																					   );
 | 
						|
  if (NULL == BiosVideoPrivate->LineBuffer) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Clear all registers
 | 
						|
  //
 | 
						|
  ZeroMem (&Regs, sizeof (Regs));
 | 
						|
 | 
						|
  if (ModeData->VbeModeNumber < 0x100) {
 | 
						|
    //
 | 
						|
    // Allocate a working buffer for BLT operations to the VGA frame buffer
 | 
						|
    //
 | 
						|
    BiosVideoPrivate->VgaFrameBuffer = (UINT8 *) AllocatePool (4 * 480 * 80);
 | 
						|
    if (NULL == BiosVideoPrivate->VgaFrameBuffer) {
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Set VGA Mode
 | 
						|
    //
 | 
						|
    Regs.X.AX = ModeData->VbeModeNumber;
 | 
						|
    BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
 | 
						|
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // Allocate a working buffer for BLT operations to the VBE frame buffer
 | 
						|
    //
 | 
						|
    BiosVideoPrivate->VbeFrameBuffer =
 | 
						|
			(EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocatePool (
 | 
						|
																					ModeData->BytesPerScanLine * ModeData->VerticalResolution
 | 
						|
																				  );
 | 
						|
    if (NULL == BiosVideoPrivate->VbeFrameBuffer) {
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Set VBE mode
 | 
						|
    //
 | 
						|
    Regs.X.AX = VESA_BIOS_EXTENSIONS_SET_MODE;
 | 
						|
    Regs.X.BX = (UINT16) (ModeData->VbeModeNumber | VESA_BIOS_EXTENSIONS_MODE_NUMBER_LINEAR_FRAME_BUFFER);
 | 
						|
    ZeroMem (BiosVideoPrivate->VbeCrtcInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK));
 | 
						|
    Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeCrtcInformationBlock);
 | 
						|
    Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeCrtcInformationBlock);
 | 
						|
    BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
 | 
						|
 | 
						|
    //
 | 
						|
    // Check to see if the call succeeded
 | 
						|
    //
 | 
						|
    if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {
 | 
						|
      REPORT_STATUS_CODE_WITH_DEVICE_PATH (
 | 
						|
        EFI_ERROR_CODE | EFI_ERROR_MINOR,
 | 
						|
        EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_OUTPUT_ERROR,
 | 
						|
        DevicePath
 | 
						|
        );
 | 
						|
      return EFI_DEVICE_ERROR;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Initialize the state of the VbeFrameBuffer
 | 
						|
    //
 | 
						|
    Status = BiosVideoPrivate->PciIo->Mem.Read (
 | 
						|
                                            BiosVideoPrivate->PciIo,
 | 
						|
                                            EfiPciIoWidthUint32,
 | 
						|
                                            EFI_PCI_IO_PASS_THROUGH_BAR,
 | 
						|
                                            (UINT64) (UINTN) ModeData->LinearFrameBuffer,
 | 
						|
                                            (ModeData->BytesPerScanLine * ModeData->VerticalResolution) >> 2,
 | 
						|
                                            BiosVideoPrivate->VbeFrameBuffer
 | 
						|
                                            );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Graphics Output protocol interface to set video mode.
 | 
						|
 | 
						|
  @param  This                   Protocol instance pointer.
 | 
						|
  @param  ModeNumber             The mode number to be set.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            Graphics mode was changed.
 | 
						|
  @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.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
BiosVideoGraphicsOutputSetMode (
 | 
						|
  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL * This,
 | 
						|
  IN  UINT32                       ModeNumber
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS              Status;
 | 
						|
  BIOS_VIDEO_DEV          *BiosVideoPrivate;
 | 
						|
  BIOS_VIDEO_MODE_DATA    *ModeData;
 | 
						|
  EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
 | 
						|
 | 
						|
  if (This == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);
 | 
						|
 | 
						|
  ModeData = &BiosVideoPrivate->ModeData[ModeNumber];
 | 
						|
 | 
						|
  if (ModeNumber >= This->Mode->MaxMode) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
  
 | 
						|
  if (ModeNumber == This->Mode->Mode) {
 | 
						|
    //
 | 
						|
    // Clear screen to black
 | 
						|
    //    
 | 
						|
    ZeroMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
 | 
						|
    BiosVideoGraphicsOutputVbeBlt (
 | 
						|
                        This,
 | 
						|
                        &Background,
 | 
						|
                        EfiBltVideoFill,
 | 
						|
                        0,
 | 
						|
                        0,
 | 
						|
                        0,
 | 
						|
                        0,
 | 
						|
                        ModeData->HorizontalResolution,
 | 
						|
                        ModeData->VerticalResolution,
 | 
						|
                        0
 | 
						|
    );
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = BiosVideoSetModeWorker (BiosVideoPrivate, ModeData, BiosVideoPrivate->GopDevicePath);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  This->Mode->Mode = ModeNumber;
 | 
						|
  This->Mode->Info->Version = 0;
 | 
						|
  This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;
 | 
						|
  This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;
 | 
						|
  This->Mode->Info->PixelFormat = ModeData->PixelFormat;
 | 
						|
  CopyMem (&(This->Mode->Info->PixelInformation), &(ModeData->PixelBitMask), sizeof (ModeData->PixelBitMask));
 | 
						|
  This->Mode->Info->PixelsPerScanLine =  (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel;
 | 
						|
  This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
 | 
						|
  This->Mode->FrameBufferSize = ModeData->FrameBufferSize;
 | 
						|
  This->Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) ModeData->LinearFrameBuffer;
 | 
						|
 | 
						|
  BiosVideoPrivate->HardwareNeedsStarting = FALSE;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Update physical frame buffer, copy 4 bytes block, then copy remaining bytes.
 | 
						|
 | 
						|
  @param   PciIo              The pointer of EFI_PCI_IO_PROTOCOL
 | 
						|
  @param   VbeBuffer          The data to transfer to screen
 | 
						|
  @param   MemAddress         Physical frame buffer base address
 | 
						|
  @param   DestinationX       The X coordinate of the destination for BltOperation
 | 
						|
  @param   DestinationY       The Y coordinate of the destination for BltOperation
 | 
						|
  @param   TotalBytes         The total bytes of copy
 | 
						|
  @param   VbePixelWidth      Bytes per pixel
 | 
						|
  @param   BytesPerScanLine   Bytes per scan line
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
CopyVideoBuffer (
 | 
						|
  IN  EFI_PCI_IO_PROTOCOL   *PciIo,
 | 
						|
  IN  UINT8                 *VbeBuffer,
 | 
						|
  IN  VOID                  *MemAddress,
 | 
						|
  IN  UINTN                 DestinationX,
 | 
						|
  IN  UINTN                 DestinationY,
 | 
						|
  IN  UINTN                 TotalBytes,
 | 
						|
  IN  UINT32                VbePixelWidth,
 | 
						|
  IN  UINTN                 BytesPerScanLine
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN                 FrameBufferAddr;
 | 
						|
  UINTN                 CopyBlockNum;
 | 
						|
  UINTN                 RemainingBytes;
 | 
						|
  UINTN                 UnalignedBytes;
 | 
						|
  EFI_STATUS            Status;
 | 
						|
 | 
						|
  FrameBufferAddr = (UINTN) MemAddress + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth;
 | 
						|
 | 
						|
  //
 | 
						|
  // If TotalBytes is less than 4 bytes, only start byte copy.
 | 
						|
  //
 | 
						|
  if (TotalBytes < 4) {
 | 
						|
    Status = PciIo->Mem.Write (
 | 
						|
                     PciIo,
 | 
						|
                     EfiPciIoWidthUint8,
 | 
						|
                     EFI_PCI_IO_PASS_THROUGH_BAR,
 | 
						|
                     (UINT64) FrameBufferAddr,
 | 
						|
                     TotalBytes,
 | 
						|
                     VbeBuffer
 | 
						|
                     );
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // If VbeBuffer is not 4-byte aligned, start byte copy.
 | 
						|
  //
 | 
						|
  UnalignedBytes  = (4 - ((UINTN) VbeBuffer & 0x3)) & 0x3;
 | 
						|
 | 
						|
  if (UnalignedBytes != 0) {
 | 
						|
    Status = PciIo->Mem.Write (
 | 
						|
                     PciIo,
 | 
						|
                     EfiPciIoWidthUint8,
 | 
						|
                     EFI_PCI_IO_PASS_THROUGH_BAR,
 | 
						|
                     (UINT64) FrameBufferAddr,
 | 
						|
                     UnalignedBytes,
 | 
						|
                     VbeBuffer
 | 
						|
                     );
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
    FrameBufferAddr += UnalignedBytes;
 | 
						|
    VbeBuffer       += UnalignedBytes;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Calculate 4-byte block count and remaining bytes.
 | 
						|
  //
 | 
						|
  CopyBlockNum   = (TotalBytes - UnalignedBytes) >> 2;
 | 
						|
  RemainingBytes = (TotalBytes - UnalignedBytes) &  3;
 | 
						|
 | 
						|
  //
 | 
						|
  // Copy 4-byte block and remaining bytes to physical frame buffer.
 | 
						|
  //
 | 
						|
  if (CopyBlockNum != 0) {
 | 
						|
    Status = PciIo->Mem.Write (
 | 
						|
                    PciIo,
 | 
						|
                    EfiPciIoWidthUint32,
 | 
						|
                    EFI_PCI_IO_PASS_THROUGH_BAR,
 | 
						|
                    (UINT64) FrameBufferAddr,
 | 
						|
                    CopyBlockNum,
 | 
						|
                    VbeBuffer
 | 
						|
                    );
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
  }
 | 
						|
 | 
						|
  if (RemainingBytes != 0) {
 | 
						|
    FrameBufferAddr += (CopyBlockNum << 2);
 | 
						|
    VbeBuffer       += (CopyBlockNum << 2);
 | 
						|
    Status = PciIo->Mem.Write (
 | 
						|
                    PciIo,
 | 
						|
                    EfiPciIoWidthUint8,
 | 
						|
                    EFI_PCI_IO_PASS_THROUGH_BAR,
 | 
						|
                    (UINT64) FrameBufferAddr,
 | 
						|
                    RemainingBytes,
 | 
						|
                    VbeBuffer
 | 
						|
                    );
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Worker function to block transfer for VBE device.
 | 
						|
 | 
						|
  @param  BiosVideoPrivate       Instance of BIOS_VIDEO_DEV
 | 
						|
  @param  BltBuffer              The data to transfer to screen
 | 
						|
  @param  BltOperation           The operation to perform
 | 
						|
  @param  SourceX                The X coordinate of the source for BltOperation
 | 
						|
  @param  SourceY                The Y coordinate of the source for BltOperation
 | 
						|
  @param  DestinationX           The X coordinate of the destination for
 | 
						|
                                 BltOperation
 | 
						|
  @param  DestinationY           The Y coordinate of the destination for
 | 
						|
                                 BltOperation
 | 
						|
  @param  Width                  The width of a rectangle in the blt rectangle in
 | 
						|
                                 pixels
 | 
						|
  @param  Height                 The height of a rectangle in the blt rectangle in
 | 
						|
                                 pixels
 | 
						|
  @param  Delta                  Not used for EfiBltVideoFill and
 | 
						|
                                 EfiBltVideoToVideo operation. If a Delta of 0 is
 | 
						|
                                 used, the entire BltBuffer will be operated on. If
 | 
						|
                                 a subrectangle of the BltBuffer is used, then
 | 
						|
                                 Delta represents the number of bytes in a row of
 | 
						|
                                 the BltBuffer.
 | 
						|
  @param  Mode                   Mode data.
 | 
						|
 | 
						|
  @retval EFI_INVALID_PARAMETER  Invalid parameter passed in
 | 
						|
  @retval EFI_SUCCESS            Blt operation success
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
BiosVideoVbeBltWorker (
 | 
						|
  IN  BIOS_VIDEO_DEV                     *BiosVideoPrivate,
 | 
						|
  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,
 | 
						|
  IN  BIOS_VIDEO_MODE_DATA               *Mode
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_PCI_IO_PROTOCOL            *PciIo;
 | 
						|
  EFI_TPL                        OriginalTPL;
 | 
						|
  UINTN                          DstY;
 | 
						|
  UINTN                          SrcY;
 | 
						|
  UINTN                          DstX;
 | 
						|
  EFI_GRAPHICS_OUTPUT_BLT_PIXEL  *Blt;
 | 
						|
  VOID                           *MemAddress;
 | 
						|
  EFI_GRAPHICS_OUTPUT_BLT_PIXEL  *VbeFrameBuffer;
 | 
						|
  UINTN                          BytesPerScanLine;
 | 
						|
  UINTN                          Index;
 | 
						|
  UINT8                          *VbeBuffer;
 | 
						|
  UINT8                          *VbeBuffer1;
 | 
						|
  UINT8                          *BltUint8;
 | 
						|
  UINT32                         VbePixelWidth;
 | 
						|
  UINT32                         Pixel;
 | 
						|
  UINTN                          TotalBytes;
 | 
						|
 | 
						|
  PciIo             = BiosVideoPrivate->PciIo;
 | 
						|
 | 
						|
  VbeFrameBuffer    = BiosVideoPrivate->VbeFrameBuffer;
 | 
						|
  MemAddress        = Mode->LinearFrameBuffer;
 | 
						|
  BytesPerScanLine  = Mode->BytesPerScanLine;
 | 
						|
  VbePixelWidth     = Mode->BitsPerPixel / 8;
 | 
						|
  BltUint8          = (UINT8 *) BltBuffer;
 | 
						|
  TotalBytes        = Width * VbePixelWidth;
 | 
						|
 | 
						|
  if (((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Width == 0 || Height == 0) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // We need to fill the Virtual Screen buffer with the blt data.
 | 
						|
  // The virtual screen is upside down, as the first row is the bootom row of
 | 
						|
  // the image.
 | 
						|
  //
 | 
						|
  if (BltOperation == EfiBltVideoToBltBuffer) {
 | 
						|
    //
 | 
						|
    // Video to BltBuffer: Source is Video, destination is BltBuffer
 | 
						|
    //
 | 
						|
    if (SourceY + Height > Mode->VerticalResolution) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    if (SourceX + Width > Mode->HorizontalResolution) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // BltBuffer to Video: Source is BltBuffer, destination is Video
 | 
						|
    //
 | 
						|
    if (DestinationY + Height > Mode->VerticalResolution) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    if (DestinationX + Width > Mode->HorizontalResolution) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // If Delta is zero, then the entire BltBuffer is being used, so Delta
 | 
						|
  // is the number of bytes in each row of BltBuffer.  Since BltBuffer is Width pixels size,
 | 
						|
  // the number of bytes in each row can be computed.
 | 
						|
  //
 | 
						|
  if (Delta == 0) {
 | 
						|
    Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
 | 
						|
  // We would not want a timer based event (Cursor, ...) to come in while we are
 | 
						|
  // doing this operation.
 | 
						|
  //
 | 
						|
  OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
 | 
						|
 | 
						|
  switch (BltOperation) {
 | 
						|
  case EfiBltVideoToBltBuffer:
 | 
						|
    for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) {
 | 
						|
      Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + DstY * Delta + DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
 | 
						|
      //
 | 
						|
      // Shuffle the packed bytes in the hardware buffer to match EFI_GRAPHICS_OUTPUT_BLT_PIXEL
 | 
						|
      //
 | 
						|
      VbeBuffer = ((UINT8 *) VbeFrameBuffer + (SrcY * BytesPerScanLine + SourceX * VbePixelWidth));
 | 
						|
      for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {
 | 
						|
        Pixel         = VbeBuffer[0] | VbeBuffer[1] << 8 | VbeBuffer[2] << 16 | VbeBuffer[3] << 24;
 | 
						|
        Blt->Red      = (UINT8) ((Pixel >> Mode->Red.Position) & Mode->Red.Mask);
 | 
						|
        Blt->Blue     = (UINT8) ((Pixel >> Mode->Blue.Position) & Mode->Blue.Mask);
 | 
						|
        Blt->Green    = (UINT8) ((Pixel >> Mode->Green.Position) & Mode->Green.Mask);
 | 
						|
        Blt->Reserved = 0;
 | 
						|
        Blt++;
 | 
						|
        VbeBuffer += VbePixelWidth;
 | 
						|
      }
 | 
						|
 | 
						|
    }
 | 
						|
    break;
 | 
						|
 | 
						|
  case EfiBltVideoToVideo:
 | 
						|
    for (Index = 0; Index < Height; Index++) {
 | 
						|
      if (DestinationY <= SourceY) {
 | 
						|
        SrcY  = SourceY + Index;
 | 
						|
        DstY  = DestinationY + Index;
 | 
						|
      } else {
 | 
						|
        SrcY  = SourceY + Height - Index - 1;
 | 
						|
        DstY  = DestinationY + Height - Index - 1;
 | 
						|
      }
 | 
						|
 | 
						|
      VbeBuffer   = ((UINT8 *) VbeFrameBuffer + DstY * BytesPerScanLine + DestinationX * VbePixelWidth);
 | 
						|
      VbeBuffer1  = ((UINT8 *) VbeFrameBuffer + SrcY * BytesPerScanLine + SourceX * VbePixelWidth);
 | 
						|
 | 
						|
      gBS->CopyMem (
 | 
						|
            VbeBuffer,
 | 
						|
            VbeBuffer1,
 | 
						|
            TotalBytes
 | 
						|
            );
 | 
						|
 | 
						|
      //
 | 
						|
      // Update physical frame buffer.
 | 
						|
      //
 | 
						|
      CopyVideoBuffer (
 | 
						|
        PciIo,
 | 
						|
        VbeBuffer,
 | 
						|
        MemAddress,
 | 
						|
        DestinationX,
 | 
						|
        DstY,
 | 
						|
        TotalBytes,
 | 
						|
        VbePixelWidth,
 | 
						|
        BytesPerScanLine
 | 
						|
        );
 | 
						|
    }
 | 
						|
    break;
 | 
						|
 | 
						|
  case EfiBltVideoFill:
 | 
						|
    VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);
 | 
						|
    Blt       = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltUint8;
 | 
						|
    //
 | 
						|
    // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer
 | 
						|
    //
 | 
						|
    Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |
 | 
						|
      (
 | 
						|
        (Blt->Green & Mode->Green.Mask) <<
 | 
						|
        Mode->Green.Position
 | 
						|
      ) |
 | 
						|
          ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);
 | 
						|
 | 
						|
    for (Index = 0; Index < Width; Index++) {
 | 
						|
      gBS->CopyMem (
 | 
						|
            VbeBuffer,
 | 
						|
            &Pixel,
 | 
						|
            VbePixelWidth
 | 
						|
            );
 | 
						|
      VbeBuffer += VbePixelWidth;
 | 
						|
    }
 | 
						|
 | 
						|
    VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);
 | 
						|
    for (DstY = DestinationY + 1; DstY < (Height + DestinationY); DstY++) {
 | 
						|
      gBS->CopyMem (
 | 
						|
            (VOID *) ((UINTN) VbeFrameBuffer + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth),
 | 
						|
            VbeBuffer,
 | 
						|
            TotalBytes
 | 
						|
            );
 | 
						|
    }
 | 
						|
 | 
						|
    for (DstY = DestinationY; DstY < (Height + DestinationY); DstY++) {
 | 
						|
      //
 | 
						|
      // Update physical frame buffer.
 | 
						|
      //
 | 
						|
      CopyVideoBuffer (
 | 
						|
        PciIo,
 | 
						|
        VbeBuffer,
 | 
						|
        MemAddress,
 | 
						|
        DestinationX,
 | 
						|
        DstY,
 | 
						|
        TotalBytes,
 | 
						|
        VbePixelWidth,
 | 
						|
        BytesPerScanLine
 | 
						|
        );
 | 
						|
    }
 | 
						|
    break;
 | 
						|
 | 
						|
  case EfiBltBufferToVideo:
 | 
						|
    for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {
 | 
						|
      Blt       = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + (SrcY * Delta) + (SourceX) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
 | 
						|
      VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth));
 | 
						|
      for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {
 | 
						|
        //
 | 
						|
        // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer
 | 
						|
        //
 | 
						|
        Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |
 | 
						|
          ((Blt->Green & Mode->Green.Mask) << Mode->Green.Position) |
 | 
						|
            ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);
 | 
						|
        gBS->CopyMem (
 | 
						|
              VbeBuffer,
 | 
						|
              &Pixel,
 | 
						|
              VbePixelWidth
 | 
						|
              );
 | 
						|
        Blt++;
 | 
						|
        VbeBuffer += VbePixelWidth;
 | 
						|
      }
 | 
						|
 | 
						|
      VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth));
 | 
						|
 | 
						|
      //
 | 
						|
      // Update physical frame buffer.
 | 
						|
      //
 | 
						|
      CopyVideoBuffer (
 | 
						|
        PciIo,
 | 
						|
        VbeBuffer,
 | 
						|
        MemAddress,
 | 
						|
        DestinationX,
 | 
						|
        DstY,
 | 
						|
        TotalBytes,
 | 
						|
        VbePixelWidth,
 | 
						|
        BytesPerScanLine
 | 
						|
        );
 | 
						|
    }
 | 
						|
    break;
 | 
						|
 | 
						|
    default: ;
 | 
						|
  }
 | 
						|
 | 
						|
  gBS->RestoreTPL (OriginalTPL);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Graphics Output protocol instance to block transfer for VBE device.
 | 
						|
 | 
						|
  @param  This                   Pointer to Graphics Output protocol instance
 | 
						|
  @param  BltBuffer              The data to transfer to screen
 | 
						|
  @param  BltOperation           The operation to perform
 | 
						|
  @param  SourceX                The X coordinate of the source for BltOperation
 | 
						|
  @param  SourceY                The Y coordinate of the source for BltOperation
 | 
						|
  @param  DestinationX           The X coordinate of the destination for
 | 
						|
                                 BltOperation
 | 
						|
  @param  DestinationY           The Y coordinate of the destination for
 | 
						|
                                 BltOperation
 | 
						|
  @param  Width                  The width of a rectangle in the blt rectangle in
 | 
						|
                                 pixels
 | 
						|
  @param  Height                 The height of a rectangle in the blt rectangle in
 | 
						|
                                 pixels
 | 
						|
  @param  Delta                  Not used for EfiBltVideoFill and
 | 
						|
                                 EfiBltVideoToVideo operation. If a Delta of 0 is
 | 
						|
                                 used, the entire BltBuffer will be operated on. If
 | 
						|
                                 a subrectangle of the BltBuffer is used, then
 | 
						|
                                 Delta represents the number of bytes in a row of
 | 
						|
                                 the BltBuffer.
 | 
						|
 | 
						|
  @retval EFI_INVALID_PARAMETER  Invalid parameter passed in
 | 
						|
  @retval EFI_SUCCESS            Blt operation success
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
BiosVideoGraphicsOutputVbeBlt (
 | 
						|
  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
 | 
						|
  )
 | 
						|
{
 | 
						|
  BIOS_VIDEO_DEV                 *BiosVideoPrivate;
 | 
						|
  BIOS_VIDEO_MODE_DATA           *Mode;
 | 
						|
 | 
						|
  if (This == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  BiosVideoPrivate  = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);
 | 
						|
  Mode              = &BiosVideoPrivate->ModeData[This->Mode->Mode];
 | 
						|
 | 
						|
  return BiosVideoVbeBltWorker (
 | 
						|
           BiosVideoPrivate,
 | 
						|
           BltBuffer,
 | 
						|
           BltOperation,
 | 
						|
           SourceX,
 | 
						|
           SourceY,
 | 
						|
           DestinationX,
 | 
						|
           DestinationY,
 | 
						|
           Width,
 | 
						|
           Height,
 | 
						|
           Delta,
 | 
						|
           Mode
 | 
						|
           );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Write graphics controller registers.
 | 
						|
 | 
						|
  @param  PciIo                  Pointer to PciIo protocol instance of the
 | 
						|
                                 controller
 | 
						|
  @param  Address                Register address
 | 
						|
  @param  Data                   Data to be written to register
 | 
						|
 | 
						|
  @return None
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
WriteGraphicsController (
 | 
						|
  IN  EFI_PCI_IO_PROTOCOL  *PciIo,
 | 
						|
  IN  UINTN                Address,
 | 
						|
  IN  UINTN                Data
 | 
						|
  )
 | 
						|
{
 | 
						|
  Address = Address | (Data << 8);
 | 
						|
  PciIo->Io.Write (
 | 
						|
              PciIo,
 | 
						|
              EfiPciIoWidthUint16,
 | 
						|
              EFI_PCI_IO_PASS_THROUGH_BAR,
 | 
						|
              VGA_GRAPHICS_CONTROLLER_ADDRESS_REGISTER,
 | 
						|
              1,
 | 
						|
              &Address
 | 
						|
              );
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Read the four bit plane of VGA frame buffer.
 | 
						|
 | 
						|
  @param  PciIo                  Pointer to PciIo protocol instance of the
 | 
						|
                                 controller
 | 
						|
  @param  HardwareBuffer         Hardware VGA frame buffer address
 | 
						|
  @param  MemoryBuffer           Memory buffer address
 | 
						|
  @param  WidthInBytes           Number of bytes in a line to read
 | 
						|
  @param  Height                 Height of the area to read
 | 
						|
 | 
						|
  @return None
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
VgaReadBitPlanes (
 | 
						|
  EFI_PCI_IO_PROTOCOL  *PciIo,
 | 
						|
  UINT8                *HardwareBuffer,
 | 
						|
  UINT8                *MemoryBuffer,
 | 
						|
  UINTN                WidthInBytes,
 | 
						|
  UINTN                Height
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN BitPlane;
 | 
						|
  UINTN Rows;
 | 
						|
  UINTN FrameBufferOffset;
 | 
						|
  UINT8 *Source;
 | 
						|
  UINT8 *Destination;
 | 
						|
 | 
						|
  //
 | 
						|
  // Program the Mode Register Write mode 0, Read mode 0
 | 
						|
  //
 | 
						|
  WriteGraphicsController (
 | 
						|
    PciIo,
 | 
						|
    VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,
 | 
						|
    VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_0
 | 
						|
    );
 | 
						|
 | 
						|
  for (BitPlane = 0, FrameBufferOffset = 0;
 | 
						|
       BitPlane < VGA_NUMBER_OF_BIT_PLANES;
 | 
						|
       BitPlane++, FrameBufferOffset += VGA_BYTES_PER_BIT_PLANE
 | 
						|
      ) {
 | 
						|
    //
 | 
						|
    // Program the Read Map Select Register to select the correct bit plane
 | 
						|
    //
 | 
						|
    WriteGraphicsController (
 | 
						|
      PciIo,
 | 
						|
      VGA_GRAPHICS_CONTROLLER_READ_MAP_SELECT_REGISTER,
 | 
						|
      BitPlane
 | 
						|
      );
 | 
						|
 | 
						|
    Source      = HardwareBuffer;
 | 
						|
    Destination = MemoryBuffer + FrameBufferOffset;
 | 
						|
 | 
						|
    for (Rows = 0; Rows < Height; Rows++, Source += VGA_BYTES_PER_SCAN_LINE, Destination += VGA_BYTES_PER_SCAN_LINE) {
 | 
						|
      PciIo->Mem.Read (
 | 
						|
                  PciIo,
 | 
						|
                  EfiPciIoWidthUint8,
 | 
						|
                  EFI_PCI_IO_PASS_THROUGH_BAR,
 | 
						|
                  (UINT64) (UINTN) Source,
 | 
						|
                  WidthInBytes,
 | 
						|
                  (VOID *) Destination
 | 
						|
                  );
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Internal routine to convert VGA color to Grahpics Output color.
 | 
						|
 | 
						|
  @param  MemoryBuffer           Buffer containing VGA color
 | 
						|
  @param  CoordinateX            The X coordinate of pixel on screen
 | 
						|
  @param  CoordinateY            The Y coordinate of pixel on screen
 | 
						|
  @param  BltBuffer              Buffer to contain converted Grahpics Output color
 | 
						|
 | 
						|
  @return None
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
VgaConvertToGraphicsOutputColor (
 | 
						|
  UINT8                          *MemoryBuffer,
 | 
						|
  UINTN                          CoordinateX,
 | 
						|
  UINTN                          CoordinateY,
 | 
						|
  EFI_GRAPHICS_OUTPUT_BLT_PIXEL  *BltBuffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN Mask;
 | 
						|
  UINTN Bit;
 | 
						|
  UINTN Color;
 | 
						|
 | 
						|
  MemoryBuffer += ((CoordinateY << 6) + (CoordinateY << 4) + (CoordinateX >> 3));
 | 
						|
  Mask = mVgaBitMaskTable[CoordinateX & 0x07];
 | 
						|
  for (Bit = 0x01, Color = 0; Bit < 0x10; Bit <<= 1, MemoryBuffer += VGA_BYTES_PER_BIT_PLANE) {
 | 
						|
    if ((*MemoryBuffer & Mask) != 0) {
 | 
						|
      Color |= Bit;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  *BltBuffer = mVgaColorToGraphicsOutputColor[Color];
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Internal routine to convert Grahpics Output color to VGA color.
 | 
						|
 | 
						|
  @param  BltBuffer              buffer containing Grahpics Output color
 | 
						|
 | 
						|
  @return Converted VGA color
 | 
						|
 | 
						|
**/
 | 
						|
UINT8
 | 
						|
VgaConvertColor (
 | 
						|
  IN  EFI_GRAPHICS_OUTPUT_BLT_PIXEL          *BltBuffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8 Color;
 | 
						|
 | 
						|
  Color = (UINT8) ((BltBuffer->Blue >> 7) | ((BltBuffer->Green >> 6) & 0x02) | ((BltBuffer->Red >> 5) & 0x04));
 | 
						|
  if ((BltBuffer->Red + BltBuffer->Green + BltBuffer->Blue) > 0x180) {
 | 
						|
    Color |= 0x08;
 | 
						|
  }
 | 
						|
 | 
						|
  return Color;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Grahpics Output protocol instance to block transfer for VGA device.
 | 
						|
 | 
						|
  @param  This                   Pointer to Grahpics Output protocol instance
 | 
						|
  @param  BltBuffer              The data to transfer to screen
 | 
						|
  @param  BltOperation           The operation to perform
 | 
						|
  @param  SourceX                The X coordinate of the source for BltOperation
 | 
						|
  @param  SourceY                The Y coordinate of the source for BltOperation
 | 
						|
  @param  DestinationX           The X coordinate of the destination for
 | 
						|
                                 BltOperation
 | 
						|
  @param  DestinationY           The Y coordinate of the destination for
 | 
						|
                                 BltOperation
 | 
						|
  @param  Width                  The width of a rectangle in the blt rectangle in
 | 
						|
                                 pixels
 | 
						|
  @param  Height                 The height of a rectangle in the blt rectangle in
 | 
						|
                                 pixels
 | 
						|
  @param  Delta                  Not used for EfiBltVideoFill and
 | 
						|
                                 EfiBltVideoToVideo operation. If a Delta of 0 is
 | 
						|
                                 used, the entire BltBuffer will be operated on. If
 | 
						|
                                 a subrectangle of the BltBuffer is used, then
 | 
						|
                                 Delta represents the number of bytes in a row of
 | 
						|
                                 the BltBuffer.
 | 
						|
 | 
						|
  @retval EFI_INVALID_PARAMETER  Invalid parameter passed in
 | 
						|
  @retval EFI_SUCCESS            Blt operation success
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
BiosVideoGraphicsOutputVgaBlt (
 | 
						|
  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
 | 
						|
  )
 | 
						|
{
 | 
						|
  BIOS_VIDEO_DEV      *BiosVideoPrivate;
 | 
						|
  EFI_TPL             OriginalTPL;
 | 
						|
  UINT8               *MemAddress;
 | 
						|
  UINTN               BytesPerScanLine;
 | 
						|
  UINTN               Bit;
 | 
						|
  UINTN               Index;
 | 
						|
  UINTN               Index1;
 | 
						|
  UINTN               StartAddress;
 | 
						|
  UINTN               Bytes;
 | 
						|
  UINTN               Offset;
 | 
						|
  UINT8               LeftMask;
 | 
						|
  UINT8               RightMask;
 | 
						|
  UINTN               Address;
 | 
						|
  UINTN               AddressFix;
 | 
						|
  UINT8               *Address1;
 | 
						|
  UINT8               *SourceAddress;
 | 
						|
  UINT8               *DestinationAddress;
 | 
						|
  EFI_PCI_IO_PROTOCOL *PciIo;
 | 
						|
  UINT8               Data;
 | 
						|
  UINT8               PixelColor;
 | 
						|
  UINT8               *VgaFrameBuffer;
 | 
						|
  UINTN               SourceOffset;
 | 
						|
  UINTN               SourceWidth;
 | 
						|
  UINTN               Rows;
 | 
						|
  UINTN               Columns;
 | 
						|
  UINTN               CoordinateX;
 | 
						|
  UINTN               CoordinateY;
 | 
						|
  UINTN               CurrentMode;
 | 
						|
 | 
						|
  if (This == NULL || ((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  BiosVideoPrivate  = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);
 | 
						|
 | 
						|
  CurrentMode = This->Mode->Mode;
 | 
						|
  PciIo             = BiosVideoPrivate->PciIo;
 | 
						|
  MemAddress        = BiosVideoPrivate->ModeData[CurrentMode].LinearFrameBuffer;
 | 
						|
  BytesPerScanLine  = BiosVideoPrivate->ModeData[CurrentMode].BytesPerScanLine >> 3;
 | 
						|
  VgaFrameBuffer    = BiosVideoPrivate->VgaFrameBuffer;
 | 
						|
 | 
						|
 | 
						|
  if (Width == 0 || Height == 0) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // We need to fill the Virtual Screen buffer with the blt data.
 | 
						|
  // The virtual screen is upside down, as the first row is the bootom row of
 | 
						|
  // the image.
 | 
						|
  //
 | 
						|
  if (BltOperation == EfiBltVideoToBltBuffer) {
 | 
						|
    //
 | 
						|
    // Video to BltBuffer: Source is Video, destination is BltBuffer
 | 
						|
    //
 | 
						|
    if (SourceY + Height > BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    if (SourceX + Width > BiosVideoPrivate->ModeData[CurrentMode].HorizontalResolution) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // BltBuffer to Video: Source is BltBuffer, destination is Video
 | 
						|
    //
 | 
						|
    if (DestinationY + Height > BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    if (DestinationX + Width > BiosVideoPrivate->ModeData[CurrentMode].HorizontalResolution) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // If Delta is zero, then the entire BltBuffer is being used, so Delta
 | 
						|
  // is the number of bytes in each row of BltBuffer.  Since BltBuffer is Width pixels size,
 | 
						|
  // the number of bytes in each row can be computed.
 | 
						|
  //
 | 
						|
  if (Delta == 0) {
 | 
						|
    Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
 | 
						|
  // We would not want a timer based event (Cursor, ...) to come in while we are
 | 
						|
  // doing this operation.
 | 
						|
  //
 | 
						|
  OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
 | 
						|
 | 
						|
  //
 | 
						|
  // Compute some values we need for VGA
 | 
						|
  //
 | 
						|
  switch (BltOperation) {
 | 
						|
  case EfiBltVideoToBltBuffer:
 | 
						|
 | 
						|
    SourceOffset  = (SourceY << 6) + (SourceY << 4) + (SourceX >> 3);
 | 
						|
    SourceWidth   = ((SourceX + Width - 1) >> 3) - (SourceX >> 3) + 1;
 | 
						|
 | 
						|
    //
 | 
						|
    // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer
 | 
						|
    //
 | 
						|
    VgaReadBitPlanes (
 | 
						|
      PciIo,
 | 
						|
      MemAddress + SourceOffset,
 | 
						|
      VgaFrameBuffer + SourceOffset,
 | 
						|
      SourceWidth,
 | 
						|
      Height
 | 
						|
      );
 | 
						|
 | 
						|
    //
 | 
						|
    // Convert VGA Bit Planes to a Graphics Output 32-bit color value
 | 
						|
    //
 | 
						|
    BltBuffer += (DestinationY * (Delta >> 2) + DestinationX);
 | 
						|
    for (Rows = 0, CoordinateY = SourceY; Rows < Height; Rows++, CoordinateY++, BltBuffer += (Delta >> 2)) {
 | 
						|
      for (Columns = 0, CoordinateX = SourceX; Columns < Width; Columns++, CoordinateX++, BltBuffer++) {
 | 
						|
        VgaConvertToGraphicsOutputColor (VgaFrameBuffer, CoordinateX, CoordinateY, BltBuffer);
 | 
						|
      }
 | 
						|
 | 
						|
      BltBuffer -= Width;
 | 
						|
    }
 | 
						|
 | 
						|
    break;
 | 
						|
 | 
						|
  case EfiBltVideoToVideo:
 | 
						|
    //
 | 
						|
    // Check for an aligned Video to Video operation
 | 
						|
    //
 | 
						|
    if ((SourceX & 0x07) == 0x00 && (DestinationX & 0x07) == 0x00 && (Width & 0x07) == 0x00) {
 | 
						|
      //
 | 
						|
      // Program the Mode Register Write mode 1, Read mode 0
 | 
						|
      //
 | 
						|
      WriteGraphicsController (
 | 
						|
        PciIo,
 | 
						|
        VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,
 | 
						|
        VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_1
 | 
						|
        );
 | 
						|
 | 
						|
      SourceAddress       = (UINT8 *) (MemAddress + (SourceY << 6) + (SourceY << 4) + (SourceX >> 3));
 | 
						|
      DestinationAddress  = (UINT8 *) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3));
 | 
						|
      Bytes               = Width >> 3;
 | 
						|
      for (Index = 0, Offset = 0; Index < Height; Index++, Offset += BytesPerScanLine) {
 | 
						|
        PciIo->CopyMem (
 | 
						|
                PciIo,
 | 
						|
                EfiPciIoWidthUint8,
 | 
						|
                EFI_PCI_IO_PASS_THROUGH_BAR,
 | 
						|
                (UINT64) (UINTN) (DestinationAddress + Offset),
 | 
						|
                EFI_PCI_IO_PASS_THROUGH_BAR,
 | 
						|
                (UINT64) (UINTN) (SourceAddress + Offset),
 | 
						|
                Bytes
 | 
						|
                );
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      SourceOffset  = (SourceY << 6) + (SourceY << 4) + (SourceX >> 3);
 | 
						|
      SourceWidth   = ((SourceX + Width - 1) >> 3) - (SourceX >> 3) + 1;
 | 
						|
 | 
						|
      //
 | 
						|
      // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer
 | 
						|
      //
 | 
						|
      VgaReadBitPlanes (
 | 
						|
        PciIo,
 | 
						|
        MemAddress + SourceOffset,
 | 
						|
        VgaFrameBuffer + SourceOffset,
 | 
						|
        SourceWidth,
 | 
						|
        Height
 | 
						|
        );
 | 
						|
    }
 | 
						|
 | 
						|
    break;
 | 
						|
 | 
						|
  case EfiBltVideoFill:
 | 
						|
    StartAddress  = (UINTN) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3));
 | 
						|
    Bytes         = ((DestinationX + Width - 1) >> 3) - (DestinationX >> 3);
 | 
						|
    LeftMask      = mVgaLeftMaskTable[DestinationX & 0x07];
 | 
						|
    RightMask     = mVgaRightMaskTable[(DestinationX + Width - 1) & 0x07];
 | 
						|
    if (Bytes == 0) {
 | 
						|
      LeftMask = (UINT8) (LeftMask & RightMask);
 | 
						|
      RightMask = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    if (LeftMask == 0xff) {
 | 
						|
      StartAddress--;
 | 
						|
      Bytes++;
 | 
						|
      LeftMask = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    if (RightMask == 0xff) {
 | 
						|
      Bytes++;
 | 
						|
      RightMask = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    PixelColor = VgaConvertColor (BltBuffer);
 | 
						|
 | 
						|
    //
 | 
						|
    // Program the Mode Register Write mode 2, Read mode 0
 | 
						|
    //
 | 
						|
    WriteGraphicsController (
 | 
						|
      PciIo,
 | 
						|
      VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,
 | 
						|
      VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2
 | 
						|
      );
 | 
						|
 | 
						|
    //
 | 
						|
    // Program the Data Rotate/Function Select Register to replace
 | 
						|
    //
 | 
						|
    WriteGraphicsController (
 | 
						|
      PciIo,
 | 
						|
      VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER,
 | 
						|
      VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE
 | 
						|
      );
 | 
						|
 | 
						|
    if (LeftMask != 0) {
 | 
						|
      //
 | 
						|
      // Program the BitMask register with the Left column mask
 | 
						|
      //
 | 
						|
      WriteGraphicsController (
 | 
						|
        PciIo,
 | 
						|
        VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,
 | 
						|
        LeftMask
 | 
						|
        );
 | 
						|
 | 
						|
      for (Index = 0, Address = StartAddress; Index < Height; Index++, Address += BytesPerScanLine) {
 | 
						|
        //
 | 
						|
        // Read data from the bit planes into the latches
 | 
						|
        //
 | 
						|
        PciIo->Mem.Read (
 | 
						|
                    PciIo,
 | 
						|
                    EfiPciIoWidthUint8,
 | 
						|
                    EFI_PCI_IO_PASS_THROUGH_BAR,
 | 
						|
                    (UINT64) (UINTN) Address,
 | 
						|
                    1,
 | 
						|
                    &Data
 | 
						|
                    );
 | 
						|
        //
 | 
						|
        // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask
 | 
						|
        //
 | 
						|
        PciIo->Mem.Write (
 | 
						|
                    PciIo,
 | 
						|
                    EfiPciIoWidthUint8,
 | 
						|
                    EFI_PCI_IO_PASS_THROUGH_BAR,
 | 
						|
                    (UINT64) (UINTN) Address,
 | 
						|
                    1,
 | 
						|
                    &PixelColor
 | 
						|
                    );
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if (Bytes > 1) {
 | 
						|
      //
 | 
						|
      // Program the BitMask register with the middle column mask of 0xff
 | 
						|
      //
 | 
						|
      WriteGraphicsController (
 | 
						|
        PciIo,
 | 
						|
        VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,
 | 
						|
        0xff
 | 
						|
        );
 | 
						|
 | 
						|
      for (Index = 0, Address = StartAddress + 1; Index < Height; Index++, Address += BytesPerScanLine) {
 | 
						|
        PciIo->Mem.Write (
 | 
						|
                    PciIo,
 | 
						|
                    EfiPciIoWidthFillUint8,
 | 
						|
                    EFI_PCI_IO_PASS_THROUGH_BAR,
 | 
						|
                    (UINT64) (UINTN) Address,
 | 
						|
                    Bytes - 1,
 | 
						|
                    &PixelColor
 | 
						|
                    );
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if (RightMask != 0) {
 | 
						|
      //
 | 
						|
      // Program the BitMask register with the Right column mask
 | 
						|
      //
 | 
						|
      WriteGraphicsController (
 | 
						|
        PciIo,
 | 
						|
        VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,
 | 
						|
        RightMask
 | 
						|
        );
 | 
						|
 | 
						|
      for (Index = 0, Address = StartAddress + Bytes; Index < Height; Index++, Address += BytesPerScanLine) {
 | 
						|
        //
 | 
						|
        // Read data from the bit planes into the latches
 | 
						|
        //
 | 
						|
        PciIo->Mem.Read (
 | 
						|
                    PciIo,
 | 
						|
                    EfiPciIoWidthUint8,
 | 
						|
                    EFI_PCI_IO_PASS_THROUGH_BAR,
 | 
						|
                    (UINT64) (UINTN) Address,
 | 
						|
                    1,
 | 
						|
                    &Data
 | 
						|
                    );
 | 
						|
        //
 | 
						|
        // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask
 | 
						|
        //
 | 
						|
        PciIo->Mem.Write (
 | 
						|
                    PciIo,
 | 
						|
                    EfiPciIoWidthUint8,
 | 
						|
                    EFI_PCI_IO_PASS_THROUGH_BAR,
 | 
						|
                    (UINT64) (UINTN) Address,
 | 
						|
                    1,
 | 
						|
                    &PixelColor
 | 
						|
                    );
 | 
						|
      }
 | 
						|
    }
 | 
						|
    break;
 | 
						|
 | 
						|
  case EfiBltBufferToVideo:
 | 
						|
    StartAddress  = (UINTN) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3));
 | 
						|
    LeftMask      = mVgaBitMaskTable[DestinationX & 0x07];
 | 
						|
 | 
						|
    //
 | 
						|
    // Program the Mode Register Write mode 2, Read mode 0
 | 
						|
    //
 | 
						|
    WriteGraphicsController (
 | 
						|
      PciIo,
 | 
						|
      VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,
 | 
						|
      VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2
 | 
						|
      );
 | 
						|
 | 
						|
    //
 | 
						|
    // Program the Data Rotate/Function Select Register to replace
 | 
						|
    //
 | 
						|
    WriteGraphicsController (
 | 
						|
      PciIo,
 | 
						|
      VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER,
 | 
						|
      VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE
 | 
						|
      );
 | 
						|
 | 
						|
    for (Index = 0, Address = StartAddress; Index < Height; Index++, Address += BytesPerScanLine) {
 | 
						|
      for (Index1 = 0; Index1 < Width; Index1++) {
 | 
						|
        BiosVideoPrivate->LineBuffer[Index1] = VgaConvertColor (&BltBuffer[(SourceY + Index) * (Delta >> 2) + SourceX + Index1]);
 | 
						|
      }
 | 
						|
      AddressFix = Address;
 | 
						|
 | 
						|
      for (Bit = 0; Bit < 8; Bit++) {
 | 
						|
        //
 | 
						|
        // Program the BitMask register with the Left column mask
 | 
						|
        //
 | 
						|
        WriteGraphicsController (
 | 
						|
          PciIo,
 | 
						|
          VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,
 | 
						|
          LeftMask
 | 
						|
          );
 | 
						|
 | 
						|
        for (Index1 = Bit, Address1 = (UINT8 *) AddressFix; Index1 < Width; Index1 += 8, Address1++) {
 | 
						|
          //
 | 
						|
          // Read data from the bit planes into the latches
 | 
						|
          //
 | 
						|
          PciIo->Mem.Read (
 | 
						|
                      PciIo,
 | 
						|
                      EfiPciIoWidthUint8,
 | 
						|
                      EFI_PCI_IO_PASS_THROUGH_BAR,
 | 
						|
                      (UINT64) (UINTN) Address1,
 | 
						|
                      1,
 | 
						|
                      &Data
 | 
						|
                      );
 | 
						|
 | 
						|
          PciIo->Mem.Write (
 | 
						|
                      PciIo,
 | 
						|
                      EfiPciIoWidthUint8,
 | 
						|
                      EFI_PCI_IO_PASS_THROUGH_BAR,
 | 
						|
                      (UINT64) (UINTN) Address1,
 | 
						|
                      1,
 | 
						|
                      &BiosVideoPrivate->LineBuffer[Index1]
 | 
						|
                      );
 | 
						|
        }
 | 
						|
 | 
						|
        LeftMask = (UINT8) (LeftMask >> 1);
 | 
						|
        if (LeftMask == 0) {
 | 
						|
          LeftMask = 0x80;
 | 
						|
          AddressFix++;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    break;
 | 
						|
 | 
						|
    default: ;
 | 
						|
  }
 | 
						|
 | 
						|
  gBS->RestoreTPL (OriginalTPL);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// VGA Mini Port Protocol Functions
 | 
						|
//
 | 
						|
 | 
						|
/**
 | 
						|
  VgaMiniPort protocol interface to set mode.
 | 
						|
 | 
						|
  @param  This                   Pointer to VgaMiniPort protocol instance
 | 
						|
  @param  ModeNumber             The index of the mode
 | 
						|
 | 
						|
  @retval EFI_UNSUPPORTED        The requested mode is not supported
 | 
						|
  @retval EFI_SUCCESS            The requested mode is set successfully
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
BiosVideoVgaMiniPortSetMode (
 | 
						|
  IN  EFI_VGA_MINI_PORT_PROTOCOL  *This,
 | 
						|
  IN  UINTN                       ModeNumber
 | 
						|
  )
 | 
						|
{
 | 
						|
  BIOS_VIDEO_DEV        *BiosVideoPrivate;
 | 
						|
  EFI_IA32_REGISTER_SET Regs;
 | 
						|
 | 
						|
  if (This == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Make sure the ModeNumber is a valid value
 | 
						|
  //
 | 
						|
  if (ModeNumber >= This->MaxMode) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Get the device structure for this device
 | 
						|
  //
 | 
						|
  BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (This);
 | 
						|
 | 
						|
  switch (ModeNumber) {
 | 
						|
  case 0:
 | 
						|
    //
 | 
						|
    // Set the 80x25 Text VGA Mode
 | 
						|
    //
 | 
						|
    Regs.H.AH = 0x00;
 | 
						|
    Regs.H.AL = 0x83;
 | 
						|
    BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
 | 
						|
 | 
						|
    Regs.H.AH = 0x11;
 | 
						|
    Regs.H.AL = 0x14;
 | 
						|
    Regs.H.BL = 0;
 | 
						|
    BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
 | 
						|
    break;
 | 
						|
 | 
						|
  case 1:
 | 
						|
    //
 | 
						|
    // Set the 80x50 Text VGA Mode
 | 
						|
    //
 | 
						|
    Regs.H.AH = 0x00;
 | 
						|
    Regs.H.AL = 0x83;
 | 
						|
    BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
 | 
						|
    Regs.H.AH = 0x11;
 | 
						|
    Regs.H.AL = 0x12;
 | 
						|
    Regs.H.BL = 0;
 | 
						|
    BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
 | 
						|
    break;
 | 
						|
 | 
						|
  default:
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Event handler for Exit Boot Service.
 | 
						|
 | 
						|
  @param  Event       The event that be siganlled when exiting boot service.
 | 
						|
  @param  Context     Pointer to instance of BIOS_VIDEO_DEV.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
BiosVideoNotifyExitBootServices (
 | 
						|
  IN  EFI_EVENT Event,
 | 
						|
  IN  VOID      *Context
 | 
						|
  )
 | 
						|
{
 | 
						|
  BIOS_VIDEO_DEV         *BiosVideoPrivate;
 | 
						|
  EFI_IA32_REGISTER_SET  Regs;
 | 
						|
 | 
						|
  BiosVideoPrivate  = (BIOS_VIDEO_DEV *)Context;
 | 
						|
 | 
						|
  //
 | 
						|
  // Set the 80x25 Text VGA Mode
 | 
						|
  //
 | 
						|
  Regs.H.AH = 0x00;
 | 
						|
  Regs.H.AL = 0x03;
 | 
						|
  BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
 | 
						|
 | 
						|
  Regs.H.AH = 0x00;
 | 
						|
  Regs.H.AL = 0x83;
 | 
						|
  BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
 | 
						|
 | 
						|
  Regs.H.AH = 0x11;
 | 
						|
  Regs.H.AL = 0x04;
 | 
						|
  Regs.H.BL = 0;
 | 
						|
  BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  The user Entry Point for module UefiBiosVideo. The user code starts with this function.
 | 
						|
 | 
						|
  @param[in] ImageHandle    The firmware allocated handle for the EFI image.
 | 
						|
  @param[in] SystemTable    A pointer to the EFI System Table.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS       The entry point is executed successfully.
 | 
						|
  @retval other             Some error occurs when executing this entry point.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
BiosVideoEntryPoint(
 | 
						|
  IN EFI_HANDLE           ImageHandle,
 | 
						|
  IN EFI_SYSTEM_TABLE     *SystemTable
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
 | 
						|
  //
 | 
						|
  // Install driver model protocol(s).
 | 
						|
  //
 | 
						|
  Status = EfiLibInstallDriverBindingComponentName2 (
 | 
						|
             ImageHandle,
 | 
						|
             SystemTable,
 | 
						|
             &gBiosVideoDriverBinding,
 | 
						|
             ImageHandle,
 | 
						|
             &gBiosVideoComponentName,
 | 
						|
             &gBiosVideoComponentName2
 | 
						|
             );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  //
 | 
						|
  // Install Legacy BIOS GUID to mark this driver as a BIOS Thunk Driver
 | 
						|
  //
 | 
						|
  return gBS->InstallMultipleProtocolInterfaces (
 | 
						|
                &ImageHandle,
 | 
						|
                &gEfiLegacyBiosGuid,
 | 
						|
                NULL,
 | 
						|
                NULL
 | 
						|
                );
 | 
						|
}
 | 
						|
 |