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
BlockIoReset(IN EFI_BLOCK_IO_PROTOCOL * This,IN BOOLEAN ExtendedVerification)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
ReadOrWriteBlocks(IN EFI_BLOCK_IO_PROTOCOL * This,IN BOOLEAN ReadData,IN UINT32 MediaId,IN EFI_LBA Lba,IN UINTN BufferSize,OUT VOID * Buffer)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
BlockIoReadBlocks(IN EFI_BLOCK_IO_PROTOCOL * This,IN UINT32 MediaId,IN EFI_LBA Lba,IN UINTN BufferSize,OUT VOID * Buffer)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
BlockIoWriteBlocks(IN EFI_BLOCK_IO_PROTOCOL * This,IN UINT32 MediaId,IN EFI_LBA Lba,IN UINTN BufferSize,IN VOID * Buffer)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
BlockIoFlushBlocks(IN EFI_BLOCK_IO_PROTOCOL * This)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
BlockIoInit(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller)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
BlockIoDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)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
BlockIoDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)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
BlockIoDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)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
BlockMmioToBlockIoEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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