Home | History | Annotate | Download | only in XenPvBlkDxe
      1 /** @file
      2   This driver produce a BlockIo protocol instance for a Xen PV block device.
      3 
      4   This driver support XenBus protocol of type 'vbd'. Every function that
      5   comsume XenBus protocol are in BlockFront, which the implementation to access
      6   a Xen PV device. The BlockIo implementation is in it's one file and will call
      7   BlockFront functions.
      8 
      9   Copyright (C) 2014, Citrix Ltd.
     10 
     11   This program and the accompanying materials
     12   are licensed and made available under the terms and conditions of the BSD License
     13   which accompanies this distribution.  The full text of the license may be found at
     14   http://opensource.org/licenses/bsd-license.php
     15 
     16   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     17   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     18 
     19 **/
     20 
     21 #include "XenPvBlkDxe.h"
     22 
     23 #include "BlockFront.h"
     24 
     25 
     26 ///
     27 /// Driver Binding Protocol instance
     28 ///
     29 EFI_DRIVER_BINDING_PROTOCOL gXenPvBlkDxeDriverBinding = {
     30   XenPvBlkDxeDriverBindingSupported,
     31   XenPvBlkDxeDriverBindingStart,
     32   XenPvBlkDxeDriverBindingStop,
     33   XEN_PV_BLK_DXE_VERSION,
     34   NULL,
     35   NULL
     36 };
     37 
     38 
     39 /**
     40   Unloads an image.
     41 
     42   @param  ImageHandle           Handle that identifies the image to be unloaded.
     43 
     44   @retval EFI_SUCCESS           The image has been unloaded.
     45   @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle.
     46 
     47 **/
     48 EFI_STATUS
     49 EFIAPI
     50 XenPvBlkDxeUnload (
     51   IN EFI_HANDLE  ImageHandle
     52   )
     53 {
     54   EFI_STATUS  Status;
     55 
     56   EFI_HANDLE  *HandleBuffer;
     57   UINTN       HandleCount;
     58   UINTN       Index;
     59 
     60 
     61   //
     62   // Retrieve array of all handles in the handle database
     63   //
     64   Status = gBS->LocateHandleBuffer (
     65                   AllHandles,
     66                   NULL,
     67                   NULL,
     68                   &HandleCount,
     69                   &HandleBuffer
     70                   );
     71   if (EFI_ERROR (Status)) {
     72     return Status;
     73   }
     74 
     75   //
     76   // Disconnect the current driver from handles in the handle database
     77   //
     78   for (Index = 0; Index < HandleCount; Index++) {
     79     gBS->DisconnectController (HandleBuffer[Index], gImageHandle, NULL);
     80   }
     81 
     82   //
     83   // Free the array of handles
     84   //
     85   FreePool (HandleBuffer);
     86 
     87 
     88   //
     89   // Uninstall protocols installed in the driver entry point
     90   //
     91   Status = gBS->UninstallMultipleProtocolInterfaces (
     92                   ImageHandle,
     93                   &gEfiDriverBindingProtocolGuid, &gXenPvBlkDxeDriverBinding,
     94                   &gEfiComponentNameProtocolGuid,  &gXenPvBlkDxeComponentName,
     95                   &gEfiComponentName2ProtocolGuid, &gXenPvBlkDxeComponentName2,
     96                   NULL
     97                   );
     98   if (EFI_ERROR (Status)) {
     99     return Status;
    100   }
    101 
    102   return EFI_SUCCESS;
    103 }
    104 
    105 /**
    106   This is the declaration of an EFI image entry point. This entry point is
    107   the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
    108   both device drivers and bus drivers.
    109 
    110   @param  ImageHandle           The firmware allocated handle for the UEFI image.
    111   @param  SystemTable           A pointer to the EFI System Table.
    112 
    113   @retval EFI_SUCCESS           The operation completed successfully.
    114   @retval Others                An unexpected error occurred.
    115 **/
    116 EFI_STATUS
    117 EFIAPI
    118 XenPvBlkDxeDriverEntryPoint (
    119   IN EFI_HANDLE        ImageHandle,
    120   IN EFI_SYSTEM_TABLE  *SystemTable
    121   )
    122 {
    123   EFI_STATUS  Status;
    124 
    125   //
    126   // Install UEFI Driver Model protocol(s).
    127   //
    128   Status = EfiLibInstallDriverBindingComponentName2 (
    129              ImageHandle,
    130              SystemTable,
    131              &gXenPvBlkDxeDriverBinding,
    132              ImageHandle,
    133              &gXenPvBlkDxeComponentName,
    134              &gXenPvBlkDxeComponentName2
    135              );
    136   ASSERT_EFI_ERROR (Status);
    137 
    138   return Status;
    139 }
    140 
    141 
    142 /**
    143   Tests to see if this driver supports a given controller. If a child device is provided,
    144   it further tests to see if this driver supports creating a handle for the specified child device.
    145 
    146   This function checks to see if the driver specified by This supports the device specified by
    147   ControllerHandle. Drivers will typically use the device path attached to
    148   ControllerHandle and/or the services from the bus I/O abstraction attached to
    149   ControllerHandle to determine if the driver supports ControllerHandle. This function
    150   may be called many times during platform initialization. In order to reduce boot times, the tests
    151   performed by this function must be very small, and take as little time as possible to execute. This
    152   function must not change the state of any hardware devices, and this function must be aware that the
    153   device specified by ControllerHandle may already be managed by the same driver or a
    154   different driver. This function must match its calls to AllocatePages() with FreePages(),
    155   AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
    156   Because ControllerHandle may have been previously started by the same driver, if a protocol is
    157   already in the opened state, then it must not be closed with CloseProtocol(). This is required
    158   to guarantee the state of ControllerHandle is not modified by this function.
    159 
    160   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
    161   @param[in]  ControllerHandle     The handle of the controller to test. This handle
    162                                    must support a protocol interface that supplies
    163                                    an I/O abstraction to the driver.
    164   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
    165                                    parameter is ignored by device drivers, and is optional for bus
    166                                    drivers. For bus drivers, if this parameter is not NULL, then
    167                                    the bus driver must determine if the bus controller specified
    168                                    by ControllerHandle and the child controller specified
    169                                    by RemainingDevicePath are both supported by this
    170                                    bus driver.
    171 
    172   @retval EFI_SUCCESS              The device specified by ControllerHandle and
    173                                    RemainingDevicePath is supported by the driver specified by This.
    174   @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle and
    175                                    RemainingDevicePath is already being managed by the driver
    176                                    specified by This.
    177   @retval EFI_ACCESS_DENIED        The device specified by ControllerHandle and
    178                                    RemainingDevicePath is already being managed by a different
    179                                    driver or an application that requires exclusive access.
    180                                    Currently not implemented.
    181   @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and
    182                                    RemainingDevicePath is not supported by the driver specified by This.
    183 **/
    184 EFI_STATUS
    185 EFIAPI
    186 XenPvBlkDxeDriverBindingSupported (
    187   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    188   IN EFI_HANDLE                   ControllerHandle,
    189   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
    190   )
    191 {
    192   EFI_STATUS Status;
    193   XENBUS_PROTOCOL *XenBusIo;
    194 
    195   Status = gBS->OpenProtocol (
    196                 ControllerHandle,
    197                 &gXenBusProtocolGuid,
    198                 (VOID **)&XenBusIo,
    199                 This->DriverBindingHandle,
    200                 ControllerHandle,
    201                 EFI_OPEN_PROTOCOL_BY_DRIVER
    202                 );
    203   if (EFI_ERROR (Status)) {
    204     return Status;
    205   }
    206   if (AsciiStrCmp (XenBusIo->Type, "vbd") == 0) {
    207     Status = EFI_SUCCESS;
    208   } else {
    209     Status = EFI_UNSUPPORTED;
    210   }
    211 
    212   gBS->CloseProtocol (ControllerHandle, &gXenBusProtocolGuid,
    213                       This->DriverBindingHandle, ControllerHandle);
    214 
    215   return Status;
    216 }
    217 
    218 /**
    219   Starts a device controller.
    220 
    221   The Start() function is designed to be invoked from the EFI boot service ConnectController().
    222   As a result, much of the error checking on the parameters to Start() has been moved into this
    223   common boot service. It is legal to call Start() from other locations,
    224   but the following calling restrictions must be followed, or the system behavior will not be deterministic.
    225   1. ControllerHandle must be a valid EFI_HANDLE.
    226   2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
    227      EFI_DEVICE_PATH_PROTOCOL.
    228   3. Prior to calling Start(), the Supported() function for the driver specified by This must
    229      have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
    230 
    231   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
    232   @param[in]  ControllerHandle     The handle of the controller to start. This handle
    233                                    must support a protocol interface that supplies
    234                                    an I/O abstraction to the driver.
    235   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
    236                                    parameter is ignored by device drivers, and is optional for bus
    237                                    drivers. For a bus driver, if this parameter is NULL, then handles
    238                                    for all the children of Controller are created by this driver.
    239                                    If this parameter is not NULL and the first Device Path Node is
    240                                    not the End of Device Path Node, then only the handle for the
    241                                    child device specified by the first Device Path Node of
    242                                    RemainingDevicePath is created by this driver.
    243                                    If the first Device Path Node of RemainingDevicePath is
    244                                    the End of Device Path Node, no child handle is created by this
    245                                    driver.
    246 
    247   @retval EFI_SUCCESS              The device was started.
    248   @retval EFI_DEVICE_ERROR         The device could not be started due to a device error.Currently not implemented.
    249   @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
    250   @retval Others                   The driver failded to start the device.
    251 
    252 **/
    253 EFI_STATUS
    254 EFIAPI
    255 XenPvBlkDxeDriverBindingStart (
    256   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    257   IN EFI_HANDLE                   ControllerHandle,
    258   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
    259   )
    260 {
    261   EFI_STATUS Status;
    262   XENBUS_PROTOCOL *XenBusIo;
    263   XEN_BLOCK_FRONT_DEVICE *Dev;
    264   EFI_BLOCK_IO_MEDIA *Media;
    265 
    266   Status = gBS->OpenProtocol (
    267                 ControllerHandle,
    268                 &gXenBusProtocolGuid,
    269                 (VOID **)&XenBusIo,
    270                 This->DriverBindingHandle,
    271                 ControllerHandle,
    272                 EFI_OPEN_PROTOCOL_BY_DRIVER
    273                 );
    274   if (EFI_ERROR (Status)) {
    275     return Status;
    276   }
    277 
    278   Status = XenPvBlockFrontInitialization (XenBusIo, XenBusIo->Node, &Dev);
    279   if (EFI_ERROR (Status)) {
    280     goto CloseProtocol;
    281   }
    282 
    283   CopyMem (&Dev->BlockIo, &gXenPvBlkDxeBlockIo, sizeof (EFI_BLOCK_IO_PROTOCOL));
    284   Media = AllocateCopyPool (sizeof (EFI_BLOCK_IO_MEDIA),
    285                             &gXenPvBlkDxeBlockIoMedia);
    286   if (Dev->MediaInfo.VDiskInfo & VDISK_REMOVABLE) {
    287     Media->RemovableMedia = TRUE;
    288   }
    289   Media->MediaPresent = TRUE;
    290   Media->ReadOnly = !Dev->MediaInfo.ReadWrite;
    291   if (Dev->MediaInfo.CdRom) {
    292     //
    293     // If it's a cdrom, the blocksize value need to be 2048 for OVMF to
    294     // recognize it as a cdrom:
    295     //    MdeModulePkg/Universal/Disk/PartitionDxe/ElTorito.c
    296     //
    297     Media->BlockSize = 2048;
    298     Media->LastBlock = DivU64x32 (Dev->MediaInfo.Sectors,
    299                                   Media->BlockSize / Dev->MediaInfo.SectorSize) - 1;
    300   } else {
    301     Media->BlockSize = Dev->MediaInfo.SectorSize;
    302     Media->LastBlock = Dev->MediaInfo.Sectors - 1;
    303   }
    304   ASSERT (Media->BlockSize % 512 == 0);
    305   Dev->BlockIo.Media = Media;
    306 
    307   Status = gBS->InstallMultipleProtocolInterfaces (
    308                     &ControllerHandle,
    309                     &gEfiBlockIoProtocolGuid, &Dev->BlockIo,
    310                     NULL
    311                     );
    312   if (EFI_ERROR (Status)) {
    313     DEBUG ((EFI_D_ERROR, "XenPvBlk: install protocol fail: %r\n", Status));
    314     goto UninitBlockFront;
    315   }
    316 
    317   return EFI_SUCCESS;
    318 
    319 UninitBlockFront:
    320   FreePool (Media);
    321   XenPvBlockFrontShutdown (Dev);
    322 CloseProtocol:
    323   gBS->CloseProtocol (ControllerHandle, &gXenBusProtocolGuid,
    324                       This->DriverBindingHandle, ControllerHandle);
    325   return Status;
    326 }
    327 
    328 /**
    329   Stops a device controller.
    330 
    331   The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
    332   As a result, much of the error checking on the parameters to Stop() has been moved
    333   into this common boot service. It is legal to call Stop() from other locations,
    334   but the following calling restrictions must be followed, or the system behavior will not be deterministic.
    335   1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
    336      same driver's Start() function.
    337   2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
    338      EFI_HANDLE. In addition, all of these handles must have been created in this driver's
    339      Start() function, and the Start() function must have called OpenProtocol() on
    340      ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
    341 
    342   @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
    343   @param[in]  ControllerHandle  A handle to the device being stopped. The handle must
    344                                 support a bus specific I/O protocol for the driver
    345                                 to use to stop the device.
    346   @param[in]  NumberOfChildren  The number of child device handles in ChildHandleBuffer.
    347   @param[in]  ChildHandleBuffer An array of child handles to be freed. May be NULL
    348                                 if NumberOfChildren is 0.
    349 
    350   @retval EFI_SUCCESS           The device was stopped.
    351   @retval EFI_DEVICE_ERROR      The device could not be stopped due to a device error.
    352 
    353 **/
    354 EFI_STATUS
    355 EFIAPI
    356 XenPvBlkDxeDriverBindingStop (
    357   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    358   IN EFI_HANDLE                   ControllerHandle,
    359   IN UINTN                        NumberOfChildren,
    360   IN EFI_HANDLE                   *ChildHandleBuffer OPTIONAL
    361   )
    362 {
    363   EFI_BLOCK_IO_PROTOCOL *BlockIo;
    364   XEN_BLOCK_FRONT_DEVICE *Dev;
    365   EFI_BLOCK_IO_MEDIA *Media;
    366   EFI_STATUS Status;
    367 
    368   Status = gBS->OpenProtocol (
    369                   ControllerHandle, &gEfiBlockIoProtocolGuid,
    370                   (VOID **)&BlockIo,
    371                   This->DriverBindingHandle, ControllerHandle,
    372                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    373                   );
    374   if (EFI_ERROR (Status)) {
    375     return Status;
    376   }
    377 
    378   Status = gBS->UninstallProtocolInterface (ControllerHandle,
    379                   &gEfiBlockIoProtocolGuid, BlockIo);
    380   if (EFI_ERROR (Status)) {
    381     return Status;
    382   }
    383 
    384   Media = BlockIo->Media;
    385   Dev = XEN_BLOCK_FRONT_FROM_BLOCK_IO (BlockIo);
    386   XenPvBlockFrontShutdown (Dev);
    387 
    388   FreePool (Media);
    389 
    390   gBS->CloseProtocol (ControllerHandle, &gXenBusProtocolGuid,
    391          This->DriverBindingHandle, ControllerHandle);
    392 
    393   return EFI_SUCCESS;
    394 }
    395