https://bugzilla.tianocore.org/show_bug.cgi?id=1373 Replace BSD 2-Clause License with BSD+Patent License. This change is based on the following emails: https://lists.01.org/pipermail/edk2-devel/2019-February/036260.html https://lists.01.org/pipermail/edk2-devel/2018-October/030385.html RFCs with detailed process for the license change: V3: https://lists.01.org/pipermail/edk2-devel/2019-March/038116.html V2: https://lists.01.org/pipermail/edk2-devel/2019-March/037669.html V1: https://lists.01.org/pipermail/edk2-devel/2019-March/037500.html Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com> Reviewed-by: Hao Wu <hao.a.wu@intel.com> Reviewed-by: Jian J Wang <jian.j.wang@intel.com>
		
			
				
	
	
		
			730 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			730 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Implementation for a generic GOP driver.
 | 
						|
 | 
						|
Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
 | 
						|
SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "GraphicsOutput.h"
 | 
						|
CONST ACPI_ADR_DEVICE_PATH mGraphicsOutputAdrNode = {
 | 
						|
  {
 | 
						|
    ACPI_DEVICE_PATH,
 | 
						|
    ACPI_ADR_DP,
 | 
						|
    { sizeof (ACPI_ADR_DEVICE_PATH), 0 },
 | 
						|
  },
 | 
						|
  ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0)
 | 
						|
};
 | 
						|
 | 
						|
EFI_PEI_GRAPHICS_DEVICE_INFO_HOB mDefaultGraphicsDeviceInfo = {
 | 
						|
  MAX_UINT16, MAX_UINT16, MAX_UINT16, MAX_UINT16, MAX_UINT8, MAX_UINT8
 | 
						|
};
 | 
						|
 | 
						|
//
 | 
						|
// The driver should only start on one graphics controller.
 | 
						|
// So a global flag is used to remember that the driver is already started.
 | 
						|
//
 | 
						|
BOOLEAN mDriverStarted = FALSE;
 | 
						|
 | 
						|
