Home | History | Annotate | Download | only in RamDiskDxe
      1 /** @file
      2   Produce EFI_BLOCK_IO_PROTOCOL on a RAM disk device.
      3 
      4   Copyright (c) 2016, Intel Corporation. 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 #include "RamDiskImpl.h"
     16 
     17 //
     18 // The EFI_BLOCK_IO_PROTOCOL instances that is installed onto the handle
     19 // for newly registered RAM disks
     20 //
     21 EFI_BLOCK_IO_PROTOCOL  mRamDiskBlockIoTemplate = {
     22   EFI_BLOCK_IO_PROTOCOL_REVISION,
     23   (EFI_BLOCK_IO_MEDIA *) 0,
     24   RamDiskBlkIoReset,
     25   RamDiskBlkIoReadBlocks,
     26   RamDiskBlkIoWriteBlocks,
     27   RamDiskBlkIoFlushBlocks
     28 };
     29 
     30 //
     31 // The EFI_BLOCK_IO_PROTOCOL2 instances that is installed onto the handle
     32 // for newly registered RAM disks
     33 //
     34 EFI_BLOCK_IO2_PROTOCOL  mRamDiskBlockIo2Template = {
     35   (EFI_BLOCK_IO_MEDIA *) 0,
     36   RamDiskBlkIo2Reset,
     37   RamDiskBlkIo2ReadBlocksEx,
     38   RamDiskBlkIo2WriteBlocksEx,
     39   RamDiskBlkIo2FlushBlocksEx
     40 };
     41 
     42 
     43 /**
     44   Initialize the BlockIO & BlockIO2 protocol of a RAM disk device.
     45 
     46   @param[in] PrivateData     Points to RAM disk private data.
     47 
     48 **/
     49 VOID
     50 RamDiskInitBlockIo (
     51   IN     RAM_DISK_PRIVATE_DATA    *PrivateData
     52   )
     53 {
     54   EFI_BLOCK_IO_PROTOCOL           *BlockIo;
     55   EFI_BLOCK_IO2_PROTOCOL          *BlockIo2;
     56   EFI_BLOCK_IO_MEDIA              *Media;
     57 
     58   BlockIo  = &PrivateData->BlockIo;
     59   BlockIo2 = &PrivateData->BlockIo2;
     60   Media    = &PrivateData->Media;
     61 
     62   CopyMem (BlockIo, &mRamDiskBlockIoTemplate, sizeof (EFI_BLOCK_IO_PROTOCOL));
     63   CopyMem (BlockIo2, &mRamDiskBlockIo2Template, sizeof (EFI_BLOCK_IO2_PROTOCOL));
     64 
     65   BlockIo->Media          = Media;
     66   BlockIo2->Media         = Media;
     67   Media->RemovableMedia   = FALSE;
     68   Media->MediaPresent     = TRUE;
     69   Media->LogicalPartition = FALSE;
     70   Media->ReadOnly         = FALSE;
     71   Media->WriteCaching     = FALSE;
     72   Media->BlockSize        = RAM_DISK_BLOCK_SIZE;
     73   Media->LastBlock        = DivU64x32 (
     74                               PrivateData->Size + RAM_DISK_BLOCK_SIZE - 1,
     75                               RAM_DISK_BLOCK_SIZE
     76                               ) - 1;
     77 }
     78 
     79 
     80 /**
     81   Reset the Block Device.
     82 
     83   @param  This                 Indicates a pointer to the calling context.
     84   @param  ExtendedVerification Driver may perform diagnostics on reset.
     85 
     86   @retval EFI_SUCCESS          The device was reset.
     87   @retval EFI_DEVICE_ERROR     The device is not functioning properly and could
     88                                not be reset.
     89 
     90 **/
     91 EFI_STATUS
     92 EFIAPI
     93 RamDiskBlkIoReset (
     94   IN EFI_BLOCK_IO_PROTOCOL        *This,
     95   IN BOOLEAN                      ExtendedVerification
     96   )
     97 {
     98   return EFI_SUCCESS;
     99 }
    100 
    101 
    102 /**
    103   Read BufferSize bytes from Lba into Buffer.
    104 
    105   @param[in]  This           Indicates a pointer to the calling context.
    106   @param[in]  MediaId        Id of the media, changes every time the media is
    107                              replaced.
    108   @param[in]  Lba            The starting Logical Block Address to read from.
    109   @param[in]  BufferSize     Size of Buffer, must be a multiple of device block
    110                              size.
    111   @param[out] Buffer         A pointer to the destination buffer for the data.
    112                              The caller is responsible for either having
    113                              implicit or explicit ownership of the buffer.
    114 
    115   @retval EFI_SUCCESS             The data was read correctly from the device.
    116   @retval EFI_DEVICE_ERROR        The device reported an error while performing
    117                                   the read.
    118   @retval EFI_NO_MEDIA            There is no media in the device.
    119   @retval EFI_MEDIA_CHANGED       The MediaId does not matched the current
    120                                   device.
    121   @retval EFI_BAD_BUFFER_SIZE     The Buffer was not a multiple of the block
    122                                   size of the device.
    123   @retval EFI_INVALID_PARAMETER   The read request contains LBAs that are not
    124                                   valid, or the buffer is not on proper alignment.
    125 
    126 **/
    127 EFI_STATUS
    128 EFIAPI
    129 RamDiskBlkIoReadBlocks (
    130   IN EFI_BLOCK_IO_PROTOCOL        *This,
    131   IN UINT32                       MediaId,
    132   IN EFI_LBA                      Lba,
    133   IN UINTN                        BufferSize,
    134   OUT VOID                        *Buffer
    135   )
    136 {
    137   RAM_DISK_PRIVATE_DATA           *PrivateData;
    138   UINTN                           NumberOfBlocks;
    139 
    140   if (Buffer == NULL) {
    141     return EFI_INVALID_PARAMETER;
    142   }
    143 
    144   if (BufferSize == 0) {
    145     return EFI_SUCCESS;
    146   }
    147 
    148   PrivateData = RAM_DISK_PRIVATE_FROM_BLKIO (This);
    149 
    150   if (MediaId != PrivateData->Media.MediaId) {
    151     return EFI_MEDIA_CHANGED;
    152   }
    153 
    154   if ((BufferSize % PrivateData->Media.BlockSize) != 0) {
    155     return EFI_BAD_BUFFER_SIZE;
    156   }
    157 
    158   if (Lba > PrivateData->Media.LastBlock) {
    159     return EFI_INVALID_PARAMETER;
    160   }
    161 
    162   NumberOfBlocks = BufferSize / PrivateData->Media.BlockSize;
    163   if ((Lba + NumberOfBlocks - 1) > PrivateData->Media.LastBlock) {
    164     return EFI_INVALID_PARAMETER;
    165   }
    166 
    167   CopyMem (
    168     Buffer,
    169     (VOID *)(UINTN)(PrivateData->StartingAddr + MultU64x32 (Lba, PrivateData->Media.BlockSize)),
    170     BufferSize
    171     );
    172 
    173   return EFI_SUCCESS;
    174 }
    175 
    176 
    177 /**
    178   Write BufferSize bytes from Lba into Buffer.
    179 
    180   @param[in] This            Indicates a pointer to the calling context.
    181   @param[in] MediaId         The media ID that the write request is for.
    182   @param[in] Lba             The starting logical block address to be written.
    183                              The caller is responsible for writing to only
    184                              legitimate locations.
    185   @param[in] BufferSize      Size of Buffer, must be a multiple of device block
    186                              size.
    187   @param[in] Buffer          A pointer to the source buffer for the data.
    188 
    189   @retval EFI_SUCCESS             The data was written correctly to the device.
    190   @retval EFI_WRITE_PROTECTED     The device can not be written to.
    191   @retval EFI_DEVICE_ERROR        The device reported an error while performing
    192                                   the write.
    193   @retval EFI_NO_MEDIA            There is no media in the device.
    194   @retval EFI_MEDIA_CHNAGED       The MediaId does not matched the current
    195                                   device.
    196   @retval EFI_BAD_BUFFER_SIZE     The Buffer was not a multiple of the block
    197                                   size of the device.
    198   @retval EFI_INVALID_PARAMETER   The write request contains LBAs that are not
    199                                   valid, or the buffer is not on proper alignment.
    200 
    201 **/
    202 EFI_STATUS
    203 EFIAPI
    204 RamDiskBlkIoWriteBlocks (
    205   IN EFI_BLOCK_IO_PROTOCOL        *This,
    206   IN UINT32                       MediaId,
    207   IN EFI_LBA                      Lba,
    208   IN UINTN                        BufferSize,
    209   IN VOID                         *Buffer
    210   )
    211 {
    212   RAM_DISK_PRIVATE_DATA           *PrivateData;
    213   UINTN                           NumberOfBlocks;
    214 
    215   if (Buffer == NULL) {
    216     return EFI_INVALID_PARAMETER;
    217   }
    218 
    219   if (BufferSize == 0) {
    220     return EFI_SUCCESS;
    221   }
    222 
    223   PrivateData = RAM_DISK_PRIVATE_FROM_BLKIO (This);
    224 
    225   if (MediaId != PrivateData->Media.MediaId) {
    226     return EFI_MEDIA_CHANGED;
    227   }
    228 
    229   if (TRUE == PrivateData->Media.ReadOnly) {
    230     return EFI_WRITE_PROTECTED;
    231   }
    232 
    233   if ((BufferSize % PrivateData->Media.BlockSize) != 0) {
    234     return EFI_BAD_BUFFER_SIZE;
    235   }
    236 
    237   if (Lba > PrivateData->Media.LastBlock) {
    238     return EFI_INVALID_PARAMETER;
    239   }
    240 
    241   NumberOfBlocks = BufferSize / PrivateData->Media.BlockSize;
    242   if ((Lba + NumberOfBlocks - 1) > PrivateData->Media.LastBlock) {
    243     return EFI_INVALID_PARAMETER;
    244   }
    245 
    246   CopyMem (
    247     (VOID *)(UINTN)(PrivateData->StartingAddr + MultU64x32 (Lba, PrivateData->Media.BlockSize)),
    248     Buffer,
    249     BufferSize
    250     );
    251 
    252   return EFI_SUCCESS;
    253 }
    254 
    255 
    256 /**
    257   Flush the Block Device.
    258 
    259   @param[in] This            Indicates a pointer to the calling context.
    260 
    261   @retval EFI_SUCCESS             All outstanding data was written to the device.
    262   @retval EFI_DEVICE_ERROR        The device reported an error while writting
    263                                   back the data
    264   @retval EFI_NO_MEDIA            There is no media in the device.
    265 
    266 **/
    267 EFI_STATUS
    268 EFIAPI
    269 RamDiskBlkIoFlushBlocks (
    270   IN EFI_BLOCK_IO_PROTOCOL        *This
    271   )
    272 {
    273   return EFI_SUCCESS;
    274 }
    275 
    276 
    277 /**
    278   Resets the block device hardware.
    279 
    280   @param[in] This                 The pointer of EFI_BLOCK_IO2_PROTOCOL.
    281   @param[in] ExtendedVerification The flag about if extend verificate.
    282 
    283   @retval EFI_SUCCESS             The device was reset.
    284   @retval EFI_DEVICE_ERROR        The block device is not functioning correctly
    285                                   and could not be reset.
    286 
    287 **/
    288 EFI_STATUS
    289 EFIAPI
    290 RamDiskBlkIo2Reset (
    291   IN EFI_BLOCK_IO2_PROTOCOL       *This,
    292   IN BOOLEAN                      ExtendedVerification
    293   )
    294 {
    295   return EFI_SUCCESS;
    296 }
    297 
    298 
    299 /**
    300   Reads the requested number of blocks from the device.
    301 
    302   @param[in]      This            Indicates a pointer to the calling context.
    303   @param[in]      MediaId         The media ID that the read request is for.
    304   @param[in]      Lba             The starting logical block address to read
    305                                   from on the device.
    306   @param[in, out] Token           A pointer to the token associated with the
    307                                   transaction.
    308   @param[in]      BufferSize      The size of the Buffer in bytes. This must be
    309                                   a multiple of the intrinsic block size of the
    310                                   device.
    311   @param[out]     Buffer          A pointer to the destination buffer for the
    312                                   data. The caller is responsible for either
    313                                   having implicit or explicit ownership of the
    314                                   buffer.
    315 
    316   @retval EFI_SUCCESS             The read request was queued if Token->Event
    317                                   is not NULL. The data was read correctly from
    318                                   the device if the Token->Event is NULL.
    319   @retval EFI_DEVICE_ERROR        The device reported an error while attempting
    320                                   to perform the read operation.
    321   @retval EFI_NO_MEDIA            There is no media in the device.
    322   @retval EFI_MEDIA_CHANGED       The MediaId is not for the current media.
    323   @retval EFI_BAD_BUFFER_SIZE     The BufferSize parameter is not a multiple of
    324                                   the intrinsic block size of the device.
    325   @retval EFI_INVALID_PARAMETER   The read request contains LBAs that are not
    326                                   valid, or the buffer is not on proper
    327                                   alignment.
    328   @retval EFI_OUT_OF_RESOURCES    The request could not be completed due to a
    329                                   lack of resources.
    330 
    331 **/
    332 EFI_STATUS
    333 EFIAPI
    334 RamDiskBlkIo2ReadBlocksEx (
    335   IN     EFI_BLOCK_IO2_PROTOCOL   *This,
    336   IN     UINT32                   MediaId,
    337   IN     EFI_LBA                  Lba,
    338   IN OUT EFI_BLOCK_IO2_TOKEN      *Token,
    339   IN     UINTN                    BufferSize,
    340      OUT VOID                     *Buffer
    341   )
    342 {
    343   RAM_DISK_PRIVATE_DATA           *PrivateData;
    344   EFI_STATUS                      Status;
    345 
    346   PrivateData = RAM_DISK_PRIVATE_FROM_BLKIO2 (This);
    347 
    348   Status = RamDiskBlkIoReadBlocks (
    349               &PrivateData->BlockIo,
    350               MediaId,
    351               Lba,
    352               BufferSize,
    353               Buffer
    354               );
    355   if (EFI_ERROR (Status)) {
    356     return Status;
    357   }
    358 
    359   //
    360   // If caller's event is given, signal it after the memory read completes.
    361   //
    362   if ((Token != NULL) && (Token->Event != NULL)) {
    363     Token->TransactionStatus = EFI_SUCCESS;
    364     gBS->SignalEvent (Token->Event);
    365   }
    366 
    367   return EFI_SUCCESS;
    368 }
    369 
    370 
    371 /**
    372   Writes a specified number of blocks to the device.
    373 
    374   @param[in]      This            Indicates a pointer to the calling context.
    375   @param[in]      MediaId         The media ID that the write request is for.
    376   @param[in]      Lba             The starting logical block address to be
    377                                   written. The caller is responsible for
    378                                   writing to only legitimate locations.
    379   @param[in, out] Token           A pointer to the token associated with the
    380                                   transaction.
    381   @param[in]      BufferSize      The size in bytes of Buffer. This must be a
    382                                   multiple of the intrinsic block size of the
    383                                   device.
    384   @param[in]      Buffer          A pointer to the source buffer for the data.
    385 
    386   @retval EFI_SUCCESS             The write request was queued if Event is not
    387                                   NULL. The data was written correctly to the
    388                                   device if the Event is NULL.
    389   @retval EFI_WRITE_PROTECTED     The device cannot be written to.
    390   @retval EFI_NO_MEDIA            There is no media in the device.
    391   @retval EFI_MEDIA_CHANGED       The MediaId is not for the current media.
    392   @retval EFI_DEVICE_ERROR        The device reported an error while attempting
    393                                   to perform the write operation.
    394   @retval EFI_BAD_BUFFER_SIZE     The BufferSize parameter is not a multiple of
    395                                   the intrinsic block size of the device.
    396   @retval EFI_INVALID_PARAMETER   The write request contains LBAs that are not
    397                                   valid, or the buffer is not on proper
    398                                   alignment.
    399   @retval EFI_OUT_OF_RESOURCES    The request could not be completed due to a
    400                                   lack of resources.
    401 
    402 **/
    403 EFI_STATUS
    404 EFIAPI
    405 RamDiskBlkIo2WriteBlocksEx (
    406   IN     EFI_BLOCK_IO2_PROTOCOL   *This,
    407   IN     UINT32                   MediaId,
    408   IN     EFI_LBA                  Lba,
    409   IN OUT EFI_BLOCK_IO2_TOKEN      *Token,
    410   IN     UINTN                    BufferSize,
    411   IN     VOID                     *Buffer
    412   )
    413 {
    414   RAM_DISK_PRIVATE_DATA           *PrivateData;
    415   EFI_STATUS                      Status;
    416 
    417   PrivateData = RAM_DISK_PRIVATE_FROM_BLKIO2 (This);
    418 
    419   Status = RamDiskBlkIoWriteBlocks (
    420               &PrivateData->BlockIo,
    421               MediaId,
    422               Lba,
    423               BufferSize,
    424               Buffer
    425               );
    426   if (EFI_ERROR (Status)) {
    427     return Status;
    428   }
    429 
    430   //
    431   // If caller's event is given, signal it after the memory write completes.
    432   //
    433   if ((Token != NULL) && (Token->Event != NULL)) {
    434     Token->TransactionStatus = EFI_SUCCESS;
    435     gBS->SignalEvent (Token->Event);
    436   }
    437 
    438   return EFI_SUCCESS;
    439 }
    440 
    441 
    442 /**
    443   Flushes all modified data to a physical block device.
    444 
    445   @param[in]      This            Indicates a pointer to the calling context.
    446   @param[in, out] Token           A pointer to the token associated with the
    447                                   transaction.
    448 
    449   @retval EFI_SUCCESS             The flush request was queued if Event is not
    450                                   NULL. All outstanding data was written
    451                                   correctly to the device if the Event is NULL.
    452   @retval EFI_DEVICE_ERROR        The device reported an error while attempting
    453                                   to write data.
    454   @retval EFI_WRITE_PROTECTED     The device cannot be written to.
    455   @retval EFI_NO_MEDIA            There is no media in the device.
    456   @retval EFI_MEDIA_CHANGED       The MediaId is not for the current media.
    457   @retval EFI_OUT_OF_RESOURCES    The request could not be completed due to a
    458                                   lack of resources.
    459 
    460 **/
    461 EFI_STATUS
    462 EFIAPI
    463 RamDiskBlkIo2FlushBlocksEx (
    464   IN     EFI_BLOCK_IO2_PROTOCOL   *This,
    465   IN OUT EFI_BLOCK_IO2_TOKEN      *Token
    466   )
    467 {
    468   RAM_DISK_PRIVATE_DATA           *PrivateData;
    469 
    470   PrivateData = RAM_DISK_PRIVATE_FROM_BLKIO2 (This);
    471 
    472   if (TRUE == PrivateData->Media.ReadOnly) {
    473     return EFI_WRITE_PROTECTED;
    474   }
    475 
    476   //
    477   // If caller's event is given, signal it directly.
    478   //
    479   if ((Token != NULL) && (Token->Event != NULL)) {
    480     Token->TransactionStatus = EFI_SUCCESS;
    481     gBS->SignalEvent (Token->Event);
    482   }
    483 
    484   return EFI_SUCCESS;
    485 }
    486