Home | History | Annotate | Download | only in EmuBlockIoDxe
      1 /**@file
      2 
      3 Copyright (c) 2004 - 2009, Intel Corporation. All rights reserved.<BR>
      4 This program and the accompanying materials
      5 are licensed and made available under the terms and conditions of the BSD License
      6 which accompanies this distribution.  The full text of the license may be found at
      7 http://opensource.org/licenses/bsd-license.php
      8 
      9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     11 bbe
     12 **/
     13 
     14 #include "EmuBlockIo.h"
     15 
     16 
     17 /**
     18   Reset the block device hardware.
     19 
     20   @param[in]  This                 Indicates a pointer to the calling context.
     21   @param[in]  ExtendedVerification Indicates that the driver may perform a more
     22                                    exhausive verfication operation of the device
     23                                    during reset.
     24 
     25   @retval EFI_SUCCESS          The device was reset.
     26   @retval EFI_DEVICE_ERROR     The device is not functioning properly and could
     27                                not be reset.
     28 
     29 **/
     30 EFI_STATUS
     31 EFIAPI
     32 EmuBlockIo2Reset (
     33   IN EFI_BLOCK_IO2_PROTOCOL  *This,
     34   IN BOOLEAN                 ExtendedVerification
     35   )
     36 {
     37   EFI_STATUS              Status;
     38   EMU_BLOCK_IO_PRIVATE    *Private;
     39   EFI_TPL                 OldTpl;
     40 
     41   Private = EMU_BLOCK_IO2_PRIVATE_DATA_FROM_THIS (This);
     42 
     43   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
     44 
     45   Status = Private->Io->Reset (Private->Io, ExtendedVerification);
     46 
     47   gBS->RestoreTPL (OldTpl);
     48   return Status;
     49 }
     50 
     51 /**
     52   Read BufferSize bytes from Lba into Buffer.
     53 
     54   This function reads the requested number of blocks from the device. All the
     55   blocks are read, or an error is returned.
     56   If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_or EFI_MEDIA_CHANGED is returned and
     57   non-blocking I/O is being used, the Event associated with this request will
     58   not be signaled.
     59 
     60   @param[in]       This       Indicates a pointer to the calling context.
     61   @param[in]       MediaId    Id of the media, changes every time the media is
     62                               replaced.
     63   @param[in]       Lba        The starting Logical Block Address to read from.
     64   @param[in, out]  Token	    A pointer to the token associated with the transaction.
     65   @param[in]       BufferSize Size of Buffer, must be a multiple of device block size.
     66   @param[out]      Buffer     A pointer to the destination buffer for the data. The
     67                               caller is responsible for either having implicit or
     68                               explicit ownership of the buffer.
     69 
     70   @retval EFI_SUCCESS           The read request was queued if Token->Event is
     71                                 not NULL.The data was read correctly from the
     72                                 device if the Token->Event is NULL.
     73   @retval EFI_DEVICE_ERROR      The device reported an error while performing
     74                                 the read.
     75   @retval EFI_NO_MEDIA          There is no media in the device.
     76   @retval EFI_MEDIA_CHANGED     The MediaId is not for the current media.
     77   @retval EFI_BAD_BUFFER_SIZE   The BufferSize parameter is not a multiple of the
     78                                 intrinsic block size of the device.
     79   @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
     80                                 or the buffer is not on proper alignment.
     81   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack
     82                                 of resources.
     83 **/
     84 EFI_STATUS
     85 EFIAPI
     86 EmuBlockIo2ReadBlocksEx (
     87   IN     EFI_BLOCK_IO2_PROTOCOL *This,
     88   IN     UINT32                 MediaId,
     89   IN     EFI_LBA                LBA,
     90   IN OUT EFI_BLOCK_IO2_TOKEN    *Token,
     91   IN     UINTN                  BufferSize,
     92      OUT VOID                  *Buffer
     93   )
     94 {
     95   EFI_STATUS              Status;
     96   EMU_BLOCK_IO_PRIVATE    *Private;
     97   EFI_TPL                 OldTpl;
     98 
     99   Private = EMU_BLOCK_IO2_PRIVATE_DATA_FROM_THIS (This);
    100 
    101   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
    102 
    103   Status = Private->Io->ReadBlocks (Private->Io, MediaId, LBA, Token, BufferSize, Buffer);
    104 
    105   gBS->RestoreTPL (OldTpl);
    106   return Status;
    107 }
    108 
    109 
    110 /**
    111   Write BufferSize bytes from Lba into Buffer.
    112 
    113   This function writes the requested number of blocks to the device. All blocks
    114   are written, or an error is returned.If EFI_DEVICE_ERROR, EFI_NO_MEDIA,
    115   EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED is returned and non-blocking I/O is
    116   being used, the Event associated with this request will not be signaled.
    117 
    118   @param[in]       This       Indicates a pointer to the calling context.
    119   @param[in]       MediaId    The media ID that the write request is for.
    120   @param[in]       Lba        The starting logical block address to be written. The
    121                               caller is responsible for writing to only legitimate
    122                               locations.
    123   @param[in, out]  Token      A pointer to the token associated with the transaction.
    124   @param[in]       BufferSize Size of Buffer, must be a multiple of device block size.
    125   @param[in]       Buffer     A pointer to the source buffer for the data.
    126 
    127   @retval EFI_SUCCESS           The write request was queued if Event is not NULL.
    128                                 The data was written correctly to the device if
    129                                 the Event is NULL.
    130   @retval EFI_WRITE_PROTECTED   The device can not be written to.
    131   @retval EFI_NO_MEDIA          There is no media in the device.
    132   @retval EFI_MEDIA_CHNAGED     The MediaId does not matched the current device.
    133   @retval EFI_DEVICE_ERROR      The device reported an error while performing the write.
    134   @retval EFI_BAD_BUFFER_SIZE   The Buffer was not a multiple of the block size of the device.
    135   @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
    136                                 or the buffer is not on proper alignment.
    137   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack
    138                                 of resources.
    139 
    140 **/
    141 EFI_STATUS
    142 EFIAPI
    143 EmuBlockIo2WriteBlocksEx (
    144   IN     EFI_BLOCK_IO2_PROTOCOL  *This,
    145   IN     UINT32                 MediaId,
    146   IN     EFI_LBA                LBA,
    147   IN OUT EFI_BLOCK_IO2_TOKEN    *Token,
    148   IN     UINTN                  BufferSize,
    149   IN     VOID                   *Buffer
    150   )
    151 {
    152   EFI_STATUS              Status;
    153   EMU_BLOCK_IO_PRIVATE    *Private;
    154   EFI_TPL                 OldTpl;
    155 
    156   Private = EMU_BLOCK_IO2_PRIVATE_DATA_FROM_THIS (This);
    157 
    158   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
    159 
    160   Status = Private->Io->WriteBlocks (Private->Io, MediaId, LBA, Token, BufferSize, Buffer);
    161 
    162   gBS->RestoreTPL (OldTpl);
    163   return Status;
    164 }
    165 
    166 
    167 
    168 /**
    169   Flush the Block Device.
    170 
    171   If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED
    172   is returned and non-blocking I/O is being used, the Event associated with
    173   this request will not be signaled.
    174 
    175   @param[in]      This     Indicates a pointer to the calling context.
    176   @param[in,out]  Token    A pointer to the token associated with the transaction
    177 
    178   @retval EFI_SUCCESS          The flush request was queued if Event is not NULL.
    179                                All outstanding data was written correctly to the
    180                                device if the Event is NULL.
    181   @retval EFI_DEVICE_ERROR     The device reported an error while writting back
    182                                the data.
    183   @retval EFI_WRITE_PROTECTED  The device cannot be written to.
    184   @retval EFI_NO_MEDIA         There is no media in the device.
    185   @retval EFI_MEDIA_CHANGED    The MediaId is not for the current media.
    186   @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
    187                                of resources.
    188 
    189 **/
    190 EFI_STATUS
    191 EFIAPI
    192 EmuBlockIo2Flush (
    193   IN     EFI_BLOCK_IO2_PROTOCOL   *This,
    194   IN OUT EFI_BLOCK_IO2_TOKEN      *Token
    195   )
    196 {
    197   EFI_STATUS              Status;
    198   EMU_BLOCK_IO_PRIVATE    *Private;
    199   EFI_TPL                 OldTpl;
    200 
    201   Private = EMU_BLOCK_IO2_PRIVATE_DATA_FROM_THIS (This);
    202 
    203   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
    204 
    205   Status = Private->Io->FlushBlocks (Private->Io, Token);
    206 
    207   gBS->RestoreTPL (OldTpl);
    208   return Status;
    209 }
    210 
    211 
    212 
    213 /**
    214   Reset the Block Device.
    215 
    216   @param  This                 Indicates a pointer to the calling context.
    217   @param  ExtendedVerification Driver may perform diagnostics on reset.
    218 
    219   @retval EFI_SUCCESS          The device was reset.
    220   @retval EFI_DEVICE_ERROR     The device is not functioning properly and could
    221                                not be reset.
    222 
    223 **/
    224 EFI_STATUS
    225 EFIAPI
    226 EmuBlockIoReset (
    227   IN EFI_BLOCK_IO_PROTOCOL          *This,
    228   IN BOOLEAN                        ExtendedVerification
    229   )
    230 {
    231   EFI_STATUS              Status;
    232   EMU_BLOCK_IO_PRIVATE    *Private;
    233   EFI_TPL                 OldTpl;
    234 
    235   Private = EMU_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);
    236 
    237   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
    238 
    239   Status = Private->Io->Reset (Private->Io, ExtendedVerification);
    240 
    241   gBS->RestoreTPL (OldTpl);
    242   return Status;
    243 }
    244 
    245 
    246 /**
    247   Read BufferSize bytes from Lba into Buffer.
    248 
    249   @param  This       Indicates a pointer to the calling context.
    250   @param  MediaId    Id of the media, changes every time the media is replaced.
    251   @param  Lba        The starting Logical Block Address to read from
    252   @param  BufferSize Size of Buffer, must be a multiple of device block size.
    253   @param  Buffer     A pointer to the destination buffer for the data. The caller is
    254                      responsible for either having implicit or explicit ownership of the buffer.
    255 
    256   @retval EFI_SUCCESS           The data was read correctly from the device.
    257   @retval EFI_DEVICE_ERROR      The device reported an error while performing the read.
    258   @retval EFI_NO_MEDIA          There is no media in the device.
    259   @retval EFI_MEDIA_CHANGED     The MediaId does not matched the current device.
    260   @retval EFI_BAD_BUFFER_SIZE   The Buffer was not a multiple of the block size of the device.
    261   @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
    262                                 or the buffer is not on proper alignment.
    263 
    264 **/
    265 EFI_STATUS
    266 EFIAPI
    267 EmuBlockIoReadBlocks (
    268   IN EFI_BLOCK_IO_PROTOCOL          *This,
    269   IN UINT32                         MediaId,
    270   IN EFI_LBA                        Lba,
    271   IN UINTN                          BufferSize,
    272   OUT VOID                          *Buffer
    273   )
    274 {
    275   EFI_STATUS              Status;
    276   EMU_BLOCK_IO_PRIVATE    *Private;
    277   EFI_TPL                 OldTpl;
    278   EFI_BLOCK_IO2_TOKEN     Token;
    279 
    280   Private = EMU_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);
    281 
    282   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
    283 
    284   Token.Event = NULL;
    285   Status = Private->Io->ReadBlocks (Private->Io, MediaId, Lba, &Token, BufferSize, Buffer);
    286 
    287   gBS->RestoreTPL (OldTpl);
    288   return Status;
    289 }
    290 
    291 
    292 /**
    293   Write BufferSize bytes from Lba into Buffer.
    294 
    295   @param  This       Indicates a pointer to the calling context.
    296   @param  MediaId    The media ID that the write request is for.
    297   @param  Lba        The starting logical block address to be written. The caller is
    298                      responsible for writing to only legitimate locations.
    299   @param  BufferSize Size of Buffer, must be a multiple of device block size.
    300   @param  Buffer     A pointer to the source buffer for the data.
    301 
    302   @retval EFI_SUCCESS           The data was written correctly to the device.
    303   @retval EFI_WRITE_PROTECTED   The device can not be written to.
    304   @retval EFI_DEVICE_ERROR      The device reported an error while performing the write.
    305   @retval EFI_NO_MEDIA          There is no media in the device.
    306   @retval EFI_MEDIA_CHNAGED     The MediaId does not matched the current device.
    307   @retval EFI_BAD_BUFFER_SIZE   The Buffer was not a multiple of the block size of the device.
    308   @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
    309                                 or the buffer is not on proper alignment.
    310 
    311 **/
    312 EFI_STATUS
    313 EFIAPI
    314 EmuBlockIoWriteBlocks (
    315   IN EFI_BLOCK_IO_PROTOCOL          *This,
    316   IN UINT32                         MediaId,
    317   IN EFI_LBA                        Lba,
    318   IN UINTN                          BufferSize,
    319   IN VOID                           *Buffer
    320   )
    321 {
    322   EFI_STATUS              Status;
    323   EMU_BLOCK_IO_PRIVATE    *Private;
    324   EFI_TPL                 OldTpl;
    325   EFI_BLOCK_IO2_TOKEN     Token;
    326 
    327   Private = EMU_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);
    328 
    329   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
    330 
    331   Token.Event = NULL;
    332   Status = Private->Io->WriteBlocks (Private->Io, MediaId, Lba, &Token, BufferSize, Buffer);
    333 
    334   gBS->RestoreTPL (OldTpl);
    335   return Status;
    336 }
    337 
    338 /**
    339   Flush the Block Device.
    340 
    341   @param  This              Indicates a pointer to the calling context.
    342 
    343   @retval EFI_SUCCESS       All outstanding data was written to the device
    344   @retval EFI_DEVICE_ERROR  The device reported an error while writting back the data
    345   @retval EFI_NO_MEDIA      There is no media in the device.
    346 
    347 **/
    348 EFI_STATUS
    349 EFIAPI
    350 EmuBlockIoFlushBlocks (
    351   IN EFI_BLOCK_IO_PROTOCOL  *This
    352   )
    353 {
    354   EFI_STATUS              Status;
    355   EMU_BLOCK_IO_PRIVATE    *Private;
    356   EFI_TPL                 OldTpl;
    357   EFI_BLOCK_IO2_TOKEN     Token;
    358 
    359   Private = EMU_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);
    360 
    361   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
    362 
    363   Token.Event = NULL;
    364   Status = Private->Io->FlushBlocks (Private->Io, &Token);
    365 
    366   gBS->RestoreTPL (OldTpl);
    367   return Status;
    368 }
    369 
    370 
    371 
    372 /**
    373   Tests to see if this driver supports a given controller. If a child device is provided,
    374   it further tests to see if this driver supports creating a handle for the specified child device.
    375 
    376   This function checks to see if the driver specified by This supports the device specified by
    377   ControllerHandle. Drivers will typically use the device path attached to
    378   ControllerHandle and/or the services from the bus I/O abstraction attached to
    379   ControllerHandle to determine if the driver supports ControllerHandle. This function
    380   may be called many times during platform initialization. In order to reduce boot times, the tests
    381   performed by this function must be very small, and take as little time as possible to execute. This
    382   function must not change the state of any hardware devices, and this function must be aware that the
    383   device specified by ControllerHandle may already be managed by the same driver or a
    384   different driver. This function must match its calls to AllocatePages() with FreePages(),
    385   AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
    386   Because ControllerHandle may have been previously started by the same driver, if a protocol is
    387   already in the opened state, then it must not be closed with CloseProtocol(). This is required
    388   to guarantee the state of ControllerHandle is not modified by this function.
    389 
    390   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
    391   @param[in]  ControllerHandle     The handle of the controller to test. This handle
    392                                    must support a protocol interface that supplies
    393                                    an I/O abstraction to the driver.
    394   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
    395                                    parameter is ignored by device drivers, and is optional for bus
    396                                    drivers. For bus drivers, if this parameter is not NULL, then
    397                                    the bus driver must determine if the bus controller specified
    398                                    by ControllerHandle and the child controller specified
    399                                    by RemainingDevicePath are both supported by this
    400                                    bus driver.
    401 
    402   @retval EFI_SUCCESS              The device specified by ControllerHandle and
    403                                    RemainingDevicePath is supported by the driver specified by This.
    404   @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle and
    405                                    RemainingDevicePath is already being managed by the driver
    406                                    specified by This.
    407   @retval EFI_ACCESS_DENIED        The device specified by ControllerHandle and
    408                                    RemainingDevicePath is already being managed by a different
    409                                    driver or an application that requires exclusive access.
    410                                    Currently not implemented.
    411   @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and
    412                                    RemainingDevicePath is not supported by the driver specified by This.
    413 **/
    414 EFI_STATUS
    415 EFIAPI
    416 EmuBlockIoDriverBindingSupported (
    417   IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
    418   IN  EFI_HANDLE                   Handle,
    419   IN  EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
    420   )
    421 {
    422   EFI_STATUS              Status;
    423   EMU_IO_THUNK_PROTOCOL   *EmuIoThunk;
    424 
    425   //
    426   // Open the IO Abstraction(s) needed to perform the supported test
    427   //
    428   Status = gBS->OpenProtocol (
    429                   Handle,
    430                   &gEmuIoThunkProtocolGuid,
    431                   (VOID **)&EmuIoThunk,
    432                   This->DriverBindingHandle,
    433                   Handle,
    434                   EFI_OPEN_PROTOCOL_BY_DRIVER
    435                   );
    436   if (EFI_ERROR (Status)) {
    437     return Status;
    438   }
    439 
    440   //
    441   // Make sure GUID is for a File System handle.
    442   //
    443   Status = EFI_UNSUPPORTED;
    444   if (CompareGuid (EmuIoThunk->Protocol, &gEmuBlockIoProtocolGuid)) {
    445     Status = EFI_SUCCESS;
    446   }
    447 
    448   //
    449   // Close the I/O Abstraction(s) used to perform the supported test
    450   //
    451   gBS->CloseProtocol (
    452         Handle,
    453         &gEmuIoThunkProtocolGuid,
    454         This->DriverBindingHandle,
    455         Handle
    456         );
    457   return Status;
    458 }
    459 
    460 
    461 /**
    462   Starts a device controller or a bus controller.
    463 
    464   The Start() function is designed to be invoked from the EFI boot service ConnectController().
    465   As a result, much of the error checking on the parameters to Start() has been moved into this
    466   common boot service. It is legal to call Start() from other locations,
    467   but the following calling restrictions must be followed, or the system behavior will not be deterministic.
    468   1. ControllerHandle must be a valid EFI_HANDLE.
    469   2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
    470      EFI_DEVICE_PATH_PROTOCOL.
    471   3. Prior to calling Start(), the Supported() function for the driver specified by This must
    472      have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
    473 
    474   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
    475   @param[in]  ControllerHandle     The handle of the controller to start. This handle
    476                                    must support a protocol interface that supplies
    477                                    an I/O abstraction to the driver.
    478   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
    479                                    parameter is ignored by device drivers, and is optional for bus
    480                                    drivers. For a bus driver, if this parameter is NULL, then handles
    481                                    for all the children of Controller are created by this driver.
    482                                    If this parameter is not NULL and the first Device Path Node is
    483                                    not the End of Device Path Node, then only the handle for the
    484                                    child device specified by the first Device Path Node of
    485                                    RemainingDevicePath is created by this driver.
    486                                    If the first Device Path Node of RemainingDevicePath is
    487                                    the End of Device Path Node, no child handle is created by this
    488                                    driver.
    489 
    490   @retval EFI_SUCCESS              The device was started.
    491   @retval EFI_DEVICE_ERROR         The device could not be started due to a device error.Currently not implemented.
    492   @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
    493   @retval Others                   The driver failded to start the device.
    494 
    495 **/
    496 EFI_STATUS
    497 EFIAPI
    498 EmuBlockIoDriverBindingStart (
    499   IN  EFI_DRIVER_BINDING_PROTOCOL   *This,
    500   IN  EFI_HANDLE                    Handle,
    501   IN  EFI_DEVICE_PATH_PROTOCOL      *RemainingDevicePath
    502   )
    503 {
    504   EFI_STATUS                  Status;
    505   EMU_IO_THUNK_PROTOCOL       *EmuIoThunk;
    506   EMU_BLOCK_IO_PRIVATE        *Private = NULL;
    507 
    508   //
    509   // Grab the protocols we need
    510   //
    511 
    512   Status = gBS->OpenProtocol (
    513                   Handle,
    514                   &gEmuIoThunkProtocolGuid,
    515                   (void *)&EmuIoThunk,
    516                   This->DriverBindingHandle,
    517                   Handle,
    518                   EFI_OPEN_PROTOCOL_BY_DRIVER
    519                   );
    520   if (EFI_ERROR (Status)) {
    521     return Status;
    522   }
    523 
    524   if (!CompareGuid (EmuIoThunk->Protocol, &gEmuBlockIoProtocolGuid)) {
    525     Status = EFI_UNSUPPORTED;
    526     goto Done;
    527   }
    528 
    529   Status = EmuIoThunk->Open (EmuIoThunk);
    530   if (EFI_ERROR (Status)) {
    531     goto Done;
    532   }
    533 
    534   Private = AllocatePool (sizeof (EMU_BLOCK_IO_PRIVATE));
    535   if (Private == NULL) {
    536     goto Done;
    537   }
    538 
    539   Private->Signature = EMU_BLOCK_IO_PRIVATE_SIGNATURE;
    540   Private->IoThunk   = EmuIoThunk;
    541   Private->Io        = EmuIoThunk->Interface;
    542   Private->EfiHandle = Handle;
    543 
    544   Private->BlockIo.Revision    = EFI_BLOCK_IO_PROTOCOL_REVISION2;
    545   Private->BlockIo.Media       = &Private->Media;
    546   Private->BlockIo.Reset       = EmuBlockIoReset;
    547   Private->BlockIo.ReadBlocks  = EmuBlockIoReadBlocks;
    548   Private->BlockIo.WriteBlocks = EmuBlockIoWriteBlocks;
    549   Private->BlockIo.FlushBlocks = EmuBlockIoFlushBlocks;
    550 
    551   Private->BlockIo2.Media         = &Private->Media;
    552   Private->BlockIo2.Reset         = EmuBlockIo2Reset;
    553   Private->BlockIo2.ReadBlocksEx  = EmuBlockIo2ReadBlocksEx;
    554   Private->BlockIo2.WriteBlocksEx = EmuBlockIo2WriteBlocksEx;
    555   Private->BlockIo2.FlushBlocksEx = EmuBlockIo2Flush;
    556 
    557   Private->ControllerNameTable = NULL;
    558 
    559   Status = Private->Io->CreateMapping (Private->Io, &Private->Media);
    560   if (EFI_ERROR (Status)) {
    561     goto Done;
    562   }
    563 
    564   AddUnicodeString2 (
    565     "eng",
    566     gEmuBlockIoComponentName.SupportedLanguages,
    567     &Private->ControllerNameTable,
    568     EmuIoThunk->ConfigString,
    569     TRUE
    570     );
    571 
    572   AddUnicodeString2 (
    573     "en",
    574     gEmuBlockIoComponentName2.SupportedLanguages,
    575     &Private->ControllerNameTable,
    576     EmuIoThunk->ConfigString,
    577     FALSE
    578     );
    579 
    580   Status = gBS->InstallMultipleProtocolInterfaces (
    581                   &Handle,
    582                   &gEfiBlockIoProtocolGuid,    &Private->BlockIo,
    583                   &gEfiBlockIo2ProtocolGuid,   &Private->BlockIo2,
    584                   NULL
    585                   );
    586 
    587 Done:
    588   if (EFI_ERROR (Status)) {
    589     if (Private != NULL) {
    590       if (Private->ControllerNameTable != NULL) {
    591         FreeUnicodeStringTable (Private->ControllerNameTable);
    592       }
    593 
    594       gBS->FreePool (Private);
    595 
    596     }
    597 
    598     gBS->CloseProtocol (
    599           Handle,
    600           &gEmuIoThunkProtocolGuid,
    601           This->DriverBindingHandle,
    602           Handle
    603           );
    604   }
    605 
    606   return Status;
    607 }
    608 
    609 
    610 /**
    611   Stops a device controller or a bus controller.
    612 
    613   The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
    614   As a result, much of the error checking on the parameters to Stop() has been moved
    615   into this common boot service. It is legal to call Stop() from other locations,
    616   but the following calling restrictions must be followed, or the system behavior will not be deterministic.
    617   1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
    618      same driver's Start() function.
    619   2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
    620      EFI_HANDLE. In addition, all of these handles must have been created in this driver's
    621      Start() function, and the Start() function must have called OpenProtocol() on
    622      ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
    623 
    624   @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
    625   @param[in]  ControllerHandle  A handle to the device being stopped. The handle must
    626                                 support a bus specific I/O protocol for the driver
    627                                 to use to stop the device.
    628   @param[in]  NumberOfChildren  The number of child device handles in ChildHandleBuffer.
    629   @param[in]  ChildHandleBuffer An array of child handles to be freed. May be NULL
    630                                 if NumberOfChildren is 0.
    631 
    632   @retval EFI_SUCCESS           The device was stopped.
    633   @retval EFI_DEVICE_ERROR      The device could not be stopped due to a device error.
    634 
    635 **/
    636 EFI_STATUS
    637 EFIAPI
    638 EmuBlockIoDriverBindingStop (
    639   IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
    640   IN  EFI_HANDLE                   Handle,
    641   IN  UINTN                        NumberOfChildren,
    642   IN  EFI_HANDLE                   *ChildHandleBuffer
    643   )
    644 {
    645   EFI_BLOCK_IO_PROTOCOL   *BlockIo;
    646   EFI_STATUS              Status;
    647   EMU_BLOCK_IO_PRIVATE *Private;
    648 
    649   //
    650   // Get our context back
    651   //
    652   Status = gBS->OpenProtocol (
    653                   Handle,
    654                   &gEfiBlockIoProtocolGuid,
    655                   (void *)&BlockIo,
    656                   This->DriverBindingHandle,
    657                   Handle,
    658                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    659                   );
    660   if (EFI_ERROR (Status)) {
    661     return EFI_UNSUPPORTED;
    662   }
    663 
    664   Private = EMU_BLOCK_IO_PRIVATE_DATA_FROM_THIS (BlockIo);
    665   Status = Private->IoThunk->Close (Private->IoThunk);
    666 
    667   Status = gBS->UninstallMultipleProtocolInterfaces (
    668                   Private->EfiHandle,
    669                   &gEfiBlockIoProtocolGuid,   &Private->BlockIo,
    670                   &gEfiBlockIo2ProtocolGuid,  &Private->BlockIo2,
    671                   NULL
    672                   );
    673   if (!EFI_ERROR (Status)) {
    674     Status = gBS->CloseProtocol (
    675                     Handle,
    676                     &gEmuIoThunkProtocolGuid,
    677                     This->DriverBindingHandle,
    678                     Handle
    679                     );
    680   }
    681 
    682   if (!EFI_ERROR (Status)) {
    683     //
    684     // Free our instance data
    685     //
    686     FreeUnicodeStringTable (Private->ControllerNameTable);
    687     gBS->FreePool (Private);
    688   }
    689 
    690   return Status;
    691 }
    692 
    693 
    694 
    695 
    696 
    697 EFI_DRIVER_BINDING_PROTOCOL gEmuBlockIoDriverBinding = {
    698   EmuBlockIoDriverBindingSupported,
    699   EmuBlockIoDriverBindingStart,
    700   EmuBlockIoDriverBindingStop,
    701   0xa,
    702   NULL,
    703   NULL
    704 };
    705 
    706 
    707 
    708 
    709 /**
    710   The user Entry Point for module EmuBlockIo . The user code starts with this function.
    711 
    712   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
    713   @param[in] SystemTable    A pointer to the EFI System Table.
    714 
    715   @retval EFI_SUCCESS       The entry point is executed successfully.
    716   @retval other             Some error occurs when executing this entry point.
    717 
    718 **/
    719 EFI_STATUS
    720 EFIAPI
    721 InitializeEmuBlockIo (
    722   IN EFI_HANDLE           ImageHandle,
    723   IN EFI_SYSTEM_TABLE     *SystemTable
    724   )
    725 {
    726   EFI_STATUS              Status;
    727 
    728   Status = EfiLibInstallAllDriverProtocols2 (
    729              ImageHandle,
    730              SystemTable,
    731              &gEmuBlockIoDriverBinding,
    732              ImageHandle,
    733              &gEmuBlockIoComponentName,
    734              &gEmuBlockIoComponentName2,
    735              NULL,
    736              NULL,
    737              &gEmuBlockIoDriverDiagnostics,
    738              &gEmuBlockIoDriverDiagnostics2
    739              );
    740   ASSERT_EFI_ERROR (Status);
    741 
    742 
    743   return Status;
    744 }
    745 
    746 
    747 
    748