2 USB Mass Storage Driver that manages USB Mass Storage Device and produces Block I/O Protocol.
4 Copyright (c) 2007 - 2011, 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
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.
17 #define USB_MASS_TRANSPORT_COUNT 3
19 // Array of USB transport interfaces.
21 USB_MASS_TRANSPORT
*mUsbMassTransport
[USB_MASS_TRANSPORT_COUNT
] = {
27 EFI_DRIVER_BINDING_PROTOCOL gUSBMassDriverBinding
= {
28 USBMassDriverBindingSupported
,
29 USBMassDriverBindingStart
,
30 USBMassDriverBindingStop
,
37 Reset the block device.
39 This function implements EFI_BLOCK_IO_PROTOCOL.Reset().
40 It resets the block device hardware.
41 ExtendedVerification is ignored in this implementation.
43 @param This Indicates a pointer to the calling context.
44 @param ExtendedVerification Indicates that the driver may perform a more exhaustive
45 verification operation of the device during reset.
47 @retval EFI_SUCCESS The block device was reset.
48 @retval EFI_DEVICE_ERROR The block device is not functioning correctly and could not be reset.
54 IN EFI_BLOCK_IO_PROTOCOL
*This
,
55 IN BOOLEAN ExtendedVerification
58 USB_MASS_DEVICE
*UsbMass
;
63 // Raise TPL to TPL_NOTIFY to serialize all its operations
64 // to protect shared data structures.
66 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
68 UsbMass
= USB_MASS_DEVICE_FROM_BLOCK_IO (This
);
69 Status
= UsbMass
->Transport
->Reset (UsbMass
->Context
, ExtendedVerification
);
71 gBS
->RestoreTPL (OldTpl
);
77 Reads the requested number of blocks from the device.
79 This function implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks().
80 It reads the requested number of blocks from the device.
81 All the blocks are read, or an error is returned.
83 @param This Indicates a pointer to the calling context.
84 @param MediaId The media ID that the read request is for.
85 @param Lba The starting logical block address to read from on the device.
86 @param BufferSize The size of the Buffer in bytes.
87 This must be a multiple of the intrinsic block size of the device.
88 @param Buffer A pointer to the destination buffer for the data. The caller is
89 responsible for either having implicit or explicit ownership of the buffer.
91 @retval EFI_SUCCESS The data was read correctly from the device.
92 @retval EFI_DEVICE_ERROR The device reported an error while attempting to perform the read operation.
93 @retval EFI_NO_MEDIA There is no media in the device.
94 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
95 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the intrinsic block size of the device.
96 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
97 or the buffer is not on proper alignment.
103 IN EFI_BLOCK_IO_PROTOCOL
*This
,
110 USB_MASS_DEVICE
*UsbMass
;
111 EFI_BLOCK_IO_MEDIA
*Media
;
117 // Raise TPL to TPL_NOTIFY to serialize all its operations
118 // to protect shared data structures.
120 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
121 UsbMass
= USB_MASS_DEVICE_FROM_BLOCK_IO (This
);
122 Media
= &UsbMass
->BlockIoMedia
;
125 // If it is a removable media, such as CD-Rom or Usb-Floppy,
126 // need to detect the media before each read/write. While some of
127 // Usb-Flash is marked as removable media.
129 if (Media
->RemovableMedia
) {
130 Status
= UsbBootDetectMedia (UsbMass
);
131 if (EFI_ERROR (Status
)) {
136 if (!(Media
->MediaPresent
)) {
137 Status
= EFI_NO_MEDIA
;
141 if (MediaId
!= Media
->MediaId
) {
142 Status
= EFI_MEDIA_CHANGED
;
146 if (BufferSize
== 0) {
147 Status
= EFI_SUCCESS
;
151 if (Buffer
== NULL
) {
152 Status
= EFI_INVALID_PARAMETER
;
157 // BufferSize must be a multiple of the intrinsic block size of the device.
159 if ((BufferSize
% Media
->BlockSize
) != 0) {
160 Status
= EFI_BAD_BUFFER_SIZE
;
164 TotalBlock
= BufferSize
/ Media
->BlockSize
;
167 // Make sure the range to read is valid.
169 if (Lba
+ TotalBlock
- 1 > Media
->LastBlock
) {
170 Status
= EFI_INVALID_PARAMETER
;
174 Status
= UsbBootReadBlocks (UsbMass
, (UINT32
) Lba
, TotalBlock
, Buffer
);
175 if (EFI_ERROR (Status
)) {
176 DEBUG ((EFI_D_ERROR
, "UsbMassReadBlocks: UsbBootReadBlocks (%r) -> Reset\n", Status
));
177 UsbMassReset (This
, TRUE
);
181 gBS
->RestoreTPL (OldTpl
);
187 Writes a specified number of blocks to the device.
189 This function implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks().
190 It writes a specified number of blocks to the device.
191 All blocks are written, or an error is returned.
193 @param This Indicates a pointer to the calling context.
194 @param MediaId The media ID that the write request is for.
195 @param Lba The starting logical block address to be written.
196 @param BufferSize The size of the Buffer in bytes.
197 This must be a multiple of the intrinsic block size of the device.
198 @param Buffer Pointer to the source buffer for the data.
200 @retval EFI_SUCCESS The data were written correctly to the device.
201 @retval EFI_WRITE_PROTECTED The device cannot be written to.
202 @retval EFI_NO_MEDIA There is no media in the device.
203 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
204 @retval EFI_DEVICE_ERROR The device reported an error while attempting to perform the write operation.
205 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the intrinsic
206 block size of the device.
207 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
208 or the buffer is not on proper alignment.
214 IN EFI_BLOCK_IO_PROTOCOL
*This
,
221 USB_MASS_DEVICE
*UsbMass
;
222 EFI_BLOCK_IO_MEDIA
*Media
;
228 // Raise TPL to TPL_NOTIFY to serialize all its operations
229 // to protect shared data structures.
231 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
232 UsbMass
= USB_MASS_DEVICE_FROM_BLOCK_IO (This
);
233 Media
= &UsbMass
->BlockIoMedia
;
236 // If it is a removable media, such as CD-Rom or Usb-Floppy,
237 // need to detect the media before each read/write. Some of
238 // USB Flash is marked as removable media.
240 if (Media
->RemovableMedia
) {
241 Status
= UsbBootDetectMedia (UsbMass
);
242 if (EFI_ERROR (Status
)) {
247 if (!(Media
->MediaPresent
)) {
248 Status
= EFI_NO_MEDIA
;
252 if (MediaId
!= Media
->MediaId
) {
253 Status
= EFI_MEDIA_CHANGED
;
257 if (BufferSize
== 0) {
258 Status
= EFI_SUCCESS
;
262 if (Buffer
== NULL
) {
263 Status
= EFI_INVALID_PARAMETER
;
268 // BufferSize must be a multiple of the intrinsic block size of the device.
270 if ((BufferSize
% Media
->BlockSize
) != 0) {
271 Status
= EFI_BAD_BUFFER_SIZE
;
275 TotalBlock
= BufferSize
/ Media
->BlockSize
;
278 // Make sure the range to write is valid.
280 if (Lba
+ TotalBlock
- 1 > Media
->LastBlock
) {
281 Status
= EFI_INVALID_PARAMETER
;
286 // Try to write the data even the device is marked as ReadOnly,
287 // and clear the status should the write succeed.
289 Status
= UsbBootWriteBlocks (UsbMass
, (UINT32
) Lba
, TotalBlock
, Buffer
);
290 if (EFI_ERROR (Status
)) {
291 DEBUG ((EFI_D_ERROR
, "UsbMassWriteBlocks: UsbBootWriteBlocks (%r) -> Reset\n", Status
));
292 UsbMassReset (This
, TRUE
);
296 gBS
->RestoreTPL (OldTpl
);
301 Flushes all modified data to a physical block device.
303 This function implements EFI_BLOCK_IO_PROTOCOL.FlushBlocks().
304 USB mass storage device doesn't support write cache,
305 so return EFI_SUCCESS directly.
307 @param This Indicates a pointer to the calling context.
309 @retval EFI_SUCCESS All outstanding data were written correctly to the device.
310 @retval EFI_DEVICE_ERROR The device reported an error while attempting to write data.
311 @retval EFI_NO_MEDIA There is no media in the device.
317 IN EFI_BLOCK_IO_PROTOCOL
*This
324 Initialize the media parameter data for EFI_BLOCK_IO_MEDIA of Block I/O Protocol.
326 @param UsbMass The USB mass storage device
328 @retval EFI_SUCCESS The media parameters are updated successfully.
329 @retval Others Failed to get the media parameters.
334 IN USB_MASS_DEVICE
*UsbMass
337 EFI_BLOCK_IO_MEDIA
*Media
;
341 Media
= &UsbMass
->BlockIoMedia
;
344 // Fields of EFI_BLOCK_IO_MEDIA are defined in UEFI 2.0 spec,
345 // section for Block I/O Protocol.
347 Media
->MediaPresent
= FALSE
;
348 Media
->LogicalPartition
= FALSE
;
349 Media
->ReadOnly
= FALSE
;
350 Media
->WriteCaching
= FALSE
;
355 // Some device may spend several seconds before it is ready.
356 // Try several times before giving up. Wait 5s at most.
358 Status
= EFI_SUCCESS
;
360 for (Index
= 0; Index
< USB_BOOT_INIT_MEDIA_RETRY
; Index
++) {
362 Status
= UsbBootGetParams (UsbMass
);
363 if ((Status
!= EFI_MEDIA_CHANGED
) && (Status
!= EFI_NOT_READY
) && (Status
!= EFI_TIMEOUT
)) {
367 Status
= UsbBootIsUnitReady (UsbMass
);
368 if (EFI_ERROR (Status
)) {
369 gBS
->Stall (USB_BOOT_RETRY_UNIT_READY_STALL
* (Index
+ 1));
377 Initilize the USB Mass Storage transport.
379 This function tries to find the matching USB Mass Storage transport
380 protocol for USB device. If found, initializes the matching transport.
382 @param This The USB mass driver's driver binding.
383 @param Controller The device to test.
384 @param Transport The pointer to pointer to USB_MASS_TRANSPORT.
385 @param Context The parameter for USB_MASS_DEVICE.Context.
386 @param MaxLun Get the MaxLun if is BOT dev.
388 @retval EFI_SUCCESS The initialization is successful.
389 @retval EFI_UNSUPPORTED No matching transport protocol is found.
390 @retval Others Failed to initialize dev.
394 UsbMassInitTransport (
395 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
396 IN EFI_HANDLE Controller
,
397 OUT USB_MASS_TRANSPORT
**Transport
,
402 EFI_USB_IO_PROTOCOL
*UsbIo
;
403 EFI_USB_INTERFACE_DESCRIPTOR Interface
;
407 Status
= gBS
->OpenProtocol (
409 &gEfiUsbIoProtocolGuid
,
411 This
->DriverBindingHandle
,
413 EFI_OPEN_PROTOCOL_BY_DRIVER
416 if (EFI_ERROR (Status
)) {
420 Status
= UsbIo
->UsbGetInterfaceDescriptor (UsbIo
, &Interface
);
421 if (EFI_ERROR (Status
)) {
425 Status
= EFI_UNSUPPORTED
;
428 // Traverse the USB_MASS_TRANSPORT arrary and try to find the
429 // matching transport protocol.
430 // If not found, return EFI_UNSUPPORTED.
431 // If found, execute USB_MASS_TRANSPORT.Init() to initialize the transport context.
433 for (Index
= 0; Index
< USB_MASS_TRANSPORT_COUNT
; Index
++) {
434 *Transport
= mUsbMassTransport
[Index
];
436 if (Interface
.InterfaceProtocol
== (*Transport
)->Protocol
) {
437 Status
= (*Transport
)->Init (UsbIo
, Context
);
442 if (EFI_ERROR (Status
)) {
447 // For BOT device, try to get its max LUN.
448 // If max LUN is 0, then it is a non-lun device.
449 // Otherwise, it is a multi-lun device.
451 if ((*Transport
)->Protocol
== USB_MASS_STORE_BOT
) {
452 (*Transport
)->GetMaxLun (*Context
, MaxLun
);
458 &gEfiUsbIoProtocolGuid
,
459 This
->DriverBindingHandle
,
466 Initialize data for device that supports multiple LUNSs.
468 @param This The Driver Binding Protocol instance.
469 @param Controller The device to initialize.
470 @param Transport Pointer to USB_MASS_TRANSPORT.
471 @param Context Parameter for USB_MASS_DEVICE.Context.
472 @param DevicePath The remaining device path.
473 @param MaxLun The max LUN number.
475 @retval EFI_SUCCESS At least one LUN is initialized successfully.
476 @retval EFI_OUT_OF_RESOURCES Out of resource while creating device path node.
477 @retval Other Initialization fails.
481 UsbMassInitMultiLun (
482 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
483 IN EFI_HANDLE Controller
,
484 IN USB_MASS_TRANSPORT
*Transport
,
486 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
490 USB_MASS_DEVICE
*UsbMass
;
491 EFI_USB_IO_PROTOCOL
*UsbIo
;
492 DEVICE_LOGICAL_UNIT_DEVICE_PATH LunNode
;
498 for (Index
= 0; Index
<= MaxLun
; Index
++) {
500 DEBUG ((EFI_D_INFO
, "UsbMassInitMultiLun: Start to initialize No.%d logic unit\n", Index
));
503 UsbMass
= AllocateZeroPool (sizeof (USB_MASS_DEVICE
));
504 ASSERT (UsbMass
!= NULL
);
506 UsbMass
->Signature
= USB_MASS_SIGNATURE
;
507 UsbMass
->UsbIo
= UsbIo
;
508 UsbMass
->BlockIo
.Media
= &UsbMass
->BlockIoMedia
;
509 UsbMass
->BlockIo
.Reset
= UsbMassReset
;
510 UsbMass
->BlockIo
.ReadBlocks
= UsbMassReadBlocks
;
511 UsbMass
->BlockIo
.WriteBlocks
= UsbMassWriteBlocks
;
512 UsbMass
->BlockIo
.FlushBlocks
= UsbMassFlushBlocks
;
513 UsbMass
->OpticalStorage
= FALSE
;
514 UsbMass
->Transport
= Transport
;
515 UsbMass
->Context
= Context
;
516 UsbMass
->Lun
= Index
;
519 // Initialize the media parameter data for EFI_BLOCK_IO_MEDIA of Block I/O Protocol.
521 Status
= UsbMassInitMedia (UsbMass
);
522 if (!EFI_ERROR (Status
)) {
524 // According to USB Mass Storage Specification for Bootability, only following
525 // 4 Peripheral Device Types are in spec.
527 if ((UsbMass
->Pdt
!= USB_PDT_DIRECT_ACCESS
) &&
528 (UsbMass
->Pdt
!= USB_PDT_CDROM
) &&
529 (UsbMass
->Pdt
!= USB_PDT_OPTICAL
) &&
530 (UsbMass
->Pdt
!= USB_PDT_SIMPLE_DIRECT
)) {
531 DEBUG ((EFI_D_ERROR
, "UsbMassInitMultiLun: Found an unsupported peripheral type[%d]\n", UsbMass
->Pdt
));
534 } else if (Status
!= EFI_NO_MEDIA
){
535 DEBUG ((EFI_D_ERROR
, "UsbMassInitMultiLun: UsbMassInitMedia (%r)\n", Status
));
540 // Create a device path node for device logic unit, and append it.
542 LunNode
.Header
.Type
= MESSAGING_DEVICE_PATH
;
543 LunNode
.Header
.SubType
= MSG_DEVICE_LOGICAL_UNIT_DP
;
544 LunNode
.Lun
= UsbMass
->Lun
;
546 SetDevicePathNodeLength (&LunNode
.Header
, sizeof (LunNode
));
548 UsbMass
->DevicePath
= AppendDevicePathNode (DevicePath
, &LunNode
.Header
);
550 if (UsbMass
->DevicePath
== NULL
) {
551 DEBUG ((EFI_D_ERROR
, "UsbMassInitMultiLun: failed to create device logic unit device path\n"));
553 Status
= EFI_OUT_OF_RESOURCES
;
557 InitializeDiskInfo (UsbMass
);
560 // Create a new handle for each LUN, and install Block I/O Protocol and Device Path Protocol.
562 Status
= gBS
->InstallMultipleProtocolInterfaces (
563 &UsbMass
->Controller
,
564 &gEfiDevicePathProtocolGuid
,
566 &gEfiBlockIoProtocolGuid
,
568 &gEfiDiskInfoProtocolGuid
,
573 if (EFI_ERROR (Status
)) {
574 DEBUG ((EFI_D_ERROR
, "UsbMassInitMultiLun: InstallMultipleProtocolInterfaces (%r)\n", Status
));
579 // Open USB I/O Protocol by child to setup a parent-child relationship.
581 Status
= gBS
->OpenProtocol (
583 &gEfiUsbIoProtocolGuid
,
585 This
->DriverBindingHandle
,
587 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
590 if (EFI_ERROR (Status
)) {
591 DEBUG ((EFI_D_ERROR
, "UsbMassInitMultiLun: OpenUsbIoProtocol By Child (%r)\n", Status
));
592 gBS
->UninstallMultipleProtocolInterfaces (
593 &UsbMass
->Controller
,
594 &gEfiDevicePathProtocolGuid
,
596 &gEfiBlockIoProtocolGuid
,
598 &gEfiDiskInfoProtocolGuid
,
605 DEBUG ((EFI_D_INFO
, "UsbMassInitMultiLun: Success to initialize No.%d logic unit\n", Index
));
611 if (UsbMass
!= NULL
) {
612 if (UsbMass
->DevicePath
!= NULL
) {
613 FreePool (UsbMass
->DevicePath
);
620 &gEfiUsbIoProtocolGuid
,
621 This
->DriverBindingHandle
,
627 // Return EFI_SUCCESS if at least one LUN is initialized successfully.
637 Initialize data for device that does not support multiple LUNSs.
639 @param This The Driver Binding Protocol instance.
640 @param Controller The device to initialize.
641 @param Transport Pointer to USB_MASS_TRANSPORT.
642 @param Context Parameter for USB_MASS_DEVICE.Context.
644 @retval EFI_SUCCESS Initialization succeeds.
645 @retval Other Initialization fails.
650 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
651 IN EFI_HANDLE Controller
,
652 IN USB_MASS_TRANSPORT
*Transport
,
656 USB_MASS_DEVICE
*UsbMass
;
657 EFI_USB_IO_PROTOCOL
*UsbIo
;
661 UsbMass
= AllocateZeroPool (sizeof (USB_MASS_DEVICE
));
662 ASSERT (UsbMass
!= NULL
);
664 Status
= gBS
->OpenProtocol (
666 &gEfiUsbIoProtocolGuid
,
668 This
->DriverBindingHandle
,
670 EFI_OPEN_PROTOCOL_BY_DRIVER
673 if (EFI_ERROR (Status
)) {
674 DEBUG ((EFI_D_ERROR
, "UsbMassInitNonLun: OpenUsbIoProtocol By Driver (%r)\n", Status
));
678 UsbMass
->Signature
= USB_MASS_SIGNATURE
;
679 UsbMass
->Controller
= Controller
;
680 UsbMass
->UsbIo
= UsbIo
;
681 UsbMass
->BlockIo
.Media
= &UsbMass
->BlockIoMedia
;
682 UsbMass
->BlockIo
.Reset
= UsbMassReset
;
683 UsbMass
->BlockIo
.ReadBlocks
= UsbMassReadBlocks
;
684 UsbMass
->BlockIo
.WriteBlocks
= UsbMassWriteBlocks
;
685 UsbMass
->BlockIo
.FlushBlocks
= UsbMassFlushBlocks
;
686 UsbMass
->OpticalStorage
= FALSE
;
687 UsbMass
->Transport
= Transport
;
688 UsbMass
->Context
= Context
;
691 // Initialize the media parameter data for EFI_BLOCK_IO_MEDIA of Block I/O Protocol.
693 Status
= UsbMassInitMedia (UsbMass
);
694 if (!EFI_ERROR (Status
)) {
696 // According to USB Mass Storage Specification for Bootability, only following
697 // 4 Peripheral Device Types are in spec.
699 if ((UsbMass
->Pdt
!= USB_PDT_DIRECT_ACCESS
) &&
700 (UsbMass
->Pdt
!= USB_PDT_CDROM
) &&
701 (UsbMass
->Pdt
!= USB_PDT_OPTICAL
) &&
702 (UsbMass
->Pdt
!= USB_PDT_SIMPLE_DIRECT
)) {
703 DEBUG ((EFI_D_ERROR
, "UsbMassInitNonLun: Found an unsupported peripheral type[%d]\n", UsbMass
->Pdt
));
706 } else if (Status
!= EFI_NO_MEDIA
){
707 DEBUG ((EFI_D_ERROR
, "UsbMassInitNonLun: UsbMassInitMedia (%r)\n", Status
));
711 InitializeDiskInfo (UsbMass
);
713 Status
= gBS
->InstallMultipleProtocolInterfaces (
715 &gEfiBlockIoProtocolGuid
,
717 &gEfiDiskInfoProtocolGuid
,
721 if (EFI_ERROR (Status
)) {
728 if (UsbMass
!= NULL
) {
734 &gEfiUsbIoProtocolGuid
,
735 This
->DriverBindingHandle
,
744 Check whether the controller is a supported USB mass storage.
746 @param This The USB mass storage driver binding protocol.
747 @param Controller The controller handle to check.
748 @param RemainingDevicePath The remaining device path.
750 @retval EFI_SUCCESS The driver supports this controller.
751 @retval other This device isn't supported.
756 USBMassDriverBindingSupported (
757 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
758 IN EFI_HANDLE Controller
,
759 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
762 EFI_USB_IO_PROTOCOL
*UsbIo
;
763 EFI_USB_INTERFACE_DESCRIPTOR Interface
;
764 USB_MASS_TRANSPORT
*Transport
;
768 Status
= gBS
->OpenProtocol (
770 &gEfiUsbIoProtocolGuid
,
772 This
->DriverBindingHandle
,
774 EFI_OPEN_PROTOCOL_BY_DRIVER
776 if (EFI_ERROR (Status
)) {
781 // Get the interface descriptor to check the USB class and find a transport
784 Status
= UsbIo
->UsbGetInterfaceDescriptor (UsbIo
, &Interface
);
785 if (EFI_ERROR (Status
)) {
789 Status
= EFI_UNSUPPORTED
;
791 if (Interface
.InterfaceClass
!= USB_MASS_STORE_CLASS
) {
796 // Traverse the USB_MASS_TRANSPORT arrary and try to find the
797 // matching transport method.
798 // If not found, return EFI_UNSUPPORTED.
799 // If found, execute USB_MASS_TRANSPORT.Init() to initialize the transport context.
801 for (Index
= 0; Index
< USB_MASS_TRANSPORT_COUNT
; Index
++) {
802 Transport
= mUsbMassTransport
[Index
];
803 if (Interface
.InterfaceProtocol
== Transport
->Protocol
) {
804 Status
= Transport
->Init (UsbIo
, NULL
);
812 &gEfiUsbIoProtocolGuid
,
813 This
->DriverBindingHandle
,
821 Starts the USB mass storage device with this driver.
823 This function consumes USB I/O Portocol, intializes USB mass storage device,
824 installs Block I/O Protocol, and submits Asynchronous Interrupt
825 Transfer to manage the USB mass storage device.
827 @param This The USB mass storage driver binding protocol.
828 @param Controller The USB mass storage device to start on
829 @param RemainingDevicePath The remaining device path.
831 @retval EFI_SUCCESS This driver supports this device.
832 @retval EFI_UNSUPPORTED This driver does not support this device.
833 @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.
834 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
835 @retval EFI_ALREADY_STARTED This driver has been started.
840 USBMassDriverBindingStart (
841 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
842 IN EFI_HANDLE Controller
,
843 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
846 USB_MASS_TRANSPORT
*Transport
;
847 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
851 EFI_USB_IO_PROTOCOL
*UsbIo
;
854 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
860 Status
= UsbMassInitTransport (This
, Controller
, &Transport
, &Context
, &MaxLun
);
862 if (EFI_ERROR (Status
)) {
863 DEBUG ((EFI_D_ERROR
, "USBMassDriverBindingStart: UsbMassInitTransport (%r)\n", Status
));
868 // Initialize data for device that does not support multiple LUNSs.
870 Status
= UsbMassInitNonLun (This
, Controller
, Transport
, Context
);
871 if (EFI_ERROR (Status
)) {
872 DEBUG ((EFI_D_ERROR
, "USBMassDriverBindingStart: UsbMassInitNonLun (%r)\n", Status
));
876 // Open device path to prepare for appending Device Logic Unit node.
878 Status
= gBS
->OpenProtocol (
880 &gEfiDevicePathProtocolGuid
,
881 (VOID
**) &DevicePath
,
882 This
->DriverBindingHandle
,
884 EFI_OPEN_PROTOCOL_BY_DRIVER
887 if (EFI_ERROR (Status
)) {
888 DEBUG ((EFI_D_ERROR
, "USBMassDriverBindingStart: OpenDevicePathProtocol By Driver (%r)\n", Status
));
892 Status
= gBS
->OpenProtocol (
894 &gEfiUsbIoProtocolGuid
,
896 This
->DriverBindingHandle
,
898 EFI_OPEN_PROTOCOL_BY_DRIVER
901 if (EFI_ERROR (Status
)) {
902 DEBUG ((EFI_D_ERROR
, "USBMassDriverBindingStart: OpenUsbIoProtocol By Driver (%r)\n", Status
));
905 &gEfiDevicePathProtocolGuid
,
906 This
->DriverBindingHandle
,
913 // Initialize data for device that supports multiple LUNSs.
914 // EFI_SUCCESS is returned if at least 1 LUN is initialized successfully.
916 Status
= UsbMassInitMultiLun (This
, Controller
, Transport
, Context
, DevicePath
, MaxLun
);
917 if (EFI_ERROR (Status
)) {
920 &gEfiDevicePathProtocolGuid
,
921 This
->DriverBindingHandle
,
926 &gEfiUsbIoProtocolGuid
,
927 This
->DriverBindingHandle
,
930 DEBUG ((EFI_D_ERROR
, "USBMassDriverBindingStart: UsbMassInitMultiLun (%r) with Maxlun=%d\n", Status
, MaxLun
));
934 gBS
->RestoreTPL (OldTpl
);
940 Stop controlling the device.
942 @param This The USB mass storage driver binding
943 @param Controller The device controller controlled by the driver.
944 @param NumberOfChildren The number of children of this device
945 @param ChildHandleBuffer The buffer of children handle.
947 @retval EFI_SUCCESS The driver stopped from controlling the device.
948 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
949 @retval EFI_UNSUPPORTED Block I/O Protocol is not installed on Controller.
950 @retval Others Failed to stop the driver
955 USBMassDriverBindingStop (
956 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
957 IN EFI_HANDLE Controller
,
958 IN UINTN NumberOfChildren
,
959 IN EFI_HANDLE
*ChildHandleBuffer
963 USB_MASS_DEVICE
*UsbMass
;
964 EFI_USB_IO_PROTOCOL
*UsbIo
;
965 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
967 BOOLEAN AllChildrenStopped
;
970 // This is a bus driver stop function since multi-lun is supported.
971 // There are three kinds of device handles that might be passed:
972 // 1st is a handle with USB I/O & Block I/O installed (non-multi-lun)
973 // 2nd is a handle with Device Path & USB I/O installed (multi-lun root)
974 // 3rd is a handle with Device Path & USB I/O & Block I/O installed (multi-lun).
976 if (NumberOfChildren
== 0) {
978 // A handle without any children, might be 1st and 2nd type.
980 Status
= gBS
->OpenProtocol (
982 &gEfiBlockIoProtocolGuid
,
984 This
->DriverBindingHandle
,
986 EFI_OPEN_PROTOCOL_GET_PROTOCOL
989 if (EFI_ERROR(Status
)) {
991 // This is a 2nd type handle(multi-lun root), it needs to close devicepath
992 // and usbio protocol.
996 &gEfiDevicePathProtocolGuid
,
997 This
->DriverBindingHandle
,
1000 gBS
->CloseProtocol (
1002 &gEfiUsbIoProtocolGuid
,
1003 This
->DriverBindingHandle
,
1006 DEBUG ((EFI_D_INFO
, "Success to stop multi-lun root handle\n"));
1011 // This is a 1st type handle(non-multi-lun), which only needs to uninstall
1012 // Block I/O Protocol, close USB I/O Protocol and free mass device.
1014 UsbMass
= USB_MASS_DEVICE_FROM_BLOCK_IO (BlockIo
);
1017 // Uninstall Block I/O protocol from the device handle,
1018 // then call the transport protocol to stop itself.
1020 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1022 &gEfiBlockIoProtocolGuid
,
1024 &gEfiDiskInfoProtocolGuid
,
1028 if (EFI_ERROR (Status
)) {
1032 gBS
->CloseProtocol (
1034 &gEfiUsbIoProtocolGuid
,
1035 This
->DriverBindingHandle
,
1039 UsbMass
->Transport
->CleanUp (UsbMass
->Context
);
1042 DEBUG ((EFI_D_INFO
, "Success to stop non-multi-lun root handle\n"));
1047 // This is a 3rd type handle(multi-lun), which needs uninstall
1048 // Block I/O Protocol and Device Path Protocol, close USB I/O Protocol and
1049 // free mass device for all children.
1051 AllChildrenStopped
= TRUE
;
1053 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
1055 Status
= gBS
->OpenProtocol (
1056 ChildHandleBuffer
[Index
],
1057 &gEfiBlockIoProtocolGuid
,
1059 This
->DriverBindingHandle
,
1061 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1063 if (EFI_ERROR (Status
)) {
1064 AllChildrenStopped
= FALSE
;
1065 DEBUG ((EFI_D_ERROR
, "Fail to stop No.%d multi-lun child handle when opening blockio\n", (UINT32
)Index
));
1069 UsbMass
= USB_MASS_DEVICE_FROM_BLOCK_IO (BlockIo
);
1071 gBS
->CloseProtocol (
1073 &gEfiUsbIoProtocolGuid
,
1074 This
->DriverBindingHandle
,
1075 ChildHandleBuffer
[Index
]
1078 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1079 ChildHandleBuffer
[Index
],
1080 &gEfiDevicePathProtocolGuid
,
1081 UsbMass
->DevicePath
,
1082 &gEfiBlockIoProtocolGuid
,
1084 &gEfiDiskInfoProtocolGuid
,
1089 if (EFI_ERROR (Status
)) {
1091 // Fail to uninstall Block I/O Protocol and Device Path Protocol, so re-open USB I/O Protocol by child.
1093 AllChildrenStopped
= FALSE
;
1094 DEBUG ((EFI_D_ERROR
, "Fail to stop No.%d multi-lun child handle when uninstalling blockio and devicepath\n", (UINT32
)Index
));
1098 &gEfiUsbIoProtocolGuid
,
1100 This
->DriverBindingHandle
,
1101 ChildHandleBuffer
[Index
],
1102 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1106 // Succeed to stop this multi-lun handle, so go on with next child.
1108 if (((Index
+ 1) == NumberOfChildren
) && AllChildrenStopped
) {
1109 UsbMass
->Transport
->CleanUp (UsbMass
->Context
);
1115 if (!AllChildrenStopped
) {
1116 return EFI_DEVICE_ERROR
;
1119 DEBUG ((EFI_D_INFO
, "Success to stop all %d multi-lun children handles\n", (UINT32
) NumberOfChildren
));
1124 Entrypoint of USB Mass Storage Driver.
1126 This function is the entrypoint of USB Mass Storage Driver. It installs Driver Binding
1127 Protocol together with Component Name Protocols.
1129 @param ImageHandle The firmware allocated handle for the EFI image.
1130 @param SystemTable A pointer to the EFI System Table.
1132 @retval EFI_SUCCESS The entry point is executed successfully.
1137 USBMassStorageEntryPoint (
1138 IN EFI_HANDLE ImageHandle
,
1139 IN EFI_SYSTEM_TABLE
*SystemTable
1145 // Install driver binding protocol
1147 Status
= EfiLibInstallDriverBindingComponentName2 (
1150 &gUSBMassDriverBinding
,
1152 &gUsbMassStorageComponentName
,
1153 &gUsbMassStorageComponentName2
1155 ASSERT_EFI_ERROR (Status
);