Home | History | Annotate | Download | only in QemuVideoDxe
      1 /** @file
      2   Graphics Output Protocol functions for the QEMU video controller.
      3 
      4   Copyright (c) 2007 - 2016, 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 of the BSD License
      8   which accompanies this distribution. The full text of the license may be found at
      9   http://opensource.org/licenses/bsd-license.php
     10 
     11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include "Qemu.h"
     17 
     18 STATIC
     19 VOID
     20 QemuVideoCompleteModeInfo (
     21   IN  QEMU_VIDEO_MODE_DATA           *ModeData,
     22   OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *Info
     23   )
     24 {
     25   Info->Version = 0;
     26   if (ModeData->ColorDepth == 8) {
     27     Info->PixelFormat = PixelBitMask;
     28     Info->PixelInformation.RedMask = PIXEL_RED_MASK;
     29     Info->PixelInformation.GreenMask = PIXEL_GREEN_MASK;
     30     Info->PixelInformation.BlueMask = PIXEL_BLUE_MASK;
     31     Info->PixelInformation.ReservedMask = 0;
     32   } else if (ModeData->ColorDepth == 24) {
     33     Info->PixelFormat = PixelBitMask;
     34     Info->PixelInformation.RedMask = PIXEL24_RED_MASK;
     35     Info->PixelInformation.GreenMask = PIXEL24_GREEN_MASK;
     36     Info->PixelInformation.BlueMask = PIXEL24_BLUE_MASK;
     37     Info->PixelInformation.ReservedMask = 0;
     38   } else if (ModeData->ColorDepth == 32) {
     39     DEBUG ((EFI_D_INFO, "PixelBlueGreenRedReserved8BitPerColor\n"));
     40     Info->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;
     41   }
     42   Info->PixelsPerScanLine = Info->HorizontalResolution;
     43 }
     44 
     45 
     46 STATIC
     47 EFI_STATUS
     48 QemuVideoCompleteModeData (
     49   IN  QEMU_VIDEO_PRIVATE_DATA           *Private,
     50   OUT EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode
     51   )
     52 {
     53   EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *Info;
     54   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR     *FrameBufDesc;
     55   QEMU_VIDEO_MODE_DATA           *ModeData;
     56 
     57   ModeData = &Private->ModeData[Mode->Mode];
     58   Info = Mode->Info;
     59   QemuVideoCompleteModeInfo (ModeData, Info);
     60 
     61   Private->PciIo->GetBarAttributes (
     62                         Private->PciIo,
     63                         0,
     64                         NULL,
     65                         (VOID**) &FrameBufDesc
     66                         );
     67 
     68   Mode->FrameBufferBase = FrameBufDesc->AddrRangeMin;
     69   Mode->FrameBufferSize = Info->HorizontalResolution * Info->VerticalResolution;
     70   Mode->FrameBufferSize = Mode->FrameBufferSize * ((ModeData->ColorDepth + 7) / 8);
     71   DEBUG ((EFI_D_INFO, "FrameBufferBase: 0x%Lx, FrameBufferSize: 0x%Lx\n",
     72     Mode->FrameBufferBase, (UINT64)Mode->FrameBufferSize));
     73 
     74   FreePool (FrameBufDesc);
     75   return EFI_SUCCESS;
     76 }
     77 
     78 
     79 //
     80 // Graphics Output Protocol Member Functions
     81 //
     82 EFI_STATUS
     83 EFIAPI
     84 QemuVideoGraphicsOutputQueryMode (
     85   IN  EFI_GRAPHICS_OUTPUT_PROTOCOL          *This,
     86   IN  UINT32                                ModeNumber,
     87   OUT UINTN                                 *SizeOfInfo,
     88   OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  **Info
     89   )
     90 /*++
     91 
     92 Routine Description:
     93 
     94   Graphics Output protocol interface to query video mode
     95 
     96   Arguments:
     97     This                  - Protocol instance pointer.
     98     ModeNumber            - The mode number to return information on.
     99     Info                  - Caller allocated buffer that returns information about ModeNumber.
    100     SizeOfInfo            - A pointer to the size, in bytes, of the Info buffer.
    101 
    102   Returns:
    103     EFI_SUCCESS           - Mode information returned.
    104     EFI_BUFFER_TOO_SMALL  - The Info buffer was too small.
    105     EFI_DEVICE_ERROR      - A hardware error occurred trying to retrieve the video mode.
    106     EFI_NOT_STARTED       - Video display is not initialized. Call SetMode ()
    107     EFI_INVALID_PARAMETER - One of the input args was NULL.
    108 
    109 --*/
    110 {
    111   QEMU_VIDEO_PRIVATE_DATA  *Private;
    112   QEMU_VIDEO_MODE_DATA     *ModeData;
    113 
    114   Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
    115 
    116   if (Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {
    117     return EFI_INVALID_PARAMETER;
    118   }
    119 
    120   *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
    121   if (*Info == NULL) {
    122     return EFI_OUT_OF_RESOURCES;
    123   }
    124 
    125   *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
    126 
    127   ModeData = &Private->ModeData[ModeNumber];
    128   (*Info)->HorizontalResolution = ModeData->HorizontalResolution;
    129   (*Info)->VerticalResolution   = ModeData->VerticalResolution;
    130   QemuVideoCompleteModeInfo (ModeData, *Info);
    131 
    132   return EFI_SUCCESS;
    133 }
    134 
    135 EFI_STATUS
    136 EFIAPI
    137 QemuVideoGraphicsOutputSetMode (
    138   IN  EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
    139   IN  UINT32                       ModeNumber
    140   )
    141 /*++
    142 
    143 Routine Description:
    144 
    145   Graphics Output protocol interface to set video mode
    146 
    147   Arguments:
    148     This             - Protocol instance pointer.
    149     ModeNumber       - The mode number to be set.
    150 
    151   Returns:
    152     EFI_SUCCESS      - Graphics mode was changed.
    153     EFI_DEVICE_ERROR - The device had an error and could not complete the request.
    154     EFI_UNSUPPORTED  - ModeNumber is not supported by this device.
    155 
    156 --*/
    157 {
    158   QEMU_VIDEO_PRIVATE_DATA    *Private;
    159   QEMU_VIDEO_MODE_DATA       *ModeData;
    160   RETURN_STATUS              Status;
    161 
    162   Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
    163 
    164   if (ModeNumber >= This->Mode->MaxMode) {
    165     return EFI_UNSUPPORTED;
    166   }
    167 
    168   ModeData = &Private->ModeData[ModeNumber];
    169 
    170   switch (Private->Variant) {
    171   case QEMU_VIDEO_CIRRUS_5430:
    172   case QEMU_VIDEO_CIRRUS_5446:
    173     InitializeCirrusGraphicsMode (Private, &QemuVideoCirrusModes[ModeData->InternalModeIndex]);
    174     break;
    175   case QEMU_VIDEO_BOCHS_MMIO:
    176   case QEMU_VIDEO_BOCHS:
    177     InitializeBochsGraphicsMode (Private, &QemuVideoBochsModes[ModeData->InternalModeIndex]);
    178     break;
    179   default:
    180     ASSERT (FALSE);
    181     return EFI_DEVICE_ERROR;
    182   }
    183 
    184   This->Mode->Mode = ModeNumber;
    185   This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;
    186   This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;
    187   This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
    188 
    189   QemuVideoCompleteModeData (Private, This->Mode);
    190 
    191   //
    192   // Allocate when using first time.
    193   //
    194   if (Private->FrameBufferBltConfigure == NULL) {
    195     Status = FrameBufferBltConfigure (
    196                (VOID*) (UINTN) This->Mode->FrameBufferBase,
    197                This->Mode->Info,
    198                Private->FrameBufferBltConfigure,
    199                &Private->FrameBufferBltConfigureSize
    200                );
    201     ASSERT (Status == RETURN_BUFFER_TOO_SMALL);
    202     Private->FrameBufferBltConfigure =
    203       AllocatePool (Private->FrameBufferBltConfigureSize);
    204   }
    205 
    206   //
    207   // Create the configuration for FrameBufferBltLib
    208   //
    209   ASSERT (Private->FrameBufferBltConfigure != NULL);
    210   Status = FrameBufferBltConfigure (
    211               (VOID*) (UINTN) This->Mode->FrameBufferBase,
    212               This->Mode->Info,
    213               Private->FrameBufferBltConfigure,
    214               &Private->FrameBufferBltConfigureSize
    215               );
    216   ASSERT (Status == RETURN_SUCCESS);
    217 
    218   return EFI_SUCCESS;
    219 }
    220 
    221 EFI_STATUS
    222 EFIAPI
    223 QemuVideoGraphicsOutputBlt (
    224   IN  EFI_GRAPHICS_OUTPUT_PROTOCOL          *This,
    225   IN  EFI_GRAPHICS_OUTPUT_BLT_PIXEL         *BltBuffer, OPTIONAL
    226   IN  EFI_GRAPHICS_OUTPUT_BLT_OPERATION     BltOperation,
    227   IN  UINTN                                 SourceX,
    228   IN  UINTN                                 SourceY,
    229   IN  UINTN                                 DestinationX,
    230   IN  UINTN                                 DestinationY,
    231   IN  UINTN                                 Width,
    232   IN  UINTN                                 Height,
    233   IN  UINTN                                 Delta
    234   )
    235 /*++
    236 
    237 Routine Description:
    238 
    239   Graphics Output protocol instance to block transfer for CirrusLogic device
    240 
    241 Arguments:
    242 
    243   This          - Pointer to Graphics Output protocol instance
    244   BltBuffer     - The data to transfer to screen
    245   BltOperation  - The operation to perform
    246   SourceX       - The X coordinate of the source for BltOperation
    247   SourceY       - The Y coordinate of the source for BltOperation
    248   DestinationX  - The X coordinate of the destination for BltOperation
    249   DestinationY  - The Y coordinate of the destination for BltOperation
    250   Width         - The width of a rectangle in the blt rectangle in pixels
    251   Height        - The height of a rectangle in the blt rectangle in pixels
    252   Delta         - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.
    253                   If a Delta of 0 is used, the entire BltBuffer will be operated on.
    254                   If a subrectangle of the BltBuffer is used, then Delta represents
    255                   the number of bytes in a row of the BltBuffer.
    256 
    257 Returns:
    258 
    259   EFI_INVALID_PARAMETER - Invalid parameter passed in
    260   EFI_SUCCESS - Blt operation success
    261 
    262 --*/
    263 {
    264   EFI_STATUS                      Status;
    265   EFI_TPL                         OriginalTPL;
    266   QEMU_VIDEO_PRIVATE_DATA         *Private;
    267 
    268   Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
    269   //
    270   // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
    271   // We would not want a timer based event (Cursor, ...) to come in while we are
    272   // doing this operation.
    273   //
    274   OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
    275 
    276   switch (BltOperation) {
    277   case EfiBltVideoToBltBuffer:
    278   case EfiBltBufferToVideo:
    279   case EfiBltVideoFill:
    280   case EfiBltVideoToVideo:
    281     Status = FrameBufferBlt (
    282       Private->FrameBufferBltConfigure,
    283       BltBuffer,
    284       BltOperation,
    285       SourceX,
    286       SourceY,
    287       DestinationX,
    288       DestinationY,
    289       Width,
    290       Height,
    291       Delta
    292       );
    293     break;
    294 
    295   default:
    296     Status = EFI_INVALID_PARAMETER;
    297     ASSERT (FALSE);
    298   }
    299 
    300   gBS->RestoreTPL (OriginalTPL);
    301 
    302   return Status;
    303 }
    304 
    305 EFI_STATUS
    306 QemuVideoGraphicsOutputConstructor (
    307   QEMU_VIDEO_PRIVATE_DATA  *Private
    308   )
    309 {
    310   EFI_STATUS                   Status;
    311   EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
    312 
    313 
    314   GraphicsOutput            = &Private->GraphicsOutput;
    315   GraphicsOutput->QueryMode = QemuVideoGraphicsOutputQueryMode;
    316   GraphicsOutput->SetMode   = QemuVideoGraphicsOutputSetMode;
    317   GraphicsOutput->Blt       = QemuVideoGraphicsOutputBlt;
    318 
    319   //
    320   // Initialize the private data
    321   //
    322   Status = gBS->AllocatePool (
    323                   EfiBootServicesData,
    324                   sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE),
    325                   (VOID **) &Private->GraphicsOutput.Mode
    326                   );
    327   if (EFI_ERROR (Status)) {
    328     return Status;
    329   }
    330 
    331   Status = gBS->AllocatePool (
    332                   EfiBootServicesData,
    333                   sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
    334                   (VOID **) &Private->GraphicsOutput.Mode->Info
    335                   );
    336   if (EFI_ERROR (Status)) {
    337     goto FreeMode;
    338   }
    339   Private->GraphicsOutput.Mode->MaxMode = (UINT32) Private->MaxMode;
    340   Private->GraphicsOutput.Mode->Mode    = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;
    341   Private->FrameBufferBltConfigure      = NULL;
    342   Private->FrameBufferBltConfigureSize  = 0;
    343 
    344   //
    345   // Initialize the hardware
    346   //
    347   Status = GraphicsOutput->SetMode (GraphicsOutput, 0);
    348   if (EFI_ERROR (Status)) {
    349     goto FreeInfo;
    350   }
    351 
    352   DrawLogo (
    353     Private,
    354     Private->ModeData[Private->GraphicsOutput.Mode->Mode].HorizontalResolution,
    355     Private->ModeData[Private->GraphicsOutput.Mode->Mode].VerticalResolution
    356     );
    357 
    358   return EFI_SUCCESS;
    359 
    360 FreeInfo:
    361   FreePool (Private->GraphicsOutput.Mode->Info);
    362 
    363 FreeMode:
    364   FreePool (Private->GraphicsOutput.Mode);
    365   Private->GraphicsOutput.Mode = NULL;
    366 
    367   return Status;
    368 }
    369 
    370 EFI_STATUS
    371 QemuVideoGraphicsOutputDestructor (
    372   QEMU_VIDEO_PRIVATE_DATA  *Private
    373   )
    374 /*++
    375 
    376 Routine Description:
    377 
    378 Arguments:
    379 
    380 Returns:
    381 
    382   None
    383 
    384 --*/
    385 {
    386   if (Private->FrameBufferBltConfigure != NULL) {
    387     FreePool (Private->FrameBufferBltConfigure);
    388   }
    389 
    390   if (Private->GraphicsOutput.Mode != NULL) {
    391     if (Private->GraphicsOutput.Mode->Info != NULL) {
    392       gBS->FreePool (Private->GraphicsOutput.Mode->Info);
    393     }
    394     gBS->FreePool (Private->GraphicsOutput.Mode);
    395   }
    396 
    397   return EFI_SUCCESS;
    398 }
    399 
    400 
    401