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
EmuBlockIo2Reset(IN EFI_BLOCK_IO2_PROTOCOL * This,IN BOOLEAN ExtendedVerification)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
EmuBlockIo2ReadBlocksEx(IN EFI_BLOCK_IO2_PROTOCOL * This,IN UINT32 MediaId,IN EFI_LBA LBA,IN OUT EFI_BLOCK_IO2_TOKEN * Token,IN UINTN BufferSize,OUT VOID * Buffer)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
EmuBlockIo2WriteBlocksEx(IN EFI_BLOCK_IO2_PROTOCOL * This,IN UINT32 MediaId,IN EFI_LBA LBA,IN OUT EFI_BLOCK_IO2_TOKEN * Token,IN UINTN BufferSize,IN VOID * Buffer)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
EmuBlockIo2Flush(IN EFI_BLOCK_IO2_PROTOCOL * This,IN OUT EFI_BLOCK_IO2_TOKEN * Token)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
EmuBlockIoReset(IN EFI_BLOCK_IO_PROTOCOL * This,IN BOOLEAN ExtendedVerification)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
EmuBlockIoReadBlocks(IN EFI_BLOCK_IO_PROTOCOL * This,IN UINT32 MediaId,IN EFI_LBA Lba,IN UINTN BufferSize,OUT VOID * Buffer)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
EmuBlockIoWriteBlocks(IN EFI_BLOCK_IO_PROTOCOL * This,IN UINT32 MediaId,IN EFI_LBA Lba,IN UINTN BufferSize,IN VOID * Buffer)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
EmuBlockIoFlushBlocks(IN EFI_BLOCK_IO_PROTOCOL * This)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
EmuBlockIoDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Handle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)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
EmuBlockIoDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Handle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)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
EmuBlockIoDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Handle,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)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
InitializeEmuBlockIo(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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