Home | History | Annotate | Download | only in BlockMmioToBlockIoDxe
      1 /** @file
      2   The driver wrappers BlockMmio protocol instances to produce
      3   Block I/O Protocol instances.
      4 
      5   Copyright (c) 2007 - 2012, Intel Corporation. All rights reserved.<BR>
      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 "BlockIo.h"
     17 
     18 EFI_DRIVER_BINDING_PROTOCOL gBlockIoDriverBinding = {
     19   BlockIoDriverBindingSupported,
     20   BlockIoDriverBindingStart,
     21   BlockIoDriverBindingStop,
     22   0x11,
     23   NULL,
     24   NULL
     25 };
     26 
     27 /**
     28   Reset the block device.
     29 
     30   This function implements EFI_BLOCK_IO_PROTOCOL.Reset().
     31   It resets the block device hardware.
     32   ExtendedVerification is ignored in this implementation.
     33 
     34   @param  This                   Indicates a pointer to the calling context.
     35   @param  ExtendedVerification   Indicates that the driver may perform a more exhaustive
     36                                  verification operation of the device during reset.
     37 
     38   @retval EFI_SUCCESS            The block device was reset.
     39   @retval EFI_DEVICE_ERROR       The block device is not functioning correctly and could not be reset.
     40 
     41 **/
     42 EFI_STATUS
     43 EFIAPI
     44 BlockIoReset (
     45   IN EFI_BLOCK_IO_PROTOCOL    *This,
     46   IN BOOLEAN                  ExtendedVerification
     47   )
     48 {
     49   return EFI_SUCCESS;
     50 }
     51 
     52 /**
     53   Reads the requested number of blocks from the device.
     54 
     55   This function implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks().
     56   It reads the requested number of blocks from the device.
     57   All the blocks are read, or an error is returned.
     58 
     59   @param  This                   Indicates a pointer to the calling context.
     60   @param  ReadData               If TRUE then read data.  If FALSE then write data.
     61   @param  MediaId                The media ID that the read request is for.
     62   @param  Lba                    The starting logical block address to read from on the device.
     63   @param  BufferSize             The size of the Buffer in bytes.
     64                                  This must be a multiple of the intrinsic block size of the device.
     65   @param  Buffer                 A pointer to the destination buffer for the data. The caller is
     66                                  responsible for either having implicit or explicit ownership of the buffer.
     67 
     68   @retval EFI_SUCCESS            The data was read correctly from the device.
     69   @retval EFI_DEVICE_ERROR       The device reported an error while attempting to perform the read operation.
     70   @retval EFI_NO_MEDIA           There is no media in the device.
     71   @retval EFI_MEDIA_CHANGED      The MediaId is not for the current media.
     72   @retval EFI_BAD_BUFFER_SIZE    The BufferSize parameter is not a multiple of the intrinsic block size of the device.
     73   @retval EFI_INVALID_PARAMETER  The read request contains LBAs that are not valid,
     74                                  or the buffer is not on proper alignment.
     75 
     76 **/
     77 EFI_STATUS
     78 EFIAPI
     79 ReadOrWriteBlocks (
     80   IN EFI_BLOCK_IO_PROTOCOL    *This,
     81   IN BOOLEAN                  ReadData,
     82   IN UINT32                   MediaId,
     83   IN EFI_LBA                  Lba,
     84   IN UINTN                    BufferSize,
     85   OUT VOID                    *Buffer
     86   )
     87 {
     88   EFI_STATUS                    Status;
     89   BLOCK_MMIO_TO_BLOCK_IO_DEVICE *Private;
     90   UINTN                         TotalBlock;
     91   EFI_BLOCK_IO_MEDIA            *Media;
     92   UINT64                        Address;
     93   UINTN                         Count;
     94   EFI_CPU_IO_PROTOCOL_IO_MEM    CpuAccessFunction;
     95 
     96   //
     97   // First, validate the parameters
     98   //
     99   if ((Buffer == NULL) || (BufferSize == 0)) {
    100     return EFI_INVALID_PARAMETER;
    101   }
    102 
    103   //
    104   // Get private data structure
    105   //
    106   Private = PRIVATE_FROM_BLOCK_IO (This);
    107   Media   = Private->BlockMmio->Media;
    108 
    109   //
    110   // BufferSize must be a multiple of the intrinsic block size of the device.
    111   //
    112   if (ModU64x32 (BufferSize, Media->BlockSize) != 0) {
    113     return EFI_BAD_BUFFER_SIZE;
    114   }
    115 
    116   TotalBlock = (UINTN) DivU64x32 (BufferSize, Media->BlockSize);
    117 
    118   //
    119   // Make sure the range to read is valid.
    120   //
    121   if (Lba + TotalBlock - 1 > Media->LastBlock) {
    122     return EFI_INVALID_PARAMETER;
    123   }
    124 
    125   if (!(Media->MediaPresent)) {
    126     return EFI_NO_MEDIA;
    127   }
    128 
    129   if (MediaId != Media->MediaId) {
    130     return EFI_MEDIA_CHANGED;
    131   }
    132 
    133   Address = Private->BlockMmio->BaseAddress;
    134   Address += MultU64x32 (Lba, Media->BlockSize);
    135 
    136   Count = BufferSize >> 3;
    137 
    138   if (ReadData) {
    139     CpuAccessFunction = Private->CpuIo->Mem.Read;
    140   } else {
    141     CpuAccessFunction = Private->CpuIo->Mem.Write;
    142   }
    143 
    144   Status = (CpuAccessFunction) (
    145              Private->CpuIo,
    146              EfiCpuIoWidthUint64,
    147              Address,
    148              Count,
    149              Buffer
    150              );
    151 
    152   return Status;
    153 }
    154 
    155 
    156 /**
    157   Reads the requested number of blocks from the device.
    158 
    159   This function implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks().
    160   It reads the requested number of blocks from the device.
    161   All the blocks are read, or an error is returned.
    162 
    163   @param  This                   Indicates a pointer to the calling context.
    164   @param  MediaId                The media ID that the read request is for.
    165   @param  Lba                    The starting logical block address to read from on the device.
    166   @param  BufferSize             The size of the Buffer in bytes.
    167                                  This must be a multiple of the intrinsic block size of the device.
    168   @param  Buffer                 A pointer to the destination buffer for the data. The caller is
    169                                  responsible for either having implicit or explicit ownership of the buffer.
    170 
    171   @retval EFI_SUCCESS            The data was read correctly from the device.
    172   @retval EFI_DEVICE_ERROR       The device reported an error while attempting to perform the read operation.
    173   @retval EFI_NO_MEDIA           There is no media in the device.
    174   @retval EFI_MEDIA_CHANGED      The MediaId is not for the current media.
    175   @retval EFI_BAD_BUFFER_SIZE    The BufferSize parameter is not a multiple of the intrinsic block size of the device.
    176   @retval EFI_INVALID_PARAMETER  The read request contains LBAs that are not valid,
    177                                  or the buffer is not on proper alignment.
    178 
    179 **/
    180 EFI_STATUS
    181 EFIAPI
    182 BlockIoReadBlocks (
    183   IN EFI_BLOCK_IO_PROTOCOL    *This,
    184   IN UINT32                   MediaId,
    185   IN EFI_LBA                  Lba,
    186   IN UINTN                    BufferSize,
    187   OUT VOID                    *Buffer
    188   )
    189 {
    190   DEBUG ((EFI_D_INFO, "BlockIo (MMIO) ReadBlocks: lba=0x%Lx, size=0x%Lx\n",
    191     Lba, (UINT64)BufferSize));
    192   return ReadOrWriteBlocks (
    193     This,
    194     TRUE,
    195     MediaId,
    196     Lba,
    197     BufferSize,
    198     Buffer
    199     );
    200 }
    201 
    202 
    203 /**
    204   Writes a specified number of blocks to the device.
    205 
    206   This function implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks().
    207   It writes a specified number of blocks to the device.
    208   All blocks are written, or an error is returned.
    209 
    210   @param  This                   Indicates a pointer to the calling context.
    211   @param  MediaId                The media ID that the write request is for.
    212   @param  Lba                    The starting logical block address to be written.
    213   @param  BufferSize             The size of the Buffer in bytes.
    214                                  This must be a multiple of the intrinsic block size of the device.
    215   @param  Buffer                 Pointer to the source buffer for the data.
    216 
    217   @retval EFI_SUCCESS            The data were written correctly to the device.
    218   @retval EFI_WRITE_PROTECTED    The device cannot be written to.
    219   @retval EFI_NO_MEDIA           There is no media in the device.
    220   @retval EFI_MEDIA_CHANGED      The MediaId is not for the current media.
    221   @retval EFI_DEVICE_ERROR       The device reported an error while attempting to perform the write operation.
    222   @retval EFI_BAD_BUFFER_SIZE    The BufferSize parameter is not a multiple of the intrinsic
    223                                  block size of the device.
    224   @retval EFI_INVALID_PARAMETER  The write request contains LBAs that are not valid,
    225                                  or the buffer is not on proper alignment.
    226 
    227 **/
    228 EFI_STATUS
    229 EFIAPI
    230 BlockIoWriteBlocks (
    231   IN EFI_BLOCK_IO_PROTOCOL    *This,
    232   IN UINT32                   MediaId,
    233   IN EFI_LBA                  Lba,
    234   IN UINTN                    BufferSize,
    235   IN VOID                     *Buffer
    236   )
    237 {
    238   DEBUG ((EFI_D_INFO, "BlockIo (MMIO) WriteBlocks: lba=0x%Lx, size=0x%Lx\n",
    239     Lba, (UINT64)BufferSize));
    240   return ReadOrWriteBlocks (
    241     This,
    242     FALSE,
    243     MediaId,
    244     Lba,
    245     BufferSize,
    246     Buffer
    247     );
    248 }
    249 
    250 /**
    251   Flushes all modified data to a physical block device.
    252 
    253   @param  This                   Indicates a pointer to the calling context.
    254 
    255   @retval EFI_SUCCESS            All outstanding data were written correctly to the device.
    256   @retval EFI_DEVICE_ERROR       The device reported an error while attempting to write data.
    257   @retval EFI_NO_MEDIA           There is no media in the device.
    258 
    259 **/
    260 EFI_STATUS
    261 EFIAPI
    262 BlockIoFlushBlocks (
    263   IN EFI_BLOCK_IO_PROTOCOL  *This
    264   )
    265 {
    266   return EFI_SUCCESS;
    267 }
    268 
    269 
    270 /**
    271   Initialize data for device that does not support multiple LUNSs.
    272 
    273   @param  This            The Driver Binding Protocol instance.
    274   @param  Controller      The device to initialize.
    275   @param  BlockMmio       Pointer to USB_MASS_TRANSPORT.
    276   @param  Context         Parameter for USB_MASS_DEVICE.Context.
    277 
    278   @retval EFI_SUCCESS     Initialization succeeds.
    279   @retval Other           Initialization fails.
    280 
    281 **/
    282 EFI_STATUS
    283 BlockIoInit (
    284   IN EFI_DRIVER_BINDING_PROTOCOL   *This,
    285   IN EFI_HANDLE                    Controller
    286   )
    287 {
    288   EFI_STATUS                     Status;
    289   BLOCK_MMIO_TO_BLOCK_IO_DEVICE  *Private;
    290   BLOCK_MMIO_PROTOCOL            *BlockMmio;
    291 
    292   Private = (BLOCK_MMIO_TO_BLOCK_IO_DEVICE*) AllocateZeroPool (sizeof (*Private));
    293   ASSERT (Private != NULL);
    294 
    295   Status = gBS->LocateProtocol (
    296                   &gEfiCpuIo2ProtocolGuid,
    297                   NULL,
    298                   (VOID **) &(Private->CpuIo)
    299                   );
    300   ASSERT_EFI_ERROR (Status);
    301 
    302   Status = gBS->OpenProtocol (
    303                   Controller,
    304                   &gBlockMmioProtocolGuid,
    305                   (VOID **) &BlockMmio,
    306                   This->DriverBindingHandle,
    307                   Controller,
    308                   EFI_OPEN_PROTOCOL_BY_DRIVER
    309                   );
    310   if (EFI_ERROR (Status)) {
    311     DEBUG ((EFI_D_ERROR, "BlockIoInit: OpenBlockMmioProtocol By Driver (%r)\n", Status));
    312     goto ON_ERROR;
    313   }
    314   DEBUG ((EFI_D_INFO, "BlockMmio: %p\n", BlockMmio));
    315   DEBUG ((EFI_D_INFO, "BlockMmio->Media->LastBlock: 0x%lx\n", BlockMmio->Media->LastBlock));
    316 
    317   Private->Signature            = BLOCK_MMIO_TO_BLOCK_IO_SIGNATURE;
    318   Private->Controller           = Controller;
    319   Private->BlockMmio            = BlockMmio;
    320   Private->BlockIo.Media        = BlockMmio->Media;
    321   Private->BlockIo.Reset        = BlockIoReset;
    322   Private->BlockIo.ReadBlocks   = BlockIoReadBlocks;
    323   Private->BlockIo.WriteBlocks  = BlockIoWriteBlocks;
    324   Private->BlockIo.FlushBlocks  = BlockIoFlushBlocks;
    325 
    326   DEBUG ((EFI_D_INFO, "Private->BlockIo.Media->LastBlock: 0x%lx\n", Private->BlockIo.Media->LastBlock));
    327 
    328   Status = gBS->InstallProtocolInterface (
    329                   &Controller,
    330                   &gEfiBlockIoProtocolGuid,
    331                   EFI_NATIVE_INTERFACE,
    332                   &Private->BlockIo
    333                   );
    334   if (EFI_ERROR (Status)) {
    335     goto ON_ERROR;
    336   }
    337 
    338   return EFI_SUCCESS;
    339 
    340 ON_ERROR:
    341   if (Private != NULL) {
    342     FreePool (Private);
    343   }
    344   if (BlockMmio != NULL) {
    345     gBS->CloseProtocol (
    346            Controller,
    347            &gBlockMmioProtocolGuid,
    348            This->DriverBindingHandle,
    349            Controller
    350            );
    351   }
    352   return Status;
    353 }
    354 
    355 
    356 /**
    357   Check whether the controller is a supported USB mass storage.
    358 
    359   @param  This                   The USB mass storage driver binding protocol.
    360   @param  Controller             The controller handle to check.
    361   @param  RemainingDevicePath    The remaining device path.
    362 
    363   @retval EFI_SUCCESS            The driver supports this controller.
    364   @retval other                  This device isn't supported.
    365 
    366 **/
    367 EFI_STATUS
    368 EFIAPI
    369 BlockIoDriverBindingSupported (
    370   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    371   IN EFI_HANDLE                   Controller,
    372   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
    373   )
    374 {
    375   EFI_STATUS                    Status;
    376   BLOCK_MMIO_PROTOCOL           *BlockMmio;
    377 
    378   Status = gBS->OpenProtocol (
    379                   Controller,
    380                   &gBlockMmioProtocolGuid,
    381                   (VOID **) &BlockMmio,
    382                   This->DriverBindingHandle,
    383                   Controller,
    384                   EFI_OPEN_PROTOCOL_BY_DRIVER
    385                   );
    386   if (EFI_ERROR (Status)) {
    387     return Status;
    388   }
    389 
    390   gBS->CloseProtocol (
    391          Controller,
    392          &gBlockMmioProtocolGuid,
    393          This->DriverBindingHandle,
    394          Controller
    395          );
    396 
    397   return Status;
    398 }
    399 
    400 /**
    401   Starts the USB mass storage device with this driver.
    402 
    403   This function consumes USB I/O Portocol, intializes USB mass storage device,
    404   installs Block I/O Protocol, and submits Asynchronous Interrupt
    405   Transfer to manage the USB mass storage device.
    406 
    407   @param  This                  The USB mass storage driver binding protocol.
    408   @param  Controller            The USB mass storage device to start on
    409   @param  RemainingDevicePath   The remaining device path.
    410 
    411   @retval EFI_SUCCESS           This driver supports this device.
    412   @retval EFI_UNSUPPORTED       This driver does not support this device.
    413   @retval EFI_DEVICE_ERROR      This driver cannot be started due to device Error.
    414   @retval EFI_OUT_OF_RESOURCES  Can't allocate memory resources.
    415   @retval EFI_ALREADY_STARTED   This driver has been started.
    416 
    417 **/
    418 EFI_STATUS
    419 EFIAPI
    420 BlockIoDriverBindingStart (
    421   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    422   IN EFI_HANDLE                   Controller,
    423   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
    424   )
    425 {
    426   EFI_STATUS                    Status;
    427 
    428   Status = BlockIoInit (This, Controller);
    429   if (EFI_ERROR (Status)) {
    430     DEBUG ((EFI_D_ERROR, "BlockIoDriverBindingStart: BlockIoInit (%r)\n", Status));
    431     return Status;
    432   }
    433 
    434   DEBUG ((EFI_D_INIT, "BlockIoDriverBindingStart: Successfully started\n"));
    435   return Status;
    436 }
    437 
    438 
    439 /**
    440   Stop controlling the device.
    441 
    442   @param  This                   The USB mass storage driver binding
    443   @param  Controller             The device controller controlled by the driver.
    444   @param  NumberOfChildren       The number of children of this device
    445   @param  ChildHandleBuffer      The buffer of children handle.
    446 
    447   @retval EFI_SUCCESS            The driver stopped from controlling the device.
    448   @retval EFI_DEVICE_ERROR       The device could not be stopped due to a device error.
    449   @retval EFI_UNSUPPORTED        Block I/O Protocol is not installed on Controller.
    450   @retval Others                 Failed to stop the driver
    451 
    452 **/
    453 EFI_STATUS
    454 EFIAPI
    455 BlockIoDriverBindingStop (
    456   IN  EFI_DRIVER_BINDING_PROTOCOL *This,
    457   IN  EFI_HANDLE                  Controller,
    458   IN  UINTN                       NumberOfChildren,
    459   IN  EFI_HANDLE                  *ChildHandleBuffer
    460   )
    461 {
    462   EFI_STATUS                    Status;
    463   BLOCK_MMIO_TO_BLOCK_IO_DEVICE *Private;
    464 
    465   Private = PRIVATE_FROM_BLOCK_IO (This);
    466 
    467   //
    468   // Uninstall Block I/O protocol from the device handle,
    469   // then call the transport protocol to stop itself.
    470   //
    471   Status = gBS->UninstallProtocolInterface (
    472                   Controller,
    473                   &gEfiBlockIoProtocolGuid,
    474                   &Private->BlockIo
    475                   );
    476   if (EFI_ERROR (Status)) {
    477     return Status;
    478   }
    479 
    480   gBS->CloseProtocol (
    481         Controller,
    482         &gBlockMmioProtocolGuid,
    483         This->DriverBindingHandle,
    484         Controller
    485         );
    486 
    487   FreePool (Private);
    488 
    489   DEBUG ((EFI_D_INFO, "Successfully stopped BlockIo on BlockMmio\n"));
    490   return EFI_SUCCESS;
    491 }
    492 
    493 /**
    494   Entrypoint of Block MMIO to Block IO Driver.
    495 
    496   This function is the entrypoint of USB Mass Storage Driver. It installs Driver Binding
    497   Protocol together with Component Name Protocols.
    498 
    499   @param  ImageHandle       The firmware allocated handle for the EFI image.
    500   @param  SystemTable       A pointer to the EFI System Table.
    501 
    502   @retval EFI_SUCCESS       The entry point is executed successfully.
    503 
    504 **/
    505 EFI_STATUS
    506 EFIAPI
    507 BlockMmioToBlockIoEntryPoint (
    508   IN EFI_HANDLE               ImageHandle,
    509   IN EFI_SYSTEM_TABLE         *SystemTable
    510   )
    511 {
    512   EFI_STATUS  Status;
    513 
    514   //
    515   // Install driver binding protocol
    516   //
    517   Status = EfiLibInstallDriverBindingComponentName2 (
    518              ImageHandle,
    519              SystemTable,
    520              &gBlockIoDriverBinding,
    521              ImageHandle,
    522              &gBlockMmioToBlockIoComponentName,
    523              &gBlockMmioToBlockIoComponentName2
    524              );
    525   ASSERT_EFI_ERROR (Status);
    526 
    527   return EFI_SUCCESS;
    528 }
    529