Home | History | Annotate | Download | only in EmuGopDxe
      1 /*++ @file
      2 
      3 Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
      4 Portions copyright (c) 2010 - 2011, Apple Inc. All rights reserved.
      5 This program and the accompanying materials
      6 are licensed and made available under the terms and conditions of the BSD License
      7 which accompanies this distribution.  The full text of the license may be found at
      8 http://opensource.org/licenses/bsd-license.php
      9 
     10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 Module Name:
     14 
     15     EmuGopScreen.c
     16 
     17 Abstract:
     18 
     19   This file produces the graphics abstration of UGA. It is called by
     20   EmuGopDriver.c file which deals with the EFI 1.1 driver model.
     21   This file just does graphics.
     22 
     23 **/
     24 
     25 #include "Gop.h"
     26 
     27 
     28 EFI_EVENT               mGopScreenExitBootServicesEvent;
     29 
     30 GOP_MODE_DATA mGopModeData[] = {
     31     { 800,  600, 0, 0 },
     32     { 640,  480, 0, 0 },
     33     { 720,  400, 0, 0 },
     34     {1024,  768, 0, 0 },
     35     {1280, 1024, 0, 0 }
     36     };
     37 
     38 
     39 /**
     40   Returns information for an available graphics mode that the graphics device
     41   and the set of active video output devices supports.
     42 
     43   @param  This                  The EFI_GRAPHICS_OUTPUT_PROTOCOL instance.
     44   @param  ModeNumber            The mode number to return information on.
     45   @param  SizeOfInfo            A pointer to the size, in bytes, of the Info buffer.
     46   @param  Info                  A pointer to callee allocated buffer that returns information about ModeNumber.
     47 
     48   @retval EFI_SUCCESS           Mode information returned.
     49   @retval EFI_BUFFER_TOO_SMALL  The Info buffer was too small.
     50   @retval EFI_DEVICE_ERROR      A hardware error occurred trying to retrieve the video mode.
     51   @retval EFI_NOT_STARTED       Video display is not initialized. Call SetMode ()
     52   @retval EFI_INVALID_PARAMETER One of the input args was NULL.
     53 
     54 **/
     55 EFI_STATUS
     56 EFIAPI
     57 EmuGopQuerytMode (
     58   IN  EFI_GRAPHICS_OUTPUT_PROTOCOL          *This,
     59   IN  UINT32                                ModeNumber,
     60   OUT UINTN                                 *SizeOfInfo,
     61   OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  **Info
     62   )
     63 {
     64   GOP_PRIVATE_DATA  *Private;
     65 
     66   Private = GOP_PRIVATE_DATA_FROM_THIS (This);
     67 
     68   if (Info == NULL || SizeOfInfo == NULL || (UINTN) ModeNumber >= This->Mode->MaxMode) {
     69     return EFI_INVALID_PARAMETER;
     70   }
     71 
     72   *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
     73   if (*Info == NULL) {
     74     return EFI_OUT_OF_RESOURCES;
     75   }
     76 
     77   *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
     78 
     79   (*Info)->Version = 0;
     80   (*Info)->HorizontalResolution = Private->ModeData[ModeNumber].HorizontalResolution;
     81   (*Info)->VerticalResolution   = Private->ModeData[ModeNumber].VerticalResolution;
     82   (*Info)->PixelFormat = PixelBltOnly;
     83   (*Info)->PixelsPerScanLine = (*Info)->HorizontalResolution;
     84 
     85   return EFI_SUCCESS;
     86 }
     87 
     88 
     89 
     90 /**
     91   Set the video device into the specified mode and clears the visible portions of
     92   the output display to black.
     93 
     94   @param  This              The EFI_GRAPHICS_OUTPUT_PROTOCOL instance.
     95   @param  ModeNumber        Abstraction that defines the current video mode.
     96 
     97   @retval EFI_SUCCESS       The graphics mode specified by ModeNumber was selected.
     98   @retval EFI_DEVICE_ERROR  The device had an error and could not complete the request.
     99   @retval EFI_UNSUPPORTED   ModeNumber is not supported by this device.
    100 
    101 **/
    102 EFI_STATUS
    103 EFIAPI
    104 EmuGopSetMode (
    105   IN  EFI_GRAPHICS_OUTPUT_PROTOCOL  *This,
    106   IN  UINT32                        ModeNumber
    107   )
    108 {
    109   EFI_STATUS                      Status;
    110   GOP_PRIVATE_DATA                *Private;
    111   GOP_MODE_DATA                   *ModeData;
    112   EFI_GRAPHICS_OUTPUT_BLT_PIXEL   Fill;
    113 
    114   Private = GOP_PRIVATE_DATA_FROM_THIS (This);
    115 
    116   if (ModeNumber >= This->Mode->MaxMode) {
    117     return EFI_UNSUPPORTED;
    118   }
    119 
    120   ModeData = &Private->ModeData[ModeNumber];
    121   This->Mode->Mode = ModeNumber;
    122   Private->GraphicsOutput.Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;
    123   Private->GraphicsOutput.Mode->Info->VerticalResolution = ModeData->VerticalResolution;
    124   Private->GraphicsOutput.Mode->Info->PixelsPerScanLine = ModeData->HorizontalResolution;
    125 
    126   if (Private->HardwareNeedsStarting) {
    127     Status = EmuGopStartWindow (
    128               Private,
    129               ModeData->HorizontalResolution,
    130               ModeData->VerticalResolution,
    131               ModeData->ColorDepth,
    132               ModeData->RefreshRate
    133               );
    134     if (EFI_ERROR (Status)) {
    135       return EFI_DEVICE_ERROR;
    136     }
    137 
    138     Private->HardwareNeedsStarting = FALSE;
    139   }
    140 
    141 
    142   Status = Private->EmuGraphicsWindow->Size(
    143                             Private->EmuGraphicsWindow,
    144                             ModeData->HorizontalResolution,
    145                             ModeData->VerticalResolution
    146                             );
    147 
    148 
    149   Fill.Red                      = 0x7f;
    150   Fill.Green                    = 0x7F;
    151   Fill.Blue                     = 0x7f;
    152   This->Blt (
    153           This,
    154           &Fill,
    155           EfiBltVideoFill,
    156           0,
    157           0,
    158           0,
    159           0,
    160           ModeData->HorizontalResolution,
    161           ModeData->VerticalResolution,
    162           ModeData->HorizontalResolution * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
    163           );
    164   return EFI_SUCCESS;
    165 }
    166 
    167 
    168 
    169 /**
    170   Blt a rectangle of pixels on the graphics screen. Blt stands for BLock Transfer.
    171 
    172   @param  This         Protocol instance pointer.
    173   @param  BltBuffer    Buffer containing data to blit into video buffer. This
    174                        buffer has a size of Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
    175   @param  BltOperation Operation to perform on BlitBuffer and video memory
    176   @param  SourceX      X coordinate of source for the BltBuffer.
    177   @param  SourceY      Y coordinate of source for the BltBuffer.
    178   @param  DestinationX X coordinate of destination for the BltBuffer.
    179   @param  DestinationY Y coordinate of destination for the BltBuffer.
    180   @param  Width        Width of rectangle in BltBuffer in pixels.
    181   @param  Height       Hight of rectangle in BltBuffer in pixels.
    182   @param  Delta        OPTIONAL
    183 
    184   @retval EFI_SUCCESS           The Blt operation completed.
    185   @retval EFI_INVALID_PARAMETER BltOperation is not valid.
    186   @retval EFI_DEVICE_ERROR      A hardware error occured writting to the video buffer.
    187 
    188 **/
    189 EFI_STATUS
    190 EFIAPI
    191 EmuGopBlt (
    192   IN  EFI_GRAPHICS_OUTPUT_PROTOCOL            *This,
    193   IN  EFI_GRAPHICS_OUTPUT_BLT_PIXEL           *BltBuffer,   OPTIONAL
    194   IN  EFI_GRAPHICS_OUTPUT_BLT_OPERATION       BltOperation,
    195   IN  UINTN                                   SourceX,
    196   IN  UINTN                                   SourceY,
    197   IN  UINTN                                   DestinationX,
    198   IN  UINTN                                   DestinationY,
    199   IN  UINTN                                   Width,
    200   IN  UINTN                                   Height,
    201   IN  UINTN                                   Delta         OPTIONAL
    202   )
    203 {
    204   GOP_PRIVATE_DATA  *Private;
    205   EFI_TPL           OriginalTPL;
    206   EFI_STATUS        Status;
    207   EMU_GRAPHICS_WINDOWS__BLT_ARGS      GopBltArgs;
    208 
    209   Private = GOP_PRIVATE_DATA_FROM_THIS (This);
    210 
    211   if ((UINT32)BltOperation >= EfiGraphicsOutputBltOperationMax) {
    212     return EFI_INVALID_PARAMETER;
    213   }
    214 
    215   if (Width == 0 || Height == 0) {
    216     return EFI_INVALID_PARAMETER;
    217   }
    218   //
    219   // If Delta is zero, then the entire BltBuffer is being used, so Delta
    220   // is the number of bytes in each row of BltBuffer.  Since BltBuffer is Width pixels size,
    221   // the number of bytes in each row can be computed.
    222   //
    223   if (Delta == 0) {
    224     Delta = Width * sizeof (EFI_UGA_PIXEL);
    225   }
    226 
    227   //
    228   // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
    229   // We would not want a timer based event (Cursor, ...) to come in while we are
    230   // doing this operation.
    231   //
    232   OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
    233 
    234   //
    235   // Pack UGA Draw protocol parameters to EMU_GRAPHICS_WINDOWS__BLT_ARGS structure to adapt to
    236   // GopBlt() API of Unix UGA IO protocol.
    237   //
    238   GopBltArgs.DestinationX = DestinationX;
    239   GopBltArgs.DestinationY = DestinationY;
    240   GopBltArgs.Height       = Height;
    241   GopBltArgs.Width        = Width;
    242   GopBltArgs.SourceX      = SourceX;
    243   GopBltArgs.SourceY      = SourceY;
    244   GopBltArgs.Delta        = Delta;
    245   Status = Private->EmuGraphicsWindow->Blt (
    246                             Private->EmuGraphicsWindow,
    247                             (EFI_UGA_PIXEL *)BltBuffer,
    248                             (EFI_UGA_BLT_OPERATION)BltOperation,
    249                             &GopBltArgs
    250                             );
    251 
    252   gBS->RestoreTPL (OriginalTPL);
    253 
    254   return Status;
    255 }
    256 
    257 
    258 //
    259 // Construction and Destruction functions
    260 //
    261 
    262 EFI_STATUS
    263 EmuGopSupported (
    264   IN  EMU_IO_THUNK_PROTOCOL  *EmuIoThunk
    265   )
    266 {
    267   //
    268   // Check to see if the IO abstraction represents a device type we support.
    269   //
    270   // This would be replaced a check of PCI subsystem ID, etc.
    271   //
    272   if (!CompareGuid (EmuIoThunk->Protocol, &gEmuGraphicsWindowProtocolGuid)) {
    273     return EFI_UNSUPPORTED;
    274   }
    275 
    276   return EFI_SUCCESS;
    277 }
    278 
    279 
    280 EFI_STATUS
    281 EmuGopStartWindow (
    282   IN  GOP_PRIVATE_DATA    *Private,
    283   IN  UINT32              HorizontalResolution,
    284   IN  UINT32              VerticalResolution,
    285   IN  UINT32              ColorDepth,
    286   IN  UINT32              RefreshRate
    287   )
    288 {
    289   EFI_STATUS          Status;
    290 
    291   //
    292   // Register to be notified on exit boot services so we can destroy the window.
    293   //
    294   Status = gBS->CreateEvent (
    295                   EVT_SIGNAL_EXIT_BOOT_SERVICES,
    296                   TPL_CALLBACK,
    297                   ShutdownGopEvent,
    298                   Private,
    299                   &mGopScreenExitBootServicesEvent
    300                   );
    301 
    302   Status = Private->EmuIoThunk->Open (Private->EmuIoThunk);
    303   if (!EFI_ERROR (Status)) {
    304     Private->EmuGraphicsWindow = Private->EmuIoThunk->Interface;
    305 
    306     // Register callback to support RegisterKeyNotify()
    307     Status  = Private->EmuGraphicsWindow->RegisterKeyNotify (
    308                                             Private->EmuGraphicsWindow,
    309                                             GopPrivateMakeCallbackFunction,
    310                                             GopPrivateBreakCallbackFunction,
    311                                             Private
    312                                             );
    313     ASSERT_EFI_ERROR (Status);
    314   }
    315   return Status;
    316 }
    317 
    318 EFI_STATUS
    319 EmuGopConstructor (
    320   GOP_PRIVATE_DATA    *Private
    321   )
    322 {
    323   Private->ModeData = mGopModeData;
    324 
    325   Private->GraphicsOutput.QueryMode      = EmuGopQuerytMode;
    326   Private->GraphicsOutput.SetMode        = EmuGopSetMode;
    327   Private->GraphicsOutput.Blt            = EmuGopBlt;
    328 
    329   //
    330   // Allocate buffer for Graphics Output Protocol mode information
    331   //
    332   Private->GraphicsOutput.Mode = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE));
    333   if (Private->GraphicsOutput.Mode == NULL) {
    334     return EFI_OUT_OF_RESOURCES;
    335   }
    336   Private->GraphicsOutput.Mode->Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
    337   if (Private->GraphicsOutput.Mode->Info == NULL) {
    338     return EFI_OUT_OF_RESOURCES;
    339   }
    340 
    341   Private->GraphicsOutput.Mode->MaxMode = sizeof(mGopModeData) / sizeof(GOP_MODE_DATA);
    342   //
    343   // Till now, we have no idea about the window size.
    344   //
    345   Private->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;
    346   Private->GraphicsOutput.Mode->Info->Version = 0;
    347   Private->GraphicsOutput.Mode->Info->HorizontalResolution = 0;
    348   Private->GraphicsOutput.Mode->Info->VerticalResolution = 0;
    349   Private->GraphicsOutput.Mode->Info->PixelFormat = PixelBltOnly;
    350   Private->GraphicsOutput.Mode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
    351   Private->GraphicsOutput.Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) NULL;
    352   Private->GraphicsOutput.Mode->FrameBufferSize = 0;
    353 
    354   Private->HardwareNeedsStarting  = TRUE;
    355   Private->EmuGraphicsWindow                  = NULL;
    356 
    357   EmuGopInitializeSimpleTextInForWindow (Private);
    358 
    359   EmuGopInitializeSimplePointerForWindow (Private);
    360 
    361   return EFI_SUCCESS;
    362 }
    363 
    364 
    365 
    366 EFI_STATUS
    367 EmuGopDestructor (
    368   GOP_PRIVATE_DATA     *Private
    369   )
    370 {
    371   if (!Private->HardwareNeedsStarting) {
    372     Private->EmuIoThunk->Close (Private->EmuIoThunk);
    373     Private->EmuGraphicsWindow = NULL;
    374   }
    375 
    376   //
    377   // Free graphics output protocol occupied resource
    378   //
    379   if (Private->GraphicsOutput.Mode != NULL) {
    380     if (Private->GraphicsOutput.Mode->Info != NULL) {
    381       FreePool (Private->GraphicsOutput.Mode->Info);
    382     }
    383     FreePool (Private->GraphicsOutput.Mode);
    384   }
    385 
    386   return EFI_SUCCESS;
    387 }
    388 
    389 
    390 VOID
    391 EFIAPI
    392 ShutdownGopEvent (
    393   IN EFI_EVENT  Event,
    394   IN VOID       *Context
    395   )
    396 /*++
    397 
    398 Routine Description:
    399 
    400   This is the UGA screen's callback notification function for exit-boot-services.
    401   All we do here is call EmuGopDestructor().
    402 
    403 Arguments:
    404 
    405   Event   - not used
    406   Context - pointer to the Private structure.
    407 
    408 Returns:
    409 
    410   None.
    411 
    412 **/
    413 {
    414   EmuGopDestructor (Context);
    415 }
    416 
    417