Nice. :) One of my motivations for BltLib was the hope that we could
make a common GOP driver. Similar to what you are doing here it was
for a platform that only supported a single video mode.

Another idea: What if we design a VideoModeSetLib? We could have a
'Null' driver that uses the GraphicsInfo HOB and supports a single
mode. Or, a platform could provide a non-null library to allow setting
other modes. For example, this might allow OVMF to use
GraphicsOutputDxe.

-Jordan

On 2015-08-17 06:45:29, Ruiyu Ni wrote:
> The driver consumes the GraphicsInfo HOB and produces GOP protocol.
> 
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Ruiyu Ni <ruiyu...@intel.com>
> Cc: Feng Tian <feng.t...@intel.com>
> ---
>  MdeModulePkg/MdeModulePkg.dsc                      |   4 +
>  .../Console/GraphicsOutputDxe/ComponentName.c      | 190 ++++++
>  .../Console/GraphicsOutputDxe/GraphicsOutput.c     | 659 
> +++++++++++++++++++++
>  .../Console/GraphicsOutputDxe/GraphicsOutput.h     |  53 ++
>  .../GraphicsOutputDxe/GraphicsOutputDxe.inf        |  57 ++
>  5 files changed, 963 insertions(+)
>  create mode 100644 
> MdeModulePkg/Universal/Console/GraphicsOutputDxe/ComponentName.c
>  create mode 100644 
> MdeModulePkg/Universal/Console/GraphicsOutputDxe/GraphicsOutput.c
>  create mode 100644 
> MdeModulePkg/Universal/Console/GraphicsOutputDxe/GraphicsOutput.h
>  create mode 100644 
> MdeModulePkg/Universal/Console/GraphicsOutputDxe/GraphicsOutputDxe.inf
> 
> diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc
> index e475dc1..cd3e21e 100644
> --- a/MdeModulePkg/MdeModulePkg.dsc
> +++ b/MdeModulePkg/MdeModulePkg.dsc
> @@ -290,6 +290,10 @@
>    MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
>    MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
>    MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
> +  MdeModulePkg/Universal/Console/GraphicsOutputDxe/GraphicsOutputDxe.inf {
> +    <LibraryClasses>
> +      BltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf
> +  }
>    MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
>    MdeModulePkg/Universal/DebugPortDxe/DebugPortDxe.inf
>    MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
> diff --git a/MdeModulePkg/Universal/Console/GraphicsOutputDxe/ComponentName.c 
> b/MdeModulePkg/Universal/Console/GraphicsOutputDxe/ComponentName.c
> new file mode 100644
> index 0000000..9f1c79d
> --- /dev/null
> +++ b/MdeModulePkg/Universal/Console/GraphicsOutputDxe/ComponentName.c
> @@ -0,0 +1,190 @@
> +/** @file
> +  UEFI Component Name(2) protocol implementation for the generic GOP driver.
> +  
> +Copyright (c) 2015, 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 <PiDxe.h>
> +#include <Library/UefiLib.h>
> +
> +extern EFI_COMPONENT_NAME_PROTOCOL  mGraphicsOutputComponentName;
> +extern EFI_COMPONENT_NAME2_PROTOCOL mGraphicsOutputComponentName2;
> +
> +//
> +// Driver name table for GraphicsOutput module.
> +// It is shared by the implementation of ComponentName & ComponentName2 
> Protocol.
> +//
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE 
> mGraphicsOutputDriverNameTable[] = {
> +  {
> +    "eng;en",
> +    L"Generic Graphics Output Driver"
> +  },
> +  {
> +    NULL,
> +    NULL
> +  }
> +};
> +
> +/**
> +  Retrieves a Unicode string that is the user readable name of the driver.
> +
> +  This function retrieves the user readable name of a driver in the form of a
> +  Unicode string. If the driver specified by This has a user readable name in
> +  the language specified by Language, then a pointer to the driver name is
> +  returned in DriverName, and EFI_SUCCESS is returned. If the driver 
> specified
> +  by This does not support the language specified by Language,
> +  then EFI_UNSUPPORTED is returned.
> +
> +  @param  This[in]              A pointer to the 
> EFI_COMPONENT_NAME2_PROTOCOL or
> +                                EFI_COMPONENT_NAME_PROTOCOL instance.
> +
> +  @param  Language[in]          A pointer to a Null-terminated ASCII string
> +                                array indicating the language. This is the
> +                                language of the driver name that the caller 
> is
> +                                requesting, and it must match one of the
> +                                languages specified in SupportedLanguages. 
> The
> +                                number of languages supported by a driver is 
> up
> +                                to the driver writer. Language is specified
> +                                in RFC 4646 or ISO 639-2 language code 
> format.
> +
> +  @param  DriverName[out]       A pointer to the Unicode string to return.
> +                                This Unicode string is the name of the
> +                                driver specified by This in the language
> +                                specified by Language.
> +
> +  @retval EFI_SUCCESS           The Unicode string for the Driver specified 
> by
> +                                This and the language specified by Language 
> was
> +                                returned in DriverName.
> +
> +  @retval EFI_INVALID_PARAMETER Language is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER DriverName is NULL.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This does not support
> +                                the language specified by Language.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +GraphicsOutputComponentNameGetDriverName (
> +  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,
> +  IN  CHAR8                        *Language,
> +  OUT CHAR16                       **DriverName
> +  )
> +{
> +  return LookupUnicodeString2 (
> +           Language,
> +           This->SupportedLanguages,
> +           mGraphicsOutputDriverNameTable,
> +           DriverName,
> +           (BOOLEAN) (This == &mGraphicsOutputComponentName)
> +           );
> +}
> +
> +/**
> +  Retrieves a Unicode string that is the user readable name of the controller
> +  that is being managed by a driver.
> +
> +  This function retrieves the user readable name of the controller specified 
> by
> +  ControllerHandle and ChildHandle in the form of a Unicode string. If the
> +  driver specified by This has a user readable name in the language 
> specified by
> +  Language, then a pointer to the controller name is returned in 
> ControllerName,
> +  and EFI_SUCCESS is returned.  If the driver specified by This is not 
> currently
> +  managing the controller specified by ControllerHandle and ChildHandle,
> +  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
> +  support the language specified by Language, then EFI_UNSUPPORTED is 
> returned.
> +
> +  @param  This[in]              A pointer to the 
> EFI_COMPONENT_NAME2_PROTOCOL or
> +                                EFI_COMPONENT_NAME_PROTOCOL instance.
> +
> +  @param  ControllerHandle[in]  The handle of a controller that the driver
> +                                specified by This is managing.  This handle
> +                                specifies the controller whose name is to be
> +                                returned.
> +
> +  @param  ChildHandle[in]       The handle of the child controller to 
> retrieve
> +                                the name of.  This is an optional parameter 
> that
> +                                may be NULL.  It will be NULL for device
> +                                drivers.  It will also be NULL for a bus 
> drivers
> +                                that wish to retrieve the name of the bus
> +                                controller.  It will not be NULL for a bus
> +                                driver that wishes to retrieve the name of a
> +                                child controller.
> +
> +  @param  Language[in]          A pointer to a Null-terminated ASCII string
> +                                array indicating the language.  This is the
> +                                language of the driver name that the caller 
> is
> +                                requesting, and it must match one of the
> +                                languages specified in SupportedLanguages. 
> The
> +                                number of languages supported by a driver is 
> up
> +                                to the driver writer. Language is specified 
> in
> +                                RFC 4646 or ISO 639-2 language code format.
> +
> +  @param  ControllerName[out]   A pointer to the Unicode string to return.
> +                                This Unicode string is the name of the
> +                                controller specified by ControllerHandle and
> +                                ChildHandle in the language specified by
> +                                Language from the point of view of the driver
> +                                specified by This.
> +
> +  @retval EFI_SUCCESS           The Unicode string for the user readable 
> name in
> +                                the language specified by Language for the
> +                                driver specified by This was returned in
> +                                DriverName.
> +
> +  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
> +                                EFI_HANDLE.
> +
> +  @retval EFI_INVALID_PARAMETER Language is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This is not currently
> +                                managing the controller specified by
> +                                ControllerHandle and ChildHandle.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This does not support
> +                                the language specified by Language.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +GraphicsOutputComponentNameGetControllerName (
> +  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,
> +  IN  EFI_HANDLE                                      ControllerHandle,
> +  IN  EFI_HANDLE                                      ChildHandle        
> OPTIONAL,
> +  IN  CHAR8                                           *Language,
> +  OUT CHAR16                                          **ControllerName
> +  )
> +{
> +  return EFI_UNSUPPORTED;
> +}
> +
> +//
> +// EFI Component Name Protocol
> +//
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL  
> mGraphicsOutputComponentName = {
> +  GraphicsOutputComponentNameGetDriverName,
> +  GraphicsOutputComponentNameGetControllerName,
> +  "eng"
> +};
> +
> +//
> +// EFI Component Name 2 Protocol
> +//
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL 
> mGraphicsOutputComponentName2 = {
> +  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) 
> GraphicsOutputComponentNameGetDriverName,
> +  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) 
> GraphicsOutputComponentNameGetControllerName,
> +  "en"
> +};
> diff --git 
> a/MdeModulePkg/Universal/Console/GraphicsOutputDxe/GraphicsOutput.c 
> b/MdeModulePkg/Universal/Console/GraphicsOutputDxe/GraphicsOutput.c
> new file mode 100644
> index 0000000..9c6b1b9
> --- /dev/null
> +++ b/MdeModulePkg/Universal/Console/GraphicsOutputDxe/GraphicsOutput.c
> @@ -0,0 +1,659 @@
> +/** @file
> +  Implementation for a generic GOP driver.
> +  
> +Copyright (c) 2015, 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 "GraphicsOutput.h"
> +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)
> +};
> +
> +/**
> +  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
> +  )
> +{
> +  EFI_GRAPHICS_OUTPUT_BLT_PIXEL    Black;
> +
> +  if (ModeNumber >= This->Mode->MaxMode) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  Black.Blue = 0;
> +  Black.Green = 0;
> +  Black.Red = 0;
> +  Black.Reserved = 0;
> +  return BltVideoFill ((VOID *) (UINTN) This->Mode->FrameBufferBase, 
> This->Mode->Info, &Black, 0, 0, This->Mode->Info->HorizontalResolution, 
> This->Mode->Info->VerticalResolution);
> +}
> +
> +/**
> +  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
> +  )
> +{
> +  EFI_STATUS                            Status;
> +  EFI_TPL                               Tpl;
> +  //
> +  // 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);
> +
> +  switch (BltOperation) {
> +  case EfiBltVideoToBltBuffer:
> +    Status = BltVideoToBuffer (
> +               (VOID *) (UINTN) This->Mode->FrameBufferBase,
> +               This->Mode->Info,
> +               BltBuffer,
> +               SourceX,
> +               SourceY,
> +               DestinationX,
> +               DestinationY,
> +               Width,
> +               Height,
> +               Delta
> +               );
> +    break;
> +
> +  case EfiBltVideoToVideo:
> +    Status = BltVideoToVideo (
> +               (VOID *) (UINTN) This->Mode->FrameBufferBase,
> +               This->Mode->Info,
> +               SourceX,
> +               SourceY,
> +               DestinationX,
> +               DestinationY,
> +               Width,
> +               Height
> +               );
> +    break;
> +
> +  case EfiBltVideoFill:
> +    Status = BltVideoFill (
> +               (VOID *) (UINTN) This->Mode->FrameBufferBase,
> +               This->Mode->Info,
> +               BltBuffer,
> +               DestinationX,
> +               DestinationY,
> +               Width,
> +               Height
> +               );
> +    break;
> +
> +  case EfiBltBufferToVideo:
> +    Status = BltBufferToVideo (
> +               (VOID *) (UINTN) This->Mode->FrameBufferBase,
> +               This->Mode->Info,
> +               BltBuffer,
> +               SourceX,
> +               SourceY,
> +               DestinationX,
> +               DestinationY,
> +               Width,
> +               Height,
> +               Delta
> +               );
> +    break;
> +
> +  default:
> +    Status = EFI_INVALID_PARAMETER;
> +    break;
> +  }
> +
> +  gBS->RestoreTPL (Tpl);
> +
> +  return Status;
> +}
> +
> +GRAPHICS_OUTPUT_PRIVATE_DATA        mGraphicsOutputInstance = {
> +  NULL,                                            // GraphicsOutputHandle
> +  {
> +    GraphicsOutputQueryMode,
> +    GraphicsOutputSetMode,
> +    GraphicsOutputBlt,
> +    &mGraphicsOutputInstance.GraphicsOutputMode
> +  },
> +  {
> +    1,                                             // MaxMode
> +    0,                                             // Mode
> +    NULL,                                          // Info
> +    sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION), // SizeOfInfo
> +    0,                                             // FrameBufferBase
> +    0                                              // FrameBufferSize
> +  },
> +  NULL,                                            // DevicePath
> +  NULL,                                            // PciIo
> +  0                                                // PciAttributes
> +};
> +
> +/**
> +  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 (mGraphicsOutputInstance.GraphicsOutputHandle != NULL) {
> +    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;
> +  EFI_PCI_IO_PROTOCOL               *PciIo;
> +  EFI_HANDLE                        Handle;
> +  EFI_DEVICE_PATH                   *PciDevicePath;
> +  PCI_TYPE00                        Pci;
> +  UINT8                             Index;
> +  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Resources;
> +
> +  //
> +  // 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,
> +                    OFFSET_OF (PCI_TYPE00, Hdr.ClassCode),
> +                    sizeof (Pci.Hdr.ClassCode),
> +                    &Pci.Hdr.ClassCode
> +                    );
> +  if (!EFI_ERROR (Status)) {
> +    if (!IS_PCI_DISPLAY (&Pci)) {
> +      Status = EFI_UNSUPPORTED;
> +    } else {
> +      //
> +      // If it's a video device, check whether the device's frame buffer 
> size matches the one in HOB.
> +      // And update the frame buffer base.
> +      //
> +      for (Index = 0; Index < MAX_PCI_BAR; Index++) {
> +        Status = PciIo->GetBarAttributes (PciIo, Index, NULL, (VOID**) 
> &Resources);
> +        if (!EFI_ERROR (Status)) {
> +          DEBUG ((EFI_D_INFO, "[GraphicsOutputDxe]: BAR[%d]: Base = %lx, 
> Length = %lx\n", 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 >= 
> mGraphicsOutputInstance.GraphicsOutputMode.FrameBufferSize) {
> +            mGraphicsOutputInstance.GraphicsOutputMode.FrameBufferBase = 
> Resources->AddrRangeMin;
> +            if (!EFI_ERROR (Status)) {
> +              DEBUG ((EFI_D_INFO, "[GraphicsOutputDxe]: ... matched!\n"));
> +              break;
> +            }
> +          }
> +        }
> +      }
> +      if (Index == MAX_PCI_BAR) {
> +        Status = EFI_UNSUPPORTED;
> +      }
> +    }
> +  }
> +
> +  if (EFI_ERROR (Status)) {
> +    goto Error;
> +  }
> +
> +  //
> +  // Set attributes
> +  //
> +  Status = PciIo->Attributes (
> +                    PciIo,
> +                    EfiPciIoAttributeOperationGet,
> +                    0,
> +                    &mGraphicsOutputInstance.PciAttributes
> +                    );
> +  if (!EFI_ERROR (Status)) {
> +    Status = PciIo->Attributes (
> +                      PciIo,
> +                      EfiPciIoAttributeOperationEnable,
> +                      EFI_PCI_DEVICE_ENABLE,
> +                      NULL
> +                      );
> +  }
> +
> +  if (EFI_ERROR (Status)) {
> +    goto Error;
> +  }
> +
> +  if ((RemainingDevicePath != NULL) && IsDevicePathEnd 
> (RemainingDevicePath)) {
> +    return EFI_SUCCESS;
> +  }
> +
> +
> +  mGraphicsOutputInstance.DevicePath = AppendDevicePathNode (PciDevicePath, 
> (EFI_DEVICE_PATH_PROTOCOL *) &mGraphicsOutputAdrNode);
> +  ASSERT (mGraphicsOutputInstance.DevicePath != NULL);
> +
> +  Handle = NULL;
> +  Status = gBS->InstallMultipleProtocolInterfaces (
> +                  &mGraphicsOutputInstance.GraphicsOutputHandle,
> +                  &gEfiGraphicsOutputProtocolGuid, 
> &mGraphicsOutputInstance.GraphicsOutput,
> +                  &gEfiDevicePathProtocolGuid, 
> mGraphicsOutputInstance.DevicePath,
> +                  NULL
> +                  );
> +
> +  if (!EFI_ERROR (Status)) {
> +    Status = gBS->OpenProtocol (
> +                    Controller,
> +                    &gEfiPciIoProtocolGuid,
> +                    (VOID **) &mGraphicsOutputInstance.PciIo,
> +                    This->DriverBindingHandle,
> +                    mGraphicsOutputInstance.GraphicsOutputHandle,
> +                    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
> +                    );
> +    if (EFI_ERROR (Status)) {
> +      gBS->UninstallMultipleProtocolInterfaces (
> +             mGraphicsOutputInstance.GraphicsOutputHandle,
> +             &gEfiGraphicsOutputProtocolGuid, 
> &mGraphicsOutputInstance.GraphicsOutput,
> +             &gEfiDevicePathProtocolGuid, mGraphicsOutputInstance.DevicePath,
> +             NULL
> +             );
> +    }
> +  }
> +
> +  if (EFI_ERROR (Status)) {
> +    mGraphicsOutputInstance.GraphicsOutputHandle = NULL;
> +    //
> +    // Restore original PCI attributes
> +    //
> +    PciIo->Attributes (
> +             PciIo,
> +             EfiPciIoAttributeOperationSet,
> +             mGraphicsOutputInstance.PciAttributes,
> +             NULL
> +             );
> +    FreePool (mGraphicsOutputInstance.DevicePath);
> +  }
> +
> +Error:
> +  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;
> +
> +  if (NumberOfChildren == 0) {
> +    //
> +    // Restore original PCI attributes
> +    //
> +    Status = mGraphicsOutputInstance.PciIo->Attributes (
> +                                              mGraphicsOutputInstance.PciIo,
> +                                              EfiPciIoAttributeOperationSet,
> +                                              
> mGraphicsOutputInstance.PciAttributes,
> +                                              NULL
> +                                              );
> +    ASSERT_EFI_ERROR (Status);
> +
> +    //
> +    // 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);
> +  ASSERT (ChildHandleBuffer[0] == 
> mGraphicsOutputInstance.GraphicsOutputHandle);
> +  Status = gBS->CloseProtocol (
> +                  Controller,
> +                  &gEfiPciIoProtocolGuid,
> +                  This->DriverBindingHandle,
> +                  mGraphicsOutputInstance.GraphicsOutputHandle
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +  //
> +  // Remove the GOP protocol interface from the system
> +  //
> +  Status = gBS->UninstallMultipleProtocolInterfaces (
> +                  mGraphicsOutputInstance.GraphicsOutputHandle,
> +                  &gEfiGraphicsOutputProtocolGuid, 
> &mGraphicsOutputInstance.GraphicsOutput,
> +                  &gEfiDevicePathProtocolGuid,     
> mGraphicsOutputInstance.DevicePath,
> +                  NULL
> +                  );
> +  if (!EFI_ERROR (Status)) {
> +    mGraphicsOutputInstance.GraphicsOutputHandle = NULL;
> +    FreePool (mGraphicsOutputInstance.DevicePath);
> +  } else {
> +    Status = gBS->OpenProtocol (
> +                    Controller,
> +                    &gEfiPciIoProtocolGuid,
> +                    (VOID **) &mGraphicsOutputInstance.PciIo,
> +                    This->DriverBindingHandle,
> +                    mGraphicsOutputInstance.GraphicsOutputHandle,
> +                    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
> +                    );
> +    ASSERT_EFI_ERROR (Status);
> +  }
> +  return Status;
> +}
> +
> +EFI_DRIVER_BINDING_PROTOCOL mGraphicsOutputDriverBinding = {
> +  GraphicsOutputDriverBindingSupported,
> +  GraphicsOutputDriverBindingStart,
> +  GraphicsOutputDriverBindingStop,
> +  0xffffffff,
> +  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;
> +  EFI_PEI_GRAPHICS_INFO_HOB            *GraphicsInfo;
> +
> +  HobStart = GetFirstGuidHob (&gEfiGraphicsInfoHobGuid);
> +
> +  if ((HobStart == NULL) || (GET_GUID_HOB_DATA_SIZE (HobStart) != sizeof 
> (*GraphicsInfo))) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  GraphicsInfo = (EFI_PEI_GRAPHICS_INFO_HOB *) (GET_GUID_HOB_DATA 
> (HobStart));
> +
> +  //
> +  // Cache in global data
> +  //
> +  DEBUG ((EFI_D_INFO, "FrameBuffer = %lx/%lx\n", 
> GraphicsInfo->FrameBufferBase, GraphicsInfo->FrameBufferSize));
> +  mGraphicsOutputInstance.GraphicsOutputMode.Info = 
> &GraphicsInfo->GraphicsMode;
> +  mGraphicsOutputInstance.GraphicsOutputMode.FrameBufferBase = 
> GraphicsInfo->FrameBufferBase;
> +  mGraphicsOutputInstance.GraphicsOutputMode.FrameBufferSize = 
> GraphicsInfo->FrameBufferSize;
> +  
> +  Status = EfiLibInstallDriverBindingComponentName2 (
> +             ImageHandle,
> +             SystemTable,
> +             &mGraphicsOutputDriverBinding,
> +             ImageHandle,
> +             &mGraphicsOutputComponentName,
> +             &mGraphicsOutputComponentName2
> +             );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  return Status;
> +}
> diff --git 
> a/MdeModulePkg/Universal/Console/GraphicsOutputDxe/GraphicsOutput.h 
> b/MdeModulePkg/Universal/Console/GraphicsOutputDxe/GraphicsOutput.h
> new file mode 100644
> index 0000000..68fc010
> --- /dev/null
> +++ b/MdeModulePkg/Universal/Console/GraphicsOutputDxe/GraphicsOutput.h
> @@ -0,0 +1,53 @@
> +/** @file
> +  Header file for a generic GOP driver.
> +  
> +Copyright (c) 2015, 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.
> +
> +
> +**/
> +#ifndef _GRAPHICS_OUTPUT_DXE_H_
> +#define _GRAPHICS_OUTPUT_DXE_H_
> +#include <PiDxe.h>
> +
> +#include <IndustryStandard/Pci.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <Guid/GraphicsInfoHob.h>
> +#include <Protocol/DriverBinding.h>
> +#include <Protocol/PciIo.h>
> +#include <Protocol/DevicePath.h>
> +#include <Protocol/GraphicsOutput.h>
> +#include <Protocol/ComponentName.h>
> +#include <Protocol/ComponentName2.h>
> +
> +#include <Library/BaseLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/HobLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/BltLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiLib.h>
> +
> +#define MAX_PCI_BAR  6
> +
> +
> +typedef struct {
> +  EFI_HANDLE                        GraphicsOutputHandle;
> +  EFI_GRAPHICS_OUTPUT_PROTOCOL      GraphicsOutput;
> +  EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE GraphicsOutputMode;
> +  EFI_DEVICE_PATH_PROTOCOL          *DevicePath;
> +  EFI_PCI_IO_PROTOCOL               *PciIo;
> +  UINT64                            PciAttributes;
> +} GRAPHICS_OUTPUT_PRIVATE_DATA;
> +
> +extern EFI_COMPONENT_NAME_PROTOCOL  mGraphicsOutputComponentName;
> +extern EFI_COMPONENT_NAME2_PROTOCOL mGraphicsOutputComponentName2;
> +#endif
> diff --git 
> a/MdeModulePkg/Universal/Console/GraphicsOutputDxe/GraphicsOutputDxe.inf 
> b/MdeModulePkg/Universal/Console/GraphicsOutputDxe/GraphicsOutputDxe.inf
> new file mode 100644
> index 0000000..f578008
> --- /dev/null
> +++ b/MdeModulePkg/Universal/Console/GraphicsOutputDxe/GraphicsOutputDxe.inf
> @@ -0,0 +1,57 @@
> +## @file
> +# This driver produces GraphicsOutput protocol based on the GraphicsInfo HOB 
> information.
> +#
> +# Copyright (c) 2015, 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.
> +#
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = GraphicsOutputDxe
> +  FILE_GUID                      = 20830080-CC28-4169-9836-7F42B8D0C8C9
> +  MODULE_TYPE                    = UEFI_DRIVER
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = InitializeGraphicsOutput
> +
> +#
> +# The following information is for reference only and not required by the 
> build tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64
> +#
> +
> +[Sources.common]
> +  GraphicsOutput.h
> +  GraphicsOutput.c
> +  ComponentName.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +
> +[LibraryClasses]
> +  UefiDriverEntryPoint
> +  UefiBootServicesTableLib
> +  DxeServicesTableLib
> +  DebugLib
> +  MemoryAllocationLib
> +  BaseMemoryLib
> +  DevicePathLib
> +  BltLib
> +  UefiLib
> +  HobLib
> +
> +[Guids]
> +  gEfiGraphicsInfoHobGuid                       # HOB TO_START
> +
> +[Protocols]
> +  gEfiGraphicsOutputProtocolGuid                # PROTOCOL BY_START
> +  gEfiDevicePathProtocolGuid                    # PROTOCOL BY_START
> +  gEfiPciIoProtocolGuid                         # PROTOCOL TO_START
> -- 
> 1.9.5.msysgit.1
> 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to