/**
 | 
						|
  Returns information for an available graphics mode that the graphics device
 | 
						|
  and the set of active video output devices supports.
 | 
						|
 | 
						|
  @param  This                  The EFI_GRAPHICS_OUTPUT_PROTOCOL instance.
 | 
						|
  @param  ModeNumber            The mode number to return information on.
 | 
						|
  @param  SizeOfInfo            A pointer to the size, in bytes, of the Info buffer.
 | 
						|
  @param  Info                  A pointer to callee allocated buffer that returns information about ModeNumber.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           Valid mode information was returned.
 | 
						|
  @retval EFI_DEVICE_ERROR      A hardware error occurred trying to retrieve the video mode.
 | 
						|
  @retval EFI_INVALID_PARAMETER ModeNumber is not valid.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
GraphicsOutputQueryMode (
 | 
						|
  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL          *This,
 | 
						|
  IN  UINT32                                ModeNumber,
 | 
						|
  OUT UINTN                                 *SizeOfInfo,
 | 
						|
  OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  **Info
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  *SizeOfInfo = This->Mode->SizeOfInfo;
 | 
						|
  *Info       = AllocateCopyPool (*SizeOfInfo, This->Mode->Info);
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Set the video device into the specified mode and clears the visible portions of
 | 
						|
  the output display to black.
 | 
						|
 | 
						|
  @param  This              The EFI_GRAPHICS_OUTPUT_PROTOCOL instance.
 | 
						|
  @param  ModeNumber        Abstraction that defines the current video mode.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS       The graphics mode specified by ModeNumber was selected.
 | 
						|
  @retval EFI_DEVICE_ERROR  The device had an error and could not complete the request.
 | 
						|
  @retval EFI_UNSUPPORTED   ModeNumber is not supported by this device.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
GraphicsOutputSetMode (
 | 
						|
  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
 | 
						|
  IN  UINT32                       ModeNumber
 | 
						|
)
 | 
						|
{
 | 
						|
  RETURN_STATUS                    Status;
 | 
						|
  EFI_GRAPHICS_OUTPUT_BLT_PIXEL    Black;
 | 
						|
  GRAPHICS_OUTPUT_PRIVATE_DATA     *Private;
 | 
						|
 | 
						|
  if (ModeNumber >= This->Mode->MaxMode) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  Private = GRAPHICS_OUTPUT_PRIVATE_FROM_THIS (This);
 | 
						|
 | 
						|
  Black.Blue = 0;
 | 
						|
  Black.Green = 0;
 | 
						|
  Black.Red = 0;
 | 
						|
  Black.Reserved = 0;
 | 
						|
 | 
						|
  Status = FrameBufferBlt (
 | 
						|
             Private->FrameBufferBltLibConfigure,
 | 
						|
             &Black,
 | 
						|
             EfiBltVideoFill,
 | 
						|
             0, 0,
 | 
						|
             0, 0,
 | 
						|
             This->Mode->Info->HorizontalResolution,
 | 
						|
             This->Mode->Info->VerticalResolution,
 | 
						|
             0
 | 
						|
             );
 | 
						|
  return RETURN_ERROR (Status) ? EFI_DEVICE_ERROR : EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Blt a rectangle of pixels on the graphics screen. Blt stands for BLock Transfer.
 | 
						|
 | 
						|
  @param  This         Protocol instance pointer.
 | 
						|
  @param  BltBuffer    The data to transfer to the graphics screen.
 | 
						|
                       Size is at least Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL).
 | 
						|
  @param  BltOperation The operation to perform when copying BltBuffer on to the graphics screen.
 | 
						|
  @param  SourceX      The X coordinate of source for the BltOperation.
 | 
						|
  @param  SourceY      The Y coordinate of source for the BltOperation.
 | 
						|
  @param  DestinationX The X coordinate of destination for the BltOperation.
 | 
						|
  @param  DestinationY The Y coordinate of destination for the 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 or the EfiBltVideoToVideo operation.
 | 
						|
                       If a Delta of zero is used, the entire BltBuffer is being operated on.
 | 
						|
                       If a subrectangle of the BltBuffer is being used then Delta
 | 
						|
                       represents the number of bytes in a row of the BltBuffer.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           BltBuffer was drawn to the graphics screen.
 | 
						|
  @retval EFI_INVALID_PARAMETER BltOperation is not valid.
 | 
						|
  @retval EFI_DEVICE_ERROR      The device had an error and could not complete the request.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
GraphicsOutputBlt (
 | 
						|
  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL      *This,
 | 
						|
  IN  EFI_GRAPHICS_OUTPUT_BLT_PIXEL     *BltBuffer, OPTIONAL
 | 
						|
  IN  EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
 | 
						|
  IN  UINTN                             SourceX,
 | 
						|
  IN  UINTN                             SourceY,
 | 
						|
  IN  UINTN                             DestinationX,
 | 
						|
  IN  UINTN                             DestinationY,
 | 
						|
  IN  UINTN                             Width,
 | 
						|
  IN  UINTN                             Height,
 | 
						|
  IN  UINTN                             Delta         OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  RETURN_STATUS                         Status;
 | 
						|
  EFI_TPL                               Tpl;
 | 
						|
  GRAPHICS_OUTPUT_PRIVATE_DATA          *Private;
 | 
						|
 | 
						|
  Private = GRAPHICS_OUTPUT_PRIVATE_FROM_THIS (This);
 | 
						|
  //
 | 
						|
  // We have to raise to TPL_NOTIFY, so we make an atomic write to the frame buffer.
 | 
						|
  // We would not want a timer based event (Cursor, ...) to come in while we are
 | 
						|
  // doing this operation.
 | 
						|
  //
 | 
						|
  Tpl = gBS->RaiseTPL (TPL_NOTIFY);
 | 
						|
  Status = FrameBufferBlt (
 | 
						|
             Private->FrameBufferBltLibConfigure,
 | 
						|
             BltBuffer,
 | 
						|
             BltOperation,
 | 
						|
             SourceX, SourceY,
 | 
						|
             DestinationX, DestinationY, Width, Height,
 | 
						|
             Delta
 | 
						|
             );
 | 
						|
  gBS->RestoreTPL (Tpl);
 | 
						|
 | 
						|
  return RETURN_ERROR (Status) ? EFI_INVALID_PARAMETER : EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
CONST GRAPHICS_OUTPUT_PRIVATE_DATA mGraphicsOutputInstanceTemplate = {
 | 
						|
  GRAPHICS_OUTPUT_PRIVATE_DATA_SIGNATURE,          // Signature
 | 
						|
  NULL,                                            // GraphicsOutputHandle
 | 
						|
  {
 | 
						|
    GraphicsOutputQueryMode,
 | 
						|
    GraphicsOutputSetMode,
 | 
						|
    GraphicsOutputBlt,
 | 
						|
    NULL                                           // Mode
 | 
						|
  },
 | 
						|
  {
 | 
						|
    1,                                             // MaxMode
 | 
						|
    0,                                             // Mode
 | 
						|
    NULL,                                          // Info
 | 
						|
    sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION), // SizeOfInfo
 | 
						|
    0,                                             // FrameBufferBase
 | 
						|
    0                                              // FrameBufferSize
 | 
						|
  },
 | 
						|
  NULL,                                            // DevicePath
 | 
						|
  NULL,                                            // PciIo
 | 
						|
  0,                                               // PciAttributes
 | 
						|
  NULL,                                            // FrameBufferBltLibConfigure
 | 
						|
  0                                                // FrameBufferBltLibConfigureSize
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
  Test whether the Controller can be managed by the driver.
 | 
						|
 | 
						|
  @param  This                 Driver Binding protocol instance pointer.
 | 
						|
  @param  Controller           The PCI controller.
 | 
						|
  @param  RemainingDevicePath  Optional parameter use to pick a specific child
 | 
						|
                               device to start.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS          The driver can manage the video device.
 | 
						|
  @retval other                The driver cannot manage the video device.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
GraphicsOutputDriverBindingSupported (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
 | 
						|
  IN EFI_HANDLE                     Controller,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  EFI_PCI_IO_PROTOCOL               *PciIo;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL          *DevicePath;
 | 
						|
 | 
						|
  //
 | 
						|
  // Since there is only one GraphicsInfo HOB, the driver only manages one video device.
 | 
						|
  //
 | 
						|
  if (mDriverStarted) {
 | 
						|
    return EFI_ALREADY_STARTED;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Test the PCI I/O Protocol
 | 
						|
  //
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Controller,
 | 
						|
                  &gEfiPciIoProtocolGuid,
 | 
						|
                  (VOID **) &PciIo,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  Controller,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_DRIVER
 | 
						|
                  );
 | 
						|
  if (Status == EFI_ALREADY_STARTED) {
 | 
						|
    Status = EFI_SUCCESS;
 | 
						|
  }
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  gBS->CloseProtocol (
 | 
						|
         Controller,
 | 
						|
         &gEfiPciIoProtocolGuid,
 | 
						|
         This->DriverBindingHandle,
 | 
						|
         Controller
 | 
						|
         );
 | 
						|
 | 
						|
  //
 | 
						|
  // Test the DevicePath protocol
 | 
						|
  //
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Controller,
 | 
						|
                  &gEfiDevicePathProtocolGuid,
 | 
						|
                  (VOID **) &DevicePath,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  Controller,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_DRIVER
 | 
						|
                  );
 | 
						|
  if (Status == EFI_ALREADY_STARTED) {
 | 
						|
    Status = EFI_SUCCESS;
 | 
						|
  }
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  gBS->CloseProtocol (
 | 
						|
         Controller,
 | 
						|
         &gEfiDevicePathProtocolGuid,
 | 
						|
         This->DriverBindingHandle,
 | 
						|
         Controller
 | 
						|
         );
 | 
						|
 | 
						|
  if ((RemainingDevicePath == NULL) ||
 | 
						|
      IsDevicePathEnd (RemainingDevicePath) ||
 | 
						|
      CompareMem (RemainingDevicePath, &mGraphicsOutputAdrNode, sizeof (mGraphicsOutputAdrNode)) == 0) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  } else {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Start the video controller.
 | 
						|
 | 
						|
  @param  This                 Driver Binding protocol instance pointer.
 | 
						|
  @param  ControllerHandle     The PCI controller.
 | 
						|
  @param  RemainingDevicePath  Optional parameter use to pick a specific child
 | 
						|
                               device to start.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS          The driver starts to manage the video device.
 | 
						|
  @retval other                The driver cannot manage the video device.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
GraphicsOutputDriverBindingStart (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
 | 
						|
  IN EFI_HANDLE                     Controller,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  RETURN_STATUS                     ReturnStatus;
 | 
						|
  GRAPHICS_OUTPUT_PRIVATE_DATA      *Private;
 | 
						|
  EFI_PCI_IO_PROTOCOL               *PciIo;
 | 
						|
  EFI_DEVICE_PATH                   *PciDevicePath;
 | 
						|
  PCI_TYPE00                        Pci;
 | 
						|
  UINT8                             Index;
 | 
						|
  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Resources;
 | 
						|
  VOID                              *HobStart;
 | 
						|
  EFI_PEI_GRAPHICS_INFO_HOB         *GraphicsInfo;
 | 
						|
  EFI_PEI_GRAPHICS_DEVICE_INFO_HOB  *DeviceInfo;
 | 
						|
  EFI_PHYSICAL_ADDRESS              FrameBufferBase;
 | 
						|
 | 
						|
  FrameBufferBase = 0;
 | 
						|
 | 
						|
  HobStart = GetFirstGuidHob (&gEfiGraphicsInfoHobGuid);
 | 
						|
  ASSERT ((HobStart != NULL) && (GET_GUID_HOB_DATA_SIZE (HobStart) == sizeof (EFI_PEI_GRAPHICS_INFO_HOB)));
 | 
						|
  GraphicsInfo = (EFI_PEI_GRAPHICS_INFO_HOB *) (GET_GUID_HOB_DATA (HobStart));
 | 
						|
 | 
						|
  HobStart = GetFirstGuidHob (&gEfiGraphicsDeviceInfoHobGuid);
 | 
						|
  if ((HobStart == NULL) || (GET_GUID_HOB_DATA_SIZE (HobStart) < sizeof (*DeviceInfo))) {
 | 
						|
    //
 | 
						|
    // Use default device infomation when the device info HOB doesn't exist
 | 
						|
    //
 | 
						|
    DeviceInfo = &mDefaultGraphicsDeviceInfo;
 | 
						|
    DEBUG ((EFI_D_INFO, "[%a]: GraphicsDeviceInfo HOB doesn't exist!\n", gEfiCallerBaseName));
 | 
						|
  } else {
 | 
						|
    DeviceInfo = (EFI_PEI_GRAPHICS_DEVICE_INFO_HOB *) (GET_GUID_HOB_DATA (HobStart));
 | 
						|
    DEBUG ((EFI_D_INFO, "[%a]: GraphicsDeviceInfo HOB:\n"
 | 
						|
            "  VendorId = %04x, DeviceId = %04x,\n"
 | 
						|
            "  RevisionId = %02x, BarIndex = %x,\n"
 | 
						|
            "  SubsystemVendorId = %04x, SubsystemId = %04x\n",
 | 
						|
            gEfiCallerBaseName,
 | 
						|
            DeviceInfo->VendorId, DeviceInfo->DeviceId,
 | 
						|
            DeviceInfo->RevisionId, DeviceInfo->BarIndex,
 | 
						|
            DeviceInfo->SubsystemVendorId, DeviceInfo->SubsystemId));
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Open the PCI I/O Protocol
 | 
						|
  //
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Controller,
 | 
						|
                  &gEfiPciIoProtocolGuid,
 | 
						|
                  (VOID **) &PciIo,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  Controller,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_DRIVER
 | 
						|
                  );
 | 
						|
  if (Status == EFI_ALREADY_STARTED) {
 | 
						|
    Status = EFI_SUCCESS;
 | 
						|
  }
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Controller,
 | 
						|
                  &gEfiDevicePathProtocolGuid,
 | 
						|
                  (VOID **) &PciDevicePath,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  Controller,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_DRIVER
 | 
						|
                  );
 | 
						|
  if (Status == EFI_ALREADY_STARTED) {
 | 
						|
    Status = EFI_SUCCESS;
 | 
						|
  }
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  //
 | 
						|
  // Read the PCI Class Code from the PCI Device
 | 
						|
  //
 | 
						|
  Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0, sizeof (Pci), &Pci);
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    if (!IS_PCI_DISPLAY (&Pci) || (
 | 
						|
        ((DeviceInfo->VendorId != MAX_UINT16) && (DeviceInfo->VendorId != Pci.Hdr.VendorId)) ||
 | 
						|
        ((DeviceInfo->DeviceId != MAX_UINT16) && (DeviceInfo->DeviceId != Pci.Hdr.DeviceId)) ||
 | 
						|
        ((DeviceInfo->RevisionId != MAX_UINT8) && (DeviceInfo->RevisionId != Pci.Hdr.RevisionID)) ||
 | 
						|
        ((DeviceInfo->SubsystemVendorId != MAX_UINT16) && (DeviceInfo->SubsystemVendorId != Pci.Device.SubsystemVendorID)) ||
 | 
						|
        ((DeviceInfo->SubsystemId != MAX_UINT16) && (DeviceInfo->SubsystemId != Pci.Device.SubsystemID))
 | 
						|
        )
 | 
						|
        ) {
 | 
						|
      //
 | 
						|
      // It's not a video device, or device infomation doesn't match.
 | 
						|
      //
 | 
						|
      Status = EFI_UNSUPPORTED;
 | 
						|
    } else {
 | 
						|
      //
 | 
						|
      // If it's a video device and device information matches, use the BarIndex
 | 
						|
      // from device information, or any BAR if BarIndex is not specified
 | 
						|
      // whose size >= the frame buffer size from GraphicsInfo HOB.
 | 
						|
      // Store the new frame buffer base.
 | 
						|
      //
 | 
						|
      for (Index = 0; Index < MAX_PCI_BAR; Index++) {
 | 
						|
        if ((DeviceInfo->BarIndex != MAX_UINT8) && (DeviceInfo->BarIndex != Index)) {
 | 
						|
          continue;
 | 
						|
        }
 | 
						|
        Status = PciIo->GetBarAttributes (PciIo, Index, NULL, (VOID**) &Resources);
 | 
						|
        if (!EFI_ERROR (Status)) {
 | 
						|
          DEBUG ((EFI_D_INFO, "[%a]: BAR[%d]: Base = %lx, Length = %lx\n",
 | 
						|
                  gEfiCallerBaseName, Index, Resources->AddrRangeMin, Resources->AddrLen));
 | 
						|
          if ((Resources->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) &&
 | 
						|
            (Resources->Len == (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3)) &&
 | 
						|
              (Resources->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) &&
 | 
						|
              (Resources->AddrLen >= GraphicsInfo->FrameBufferSize)
 | 
						|
              ) {
 | 
						|
            FrameBufferBase = Resources->AddrRangeMin;
 | 
						|
            DEBUG ((EFI_D_INFO, "[%a]: ... matched!\n", gEfiCallerBaseName));
 | 
						|
            break;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
      if (Index == MAX_PCI_BAR) {
 | 
						|
        Status = EFI_UNSUPPORTED;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto CloseProtocols;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((RemainingDevicePath != NULL) && IsDevicePathEnd (RemainingDevicePath)) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  Private = AllocateCopyPool (sizeof (mGraphicsOutputInstanceTemplate), &mGraphicsOutputInstanceTemplate);
 | 
						|
  if (Private == NULL) {
 | 
						|
    Status = EFI_OUT_OF_RESOURCES;
 | 
						|
    goto CloseProtocols;
 | 
						|
  }
 | 
						|
 | 
						|
  Private->GraphicsOutputMode.FrameBufferBase = FrameBufferBase;
 | 
						|
  Private->GraphicsOutputMode.FrameBufferSize = GraphicsInfo->FrameBufferSize;
 | 
						|
  Private->GraphicsOutputMode.Info = &GraphicsInfo->GraphicsMode;
 | 
						|
 | 
						|
  //
 | 
						|
  // Fix up Mode pointer in GraphicsOutput
 | 
						|
  //
 | 
						|
  Private->GraphicsOutput.Mode = &Private->GraphicsOutputMode;
 | 
						|
 | 
						|
  //
 | 
						|
  // Set attributes
 | 
						|
  //
 | 
						|
  Status = PciIo->Attributes (
 | 
						|
                    PciIo,
 | 
						|
                    EfiPciIoAttributeOperationGet,
 | 
						|
                    0,
 | 
						|
                    &Private->PciAttributes
 | 
						|
                    );
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    Status = PciIo->Attributes (
 | 
						|
                      PciIo,
 | 
						|
                      EfiPciIoAttributeOperationEnable,
 | 
						|
                      EFI_PCI_DEVICE_ENABLE,
 | 
						|
                      NULL
 | 
						|
                      );
 | 
						|
  }
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto FreeMemory;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Create the FrameBufferBltLib configuration.
 | 
						|
  //
 | 
						|
  ReturnStatus = FrameBufferBltConfigure (
 | 
						|
                   (VOID *) (UINTN) Private->GraphicsOutput.Mode->FrameBufferBase,
 | 
						|
                   Private->GraphicsOutput.Mode->Info,
 | 
						|
                   Private->FrameBufferBltLibConfigure,
 | 
						|
                   &Private->FrameBufferBltLibConfigureSize
 | 
						|
                   );
 | 
						|
  if (ReturnStatus == RETURN_BUFFER_TOO_SMALL) {
 | 
						|
    Private->FrameBufferBltLibConfigure = AllocatePool (Private->FrameBufferBltLibConfigureSize);
 | 
						|
    if (Private->FrameBufferBltLibConfigure != NULL) {
 | 
						|
      ReturnStatus = FrameBufferBltConfigure (
 | 
						|
                       (VOID *) (UINTN) Private->GraphicsOutput.Mode->FrameBufferBase,
 | 
						|
                       Private->GraphicsOutput.Mode->Info,
 | 
						|
                       Private->FrameBufferBltLibConfigure,
 | 
						|
                       &Private->FrameBufferBltLibConfigureSize
 | 
						|
                       );
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (RETURN_ERROR (ReturnStatus)) {
 | 
						|
    Status = EFI_OUT_OF_RESOURCES;
 | 
						|
    goto RestorePciAttributes;
 | 
						|
  }
 | 
						|
 | 
						|
  Private->DevicePath = AppendDevicePathNode (PciDevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &mGraphicsOutputAdrNode);
 | 
						|
  if (Private->DevicePath == NULL) {
 | 
						|
    Status = EFI_OUT_OF_RESOURCES;
 | 
						|
    goto RestorePciAttributes;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = gBS->InstallMultipleProtocolInterfaces (
 | 
						|
                  &Private->GraphicsOutputHandle,
 | 
						|
                  &gEfiGraphicsOutputProtocolGuid, &Private->GraphicsOutput,
 | 
						|
                  &gEfiDevicePathProtocolGuid, Private->DevicePath,
 | 
						|
                  NULL
 | 
						|
                  );
 | 
						|
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    Status = gBS->OpenProtocol (
 | 
						|
                    Controller,
 | 
						|
                    &gEfiPciIoProtocolGuid,
 | 
						|
                    (VOID **) &Private->PciIo,
 | 
						|
                    This->DriverBindingHandle,
 | 
						|
                    Private->GraphicsOutputHandle,
 | 
						|
                    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
 | 
						|
                    );
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      mDriverStarted = TRUE;
 | 
						|
    } else {
 | 
						|
      gBS->UninstallMultipleProtocolInterfaces (
 | 
						|
             Private->GraphicsOutputHandle,
 | 
						|
             &gEfiGraphicsOutputProtocolGuid, &Private->GraphicsOutput,
 | 
						|
             &gEfiDevicePathProtocolGuid, Private->DevicePath,
 | 
						|
             NULL
 | 
						|
             );
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
RestorePciAttributes:
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    //
 | 
						|
    // Restore original PCI attributes
 | 
						|
    //
 | 
						|
    PciIo->Attributes (
 | 
						|
             PciIo,
 | 
						|
             EfiPciIoAttributeOperationSet,
 | 
						|
             Private->PciAttributes,
 | 
						|
             NULL
 | 
						|
             );
 | 
						|
  }
 | 
						|
 | 
						|
FreeMemory:
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    if (Private != NULL) {
 | 
						|
      if (Private->DevicePath != NULL) {
 | 
						|
        FreePool (Private->DevicePath);
 | 
						|
      }
 | 
						|
      if (Private->FrameBufferBltLibConfigure != NULL) {
 | 
						|
        FreePool (Private->FrameBufferBltLibConfigure);
 | 
						|
      }
 | 
						|
      FreePool (Private);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
CloseProtocols:
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    //
 | 
						|
    // Close the PCI I/O Protocol
 | 
						|
    //
 | 
						|
    gBS->CloseProtocol (
 | 
						|
           Controller,
 | 
						|
           &gEfiDevicePathProtocolGuid,
 | 
						|
           This->DriverBindingHandle,
 | 
						|
           Controller
 | 
						|
           );
 | 
						|
 | 
						|
    //
 | 
						|
    // Close the PCI I/O Protocol
 | 
						|
    //
 | 
						|
    gBS->CloseProtocol (
 | 
						|
           Controller,
 | 
						|
           &gEfiPciIoProtocolGuid,
 | 
						|
           This->DriverBindingHandle,
 | 
						|
           Controller
 | 
						|
           );
 | 
						|
  }
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Stop the video controller.
 | 
						|
 | 
						|
  @param  This                 Driver Binding protocol instance pointer.
 | 
						|
  @param  Controller           The PCI controller.
 | 
						|
  @param  NumberOfChildren     The number of child device handles in ChildHandleBuffer.
 | 
						|
  @param  ChildHandleBuffer    An array of child handles to be freed. May be NULL
 | 
						|
                               if NumberOfChildren is 0.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS          The device was stopped.
 | 
						|
  @retval EFI_DEVICE_ERROR     The device could not be stopped due to a device error.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
GraphicsOutputDriverBindingStop (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
 | 
						|
  IN EFI_HANDLE                     Controller,
 | 
						|
  IN UINTN                          NumberOfChildren,
 | 
						|
  IN EFI_HANDLE                     *ChildHandleBuffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  EFI_GRAPHICS_OUTPUT_PROTOCOL      *Gop;
 | 
						|
  GRAPHICS_OUTPUT_PRIVATE_DATA      *Private;
 | 
						|
 | 
						|
  if (NumberOfChildren == 0) {
 | 
						|
 | 
						|
    //
 | 
						|
    // Close the PCI I/O Protocol
 | 
						|
    //
 | 
						|
    Status = gBS->CloseProtocol (
 | 
						|
                    Controller,
 | 
						|
                    &gEfiPciIoProtocolGuid,
 | 
						|
                    This->DriverBindingHandle,
 | 
						|
                    Controller
 | 
						|
                    );
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
    Status = gBS->CloseProtocol (
 | 
						|
                    Controller,
 | 
						|
                    &gEfiDevicePathProtocolGuid,
 | 
						|
                    This->DriverBindingHandle,
 | 
						|
                    Controller
 | 
						|
                    );
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  ASSERT (NumberOfChildren == 1);
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  ChildHandleBuffer[0],
 | 
						|
                  &gEfiGraphicsOutputProtocolGuid,
 | 
						|
                  (VOID **) &Gop,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  ChildHandleBuffer[0],
 | 
						|
                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  Private = GRAPHICS_OUTPUT_PRIVATE_FROM_THIS (Gop);
 | 
						|
 | 
						|
  Status = gBS->CloseProtocol (
 | 
						|
                  Controller,
 | 
						|
                  &gEfiPciIoProtocolGuid,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  Private->GraphicsOutputHandle
 | 
						|
                  );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
  //
 | 
						|
  // Remove the GOP protocol interface from the system
 | 
						|
  //
 | 
						|
  Status = gBS->UninstallMultipleProtocolInterfaces (
 | 
						|
                  Private->GraphicsOutputHandle,
 | 
						|
                  &gEfiGraphicsOutputProtocolGuid, &Private->GraphicsOutput,
 | 
						|
                  &gEfiDevicePathProtocolGuid, Private->DevicePath,
 | 
						|
                  NULL
 | 
						|
                  );
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    //
 | 
						|
    // Restore original PCI attributes
 | 
						|
    //
 | 
						|
    Status = Private->PciIo->Attributes (
 | 
						|
                               Private->PciIo,
 | 
						|
                               EfiPciIoAttributeOperationSet,
 | 
						|
                               Private->PciAttributes,
 | 
						|
                               NULL
 | 
						|
                               );
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
    FreePool (Private->DevicePath);
 | 
						|
    FreePool (Private->FrameBufferBltLibConfigure);
 | 
						|
    mDriverStarted = FALSE;
 | 
						|
  } else {
 | 
						|
    Status = gBS->OpenProtocol (
 | 
						|
                    Controller,
 | 
						|
                    &gEfiPciIoProtocolGuid,
 | 
						|
                    (VOID **) &Private->PciIo,
 | 
						|
                    This->DriverBindingHandle,
 | 
						|
                    Private->GraphicsOutputHandle,
 | 
						|
                    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
 | 
						|
                    );
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
  }
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
EFI_DRIVER_BINDING_PROTOCOL mGraphicsOutputDriverBinding = {
 | 
						|
  GraphicsOutputDriverBindingSupported,
 | 
						|
  GraphicsOutputDriverBindingStart,
 | 
						|
  GraphicsOutputDriverBindingStop,
 | 
						|
  0x10,
 | 
						|
  NULL,
 | 
						|
  NULL
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
  The Entry Point for GraphicsOutput driver.
 | 
						|
 | 
						|
  It installs DriverBinding, ComponentName and ComponentName2 protocol if there is
 | 
						|
  GraphicsInfo HOB passed from Graphics PEIM.
 | 
						|
 | 
						|
  @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
 | 
						|
InitializeGraphicsOutput (
 | 
						|
  IN EFI_HANDLE                        ImageHandle,
 | 
						|
  IN EFI_SYSTEM_TABLE                  *SystemTable
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                           Status;
 | 
						|
  VOID                                 *HobStart;
 | 
						|
 | 
						|
  HobStart = GetFirstGuidHob (&gEfiGraphicsInfoHobGuid);
 | 
						|
 | 
						|
  if ((HobStart == NULL) || (GET_GUID_HOB_DATA_SIZE (HobStart) < sizeof (EFI_PEI_GRAPHICS_INFO_HOB))) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = EfiLibInstallDriverBindingComponentName2 (
 | 
						|
             ImageHandle,
 | 
						|
             SystemTable,
 | 
						|
             &mGraphicsOutputDriverBinding,
 | 
						|
             ImageHandle,
 | 
						|
             &mGraphicsOutputComponentName,
 | 
						|
             &mGraphicsOutputComponentName2
 | 
						|
             );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 |