3 Copyright (c) 2007 - 2008, Intel Corporation
4 All rights reserved. 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
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.
18 The implementation of USB mass storage class device driver.
19 The command set supported is "USB Mass Storage Specification
27 #include "UsbMassImpl.h"
30 // The underlying transport protocol. CBI support isn't included
31 // in the current build. It is being obseleted by the standard
32 // body. If you want to enable it, remove the if directive here,
33 // then add the UsbMassCbi.c/.h to the driver's inf file.
36 USB_MASS_TRANSPORT
*mUsbMassTransport
[] = {
44 Reset the block device. ExtendedVerification is ignored for this.
46 @param This The BLOCK IO protocol
47 @param ExtendedVerification Whether to execute extended verfication.
49 @retval EFI_SUCCESS The device is successfully resetted.
50 @retval Others Failed to reset the device.
56 IN EFI_BLOCK_IO_PROTOCOL
*This
,
57 IN BOOLEAN ExtendedVerification
60 USB_MASS_DEVICE
*UsbMass
;
64 OldTpl
= gBS
->RaiseTPL (USB_MASS_TPL
);
66 UsbMass
= USB_MASS_DEVICE_FROM_BLOCKIO (This
);
67 Status
= UsbMass
->Transport
->Reset (UsbMass
->Context
, ExtendedVerification
);
69 gBS
->RestoreTPL (OldTpl
);
75 Read some blocks of data from the block device.
77 @param This The Block IO protocol
78 @param MediaId The media's ID of the device for current request
79 @param Lba The start block number
80 @param BufferSize The size of buffer to read data in
81 @param Buffer The buffer to read data to
83 @retval EFI_SUCCESS The data is successfully read
84 @retval EFI_NO_MEDIA Media isn't present
85 @retval EFI_MEDIA_CHANGED The device media has been changed, that is,
87 @retval EFI_INVALID_PARAMETER Some parameters are invalid, such as Buffer is
89 @retval EFI_BAD_BUFFER_SIZE The buffer size isn't a multiple of media's block
90 size, or overflow the last block number.
96 IN EFI_BLOCK_IO_PROTOCOL
*This
,
103 USB_MASS_DEVICE
*UsbMass
;
104 EFI_BLOCK_IO_MEDIA
*Media
;
109 OldTpl
= gBS
->RaiseTPL (USB_MASS_TPL
);
110 UsbMass
= USB_MASS_DEVICE_FROM_BLOCKIO (This
);
111 Media
= &UsbMass
->BlockIoMedia
;
114 // First, validate the parameters
116 if ((Buffer
== NULL
) || (BufferSize
== 0)) {
117 Status
= EFI_INVALID_PARAMETER
;
122 // If it is a removable media, such as CD-Rom or Usb-Floppy,
123 // need to detect the media before each rw. While some of
124 // Usb-Flash is marked as removable media.
127 if (Media
->RemovableMedia
== TRUE
) {
128 Status
= UsbBootDetectMedia (UsbMass
);
129 if (EFI_ERROR (Status
)) {
130 DEBUG ((EFI_D_ERROR
, "UsbMassReadBlocks: UsbBootDetectMedia (%r)\n", Status
));
136 // Make sure BlockSize and LBA is consistent with BufferSize
138 if ((BufferSize
% Media
->BlockSize
) != 0) {
139 Status
= EFI_BAD_BUFFER_SIZE
;
143 TotalBlock
= BufferSize
/ Media
->BlockSize
;
145 if (Lba
+ TotalBlock
- 1 > Media
->LastBlock
) {
146 Status
= EFI_INVALID_PARAMETER
;
150 if (!(Media
->MediaPresent
)) {
151 Status
= EFI_NO_MEDIA
;
155 if (MediaId
!= Media
->MediaId
) {
156 Status
= EFI_MEDIA_CHANGED
;
160 Status
= UsbBootReadBlocks (UsbMass
, (UINT32
) Lba
, TotalBlock
, Buffer
);
161 if (EFI_ERROR (Status
)) {
162 DEBUG ((EFI_D_ERROR
, "UsbMassReadBlocks: UsbBootReadBlocks (%r) -> Reset\n", Status
));
163 UsbMassReset (This
, TRUE
);
167 gBS
->RestoreTPL (OldTpl
);
173 Write some blocks of data to the block device.
175 @param This The Block IO protocol
176 @param MediaId The media's ID of the device for current request
177 @param Lba The start block number
178 @param BufferSize The size of buffer to write data to
179 @param Buffer The buffer to write data to
181 @retval EFI_SUCCESS The data is successfully written
182 @retval EFI_NO_MEDIA Media isn't present
183 @retval EFI_MEDIA_CHANGED The device media has been changed, that is,
185 @retval EFI_INVALID_PARAMETER Some parameters are invalid, such as Buffer is
187 @retval EFI_BAD_BUFFER_SIZE The buffer size isn't a multiple of media's block
194 IN EFI_BLOCK_IO_PROTOCOL
*This
,
201 USB_MASS_DEVICE
*UsbMass
;
202 EFI_BLOCK_IO_MEDIA
*Media
;
207 OldTpl
= gBS
->RaiseTPL (USB_MASS_TPL
);
208 UsbMass
= USB_MASS_DEVICE_FROM_BLOCKIO (This
);
209 Media
= &UsbMass
->BlockIoMedia
;
212 // First, validate the parameters
214 if ((Buffer
== NULL
) || (BufferSize
== 0)) {
215 Status
= EFI_INVALID_PARAMETER
;
220 // If it is a removable media, such as CD-Rom or Usb-Floppy,
221 // need to detect the media before each rw. While some of
222 // Usb-Flash is marked as removable media.
225 if (Media
->RemovableMedia
== TRUE
) {
226 Status
= UsbBootDetectMedia (UsbMass
);
227 if (EFI_ERROR (Status
)) {
228 DEBUG ((EFI_D_ERROR
, "UsbMassWriteBlocks: UsbBootDetectMedia (%r)\n", Status
));
234 // Make sure BlockSize and LBA is consistent with BufferSize
236 if ((BufferSize
% Media
->BlockSize
) != 0) {
237 Status
= EFI_BAD_BUFFER_SIZE
;
241 TotalBlock
= BufferSize
/ Media
->BlockSize
;
243 if (Lba
+ TotalBlock
- 1 > Media
->LastBlock
) {
244 Status
= EFI_INVALID_PARAMETER
;
248 if (!(Media
->MediaPresent
)) {
249 Status
= EFI_NO_MEDIA
;
253 if (MediaId
!= Media
->MediaId
) {
254 Status
= EFI_MEDIA_CHANGED
;
259 // Try to write the data even the device is marked as ReadOnly,
260 // and clear the status should the write succeed.
262 Status
= UsbBootWriteBlocks (UsbMass
, (UINT32
) Lba
, TotalBlock
, Buffer
);
263 if (EFI_ERROR (Status
)) {
264 DEBUG ((EFI_D_ERROR
, "UsbMassWriteBlocks: UsbBootWriteBlocks (%r) -> Reset\n", Status
));
265 UsbMassReset (This
, TRUE
);
269 gBS
->RestoreTPL (OldTpl
);
274 Flush the cached writes to disks. USB mass storage device doesn't
275 support write cache, so return EFI_SUCCESS directly.
277 @param This The BLOCK IO protocol
279 @retval EFI_SUCCESS Always returns success
285 IN EFI_BLOCK_IO_PROTOCOL
*This
292 Retrieve the media parameters such as disk gemotric for the
293 device's BLOCK IO protocol.
295 @param UsbMass The USB mass storage device
297 @retval EFI_SUCCESS The media parameters is updated successfully.
298 @retval Others Failed to get the media parameters.
303 IN USB_MASS_DEVICE
*UsbMass
306 EFI_BLOCK_IO_MEDIA
*Media
;
310 Media
= &UsbMass
->BlockIoMedia
;
313 // Initialize the MediaPrsent/ReadOnly and others to the default.
314 // We are not forced to get it right at this time, check UEFI2.0
315 // spec for more information:
317 // MediaPresent: This field shows the media present status as
318 // of the most recent ReadBlocks or WriteBlocks call.
320 // ReadOnly : This field shows the read-only status as of the
321 // recent WriteBlocks call.
323 // but remember to update MediaId/MediaPresent/ReadOnly status
324 // after ReadBlocks and WriteBlocks
326 Media
->MediaPresent
= FALSE
;
327 Media
->LogicalPartition
= FALSE
;
328 Media
->ReadOnly
= FALSE
;
329 Media
->WriteCaching
= FALSE
;
334 // Some device may spend several seconds before it is ready.
335 // Try several times before giving up. Wait 5s at most.
337 Status
= EFI_SUCCESS
;
339 for (Index
= 0; Index
< USB_BOOT_INIT_MEDIA_RETRY
; Index
++) {
341 Status
= UsbBootGetParams (UsbMass
);
342 if ((Status
!= EFI_MEDIA_CHANGED
)
343 && (Status
!= EFI_NOT_READY
)
344 && (Status
!= EFI_TIMEOUT
)) {
348 Status
= UsbBootIsUnitReady (UsbMass
);
349 if (EFI_ERROR (Status
)) {
350 gBS
->Stall (USB_BOOT_RETRY_UNIT_READY_STALL
* (Index
+ 1));
360 UsbMassInitTransport (
361 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
362 IN EFI_HANDLE Controller
,
363 OUT USB_MASS_TRANSPORT
**Transport
,
368 EFI_USB_IO_PROTOCOL
*UsbIo
;
369 EFI_USB_INTERFACE_DESCRIPTOR Interface
;
373 Status
= gBS
->OpenProtocol (
375 &gEfiUsbIoProtocolGuid
,
377 This
->DriverBindingHandle
,
379 EFI_OPEN_PROTOCOL_BY_DRIVER
382 if (EFI_ERROR (Status
)) {
383 DEBUG ((EFI_D_ERROR
, "UsbMassInitTransport: OpenUsbIoProtocol By Driver (%r)\n", Status
));
387 Status
= UsbIo
->UsbGetInterfaceDescriptor (UsbIo
, &Interface
);
388 if (EFI_ERROR (Status
)) {
389 DEBUG ((EFI_D_ERROR
, "UsbMassInitTransport: UsbIo->UsbGetInterfaceDescriptor (%r)\n", Status
));
393 Status
= EFI_UNSUPPORTED
;
395 for (Index
= 0; mUsbMassTransport
[Index
] != NULL
; Index
++) {
396 *Transport
= mUsbMassTransport
[Index
];
398 if (Interface
.InterfaceProtocol
== (*Transport
)->Protocol
) {
399 Status
= (*Transport
)->Init (UsbIo
, Context
);
404 if (EFI_ERROR (Status
)) {
405 DEBUG ((EFI_D_ERROR
, "UsbMassInitTransport: Transport->Init (%r)\n", Status
));
410 // For bot device, try to get max lun.
411 // If maxlun=0, then non-lun device, else multi-lun device.
413 if ((*Transport
)->Protocol
== USB_MASS_STORE_BOT
) {
414 (*Transport
)->GetMaxLun (*Context
, MaxLun
);
415 DEBUG ((EFI_D_INFO
, "UsbMassInitTransport: GetMaxLun = %d\n", *MaxLun
));
421 &gEfiUsbIoProtocolGuid
,
422 This
->DriverBindingHandle
,
430 UsbMassInitMultiLun (
431 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
432 IN EFI_HANDLE Controller
,
433 IN USB_MASS_TRANSPORT
*Transport
,
435 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
439 USB_MASS_DEVICE
*UsbMass
;
440 EFI_USB_IO_PROTOCOL
*UsbIo
;
441 DEVICE_LOGICAL_UNIT_DEVICE_PATH LunNode
;
447 for (Index
= 0; Index
<= MaxLun
; Index
++) {
449 DEBUG ((EFI_D_INFO
, "UsbMassInitMultiLun: Start to initialize No.%d logic unit\n", Index
));
452 UsbMass
= AllocateZeroPool (sizeof (USB_MASS_DEVICE
));
453 if (UsbMass
== NULL
) {
454 Status
= EFI_OUT_OF_RESOURCES
;
458 UsbMass
->Signature
= USB_MASS_SIGNATURE
;
459 UsbMass
->UsbIo
= UsbIo
;
460 UsbMass
->BlockIo
.Media
= &UsbMass
->BlockIoMedia
;
461 UsbMass
->BlockIo
.Reset
= UsbMassReset
;
462 UsbMass
->BlockIo
.ReadBlocks
= UsbMassReadBlocks
;
463 UsbMass
->BlockIo
.WriteBlocks
= UsbMassWriteBlocks
;
464 UsbMass
->BlockIo
.FlushBlocks
= UsbMassFlushBlocks
;
465 UsbMass
->OpticalStorage
= FALSE
;
466 UsbMass
->Transport
= Transport
;
467 UsbMass
->Context
= Context
;
468 UsbMass
->Lun
= Index
;
471 // Get the storage's parameters, such as last block number.
472 // then install the BLOCK_IO
474 Status
= UsbMassInitMedia (UsbMass
);
475 if (!EFI_ERROR (Status
)) {
476 if ((UsbMass
->Pdt
!= USB_PDT_DIRECT_ACCESS
) &&
477 (UsbMass
->Pdt
!= USB_PDT_CDROM
) &&
478 (UsbMass
->Pdt
!= USB_PDT_OPTICAL
) &&
479 (UsbMass
->Pdt
!= USB_PDT_SIMPLE_DIRECT
)) {
480 DEBUG ((EFI_D_ERROR
, "UsbMassInitMultiLun: Found an unsupported peripheral type[%d]\n", UsbMass
->Pdt
));
483 } else if (Status
!= EFI_NO_MEDIA
){
484 DEBUG ((EFI_D_ERROR
, "UsbMassInitMultiLun: UsbMassInitMedia (%r)\n", Status
));
489 // Create a device path node of device logic unit, and append it
491 LunNode
.Header
.Type
= MESSAGING_DEVICE_PATH
;
492 LunNode
.Header
.SubType
= MSG_DEVICE_LOGICAL_UNIT_DP
;
493 LunNode
.Lun
= UsbMass
->Lun
;
495 SetDevicePathNodeLength (&LunNode
.Header
, sizeof (LunNode
));
497 UsbMass
->DevicePath
= AppendDevicePathNode (DevicePath
, &LunNode
.Header
);
499 if (UsbMass
->DevicePath
== NULL
) {
500 DEBUG ((EFI_D_ERROR
, "UsbMassInitMultiLun: failed to create device logic unit device path\n"));
502 Status
= EFI_OUT_OF_RESOURCES
;
507 // Create a UsbMass handle for each lun, and install blockio and devicepath protocols.
509 Status
= gBS
->InstallMultipleProtocolInterfaces (
510 &UsbMass
->Controller
,
511 &gEfiDevicePathProtocolGuid
,
513 &gEfiBlockIoProtocolGuid
,
518 if (EFI_ERROR (Status
)) {
519 DEBUG ((EFI_D_ERROR
, "UsbMassInitMultiLun: InstallMultipleProtocolInterfaces (%r)\n", Status
));
524 // Open UsbIo protocol by child to setup a parent-child relationship.
526 Status
= gBS
->OpenProtocol (
528 &gEfiUsbIoProtocolGuid
,
530 This
->DriverBindingHandle
,
532 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
535 if (EFI_ERROR (Status
)) {
536 DEBUG ((EFI_D_ERROR
, "UsbMassInitMultiLun: OpenUsbIoProtocol By Child (%r)\n", Status
));
537 gBS
->UninstallMultipleProtocolInterfaces (
538 &UsbMass
->Controller
,
539 &gEfiDevicePathProtocolGuid
,
541 &gEfiBlockIoProtocolGuid
,
548 DEBUG ((EFI_D_INFO
, "UsbMassInitMultiLun: Success to initialize No.%d logic unit\n", Index
));
554 if (UsbMass
->DevicePath
!= NULL
) {
555 gBS
->FreePool (UsbMass
->DevicePath
);
557 if (UsbMass
!= NULL
) {
558 gBS
->FreePool (UsbMass
);
563 &gEfiUsbIoProtocolGuid
,
564 This
->DriverBindingHandle
,
570 // If only success to initialize one lun, return success, or else return error
582 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
583 IN EFI_HANDLE Controller
,
584 IN USB_MASS_TRANSPORT
*Transport
,
588 USB_MASS_DEVICE
*UsbMass
;
589 EFI_USB_IO_PROTOCOL
*UsbIo
;
593 UsbMass
= AllocateZeroPool (sizeof (USB_MASS_DEVICE
));
594 if (UsbMass
== NULL
) {
595 return EFI_OUT_OF_RESOURCES
;
597 Status
= gBS
->OpenProtocol (
599 &gEfiUsbIoProtocolGuid
,
601 This
->DriverBindingHandle
,
603 EFI_OPEN_PROTOCOL_BY_DRIVER
606 if (EFI_ERROR (Status
)) {
607 DEBUG ((EFI_D_ERROR
, "UsbMassInitNonLun: OpenUsbIoProtocol By Driver (%r)\n", Status
));
611 UsbMass
->Signature
= USB_MASS_SIGNATURE
;
612 UsbMass
->Controller
= Controller
;
613 UsbMass
->UsbIo
= UsbIo
;
614 UsbMass
->BlockIo
.Media
= &UsbMass
->BlockIoMedia
;
615 UsbMass
->BlockIo
.Reset
= UsbMassReset
;
616 UsbMass
->BlockIo
.ReadBlocks
= UsbMassReadBlocks
;
617 UsbMass
->BlockIo
.WriteBlocks
= UsbMassWriteBlocks
;
618 UsbMass
->BlockIo
.FlushBlocks
= UsbMassFlushBlocks
;
619 UsbMass
->OpticalStorage
= FALSE
;
620 UsbMass
->Transport
= Transport
;
621 UsbMass
->Context
= Context
;
624 // Get the storage's parameters, such as last block number.
625 // then install the BLOCK_IO
627 Status
= UsbMassInitMedia (UsbMass
);
628 if (!EFI_ERROR (Status
)) {
629 if ((UsbMass
->Pdt
!= USB_PDT_DIRECT_ACCESS
) &&
630 (UsbMass
->Pdt
!= USB_PDT_CDROM
) &&
631 (UsbMass
->Pdt
!= USB_PDT_OPTICAL
) &&
632 (UsbMass
->Pdt
!= USB_PDT_SIMPLE_DIRECT
)) {
633 DEBUG ((EFI_D_ERROR
, "UsbMassInitNonLun: Found an unsupported peripheral type[%d]\n", UsbMass
->Pdt
));
636 } else if (Status
!= EFI_NO_MEDIA
){
637 DEBUG ((EFI_D_ERROR
, "UsbMassInitNonLun: UsbMassInitMedia (%r)\n", Status
));
641 Status
= gBS
->InstallProtocolInterface (
643 &gEfiBlockIoProtocolGuid
,
644 EFI_NATIVE_INTERFACE
,
647 if (EFI_ERROR (Status
)) {
654 if (UsbMass
!= NULL
) {
655 gBS
->FreePool (UsbMass
);
659 &gEfiUsbIoProtocolGuid
,
660 This
->DriverBindingHandle
,
668 Check whether the controller is a supported USB mass storage.
670 @param This The USB mass driver's driver binding.
671 @param Controller The device to test against.
672 @param RemainingDevicePath The remaining device path
674 @retval EFI_SUCCESS This device is a supported USB mass storage.
675 @retval EFI_UNSUPPORTED The device isn't supported
676 @retval Others Some error happened.
681 USBMassDriverBindingSupported (
682 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
683 IN EFI_HANDLE Controller
,
684 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
687 EFI_USB_IO_PROTOCOL
*UsbIo
;
688 EFI_USB_INTERFACE_DESCRIPTOR Interface
;
689 USB_MASS_TRANSPORT
*Transport
;
694 // Check whether the controlelr support USB_IO
696 Status
= gBS
->OpenProtocol (
698 &gEfiUsbIoProtocolGuid
,
700 This
->DriverBindingHandle
,
702 EFI_OPEN_PROTOCOL_BY_DRIVER
704 if (EFI_ERROR (Status
)) {
709 // Get the interface to check the USB class and find a transport
712 Status
= UsbIo
->UsbGetInterfaceDescriptor (UsbIo
, &Interface
);
713 if (EFI_ERROR (Status
)) {
717 Status
= EFI_UNSUPPORTED
;
719 if (Interface
.InterfaceClass
!= USB_MASS_STORE_CLASS
) {
723 for (Index
= 0; mUsbMassTransport
[Index
] != NULL
; Index
++) {
724 Transport
= mUsbMassTransport
[Index
];
725 if (Interface
.InterfaceProtocol
== Transport
->Protocol
) {
726 Status
= Transport
->Init (UsbIo
, NULL
);
731 DEBUG ((EFI_D_INFO
, "Found a USB mass store device %r\n", Status
));
736 &gEfiUsbIoProtocolGuid
,
737 This
->DriverBindingHandle
,
746 Start the USB mass storage device on the controller. It will
747 install a BLOCK_IO protocol on the device if everything is OK.
749 @param This The USB mass storage driver binding.
750 @param Controller The USB mass storage device to start on
751 @param RemainingDevicePath The remaining device path.
753 @retval EFI_SUCCESS The driver has started on the device.
754 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory
755 @retval Others Failed to start the driver on the device.
760 USBMassDriverBindingStart (
761 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
762 IN EFI_HANDLE Controller
,
763 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
766 USB_MASS_TRANSPORT
*Transport
;
767 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
777 // Get interface and protocols, initialize transport
779 Status
= UsbMassInitTransport (This
, Controller
, &Transport
, &Context
, &MaxLun
);
781 if (EFI_ERROR (Status
)) {
782 DEBUG ((EFI_D_ERROR
, "USBMassDriverBindingStart: UsbMassInitTransport (%r)\n", Status
));
787 // Initialize No/Unsupported LUN device
789 Status
= UsbMassInitNonLun(This
, Controller
, Transport
, Context
);
790 if (EFI_ERROR (Status
)) {
791 DEBUG ((EFI_D_ERROR
, "USBMassDriverBindingStart: UsbMassInitNonLun (%r)\n", Status
));
795 // Open device path to perpare append Device Logic Unit node.
797 Status
= gBS
->OpenProtocol (
799 &gEfiDevicePathProtocolGuid
,
800 (VOID
**) &DevicePath
,
801 This
->DriverBindingHandle
,
803 EFI_OPEN_PROTOCOL_BY_DRIVER
806 if (EFI_ERROR (Status
)) {
807 DEBUG ((EFI_D_ERROR
, "USBMassDriverBindingStart: OpenDevicePathProtocol By Driver (%r)\n", Status
));
812 // Try best to initialize all LUNs, and return success only if one of LUNs successed to initialized.
814 Status
= UsbMassInitMultiLun(This
, Controller
, Transport
, Context
, DevicePath
, MaxLun
);
815 if (EFI_ERROR (Status
)) {
818 &gEfiDevicePathProtocolGuid
,
819 This
->DriverBindingHandle
,
822 DEBUG ((EFI_D_ERROR
, "USBMassDriverBindingStart: UsbMassInitMultiLun (%r) with Maxlun=%d\n", Status
, MaxLun
));
830 Stop controlling the device.
832 @param This The USB mass storage driver binding
833 @param Controller The device controller controlled by the driver.
834 @param NumberOfChildren The number of children of this device
835 @param ChildHandleBuffer The buffer of children handle.
837 @retval EFI_SUCCESS The driver stopped from controlling the device.
838 @retval Others Failed to stop the driver
843 USBMassDriverBindingStop (
844 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
845 IN EFI_HANDLE Controller
,
846 IN UINTN NumberOfChildren
,
847 IN EFI_HANDLE
*ChildHandleBuffer
851 USB_MASS_DEVICE
*UsbMass
;
852 EFI_USB_IO_PROTOCOL
*UsbIo
;
853 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
855 BOOLEAN AllChildrenStopped
;
858 // This a bus driver stop function since multi-lun supported. There are three
859 // kinds of device handle might be passed, 1st is a handle with devicepath/
860 // usbio/blockio installed(non-multi-lun), 2nd is a handle with devicepath/
861 // usbio installed(multi-lun root), 3rd is a handle with devicepath/blockio
862 // installed(multi-lun).
864 if (NumberOfChildren
== 0) {
866 // A handle without any children, might be 1st and 2nd type.
868 Status
= gBS
->OpenProtocol (
870 &gEfiBlockIoProtocolGuid
,
872 This
->DriverBindingHandle
,
874 EFI_OPEN_PROTOCOL_GET_PROTOCOL
877 if (EFI_ERROR(Status
)) {
879 // This is a 2nd type handle(multi-lun root), which only needs close
880 // devicepath protocol.
884 &gEfiDevicePathProtocolGuid
,
885 This
->DriverBindingHandle
,
888 DEBUG ((EFI_D_INFO
, "Success to stop multi-lun root handle\n"));
893 // This is a 1st type handle(non-multi-lun), which only needs uninstall
894 // blockio protocol, close usbio protocol and free mass device.
896 UsbMass
= USB_MASS_DEVICE_FROM_BLOCKIO (BlockIo
);
899 // Uninstall Block I/O protocol from the device handle,
900 // then call the transport protocol to stop itself.
902 Status
= gBS
->UninstallProtocolInterface (
904 &gEfiBlockIoProtocolGuid
,
907 if (EFI_ERROR (Status
)) {
913 &gEfiUsbIoProtocolGuid
,
914 This
->DriverBindingHandle
,
918 UsbMass
->Transport
->Fini (UsbMass
->Context
);
919 gBS
->FreePool (UsbMass
);
921 DEBUG ((EFI_D_INFO
, "Success to stop non-multi-lun root handle\n"));
926 // This is a 3rd type handle(multi-lun), which needs uninstall
927 // blockio and devicepath protocol, close usbio protocol and
930 AllChildrenStopped
= TRUE
;
932 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
934 Status
= gBS
->OpenProtocol (
935 ChildHandleBuffer
[Index
],
936 &gEfiBlockIoProtocolGuid
,
938 This
->DriverBindingHandle
,
940 EFI_OPEN_PROTOCOL_GET_PROTOCOL
942 if (EFI_ERROR (Status
)) {
943 AllChildrenStopped
= FALSE
;
944 DEBUG ((EFI_D_ERROR
, "Fail to stop No.%d multi-lun child handle when opening blockio\n", Index
));
948 UsbMass
= USB_MASS_DEVICE_FROM_BLOCKIO (BlockIo
);
952 &gEfiUsbIoProtocolGuid
,
953 This
->DriverBindingHandle
,
954 ChildHandleBuffer
[Index
]
957 Status
= gBS
->UninstallMultipleProtocolInterfaces (
958 ChildHandleBuffer
[Index
],
959 &gEfiDevicePathProtocolGuid
,
961 &gEfiBlockIoProtocolGuid
,
966 if (EFI_ERROR (Status
)) {
968 // Fail to uninstall blockio and devicepath protocol, so re-open usbio by child.
970 AllChildrenStopped
= FALSE
;
971 DEBUG ((EFI_D_ERROR
, "Fail to stop No.%d multi-lun child handle when uninstalling blockio and devicepath\n", Index
));
975 &gEfiUsbIoProtocolGuid
,
977 This
->DriverBindingHandle
,
978 ChildHandleBuffer
[Index
],
979 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
983 // Success to stop this multi-lun handle, so go on next child.
985 if (((Index
+ 1) == NumberOfChildren
) && AllChildrenStopped
) {
986 UsbMass
->Transport
->Fini (UsbMass
->Context
);
988 gBS
->FreePool (UsbMass
);
992 if (!AllChildrenStopped
) {
993 return EFI_DEVICE_ERROR
;
996 DEBUG ((EFI_D_INFO
, "Success to stop all %d multi-lun children handles\n", NumberOfChildren
));
1000 EFI_DRIVER_BINDING_PROTOCOL gUSBMassDriverBinding
= {
1001 USBMassDriverBindingSupported
,
1002 USBMassDriverBindingStart
,
1003 USBMassDriverBindingStop
,
1011 USBMassStorageEntryPoint (
1012 IN EFI_HANDLE ImageHandle
,
1013 IN EFI_SYSTEM_TABLE
*SystemTable
1017 Routine Description:
1019 The entry point for the driver, which will install the driver binding and
1020 component name protocol
1024 ImageHandle - The image handle of this driver
1025 SystemTable - The system table
1029 EFI_SUCCESS - the protocols are installed OK
1030 Others - Failed to install protocols.
1037 // Install driver binding protocol
1039 Status
= EfiLibInstallDriverBindingComponentName2 (
1042 &gUSBMassDriverBinding
,
1044 &gUsbMassStorageComponentName
,
1045 &gUsbMassStorageComponentName2