Home | History | Annotate | Download | only in EmuGopDxe
      1 /*++ @file
      2 
      3 Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
      4 Portions copyright (c) 2010,Apple Inc. All rights reserved.<BR>
      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 
     14 **/
     15 
     16 #include "Gop.h"
     17 
     18 
     19 EFI_STATUS
     20 FreeNotifyList (
     21   IN OUT LIST_ENTRY           *ListHead
     22   )
     23 /*++
     24 
     25 Routine Description:
     26 
     27 Arguments:
     28 
     29   ListHead   - The list head
     30 
     31 Returns:
     32 
     33   EFI_SUCCESS           - Free the notify list successfully
     34   EFI_INVALID_PARAMETER - ListHead is invalid.
     35 
     36 **/
     37 {
     38   EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY *NotifyNode;
     39 
     40   if (ListHead == NULL) {
     41     return EFI_INVALID_PARAMETER;
     42   }
     43   while (!IsListEmpty (ListHead)) {
     44     NotifyNode = CR (
     45                    ListHead->ForwardLink,
     46                    EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY,
     47                    NotifyEntry,
     48                    EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE
     49                    );
     50     RemoveEntryList (ListHead->ForwardLink);
     51     gBS->FreePool (NotifyNode);
     52   }
     53 
     54   return EFI_SUCCESS;
     55 }
     56 
     57 
     58 /**
     59   Tests to see if this driver supports a given controller. If a child device is provided,
     60   it further tests to see if this driver supports creating a handle for the specified child device.
     61 
     62   This function checks to see if the driver specified by This supports the device specified by
     63   ControllerHandle. Drivers will typically use the device path attached to
     64   ControllerHandle and/or the services from the bus I/O abstraction attached to
     65   ControllerHandle to determine if the driver supports ControllerHandle. This function
     66   may be called many times during platform initialization. In order to reduce boot times, the tests
     67   performed by this function must be very small, and take as little time as possible to execute. This
     68   function must not change the state of any hardware devices, and this function must be aware that the
     69   device specified by ControllerHandle may already be managed by the same driver or a
     70   different driver. This function must match its calls to AllocatePages() with FreePages(),
     71   AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
     72   Because ControllerHandle may have been previously started by the same driver, if a protocol is
     73   already in the opened state, then it must not be closed with CloseProtocol(). This is required
     74   to guarantee the state of ControllerHandle is not modified by this function.
     75 
     76   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
     77   @param[in]  ControllerHandle     The handle of the controller to test. This handle
     78                                    must support a protocol interface that supplies
     79                                    an I/O abstraction to the driver.
     80   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
     81                                    parameter is ignored by device drivers, and is optional for bus
     82                                    drivers. For bus drivers, if this parameter is not NULL, then
     83                                    the bus driver must determine if the bus controller specified
     84                                    by ControllerHandle and the child controller specified
     85                                    by RemainingDevicePath are both supported by this
     86                                    bus driver.
     87 
     88   @retval EFI_SUCCESS              The device specified by ControllerHandle and
     89                                    RemainingDevicePath is supported by the driver specified by This.
     90   @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle and
     91                                    RemainingDevicePath is already being managed by the driver
     92                                    specified by This.
     93   @retval EFI_ACCESS_DENIED        The device specified by ControllerHandle and
     94                                    RemainingDevicePath is already being managed by a different
     95                                    driver or an application that requires exclusive access.
     96                                    Currently not implemented.
     97   @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and
     98                                    RemainingDevicePath is not supported by the driver specified by This.
     99 **/
    100 EFI_STATUS
    101 EFIAPI
    102 EmuGopDriverBindingSupported (
    103   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
    104   IN  EFI_HANDLE                      Handle,
    105   IN  EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath
    106   )
    107 {
    108   EFI_STATUS              Status;
    109   EMU_IO_THUNK_PROTOCOL   *EmuIoThunk;
    110 
    111   //
    112   // Open the IO Abstraction(s) needed to perform the supported test
    113   //
    114   Status = gBS->OpenProtocol (
    115                   Handle,
    116                   &gEmuIoThunkProtocolGuid,
    117                   (VOID **)&EmuIoThunk,
    118                   This->DriverBindingHandle,
    119                   Handle,
    120                   EFI_OPEN_PROTOCOL_BY_DRIVER
    121                   );
    122   if (EFI_ERROR (Status)) {
    123     return Status;
    124   }
    125 
    126   Status = EmuGopSupported (EmuIoThunk);
    127 
    128   //
    129   // Close the I/O Abstraction(s) used to perform the supported test
    130   //
    131   gBS->CloseProtocol (
    132         Handle,
    133         &gEmuIoThunkProtocolGuid,
    134         This->DriverBindingHandle,
    135         Handle
    136         );
    137 
    138   return Status;
    139 }
    140 
    141 
    142 /**
    143   Starts a device controller or a bus controller.
    144 
    145   The Start() function is designed to be invoked from the EFI boot service ConnectController().
    146   As a result, much of the error checking on the parameters to Start() has been moved into this
    147   common boot service. It is legal to call Start() from other locations,
    148   but the following calling restrictions must be followed, or the system behavior will not be deterministic.
    149   1. ControllerHandle must be a valid EFI_HANDLE.
    150   2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
    151      EFI_DEVICE_PATH_PROTOCOL.
    152   3. Prior to calling Start(), the Supported() function for the driver specified by This must
    153      have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
    154 
    155   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
    156   @param[in]  ControllerHandle     The handle of the controller to start. This handle
    157                                    must support a protocol interface that supplies
    158                                    an I/O abstraction to the driver.
    159   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
    160                                    parameter is ignored by device drivers, and is optional for bus
    161                                    drivers. For a bus driver, if this parameter is NULL, then handles
    162                                    for all the children of Controller are created by this driver.
    163                                    If this parameter is not NULL and the first Device Path Node is
    164                                    not the End of Device Path Node, then only the handle for the
    165                                    child device specified by the first Device Path Node of
    166                                    RemainingDevicePath is created by this driver.
    167                                    If the first Device Path Node of RemainingDevicePath is
    168                                    the End of Device Path Node, no child handle is created by this
    169                                    driver.
    170 
    171   @retval EFI_SUCCESS              The device was started.
    172   @retval EFI_DEVICE_ERROR         The device could not be started due to a device error.Currently not implemented.
    173   @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
    174   @retval Others                   The driver failded to start the device.
    175 
    176 **/
    177 EFI_STATUS
    178 EFIAPI
    179 EmuGopDriverBindingStart (
    180   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
    181   IN  EFI_HANDLE                      Handle,
    182   IN  EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath
    183   )
    184 {
    185   EMU_IO_THUNK_PROTOCOL   *EmuIoThunk;
    186   EFI_STATUS              Status;
    187   GOP_PRIVATE_DATA        *Private;
    188 
    189   //
    190   // Grab the protocols we need
    191   //
    192   Status = gBS->OpenProtocol (
    193                   Handle,
    194                   &gEmuIoThunkProtocolGuid,
    195                   (VOID **)&EmuIoThunk,
    196                   This->DriverBindingHandle,
    197                   Handle,
    198                   EFI_OPEN_PROTOCOL_BY_DRIVER
    199                   );
    200   if (EFI_ERROR (Status)) {
    201     return EFI_UNSUPPORTED;
    202   }
    203 
    204   //
    205   // Allocate Private context data for SGO inteface.
    206   //
    207   Private = NULL;
    208   Status = gBS->AllocatePool (
    209                   EfiBootServicesData,
    210                   sizeof (GOP_PRIVATE_DATA),
    211                   (VOID **)&Private
    212                   );
    213   if (EFI_ERROR (Status)) {
    214     goto Done;
    215   }
    216   //
    217   // Set up context record
    218   //
    219   Private->Signature           = GOP_PRIVATE_DATA_SIGNATURE;
    220   Private->Handle              = Handle;
    221   Private->EmuIoThunk          = EmuIoThunk;
    222   Private->WindowName          = EmuIoThunk->ConfigString;
    223   Private->ControllerNameTable = NULL;
    224 
    225   AddUnicodeString (
    226     "eng",
    227     gEmuGopComponentName.SupportedLanguages,
    228     &Private->ControllerNameTable,
    229     EmuIoThunk->ConfigString
    230     );
    231   AddUnicodeString2 (
    232     "en",
    233     gEmuGopComponentName2.SupportedLanguages,
    234     &Private->ControllerNameTable,
    235     EmuIoThunk->ConfigString,
    236     FALSE
    237     );
    238 
    239   Status = EmuGopConstructor (Private);
    240   if (EFI_ERROR (Status)) {
    241     goto Done;
    242   }
    243   //
    244   // Publish the Gop interface to the world
    245   //
    246   Status = gBS->InstallMultipleProtocolInterfaces (
    247                   &Private->Handle,
    248                   &gEfiGraphicsOutputProtocolGuid,    &Private->GraphicsOutput,
    249                   &gEfiSimpleTextInProtocolGuid,      &Private->SimpleTextIn,
    250                   &gEfiSimplePointerProtocolGuid,     &Private->SimplePointer,
    251                   &gEfiSimpleTextInputExProtocolGuid, &Private->SimpleTextInEx,
    252                   NULL
    253                   );
    254 
    255 Done:
    256   if (EFI_ERROR (Status)) {
    257 
    258     gBS->CloseProtocol (
    259           Handle,
    260           &gEmuIoThunkProtocolGuid,
    261           This->DriverBindingHandle,
    262           Handle
    263           );
    264 
    265     if (Private != NULL) {
    266       //
    267       // On Error Free back private data
    268       //
    269       if (Private->ControllerNameTable != NULL) {
    270         FreeUnicodeStringTable (Private->ControllerNameTable);
    271       }
    272       if (Private->SimpleTextIn.WaitForKey != NULL) {
    273         gBS->CloseEvent (Private->SimpleTextIn.WaitForKey);
    274       }
    275       if (Private->SimpleTextInEx.WaitForKeyEx != NULL) {
    276         gBS->CloseEvent (Private->SimpleTextInEx.WaitForKeyEx);
    277       }
    278       FreeNotifyList (&Private->NotifyList);
    279 
    280       gBS->FreePool (Private);
    281     }
    282   }
    283 
    284   return Status;
    285 }
    286 
    287 
    288 
    289 /**
    290   Stops a device controller or a bus controller.
    291 
    292   The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
    293   As a result, much of the error checking on the parameters to Stop() has been moved
    294   into this common boot service. It is legal to call Stop() from other locations,
    295   but the following calling restrictions must be followed, or the system behavior will not be deterministic.
    296   1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
    297      same driver's Start() function.
    298   2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
    299      EFI_HANDLE. In addition, all of these handles must have been created in this driver's
    300      Start() function, and the Start() function must have called OpenProtocol() on
    301      ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
    302 
    303   @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
    304   @param[in]  ControllerHandle  A handle to the device being stopped. The handle must
    305                                 support a bus specific I/O protocol for the driver
    306                                 to use to stop the device.
    307   @param[in]  NumberOfChildren  The number of child device handles in ChildHandleBuffer.
    308   @param[in]  ChildHandleBuffer An array of child handles to be freed. May be NULL
    309                                 if NumberOfChildren is 0.
    310 
    311   @retval EFI_SUCCESS           The device was stopped.
    312   @retval EFI_DEVICE_ERROR      The device could not be stopped due to a device error.
    313 
    314 **/
    315 EFI_STATUS
    316 EFIAPI
    317 EmuGopDriverBindingStop (
    318   IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
    319   IN  EFI_HANDLE                   Handle,
    320   IN  UINTN                        NumberOfChildren,
    321   IN  EFI_HANDLE                   *ChildHandleBuffer
    322   )
    323 {
    324   EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
    325   EFI_STATUS                   Status;
    326   GOP_PRIVATE_DATA             *Private;
    327 
    328   Status = gBS->OpenProtocol (
    329                   Handle,
    330                   &gEfiGraphicsOutputProtocolGuid,
    331                   (VOID **)&GraphicsOutput,
    332                   This->DriverBindingHandle,
    333                   Handle,
    334                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    335                   );
    336   if (EFI_ERROR (Status)) {
    337     //
    338     // If the GOP interface does not exist the driver is not started
    339     //
    340     return EFI_NOT_STARTED;
    341   }
    342 
    343   //
    344   // Get our private context information
    345   //
    346   Private = GOP_PRIVATE_DATA_FROM_THIS (GraphicsOutput);
    347 
    348   //
    349   // Remove the SGO interface from the system
    350   //
    351   Status = gBS->UninstallMultipleProtocolInterfaces (
    352                   Private->Handle,
    353                   &gEfiGraphicsOutputProtocolGuid,    &Private->GraphicsOutput,
    354                   &gEfiSimpleTextInProtocolGuid,      &Private->SimpleTextIn,
    355                   &gEfiSimplePointerProtocolGuid,     &Private->SimplePointer,
    356                   &gEfiSimpleTextInputExProtocolGuid, &Private->SimpleTextInEx,
    357                   NULL
    358                   );
    359   if (!EFI_ERROR (Status)) {
    360     //
    361     // Shutdown the hardware
    362     //
    363     Status = EmuGopDestructor (Private);
    364     if (EFI_ERROR (Status)) {
    365       return EFI_DEVICE_ERROR;
    366     }
    367 
    368     gBS->CloseProtocol (
    369           Handle,
    370           &gEmuIoThunkProtocolGuid,
    371           This->DriverBindingHandle,
    372           Handle
    373           );
    374 
    375     //
    376     // Free our instance data
    377     //
    378     FreeUnicodeStringTable (Private->ControllerNameTable);
    379 
    380     Status = gBS->CloseEvent (Private->SimpleTextIn.WaitForKey);
    381     ASSERT_EFI_ERROR (Status);
    382 
    383     Status = gBS->CloseEvent (Private->SimpleTextInEx.WaitForKeyEx);
    384     ASSERT_EFI_ERROR (Status);
    385 
    386     FreeNotifyList (&Private->NotifyList);
    387 
    388     gBS->FreePool (Private);
    389 
    390   }
    391 
    392   return Status;
    393 }
    394 
    395 
    396 ///
    397 /// This protocol provides the services required to determine if a driver supports a given controller.
    398 /// If a controller is supported, then it also provides routines to start and stop the controller.
    399 ///
    400 EFI_DRIVER_BINDING_PROTOCOL gEmuGopDriverBinding = {
    401   EmuGopDriverBindingSupported,
    402   EmuGopDriverBindingStart,
    403   EmuGopDriverBindingStop,
    404   0xa,
    405   NULL,
    406   NULL
    407 };
    408 
    409 
    410 
    411 /**
    412   The user Entry Point for module EmuGop. The user code starts with this function.
    413 
    414   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
    415   @param[in] SystemTable    A pointer to the EFI System Table.
    416 
    417   @retval EFI_SUCCESS       The entry point is executed successfully.
    418   @retval other             Some error occurs when executing this entry point.
    419 
    420 **/
    421 EFI_STATUS
    422 EFIAPI
    423 InitializeEmuGop (
    424   IN EFI_HANDLE           ImageHandle,
    425   IN EFI_SYSTEM_TABLE     *SystemTable
    426   )
    427 {
    428   EFI_STATUS              Status;
    429 
    430   Status = EfiLibInstallDriverBindingComponentName2 (
    431              ImageHandle,
    432              SystemTable,
    433              &gEmuGopDriverBinding,
    434              ImageHandle,
    435              &gEmuGopComponentName,
    436              &gEmuGopComponentName2
    437              );
    438   ASSERT_EFI_ERROR (Status);
    439 
    440 
    441   return Status;
    442 }
    443 
    444