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;
 | |
| }
 |