Home | History | Annotate | Download | only in FbGop
      1 /** @file
      2   ConsoleOut Routines that speak VGA.
      3 
      4 Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>
      5 
      6 This program and the accompanying materials
      7 are licensed and made available under the terms and conditions
      8 of the BSD License which accompanies this distribution.  The
      9 full text of the license may be found at
     10 http://opensource.org/licenses/bsd-license.php
     11 
     12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     14 
     15 **/
     16 
     17 #include "FbGop.h"
     18 
     19 EFI_PIXEL_BITMASK  mPixelBitMask = {0x0000FF, 0x00FF00, 0xFF0000, 0x000000};
     20 
     21 //
     22 // Save controller attributes during first start
     23 //
     24 UINT64                         mOriginalPciAttributes;
     25 BOOLEAN                        mPciAttributesSaved = FALSE;
     26 
     27 
     28 //
     29 // EFI Driver Binding Protocol Instance
     30 //
     31 EFI_DRIVER_BINDING_PROTOCOL gFbGopDriverBinding = {
     32   FbGopDriverBindingSupported,
     33   FbGopDriverBindingStart,
     34   FbGopDriverBindingStop,
     35   0x3,
     36   NULL,
     37   NULL
     38 };
     39 
     40 //
     41 // Native resolution in EDID DetailedTiming[0]
     42 //
     43 UINT32    mNativeModeHorizontal;
     44 UINT32    mNativeModeVertical;
     45 
     46 /**
     47   Supported.
     48 
     49   @param  This                   Pointer to driver binding protocol
     50   @param  Controller             Controller handle to connect
     51   @param  RemainingDevicePath    A pointer to the remaining portion of a device
     52                                  path
     53 
     54   @retval EFI_STATUS             EFI_SUCCESS:This controller can be managed by this
     55                                  driver, Otherwise, this controller cannot be
     56                                  managed by this driver
     57 
     58 **/
     59 EFI_STATUS
     60 EFIAPI
     61 FbGopDriverBindingSupported (
     62   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
     63   IN EFI_HANDLE                   Controller,
     64   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
     65   )
     66 {
     67   EFI_STATUS                Status;
     68   EFI_PCI_IO_PROTOCOL       *PciIo;
     69   PCI_TYPE00                Pci;
     70   EFI_DEV_PATH              *Node;
     71 
     72   //
     73   // Open the IO Abstraction(s) needed to perform the supported test
     74   //
     75   Status = gBS->OpenProtocol (
     76                   Controller,
     77                   &gEfiPciIoProtocolGuid,
     78                   (VOID **) &PciIo,
     79                   This->DriverBindingHandle,
     80                   Controller,
     81                   EFI_OPEN_PROTOCOL_BY_DRIVER
     82                   );
     83   if (EFI_ERROR (Status)) {
     84     return Status;
     85   }
     86 
     87   //
     88   // See if this is a PCI Graphics Controller by looking at the Command register and
     89   // Class Code Register
     90   //
     91   Status = PciIo->Pci.Read (
     92                         PciIo,
     93                         EfiPciIoWidthUint32,
     94                         0,
     95                         sizeof (Pci) / sizeof (UINT32),
     96                         &Pci
     97                         );
     98   if (EFI_ERROR (Status)) {
     99     Status = EFI_UNSUPPORTED;
    100     goto Done;
    101   }
    102 
    103   Status = EFI_UNSUPPORTED;
    104   if (Pci.Hdr.ClassCode[2] == 0x03 || (Pci.Hdr.ClassCode[2] == 0x00 && Pci.Hdr.ClassCode[1] == 0x01)) {
    105 
    106     Status = EFI_SUCCESS;
    107     //
    108     // If this is a graphics controller,
    109     // go further check RemainingDevicePath validation
    110     //
    111     if (RemainingDevicePath != NULL) {
    112       Node = (EFI_DEV_PATH *) RemainingDevicePath;
    113       //
    114       // Check if RemainingDevicePath is the End of Device Path Node,
    115       // if yes, return EFI_SUCCESS
    116       //
    117       if (!IsDevicePathEnd (Node)) {
    118         //
    119         // If RemainingDevicePath isn't the End of Device Path Node,
    120         // check its validation
    121         //
    122         if (Node->DevPath.Type != ACPI_DEVICE_PATH ||
    123             Node->DevPath.SubType != ACPI_ADR_DP ||
    124             DevicePathNodeLength(&Node->DevPath) < sizeof(ACPI_ADR_DEVICE_PATH)) {
    125           Status = EFI_UNSUPPORTED;
    126         }
    127       }
    128     }
    129   }
    130 
    131 Done:
    132   gBS->CloseProtocol (
    133          Controller,
    134          &gEfiPciIoProtocolGuid,
    135          This->DriverBindingHandle,
    136          Controller
    137          );
    138 
    139   return Status;
    140 }
    141 
    142 
    143 /**
    144   Install Graphics Output Protocol onto VGA device handles.
    145 
    146   @param  This                   Pointer to driver binding protocol
    147   @param  Controller             Controller handle to connect
    148   @param  RemainingDevicePath    A pointer to the remaining portion of a device
    149                                  path
    150 
    151   @return EFI_STATUS
    152 
    153 **/
    154 EFI_STATUS
    155 EFIAPI
    156 FbGopDriverBindingStart (
    157   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    158   IN EFI_HANDLE                   Controller,
    159   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
    160   )
    161 {
    162   EFI_STATUS                Status;
    163   EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath;
    164   EFI_PCI_IO_PROTOCOL       *PciIo;
    165   UINT64                    Supports;
    166 
    167   DEBUG ((EFI_D_INFO, "GOP START\n"));
    168 
    169   //
    170   // Initialize local variables
    171   //
    172   PciIo            = NULL;
    173   ParentDevicePath = NULL;
    174 
    175   //
    176   // Prepare for status code
    177   //
    178   Status = gBS->HandleProtocol (
    179                   Controller,
    180                   &gEfiDevicePathProtocolGuid,
    181                   (VOID **) &ParentDevicePath
    182                   );
    183   if (EFI_ERROR (Status)) {
    184     return Status;
    185   }
    186 
    187   //
    188   // Open the IO Abstraction(s) needed
    189   //
    190   Status = gBS->OpenProtocol (
    191                   Controller,
    192                   &gEfiPciIoProtocolGuid,
    193                   (VOID **) &PciIo,
    194                   This->DriverBindingHandle,
    195                   Controller,
    196                   EFI_OPEN_PROTOCOL_BY_DRIVER
    197                   );
    198   if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
    199     return Status;
    200   }
    201 
    202   //
    203   // Save original PCI attributes
    204   //
    205   if (!mPciAttributesSaved) {
    206     Status = PciIo->Attributes (
    207                       PciIo,
    208                       EfiPciIoAttributeOperationGet,
    209                       0,
    210                       &mOriginalPciAttributes
    211                       );
    212 
    213     if (EFI_ERROR (Status)) {
    214       goto Done;
    215     }
    216     mPciAttributesSaved = TRUE;
    217   }
    218 
    219   //
    220   // Get supported PCI attributes
    221   //
    222   Status = PciIo->Attributes (
    223                     PciIo,
    224                     EfiPciIoAttributeOperationSupported,
    225                     0,
    226                     &Supports
    227                     );
    228   if (EFI_ERROR (Status)) {
    229     goto Done;
    230   }
    231 
    232   Supports &= (EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16);
    233   if (Supports == 0 || Supports == (EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) {
    234     Status = EFI_UNSUPPORTED;
    235     goto Done;
    236   }
    237 
    238   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
    239     EFI_PROGRESS_CODE,
    240     EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_ENABLE,
    241     ParentDevicePath
    242     );
    243   //
    244   // Enable the device and make sure VGA cycles are being forwarded to this VGA device
    245   //
    246   Status = PciIo->Attributes (
    247              PciIo,
    248              EfiPciIoAttributeOperationEnable,
    249              EFI_PCI_DEVICE_ENABLE,
    250              NULL
    251              );
    252   if (EFI_ERROR (Status)) {
    253     REPORT_STATUS_CODE_WITH_DEVICE_PATH (
    254       EFI_ERROR_CODE | EFI_ERROR_MINOR,
    255       EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_RESOURCE_CONFLICT,
    256       ParentDevicePath
    257       );
    258     goto Done;
    259   }
    260 
    261   if (RemainingDevicePath != NULL) {
    262     if (IsDevicePathEnd (RemainingDevicePath)) {
    263       //
    264       // If RemainingDevicePath is the End of Device Path Node,
    265       // don't create any child device and return EFI_SUCESS
    266       Status = EFI_SUCCESS;
    267       goto Done;
    268     }
    269   }
    270 
    271   //
    272   // Create child handle and install GraphicsOutputProtocol on it
    273   //
    274   Status = FbGopChildHandleInstall (
    275              This,
    276              Controller,
    277              PciIo,
    278              NULL,
    279              ParentDevicePath,
    280              RemainingDevicePath
    281              );
    282 
    283 Done:
    284   if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {
    285 
    286     REPORT_STATUS_CODE_WITH_DEVICE_PATH (
    287       EFI_PROGRESS_CODE,
    288       EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_DISABLE,
    289       ParentDevicePath
    290       );
    291 
    292     REPORT_STATUS_CODE_WITH_DEVICE_PATH (
    293       EFI_PROGRESS_CODE,
    294       EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_NOT_DETECTED,
    295       ParentDevicePath
    296       );
    297     if (!HasChildHandle (Controller)) {
    298       if (mPciAttributesSaved) {
    299         //
    300         // Restore original PCI attributes
    301         //
    302         PciIo->Attributes (
    303                         PciIo,
    304                         EfiPciIoAttributeOperationSet,
    305                         mOriginalPciAttributes,
    306                         NULL
    307                         );
    308       }
    309     }
    310     //
    311     // Release PCI I/O Protocols on the controller handle.
    312     //
    313     gBS->CloseProtocol (
    314            Controller,
    315            &gEfiPciIoProtocolGuid,
    316            This->DriverBindingHandle,
    317            Controller
    318            );
    319   }
    320 
    321   return Status;
    322 }
    323 
    324 
    325 /**
    326   Stop.
    327 
    328   @param  This                   Pointer to driver binding protocol
    329   @param  Controller             Controller handle to connect
    330   @param  NumberOfChildren       Number of children handle created by this driver
    331   @param  ChildHandleBuffer      Buffer containing child handle created
    332 
    333   @retval EFI_SUCCESS            Driver disconnected successfully from controller
    334   @retval EFI_UNSUPPORTED        Cannot find FB_VIDEO_DEV structure
    335 
    336 **/
    337 EFI_STATUS
    338 EFIAPI
    339 FbGopDriverBindingStop (
    340   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
    341   IN  EFI_HANDLE                      Controller,
    342   IN  UINTN                           NumberOfChildren,
    343   IN  EFI_HANDLE                      *ChildHandleBuffer
    344   )
    345 {
    346   EFI_STATUS                   Status;
    347   BOOLEAN                      AllChildrenStopped;
    348   UINTN                        Index;
    349   EFI_PCI_IO_PROTOCOL          *PciIo;
    350 
    351   AllChildrenStopped = TRUE;
    352 
    353   if (NumberOfChildren == 0) {
    354     //
    355     // Close PCI I/O protocol on the controller handle
    356     //
    357     gBS->CloseProtocol (
    358            Controller,
    359            &gEfiPciIoProtocolGuid,
    360            This->DriverBindingHandle,
    361            Controller
    362            );
    363 
    364     return EFI_SUCCESS;
    365   }
    366 
    367   for (Index = 0; Index < NumberOfChildren; Index++) {
    368 
    369     Status = EFI_SUCCESS;
    370 
    371     FbGopChildHandleUninstall (This, Controller, ChildHandleBuffer[Index]);
    372 
    373     if (EFI_ERROR (Status)) {
    374       AllChildrenStopped = FALSE;
    375     }
    376   }
    377 
    378   if (!AllChildrenStopped) {
    379     return EFI_DEVICE_ERROR;
    380   }
    381 
    382   if (!HasChildHandle (Controller)) {
    383     if (mPciAttributesSaved) {
    384       Status = gBS->HandleProtocol (
    385                       Controller,
    386                       &gEfiPciIoProtocolGuid,
    387                       (VOID **) &PciIo
    388                       );
    389       ASSERT_EFI_ERROR (Status);
    390 
    391       //
    392       // Restore original PCI attributes
    393       //
    394       Status = PciIo->Attributes (
    395                         PciIo,
    396                         EfiPciIoAttributeOperationSet,
    397                         mOriginalPciAttributes,
    398                         NULL
    399                         );
    400       ASSERT_EFI_ERROR (Status);
    401     }
    402   }
    403 
    404 
    405   return EFI_SUCCESS;
    406 }
    407 
    408 
    409 /**
    410   Install child handles if the Handle supports MBR format.
    411 
    412   @param  This                   Calling context.
    413   @param  ParentHandle           Parent Handle
    414   @param  ParentPciIo            Parent PciIo interface
    415   @param  ParentLegacyBios       Parent LegacyBios interface
    416   @param  ParentDevicePath       Parent Device Path
    417   @param  RemainingDevicePath    Remaining Device Path
    418 
    419   @retval EFI_SUCCESS            If a child handle was added
    420   @retval other                  A child handle was not added
    421 
    422 **/
    423 EFI_STATUS
    424 FbGopChildHandleInstall (
    425   IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
    426   IN  EFI_HANDLE                   ParentHandle,
    427   IN  EFI_PCI_IO_PROTOCOL          *ParentPciIo,
    428   IN  VOID                         *ParentLegacyBios,
    429   IN  EFI_DEVICE_PATH_PROTOCOL     *ParentDevicePath,
    430   IN  EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
    431   )
    432 {
    433   EFI_STATUS               Status;
    434   FB_VIDEO_DEV            *FbGopPrivate;
    435   PCI_TYPE00               Pci;
    436   ACPI_ADR_DEVICE_PATH     AcpiDeviceNode;
    437   BOOLEAN                  ProtocolInstalled;
    438 
    439   //
    440   // Allocate the private device structure for video device
    441   //
    442   FbGopPrivate = (FB_VIDEO_DEV *) AllocateZeroPool (
    443 																					sizeof (FB_VIDEO_DEV)
    444 																					);
    445   if (NULL == FbGopPrivate) {
    446 		Status = EFI_OUT_OF_RESOURCES;
    447     goto Done;
    448   }
    449 
    450   //
    451   // See if this is a VGA compatible controller or not
    452   //
    453   Status = ParentPciIo->Pci.Read (
    454                           ParentPciIo,
    455                           EfiPciIoWidthUint32,
    456                           0,
    457                           sizeof (Pci) / sizeof (UINT32),
    458                           &Pci
    459                           );
    460   if (EFI_ERROR (Status)) {
    461     REPORT_STATUS_CODE_WITH_DEVICE_PATH (
    462       EFI_ERROR_CODE | EFI_ERROR_MINOR,
    463       EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR,
    464       ParentDevicePath
    465       );
    466     goto Done;
    467   }
    468 
    469   //
    470   // Initialize the child private structure
    471   //
    472   FbGopPrivate->Signature = FB_VIDEO_DEV_SIGNATURE;
    473 
    474   //
    475   // Fill in Graphics Output specific mode structures
    476   //
    477   FbGopPrivate->ModeData              = NULL;
    478 
    479   FbGopPrivate->VbeFrameBuffer        = NULL;
    480 
    481   FbGopPrivate->EdidDiscovered.SizeOfEdid  = 0;
    482   FbGopPrivate->EdidDiscovered.Edid        = NULL;
    483   FbGopPrivate->EdidActive.SizeOfEdid      = 0;
    484   FbGopPrivate->EdidActive.Edid            = NULL;
    485 
    486   //
    487   // Fill in the Graphics Output Protocol
    488   //
    489   FbGopPrivate->GraphicsOutput.QueryMode = FbGopGraphicsOutputQueryMode;
    490   FbGopPrivate->GraphicsOutput.SetMode   = FbGopGraphicsOutputSetMode;
    491 
    492 
    493   //
    494   // Allocate buffer for Graphics Output Protocol mode information
    495   //
    496   FbGopPrivate->GraphicsOutput.Mode = (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *) AllocatePool (
    497                                              sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE)
    498                                              );
    499   if (NULL == FbGopPrivate->GraphicsOutput.Mode) {
    500     Status = EFI_OUT_OF_RESOURCES;
    501     goto Done;
    502   }
    503 
    504   FbGopPrivate->GraphicsOutput.Mode->Info = (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) AllocatePool (
    505                                              sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)
    506                                              );
    507   if (NULL ==  FbGopPrivate->GraphicsOutput.Mode->Info) {
    508     Status = EFI_OUT_OF_RESOURCES;
    509     goto Done;
    510   }
    511 
    512   //
    513   // Set Gop Device Path, here RemainingDevicePath will not be one End of Device Path Node.
    514   //
    515   if ((RemainingDevicePath == NULL) || (!IsDevicePathEnd (RemainingDevicePath))) {
    516     if (RemainingDevicePath == NULL) {
    517       ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));
    518       AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;
    519       AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;
    520       AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0);
    521       SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH));
    522 
    523       FbGopPrivate->GopDevicePath = AppendDevicePathNode (
    524                                           ParentDevicePath,
    525                                           (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode
    526                                           );
    527     } else {
    528       FbGopPrivate->GopDevicePath = AppendDevicePathNode (ParentDevicePath, RemainingDevicePath);
    529     }
    530 
    531     //
    532     // Creat child handle and device path protocol firstly
    533     //
    534     FbGopPrivate->Handle = NULL;
    535     Status = gBS->InstallMultipleProtocolInterfaces (
    536                     &FbGopPrivate->Handle,
    537                     &gEfiDevicePathProtocolGuid,
    538                     FbGopPrivate->GopDevicePath,
    539                     NULL
    540                     );
    541     if (EFI_ERROR (Status)) {
    542       goto Done;
    543     }
    544   }
    545 
    546   //
    547   // When check for VBE, PCI I/O protocol is needed, so use parent's protocol interface temporally
    548   //
    549   FbGopPrivate->PciIo                 = ParentPciIo;
    550 
    551   //
    552   // Check for VESA BIOS Extensions for modes that are compatible with Graphics Output
    553   //
    554   Status = FbGopCheckForVbe (FbGopPrivate);
    555   DEBUG ((EFI_D_INFO, "FbGopCheckForVbe - %r\n", Status));
    556 
    557   if (EFI_ERROR (Status)) {
    558     Status = EFI_UNSUPPORTED;
    559     //goto Done;
    560   }
    561 
    562   ProtocolInstalled = FALSE;
    563 
    564   //
    565   // Creat child handle and install Graphics Output Protocol,EDID Discovered/Active Protocol
    566   //
    567   Status = gBS->InstallMultipleProtocolInterfaces (
    568                   &FbGopPrivate->Handle,
    569                   &gEfiGraphicsOutputProtocolGuid,
    570                   &FbGopPrivate->GraphicsOutput,
    571                   &gEfiEdidDiscoveredProtocolGuid,
    572                   &FbGopPrivate->EdidDiscovered,
    573                   &gEfiEdidActiveProtocolGuid,
    574                   &FbGopPrivate->EdidActive,
    575                   NULL
    576                   );
    577 
    578   if (!EFI_ERROR (Status)) {
    579     //
    580     // Open the Parent Handle for the child
    581     //
    582     Status = gBS->OpenProtocol (
    583                     ParentHandle,
    584                     &gEfiPciIoProtocolGuid,
    585                     (VOID **) &FbGopPrivate->PciIo,
    586                     This->DriverBindingHandle,
    587                     FbGopPrivate->Handle,
    588                     EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
    589                     );
    590     if (EFI_ERROR (Status)) {
    591       goto Done;
    592     }
    593     ProtocolInstalled = TRUE;
    594   }
    595 
    596 Done:
    597   if (EFI_ERROR (Status)) {
    598     //
    599     // Free private data structure
    600     //
    601     FbGopDeviceReleaseResource (FbGopPrivate);
    602   }
    603 
    604   return Status;
    605 }
    606 
    607 
    608 /**
    609   Deregister an video child handle and free resources.
    610 
    611   @param  This                   Protocol instance pointer.
    612   @param  Controller             Video controller handle
    613   @param  Handle                 Video child handle
    614 
    615   @return EFI_STATUS
    616 
    617 **/
    618 EFI_STATUS
    619 FbGopChildHandleUninstall (
    620   EFI_DRIVER_BINDING_PROTOCOL    *This,
    621   EFI_HANDLE                     Controller,
    622   EFI_HANDLE                     Handle
    623   )
    624 {
    625   EFI_STATUS                    Status;
    626   EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
    627   FB_VIDEO_DEV                 *FbGopPrivate;
    628   EFI_PCI_IO_PROTOCOL          *PciIo;
    629 
    630   FbGopPrivate     = NULL;
    631   GraphicsOutput   = NULL;
    632   PciIo            = NULL;
    633   Status           = EFI_UNSUPPORTED;
    634 
    635   Status = gBS->OpenProtocol (
    636                   Handle,
    637                   &gEfiGraphicsOutputProtocolGuid,
    638                   (VOID **) &GraphicsOutput,
    639                   This->DriverBindingHandle,
    640                   Handle,
    641                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    642                   );
    643   if (!EFI_ERROR (Status)) {
    644       FbGopPrivate = FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput);
    645   }
    646 
    647   if (FbGopPrivate == NULL) {
    648     return EFI_UNSUPPORTED;
    649   }
    650 
    651   //
    652   // Close PCI I/O protocol that opened by child handle
    653   //
    654   Status = gBS->CloseProtocol (
    655                   Controller,
    656                   &gEfiPciIoProtocolGuid,
    657                   This->DriverBindingHandle,
    658                   Handle
    659                   );
    660 
    661   //
    662   // Uninstall protocols on child handle
    663   //
    664   Status = gBS->UninstallMultipleProtocolInterfaces (
    665                     FbGopPrivate->Handle,
    666                     &gEfiDevicePathProtocolGuid,
    667                     FbGopPrivate->GopDevicePath,
    668                     &gEfiGraphicsOutputProtocolGuid,
    669                     &FbGopPrivate->GraphicsOutput,
    670                     NULL
    671                     );
    672 
    673   if (EFI_ERROR (Status)) {
    674     gBS->OpenProtocol (
    675            Controller,
    676            &gEfiPciIoProtocolGuid,
    677            (VOID **) &PciIo,
    678            This->DriverBindingHandle,
    679            Handle,
    680            EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
    681            );
    682     return Status;
    683   }
    684 
    685   //
    686   // Release all allocated resources
    687   //
    688   FbGopDeviceReleaseResource (FbGopPrivate);
    689 
    690   return EFI_SUCCESS;
    691 }
    692 
    693 
    694 /**
    695   Release resource for biso video instance.
    696 
    697   @param  FbGopPrivate       Video child device private data structure
    698 
    699 **/
    700 VOID
    701 FbGopDeviceReleaseResource (
    702   FB_VIDEO_DEV  *FbGopPrivate
    703   )
    704 {
    705   if (FbGopPrivate == NULL) {
    706     return ;
    707   }
    708 
    709   //
    710   // Release all the resourses occupied by the FB_VIDEO_DEV
    711   //
    712 
    713   //
    714   // Free VBE Frame Buffer
    715   //
    716   if (FbGopPrivate->VbeFrameBuffer != NULL) {
    717     FreePool (FbGopPrivate->VbeFrameBuffer);
    718   }
    719 
    720   //
    721   // Free mode data
    722   //
    723   if (FbGopPrivate->ModeData != NULL) {
    724     FreePool (FbGopPrivate->ModeData);
    725   }
    726 
    727   //
    728   // Free graphics output protocol occupied resource
    729   //
    730   if (FbGopPrivate->GraphicsOutput.Mode != NULL) {
    731     if (FbGopPrivate->GraphicsOutput.Mode->Info != NULL) {
    732         FreePool (FbGopPrivate->GraphicsOutput.Mode->Info);
    733         FbGopPrivate->GraphicsOutput.Mode->Info = NULL;
    734     }
    735     FreePool (FbGopPrivate->GraphicsOutput.Mode);
    736     FbGopPrivate->GraphicsOutput.Mode = NULL;
    737   }
    738 
    739   if (FbGopPrivate->GopDevicePath!= NULL) {
    740     FreePool (FbGopPrivate->GopDevicePath);
    741   }
    742 
    743   FreePool (FbGopPrivate);
    744 
    745   return ;
    746 }
    747 
    748 
    749 
    750 /**
    751   Check if all video child handles have been uninstalled.
    752 
    753   @param  Controller             Video controller handle
    754 
    755   @return TRUE                   Child handles exist.
    756   @return FALSE                  All video child handles have been uninstalled.
    757 
    758 **/
    759 BOOLEAN
    760 HasChildHandle (
    761   IN EFI_HANDLE  Controller
    762   )
    763 {
    764   UINTN                                Index;
    765   EFI_OPEN_PROTOCOL_INFORMATION_ENTRY  *OpenInfoBuffer;
    766   UINTN                                EntryCount;
    767   BOOLEAN                              HasChild;
    768   EFI_STATUS                           Status;
    769 
    770   EntryCount = 0;
    771   HasChild   = FALSE;
    772   Status = gBS->OpenProtocolInformation (
    773                   Controller,
    774                   &gEfiPciIoProtocolGuid,
    775                   &OpenInfoBuffer,
    776                   &EntryCount
    777                   );
    778   for (Index = 0; Index < EntryCount; Index++) {
    779     if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
    780       HasChild = TRUE;
    781     }
    782   }
    783 
    784   return HasChild;
    785 }
    786 
    787 /**
    788   Check for VBE device.
    789 
    790   @param  FbGopPrivate       Pointer to FB_VIDEO_DEV structure
    791 
    792   @retval EFI_SUCCESS            VBE device found
    793 
    794 **/
    795 EFI_STATUS
    796 FbGopCheckForVbe (
    797   IN OUT FB_VIDEO_DEV  *FbGopPrivate
    798   )
    799 {
    800   EFI_STATUS                             Status;
    801   FB_VIDEO_MODE_DATA                     *ModeBuffer;
    802   FB_VIDEO_MODE_DATA                     *CurrentModeData;
    803   UINTN                                  ModeNumber;
    804   UINTN                                  BitsPerPixel;
    805   UINTN                                  BytesPerScanLine;
    806   UINT32                                 HorizontalResolution;
    807   UINT32                                 VerticalResolution;
    808   EFI_GRAPHICS_OUTPUT_BLT_PIXEL          *VbeFrameBuffer;
    809   EFI_HOB_GUID_TYPE                      *GuidHob;
    810   FRAME_BUFFER_INFO                      *pFbInfo;
    811 
    812   Status = EFI_SUCCESS;
    813   //
    814   // Find the frame buffer information guid hob
    815   //
    816   GuidHob = GetFirstGuidHob (&gUefiFrameBufferInfoGuid);
    817   ASSERT (GuidHob != NULL);
    818   pFbInfo = (FRAME_BUFFER_INFO *)GET_GUID_HOB_DATA (GuidHob);
    819 
    820   //
    821   // Add mode to the list of available modes
    822   //
    823   VbeFrameBuffer = NULL;
    824   ModeBuffer     = NULL;
    825 
    826   ModeNumber           = 1;
    827   BitsPerPixel         = pFbInfo->BitsPerPixel;
    828   HorizontalResolution = pFbInfo->HorizontalResolution;
    829   VerticalResolution   = pFbInfo->VerticalResolution;
    830   BytesPerScanLine     = HorizontalResolution * (BitsPerPixel / 8);
    831 
    832   ModeBuffer = (FB_VIDEO_MODE_DATA *) AllocatePool (
    833 																						ModeNumber * sizeof (FB_VIDEO_MODE_DATA)
    834 																			);
    835   if (NULL == ModeBuffer) {
    836 	  Status = EFI_OUT_OF_RESOURCES;
    837     goto Done;
    838   }
    839 
    840   VbeFrameBuffer =
    841 			(EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocatePool (
    842 																					BytesPerScanLine * VerticalResolution
    843 																				  );
    844   if (NULL == VbeFrameBuffer) {
    845 	  Status = EFI_OUT_OF_RESOURCES;
    846     goto Done;
    847   }
    848 
    849   if (FbGopPrivate->ModeData != NULL) {
    850     FreePool (FbGopPrivate->ModeData);
    851   }
    852 
    853   if (FbGopPrivate->VbeFrameBuffer != NULL) {
    854     FreePool (FbGopPrivate->VbeFrameBuffer);
    855   }
    856 
    857   CurrentModeData = &ModeBuffer[ModeNumber - 1];
    858   CurrentModeData->BytesPerScanLine = (UINT16)BytesPerScanLine;
    859 
    860   CurrentModeData->Red      = *(FB_VIDEO_COLOR_PLACEMENT *)&(pFbInfo->Red);
    861   CurrentModeData->Blue     = *(FB_VIDEO_COLOR_PLACEMENT *)&(pFbInfo->Blue);
    862   CurrentModeData->Green    = *(FB_VIDEO_COLOR_PLACEMENT *)&(pFbInfo->Green);
    863   CurrentModeData->Reserved = *(FB_VIDEO_COLOR_PLACEMENT *)&(pFbInfo->Reserved);
    864 
    865   CurrentModeData->BitsPerPixel    = (UINT32)BitsPerPixel;
    866   CurrentModeData->HorizontalResolution = HorizontalResolution;
    867   CurrentModeData->VerticalResolution   = VerticalResolution;
    868   CurrentModeData->FrameBufferSize = CurrentModeData->BytesPerScanLine * CurrentModeData->VerticalResolution;
    869   CurrentModeData->LinearFrameBuffer = (VOID *) (UINTN) pFbInfo->LinearFrameBuffer;
    870   CurrentModeData->VbeModeNumber        = 0;
    871   CurrentModeData->ColorDepth           = 32;
    872   CurrentModeData->RefreshRate          = 60;
    873 
    874   CurrentModeData->PixelFormat = PixelBitMask;
    875   if ((CurrentModeData->BitsPerPixel == 32) &&
    876       (CurrentModeData->Red.Mask == 0xff) && (CurrentModeData->Green.Mask == 0xff) && (CurrentModeData->Blue.Mask == 0xff)) {
    877     if ((CurrentModeData->Red.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Blue.Position == 16)) {
    878       CurrentModeData->PixelFormat = PixelRedGreenBlueReserved8BitPerColor;
    879     } else if ((CurrentModeData->Blue.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Red.Position == 16)) {
    880       CurrentModeData->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;
    881     }
    882   }
    883 
    884   CopyMem (&(CurrentModeData->PixelBitMask), &mPixelBitMask, sizeof (EFI_PIXEL_BITMASK));
    885 
    886   FbGopPrivate->ModeData       = ModeBuffer;
    887   FbGopPrivate->VbeFrameBuffer = VbeFrameBuffer;
    888 
    889   //
    890   // Assign Gop's Blt function
    891   //
    892   FbGopPrivate->GraphicsOutput.Blt     = FbGopGraphicsOutputVbeBlt;
    893 
    894   FbGopPrivate->GraphicsOutput.Mode->MaxMode = 1;
    895   FbGopPrivate->GraphicsOutput.Mode->Mode    = 0;
    896   FbGopPrivate->GraphicsOutput.Mode->Info->Version = 0;
    897   FbGopPrivate->GraphicsOutput.Mode->Info->HorizontalResolution = HorizontalResolution;
    898   FbGopPrivate->GraphicsOutput.Mode->Info->VerticalResolution   = VerticalResolution;
    899   FbGopPrivate->GraphicsOutput.Mode->Info->PixelFormat = CurrentModeData->PixelFormat;
    900   CopyMem (&(FbGopPrivate->GraphicsOutput.Mode->Info->PixelInformation), &mPixelBitMask, sizeof (EFI_PIXEL_BITMASK));
    901   FbGopPrivate->GraphicsOutput.Mode->Info->PixelsPerScanLine = HorizontalResolution;
    902   FbGopPrivate->GraphicsOutput.Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
    903   FbGopPrivate->GraphicsOutput.Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) CurrentModeData->LinearFrameBuffer;
    904   FbGopPrivate->GraphicsOutput.Mode->FrameBufferSize =  CurrentModeData->FrameBufferSize;
    905 
    906   //
    907   // Find the best mode to initialize
    908   //
    909 
    910 Done:
    911   //
    912   // If there was an error, then free the mode structure
    913   //
    914   if (EFI_ERROR (Status)) {
    915 
    916     if (VbeFrameBuffer != NULL) {
    917       FreePool (VbeFrameBuffer);
    918     }
    919 
    920     if (ModeBuffer != NULL) {
    921       FreePool (ModeBuffer);
    922     }
    923   }
    924 
    925   return Status;
    926 }
    927 
    928 
    929 //
    930 // Graphics Output Protocol Member Functions for VESA BIOS Extensions
    931 //
    932 
    933 /**
    934   Graphics Output protocol interface to get video mode.
    935 
    936   @param  This                   Protocol instance pointer.
    937   @param  ModeNumber             The mode number to return information on.
    938   @param  SizeOfInfo             A pointer to the size, in bytes, of the Info
    939                                  buffer.
    940   @param  Info                   Caller allocated buffer that returns information
    941                                  about ModeNumber.
    942 
    943   @retval EFI_SUCCESS            Mode information returned.
    944   @retval EFI_DEVICE_ERROR       A hardware error occurred trying to retrieve the
    945                                  video mode.
    946   @retval EFI_NOT_STARTED        Video display is not initialized. Call SetMode ()
    947   @retval EFI_INVALID_PARAMETER  One of the input args was NULL.
    948 
    949 **/
    950 EFI_STATUS
    951 EFIAPI
    952 FbGopGraphicsOutputQueryMode (
    953   IN  EFI_GRAPHICS_OUTPUT_PROTOCOL          *This,
    954   IN  UINT32                                ModeNumber,
    955   OUT UINTN                                 *SizeOfInfo,
    956   OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  **Info
    957   )
    958 {
    959   FB_VIDEO_DEV        *FbGopPrivate;
    960   FB_VIDEO_MODE_DATA  *ModeData;
    961 
    962   FbGopPrivate = FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);
    963 
    964   if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {
    965     return EFI_INVALID_PARAMETER;
    966   }
    967 
    968   *Info = (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) AllocatePool (
    969 																										sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)
    970 																										);
    971   if (NULL == *Info) {
    972     return EFI_OUT_OF_RESOURCES;
    973   }
    974 
    975   *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
    976 
    977   ModeData = &FbGopPrivate->ModeData[ModeNumber];
    978   (*Info)->Version = 0;
    979   (*Info)->HorizontalResolution = ModeData->HorizontalResolution;
    980   (*Info)->VerticalResolution   = ModeData->VerticalResolution;
    981   (*Info)->PixelFormat = ModeData->PixelFormat;
    982   CopyMem (&((*Info)->PixelInformation), &(ModeData->PixelBitMask), sizeof(ModeData->PixelBitMask));
    983 
    984   (*Info)->PixelsPerScanLine =  (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel;
    985 
    986   return EFI_SUCCESS;
    987 }
    988 
    989 /**
    990   Graphics Output protocol interface to set video mode.
    991 
    992   @param  This                   Protocol instance pointer.
    993   @param  ModeNumber             The mode number to be set.
    994 
    995   @retval EFI_SUCCESS            Graphics mode was changed.
    996   @retval EFI_DEVICE_ERROR       The device had an error and could not complete the
    997                                  request.
    998   @retval EFI_UNSUPPORTED        ModeNumber is not supported by this device.
    999 
   1000 **/
   1001 EFI_STATUS
   1002 EFIAPI
   1003 FbGopGraphicsOutputSetMode (
   1004   IN  EFI_GRAPHICS_OUTPUT_PROTOCOL * This,
   1005   IN  UINT32                       ModeNumber
   1006   )
   1007 {
   1008   FB_VIDEO_DEV          *FbGopPrivate;
   1009   FB_VIDEO_MODE_DATA    *ModeData;
   1010   EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
   1011 
   1012   if (This == NULL) {
   1013     return EFI_INVALID_PARAMETER;
   1014   }
   1015 
   1016   FbGopPrivate = FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);
   1017 
   1018   ModeData = &FbGopPrivate->ModeData[ModeNumber];
   1019 
   1020   if (ModeNumber >= This->Mode->MaxMode) {
   1021     return EFI_UNSUPPORTED;
   1022   }
   1023 
   1024   if (ModeNumber == This->Mode->Mode) {
   1025     //
   1026     // Clear screen to black
   1027     //
   1028     ZeroMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
   1029     FbGopGraphicsOutputVbeBlt (
   1030                         This,
   1031                         &Background,
   1032                         EfiBltVideoFill,
   1033                         0,
   1034                         0,
   1035                         0,
   1036                         0,
   1037                         ModeData->HorizontalResolution,
   1038                         ModeData->VerticalResolution,
   1039                         0
   1040     );
   1041     return EFI_SUCCESS;
   1042   } else {
   1043     return EFI_UNSUPPORTED;
   1044   }
   1045 
   1046 }
   1047 
   1048 /**
   1049   Update physical frame buffer, copy 4 bytes block, then copy remaining bytes.
   1050 
   1051   @param   PciIo              The pointer of EFI_PCI_IO_PROTOCOL
   1052   @param   VbeBuffer          The data to transfer to screen
   1053   @param   MemAddress         Physical frame buffer base address
   1054   @param   DestinationX       The X coordinate of the destination for BltOperation
   1055   @param   DestinationY       The Y coordinate of the destination for BltOperation
   1056   @param   TotalBytes         The total bytes of copy
   1057   @param   VbePixelWidth      Bytes per pixel
   1058   @param   BytesPerScanLine   Bytes per scan line
   1059 
   1060 **/
   1061 VOID
   1062 CopyVideoBuffer (
   1063   IN  EFI_PCI_IO_PROTOCOL   *PciIo,
   1064   IN  UINT8                 *VbeBuffer,
   1065   IN  VOID                  *MemAddress,
   1066   IN  UINTN                 DestinationX,
   1067   IN  UINTN                 DestinationY,
   1068   IN  UINTN                 TotalBytes,
   1069   IN  UINT32                VbePixelWidth,
   1070   IN  UINTN                 BytesPerScanLine
   1071   )
   1072 {
   1073   UINTN                 FrameBufferAddr;
   1074   UINTN                 CopyBlockNum;
   1075   UINTN                 RemainingBytes;
   1076   UINTN                 UnalignedBytes;
   1077   EFI_STATUS            Status;
   1078 
   1079   FrameBufferAddr = (UINTN) MemAddress + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth;
   1080 
   1081   //
   1082   // If TotalBytes is less than 4 bytes, only start byte copy.
   1083   //
   1084   if (TotalBytes < 4) {
   1085     Status = PciIo->Mem.Write (
   1086                      PciIo,
   1087                      EfiPciIoWidthUint8,
   1088                      EFI_PCI_IO_PASS_THROUGH_BAR,
   1089                      (UINT64) FrameBufferAddr,
   1090                      TotalBytes,
   1091                      VbeBuffer
   1092                      );
   1093     ASSERT_EFI_ERROR (Status);
   1094     return;
   1095   }
   1096 
   1097   //
   1098   // If VbeBuffer is not 4-byte aligned, start byte copy.
   1099   //
   1100   UnalignedBytes  = (4 - ((UINTN) VbeBuffer & 0x3)) & 0x3;
   1101 
   1102   if (UnalignedBytes != 0) {
   1103     Status = PciIo->Mem.Write (
   1104                      PciIo,
   1105                      EfiPciIoWidthUint8,
   1106                      EFI_PCI_IO_PASS_THROUGH_BAR,
   1107                      (UINT64) FrameBufferAddr,
   1108                      UnalignedBytes,
   1109                      VbeBuffer
   1110                      );
   1111     ASSERT_EFI_ERROR (Status);
   1112     FrameBufferAddr += UnalignedBytes;
   1113     VbeBuffer       += UnalignedBytes;
   1114   }
   1115 
   1116   //
   1117   // Calculate 4-byte block count and remaining bytes.
   1118   //
   1119   CopyBlockNum   = (TotalBytes - UnalignedBytes) >> 2;
   1120   RemainingBytes = (TotalBytes - UnalignedBytes) &  3;
   1121 
   1122   //
   1123   // Copy 4-byte block and remaining bytes to physical frame buffer.
   1124   //
   1125   if (CopyBlockNum != 0) {
   1126     Status = PciIo->Mem.Write (
   1127                     PciIo,
   1128                     EfiPciIoWidthUint32,
   1129                     EFI_PCI_IO_PASS_THROUGH_BAR,
   1130                     (UINT64) FrameBufferAddr,
   1131                     CopyBlockNum,
   1132                     VbeBuffer
   1133                     );
   1134     ASSERT_EFI_ERROR (Status);
   1135   }
   1136 
   1137   if (RemainingBytes != 0) {
   1138     FrameBufferAddr += (CopyBlockNum << 2);
   1139     VbeBuffer       += (CopyBlockNum << 2);
   1140     Status = PciIo->Mem.Write (
   1141                     PciIo,
   1142                     EfiPciIoWidthUint8,
   1143                     EFI_PCI_IO_PASS_THROUGH_BAR,
   1144                     (UINT64) FrameBufferAddr,
   1145                     RemainingBytes,
   1146                     VbeBuffer
   1147                     );
   1148     ASSERT_EFI_ERROR (Status);
   1149   }
   1150 }
   1151 
   1152 /**
   1153   Worker function to block transfer for VBE device.
   1154 
   1155   @param  FbGopPrivate       Instance of FB_VIDEO_DEV
   1156   @param  BltBuffer              The data to transfer to screen
   1157   @param  BltOperation           The operation to perform
   1158   @param  SourceX                The X coordinate of the source for BltOperation
   1159   @param  SourceY                The Y coordinate of the source for BltOperation
   1160   @param  DestinationX           The X coordinate of the destination for
   1161                                  BltOperation
   1162   @param  DestinationY           The Y coordinate of the destination for
   1163                                  BltOperation
   1164   @param  Width                  The width of a rectangle in the blt rectangle in
   1165                                  pixels
   1166   @param  Height                 The height of a rectangle in the blt rectangle in
   1167                                  pixels
   1168   @param  Delta                  Not used for EfiBltVideoFill and
   1169                                  EfiBltVideoToVideo operation. If a Delta of 0 is
   1170                                  used, the entire BltBuffer will be operated on. If
   1171                                  a subrectangle of the BltBuffer is used, then
   1172                                  Delta represents the number of bytes in a row of
   1173                                  the BltBuffer.
   1174   @param  Mode                   Mode data.
   1175 
   1176   @retval EFI_INVALID_PARAMETER  Invalid parameter passed in
   1177   @retval EFI_SUCCESS            Blt operation success
   1178 
   1179 **/
   1180 EFI_STATUS
   1181 FbGopVbeBltWorker (
   1182   IN  FB_VIDEO_DEV                       *FbGopPrivate,
   1183   IN  EFI_GRAPHICS_OUTPUT_BLT_PIXEL      *BltBuffer, OPTIONAL
   1184   IN  EFI_GRAPHICS_OUTPUT_BLT_OPERATION  BltOperation,
   1185   IN  UINTN                              SourceX,
   1186   IN  UINTN                              SourceY,
   1187   IN  UINTN                              DestinationX,
   1188   IN  UINTN                              DestinationY,
   1189   IN  UINTN                              Width,
   1190   IN  UINTN                              Height,
   1191   IN  UINTN                              Delta,
   1192   IN  FB_VIDEO_MODE_DATA               *Mode
   1193   )
   1194 {
   1195   EFI_PCI_IO_PROTOCOL            *PciIo;
   1196   EFI_TPL                        OriginalTPL;
   1197   UINTN                          DstY;
   1198   UINTN                          SrcY;
   1199   UINTN                          DstX;
   1200   EFI_GRAPHICS_OUTPUT_BLT_PIXEL  *Blt;
   1201   VOID                           *MemAddress;
   1202   EFI_GRAPHICS_OUTPUT_BLT_PIXEL  *VbeFrameBuffer;
   1203   UINTN                          BytesPerScanLine;
   1204   UINTN                          Index;
   1205   UINT8                          *VbeBuffer;
   1206   UINT8                          *VbeBuffer1;
   1207   UINT8                          *BltUint8;
   1208   UINT32                         VbePixelWidth;
   1209   UINT32                         Pixel;
   1210   UINTN                          TotalBytes;
   1211 
   1212   PciIo             = FbGopPrivate->PciIo;
   1213 
   1214   VbeFrameBuffer    = FbGopPrivate->VbeFrameBuffer;
   1215   MemAddress        = Mode->LinearFrameBuffer;
   1216   BytesPerScanLine  = Mode->BytesPerScanLine;
   1217   VbePixelWidth     = Mode->BitsPerPixel / 8;
   1218   BltUint8          = (UINT8 *) BltBuffer;
   1219   TotalBytes        = Width * VbePixelWidth;
   1220 
   1221   if (((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) {
   1222     return EFI_INVALID_PARAMETER;
   1223   }
   1224 
   1225   if (Width == 0 || Height == 0) {
   1226     return EFI_INVALID_PARAMETER;
   1227   }
   1228   //
   1229   // We need to fill the Virtual Screen buffer with the blt data.
   1230   // The virtual screen is upside down, as the first row is the bootom row of
   1231   // the image.
   1232   //
   1233   if (BltOperation == EfiBltVideoToBltBuffer) {
   1234     //
   1235     // Video to BltBuffer: Source is Video, destination is BltBuffer
   1236     //
   1237     if (SourceY + Height > Mode->VerticalResolution) {
   1238       return EFI_INVALID_PARAMETER;
   1239     }
   1240 
   1241     if (SourceX + Width > Mode->HorizontalResolution) {
   1242       return EFI_INVALID_PARAMETER;
   1243     }
   1244   } else {
   1245     //
   1246     // BltBuffer to Video: Source is BltBuffer, destination is Video
   1247     //
   1248     if (DestinationY + Height > Mode->VerticalResolution) {
   1249       return EFI_INVALID_PARAMETER;
   1250     }
   1251 
   1252     if (DestinationX + Width > Mode->HorizontalResolution) {
   1253       return EFI_INVALID_PARAMETER;
   1254     }
   1255   }
   1256   //
   1257   // If Delta is zero, then the entire BltBuffer is being used, so Delta
   1258   // is the number of bytes in each row of BltBuffer.  Since BltBuffer is Width pixels size,
   1259   // the number of bytes in each row can be computed.
   1260   //
   1261   if (Delta == 0) {
   1262     Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
   1263   }
   1264   //
   1265   // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
   1266   // We would not want a timer based event (Cursor, ...) to come in while we are
   1267   // doing this operation.
   1268   //
   1269   OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
   1270 
   1271   switch (BltOperation) {
   1272   case EfiBltVideoToBltBuffer:
   1273     for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) {
   1274       Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + DstY * Delta + DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
   1275       //
   1276       // Shuffle the packed bytes in the hardware buffer to match EFI_GRAPHICS_OUTPUT_BLT_PIXEL
   1277       //
   1278       VbeBuffer = ((UINT8 *) VbeFrameBuffer + (SrcY * BytesPerScanLine + SourceX * VbePixelWidth));
   1279       for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {
   1280         Pixel         = VbeBuffer[0] | VbeBuffer[1] << 8 | VbeBuffer[2] << 16 | VbeBuffer[3] << 24;
   1281         Blt->Red      = (UINT8) ((Pixel >> Mode->Red.Position) & Mode->Red.Mask);
   1282         Blt->Blue     = (UINT8) ((Pixel >> Mode->Blue.Position) & Mode->Blue.Mask);
   1283         Blt->Green    = (UINT8) ((Pixel >> Mode->Green.Position) & Mode->Green.Mask);
   1284         Blt->Reserved = 0;
   1285         Blt++;
   1286         VbeBuffer += VbePixelWidth;
   1287       }
   1288 
   1289     }
   1290     break;
   1291 
   1292   case EfiBltVideoToVideo:
   1293     for (Index = 0; Index < Height; Index++) {
   1294       if (DestinationY <= SourceY) {
   1295         SrcY  = SourceY + Index;
   1296         DstY  = DestinationY + Index;
   1297       } else {
   1298         SrcY  = SourceY + Height - Index - 1;
   1299         DstY  = DestinationY + Height - Index - 1;
   1300       }
   1301 
   1302       VbeBuffer   = ((UINT8 *) VbeFrameBuffer + DstY * BytesPerScanLine + DestinationX * VbePixelWidth);
   1303       VbeBuffer1  = ((UINT8 *) VbeFrameBuffer + SrcY * BytesPerScanLine + SourceX * VbePixelWidth);
   1304 
   1305       gBS->CopyMem (
   1306             VbeBuffer,
   1307             VbeBuffer1,
   1308             TotalBytes
   1309             );
   1310 
   1311       //
   1312       // Update physical frame buffer.
   1313       //
   1314       CopyVideoBuffer (
   1315         PciIo,
   1316         VbeBuffer,
   1317         MemAddress,
   1318         DestinationX,
   1319         DstY,
   1320         TotalBytes,
   1321         VbePixelWidth,
   1322         BytesPerScanLine
   1323         );
   1324     }
   1325     break;
   1326 
   1327   case EfiBltVideoFill:
   1328     VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);
   1329     Blt       = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltUint8;
   1330     //
   1331     // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer
   1332     //
   1333     Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |
   1334       (
   1335         (Blt->Green & Mode->Green.Mask) <<
   1336         Mode->Green.Position
   1337       ) |
   1338           ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);
   1339 
   1340     for (Index = 0; Index < Width; Index++) {
   1341       gBS->CopyMem (
   1342             VbeBuffer,
   1343             &Pixel,
   1344             VbePixelWidth
   1345             );
   1346       VbeBuffer += VbePixelWidth;
   1347     }
   1348 
   1349     VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);
   1350     for (DstY = DestinationY + 1; DstY < (Height + DestinationY); DstY++) {
   1351       gBS->CopyMem (
   1352             (VOID *) ((UINTN) VbeFrameBuffer + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth),
   1353             VbeBuffer,
   1354             TotalBytes
   1355             );
   1356     }
   1357 
   1358     for (DstY = DestinationY; DstY < (Height + DestinationY); DstY++) {
   1359       //
   1360       // Update physical frame buffer.
   1361       //
   1362       CopyVideoBuffer (
   1363         PciIo,
   1364         VbeBuffer,
   1365         MemAddress,
   1366         DestinationX,
   1367         DstY,
   1368         TotalBytes,
   1369         VbePixelWidth,
   1370         BytesPerScanLine
   1371         );
   1372     }
   1373     break;
   1374 
   1375   case EfiBltBufferToVideo:
   1376     for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {
   1377       Blt       = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + (SrcY * Delta) + (SourceX) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
   1378       VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth));
   1379       for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {
   1380         //
   1381         // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer
   1382         //
   1383         Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |
   1384           ((Blt->Green & Mode->Green.Mask) << Mode->Green.Position) |
   1385             ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);
   1386         gBS->CopyMem (
   1387               VbeBuffer,
   1388               &Pixel,
   1389               VbePixelWidth
   1390               );
   1391         Blt++;
   1392         VbeBuffer += VbePixelWidth;
   1393       }
   1394 
   1395       VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth));
   1396 
   1397       //
   1398       // Update physical frame buffer.
   1399       //
   1400       CopyVideoBuffer (
   1401         PciIo,
   1402         VbeBuffer,
   1403         MemAddress,
   1404         DestinationX,
   1405         DstY,
   1406         TotalBytes,
   1407         VbePixelWidth,
   1408         BytesPerScanLine
   1409         );
   1410     }
   1411     break;
   1412 
   1413     default: ;
   1414   }
   1415 
   1416   gBS->RestoreTPL (OriginalTPL);
   1417 
   1418   return EFI_SUCCESS;
   1419 }
   1420 
   1421 /**
   1422   Graphics Output protocol instance to block transfer for VBE device.
   1423 
   1424   @param  This                   Pointer to Graphics Output protocol instance
   1425   @param  BltBuffer              The data to transfer to screen
   1426   @param  BltOperation           The operation to perform
   1427   @param  SourceX                The X coordinate of the source for BltOperation
   1428   @param  SourceY                The Y coordinate of the source for BltOperation
   1429   @param  DestinationX           The X coordinate of the destination for
   1430                                  BltOperation
   1431   @param  DestinationY           The Y coordinate of the destination for
   1432                                  BltOperation
   1433   @param  Width                  The width of a rectangle in the blt rectangle in
   1434                                  pixels
   1435   @param  Height                 The height of a rectangle in the blt rectangle in
   1436                                  pixels
   1437   @param  Delta                  Not used for EfiBltVideoFill and
   1438                                  EfiBltVideoToVideo operation. If a Delta of 0 is
   1439                                  used, the entire BltBuffer will be operated on. If
   1440                                  a subrectangle of the BltBuffer is used, then
   1441                                  Delta represents the number of bytes in a row of
   1442                                  the BltBuffer.
   1443 
   1444   @retval EFI_INVALID_PARAMETER  Invalid parameter passed in
   1445   @retval EFI_SUCCESS            Blt operation success
   1446 
   1447 **/
   1448 EFI_STATUS
   1449 EFIAPI
   1450 FbGopGraphicsOutputVbeBlt (
   1451   IN  EFI_GRAPHICS_OUTPUT_PROTOCOL       *This,
   1452   IN  EFI_GRAPHICS_OUTPUT_BLT_PIXEL      *BltBuffer, OPTIONAL
   1453   IN  EFI_GRAPHICS_OUTPUT_BLT_OPERATION  BltOperation,
   1454   IN  UINTN                              SourceX,
   1455   IN  UINTN                              SourceY,
   1456   IN  UINTN                              DestinationX,
   1457   IN  UINTN                              DestinationY,
   1458   IN  UINTN                              Width,
   1459   IN  UINTN                              Height,
   1460   IN  UINTN                              Delta
   1461   )
   1462 {
   1463   FB_VIDEO_DEV                 *FbGopPrivate;
   1464   FB_VIDEO_MODE_DATA           *Mode;
   1465 
   1466   if (This == NULL) {
   1467     return EFI_INVALID_PARAMETER;
   1468   }
   1469 
   1470   FbGopPrivate  = FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);
   1471   Mode          = &FbGopPrivate->ModeData[This->Mode->Mode];
   1472 
   1473   return FbGopVbeBltWorker (
   1474            FbGopPrivate,
   1475            BltBuffer,
   1476            BltOperation,
   1477            SourceX,
   1478            SourceY,
   1479            DestinationX,
   1480            DestinationY,
   1481            Width,
   1482            Height,
   1483            Delta,
   1484            Mode
   1485            );
   1486 }
   1487 
   1488 
   1489 /**
   1490   The user Entry Point for module UefiFbGop. The user code starts with this function.
   1491 
   1492   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
   1493   @param[in] SystemTable    A pointer to the EFI System Table.
   1494 
   1495   @retval EFI_SUCCESS       The entry point is executed successfully.
   1496   @retval other             Some error occurs when executing this entry point.
   1497 
   1498 **/
   1499 EFI_STATUS
   1500 EFIAPI
   1501 FbGopEntryPoint(
   1502   IN EFI_HANDLE           ImageHandle,
   1503   IN EFI_SYSTEM_TABLE     *SystemTable
   1504   )
   1505 {
   1506   EFI_STATUS  Status;
   1507   EFI_HOB_GUID_TYPE  *GuidHob;
   1508 
   1509   //
   1510   // Find the frame buffer information guid hob
   1511   //
   1512   GuidHob = GetFirstGuidHob (&gUefiFrameBufferInfoGuid);
   1513   if (GuidHob != NULL) {
   1514     //
   1515     // Install driver model protocol(s).
   1516     //
   1517     Status = EfiLibInstallDriverBindingComponentName2 (
   1518                ImageHandle,
   1519                SystemTable,
   1520                &gFbGopDriverBinding,
   1521                ImageHandle,
   1522                &gFbGopComponentName,
   1523                &gFbGopComponentName2
   1524                );
   1525     ASSERT_EFI_ERROR (Status);
   1526   } else {
   1527     DEBUG ((EFI_D_ERROR, "No FrameBuffer information from coreboot.  NO GOP driver !!!\n"));
   1528     Status = EFI_ABORTED;
   1529   }
   1530   return Status;
   1531 }
   1532 
   1533