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.
15 #include "UsbMassImpl.h"
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
;
558 // Create a new handle for each LUN, and install Block I/O Protocol and Device Path Protocol.
560 Status
= gBS
->InstallMultipleProtocolInterfaces (
561 &UsbMass
->Controller
,
562 &gEfiDevicePathProtocolGuid
,
564 &gEfiBlockIoProtocolGuid
,
569 if (EFI_ERROR (Status
)) {
570 DEBUG ((EFI_D_ERROR
, "UsbMassInitMultiLun: InstallMultipleProtocolInterfaces (%r)\n", Status
));
575 // Open USB I/O Protocol by child to setup a parent-child relationship.
577 Status
= gBS
->OpenProtocol (
579 &gEfiUsbIoProtocolGuid
,
581 This
->DriverBindingHandle
,
583 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
586 if (EFI_ERROR (Status
)) {
587 DEBUG ((EFI_D_ERROR
, "UsbMassInitMultiLun: OpenUsbIoProtocol By Child (%r)\n", Status
));
588 gBS
->UninstallMultipleProtocolInterfaces (
589 &UsbMass
->Controller
,
590 &gEfiDevicePathProtocolGuid
,
592 &gEfiBlockIoProtocolGuid
,
599 DEBUG ((EFI_D_INFO
, "UsbMassInitMultiLun: Success to initialize No.%d logic unit\n", Index
));
605 if (UsbMass
!= NULL
) {
606 if (UsbMass
->DevicePath
!= NULL
) {
607 FreePool (UsbMass
->DevicePath
);
614 &gEfiUsbIoProtocolGuid
,
615 This
->DriverBindingHandle
,
621 // Return EFI_SUCCESS if at least one LUN is initialized successfully.
631 Initialize data for device that does not support multiple LUNSs.
633 @param This The Driver Binding Protocol instance.
634 @param Controller The device to initialize.
635 @param Transport Pointer to USB_MASS_TRANSPORT.
636 @param Context Parameter for USB_MASS_DEVICE.Context.
638 @retval EFI_SUCCESS Initialization succeeds.
639 @retval Other Initialization fails.
644 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
645 IN EFI_HANDLE Controller
,
646 IN USB_MASS_TRANSPORT
*Transport
,
650 USB_MASS_DEVICE
*UsbMass
;
651 EFI_USB_IO_PROTOCOL
*UsbIo
;
655 UsbMass
= AllocateZeroPool (sizeof (USB_MASS_DEVICE
));
656 ASSERT (UsbMass
!= NULL
);
658 Status
= gBS
->OpenProtocol (
660 &gEfiUsbIoProtocolGuid
,
662 This
->DriverBindingHandle
,
664 EFI_OPEN_PROTOCOL_BY_DRIVER
667 if (EFI_ERROR (Status
)) {
668 DEBUG ((EFI_D_ERROR
, "UsbMassInitNonLun: OpenUsbIoProtocol By Driver (%r)\n", Status
));
672 UsbMass
->Signature
= USB_MASS_SIGNATURE
;
673 UsbMass
->Controller
= Controller
;
674 UsbMass
->UsbIo
= UsbIo
;
675 UsbMass
->BlockIo
.Media
= &UsbMass
->BlockIoMedia
;
676 UsbMass
->BlockIo
.Reset
= UsbMassReset
;
677 UsbMass
->BlockIo
.ReadBlocks
= UsbMassReadBlocks
;
678 UsbMass
->BlockIo
.WriteBlocks
= UsbMassWriteBlocks
;
679 UsbMass
->BlockIo
.FlushBlocks
= UsbMassFlushBlocks
;
680 UsbMass
->OpticalStorage
= FALSE
;
681 UsbMass
->Transport
= Transport
;
682 UsbMass
->Context
= Context
;
685 // Initialize the media parameter data for EFI_BLOCK_IO_MEDIA of Block I/O Protocol.
687 Status
= UsbMassInitMedia (UsbMass
);
688 if (!EFI_ERROR (Status
)) {
690 // According to USB Mass Storage Specification for Bootability, only following
691 // 4 Peripheral Device Types are in spec.
693 if ((UsbMass
->Pdt
!= USB_PDT_DIRECT_ACCESS
) &&
694 (UsbMass
->Pdt
!= USB_PDT_CDROM
) &&
695 (UsbMass
->Pdt
!= USB_PDT_OPTICAL
) &&
696 (UsbMass
->Pdt
!= USB_PDT_SIMPLE_DIRECT
)) {
697 DEBUG ((EFI_D_ERROR
, "UsbMassInitNonLun: Found an unsupported peripheral type[%d]\n", UsbMass
->Pdt
));
700 } else if (Status
!= EFI_NO_MEDIA
){
701 DEBUG ((EFI_D_ERROR
, "UsbMassInitNonLun: UsbMassInitMedia (%r)\n", Status
));
705 Status
= gBS
->InstallProtocolInterface (
707 &gEfiBlockIoProtocolGuid
,
708 EFI_NATIVE_INTERFACE
,
711 if (EFI_ERROR (Status
)) {
718 if (UsbMass
!= NULL
) {
724 &gEfiUsbIoProtocolGuid
,
725 This
->DriverBindingHandle
,
734 Check whether the controller is a supported USB mass storage.
736 @param This The USB mass storage driver binding protocol.
737 @param Controller The controller handle to check.
738 @param RemainingDevicePath The remaining device path.
740 @retval EFI_SUCCESS The driver supports this controller.
741 @retval other This device isn't supported.
746 USBMassDriverBindingSupported (
747 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
748 IN EFI_HANDLE Controller
,
749 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
752 EFI_USB_IO_PROTOCOL
*UsbIo
;
753 EFI_USB_INTERFACE_DESCRIPTOR Interface
;
754 USB_MASS_TRANSPORT
*Transport
;
758 Status
= gBS
->OpenProtocol (
760 &gEfiUsbIoProtocolGuid
,
762 This
->DriverBindingHandle
,
764 EFI_OPEN_PROTOCOL_BY_DRIVER
766 if (EFI_ERROR (Status
)) {
771 // Get the interface descriptor to check the USB class and find a transport
774 Status
= UsbIo
->UsbGetInterfaceDescriptor (UsbIo
, &Interface
);
775 if (EFI_ERROR (Status
)) {
779 Status
= EFI_UNSUPPORTED
;
781 if (Interface
.InterfaceClass
!= USB_MASS_STORE_CLASS
) {
786 // Traverse the USB_MASS_TRANSPORT arrary and try to find the
787 // matching transport method.
788 // If not found, return EFI_UNSUPPORTED.
789 // If found, execute USB_MASS_TRANSPORT.Init() to initialize the transport context.
791 for (Index
= 0; Index
< USB_MASS_TRANSPORT_COUNT
; Index
++) {
792 Transport
= mUsbMassTransport
[Index
];
793 if (Interface
.InterfaceProtocol
== Transport
->Protocol
) {
794 Status
= Transport
->Init (UsbIo
, NULL
);
802 &gEfiUsbIoProtocolGuid
,
803 This
->DriverBindingHandle
,
811 Starts the USB mass storage device with this driver.
813 This function consumes USB I/O Portocol, intializes USB mass storage device,
814 installs Block I/O Protocol, and submits Asynchronous Interrupt
815 Transfer to manage the USB mass storage device.
817 @param This The USB mass storage driver binding protocol.
818 @param Controller The USB mass storage device to start on
819 @param RemainingDevicePath The remaining device path.
821 @retval EFI_SUCCESS This driver supports this device.
822 @retval EFI_UNSUPPORTED This driver does not support this device.
823 @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.
824 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
825 @retval EFI_ALREADY_STARTED This driver has been started.
830 USBMassDriverBindingStart (
831 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
832 IN EFI_HANDLE Controller
,
833 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
836 USB_MASS_TRANSPORT
*Transport
;
837 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
841 EFI_USB_IO_PROTOCOL
*UsbIo
;
844 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
850 Status
= UsbMassInitTransport (This
, Controller
, &Transport
, &Context
, &MaxLun
);
852 if (EFI_ERROR (Status
)) {
853 DEBUG ((EFI_D_ERROR
, "USBMassDriverBindingStart: UsbMassInitTransport (%r)\n", Status
));
858 // Initialize data for device that does not support multiple LUNSs.
860 Status
= UsbMassInitNonLun (This
, Controller
, Transport
, Context
);
861 if (EFI_ERROR (Status
)) {
862 DEBUG ((EFI_D_ERROR
, "USBMassDriverBindingStart: UsbMassInitNonLun (%r)\n", Status
));
866 // Open device path to prepare for appending Device Logic Unit node.
868 Status
= gBS
->OpenProtocol (
870 &gEfiDevicePathProtocolGuid
,
871 (VOID
**) &DevicePath
,
872 This
->DriverBindingHandle
,
874 EFI_OPEN_PROTOCOL_BY_DRIVER
877 if (EFI_ERROR (Status
)) {
878 DEBUG ((EFI_D_ERROR
, "USBMassDriverBindingStart: OpenDevicePathProtocol By Driver (%r)\n", Status
));
882 Status
= gBS
->OpenProtocol (
884 &gEfiUsbIoProtocolGuid
,
886 This
->DriverBindingHandle
,
888 EFI_OPEN_PROTOCOL_BY_DRIVER
891 if (EFI_ERROR (Status
)) {
892 DEBUG ((EFI_D_ERROR
, "USBMassDriverBindingStart: OpenUsbIoProtocol By Driver (%r)\n", Status
));
895 &gEfiDevicePathProtocolGuid
,
896 This
->DriverBindingHandle
,
903 // Initialize data for device that supports multiple LUNSs.
904 // EFI_SUCCESS is returned if at least 1 LUN is initialized successfully.
906 Status
= UsbMassInitMultiLun (This
, Controller
, Transport
, Context
, DevicePath
, MaxLun
);
907 if (EFI_ERROR (Status
)) {
910 &gEfiDevicePathProtocolGuid
,
911 This
->DriverBindingHandle
,
916 &gEfiUsbIoProtocolGuid
,
917 This
->DriverBindingHandle
,
920 DEBUG ((EFI_D_ERROR
, "USBMassDriverBindingStart: UsbMassInitMultiLun (%r) with Maxlun=%d\n", Status
, MaxLun
));
924 gBS
->RestoreTPL (OldTpl
);
930 Stop controlling the device.
932 @param This The USB mass storage driver binding
933 @param Controller The device controller controlled by the driver.
934 @param NumberOfChildren The number of children of this device
935 @param ChildHandleBuffer The buffer of children handle.
937 @retval EFI_SUCCESS The driver stopped from controlling the device.
938 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
939 @retval EFI_UNSUPPORTED Block I/O Protocol is not installed on Controller.
940 @retval Others Failed to stop the driver
945 USBMassDriverBindingStop (
946 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
947 IN EFI_HANDLE Controller
,
948 IN UINTN NumberOfChildren
,
949 IN EFI_HANDLE
*ChildHandleBuffer
953 USB_MASS_DEVICE
*UsbMass
;
954 EFI_USB_IO_PROTOCOL
*UsbIo
;
955 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
957 BOOLEAN AllChildrenStopped
;
960 // This is a bus driver stop function since multi-lun is supported.
961 // There are three kinds of device handles that might be passed:
962 // 1st is a handle with USB I/O & Block I/O installed (non-multi-lun)
963 // 2nd is a handle with Device Path & USB I/O installed (multi-lun root)
964 // 3rd is a handle with Device Path & USB I/O & Block I/O installed (multi-lun).
966 if (NumberOfChildren
== 0) {
968 // A handle without any children, might be 1st and 2nd type.
970 Status
= gBS
->OpenProtocol (
972 &gEfiBlockIoProtocolGuid
,
974 This
->DriverBindingHandle
,
976 EFI_OPEN_PROTOCOL_GET_PROTOCOL
979 if (EFI_ERROR(Status
)) {
981 // This is a 2nd type handle(multi-lun root), it needs to close devicepath
982 // and usbio protocol.
986 &gEfiDevicePathProtocolGuid
,
987 This
->DriverBindingHandle
,
992 &gEfiUsbIoProtocolGuid
,
993 This
->DriverBindingHandle
,
996 DEBUG ((EFI_D_INFO
, "Success to stop multi-lun root handle\n"));
1001 // This is a 1st type handle(non-multi-lun), which only needs to uninstall
1002 // Block I/O Protocol, close USB I/O Protocol and free mass device.
1004 UsbMass
= USB_MASS_DEVICE_FROM_BLOCK_IO (BlockIo
);
1007 // Uninstall Block I/O protocol from the device handle,
1008 // then call the transport protocol to stop itself.
1010 Status
= gBS
->UninstallProtocolInterface (
1012 &gEfiBlockIoProtocolGuid
,
1015 if (EFI_ERROR (Status
)) {
1019 gBS
->CloseProtocol (
1021 &gEfiUsbIoProtocolGuid
,
1022 This
->DriverBindingHandle
,
1026 UsbMass
->Transport
->CleanUp (UsbMass
->Context
);
1029 DEBUG ((EFI_D_INFO
, "Success to stop non-multi-lun root handle\n"));
1034 // This is a 3rd type handle(multi-lun), which needs uninstall
1035 // Block I/O Protocol and Device Path Protocol, close USB I/O Protocol and
1036 // free mass device for all children.
1038 AllChildrenStopped
= TRUE
;
1040 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
1042 Status
= gBS
->OpenProtocol (
1043 ChildHandleBuffer
[Index
],
1044 &gEfiBlockIoProtocolGuid
,
1046 This
->DriverBindingHandle
,
1048 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1050 if (EFI_ERROR (Status
)) {
1051 AllChildrenStopped
= FALSE
;
1052 DEBUG ((EFI_D_ERROR
, "Fail to stop No.%d multi-lun child handle when opening blockio\n", (UINT32
)Index
));
1056 UsbMass
= USB_MASS_DEVICE_FROM_BLOCK_IO (BlockIo
);
1058 gBS
->CloseProtocol (
1060 &gEfiUsbIoProtocolGuid
,
1061 This
->DriverBindingHandle
,
1062 ChildHandleBuffer
[Index
]
1065 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1066 ChildHandleBuffer
[Index
],
1067 &gEfiDevicePathProtocolGuid
,
1068 UsbMass
->DevicePath
,
1069 &gEfiBlockIoProtocolGuid
,
1074 if (EFI_ERROR (Status
)) {
1076 // Fail to uninstall Block I/O Protocol and Device Path Protocol, so re-open USB I/O Protocol by child.
1078 AllChildrenStopped
= FALSE
;
1079 DEBUG ((EFI_D_ERROR
, "Fail to stop No.%d multi-lun child handle when uninstalling blockio and devicepath\n", (UINT32
)Index
));
1083 &gEfiUsbIoProtocolGuid
,
1085 This
->DriverBindingHandle
,
1086 ChildHandleBuffer
[Index
],
1087 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1091 // Succeed to stop this multi-lun handle, so go on with next child.
1093 if (((Index
+ 1) == NumberOfChildren
) && AllChildrenStopped
) {
1094 UsbMass
->Transport
->CleanUp (UsbMass
->Context
);
1100 if (!AllChildrenStopped
) {
1101 return EFI_DEVICE_ERROR
;
1104 DEBUG ((EFI_D_INFO
, "Success to stop all %d multi-lun children handles\n", (UINT32
) NumberOfChildren
));
1109 Entrypoint of USB Mass Storage Driver.
1111 This function is the entrypoint of USB Mass Storage Driver. It installs Driver Binding
1112 Protocol together with Component Name Protocols.
1114 @param ImageHandle The firmware allocated handle for the EFI image.
1115 @param SystemTable A pointer to the EFI System Table.
1117 @retval EFI_SUCCESS The entry point is executed successfully.
1122 USBMassStorageEntryPoint (
1123 IN EFI_HANDLE ImageHandle
,
1124 IN EFI_SYSTEM_TABLE
*SystemTable
1130 // Install driver binding protocol
1132 Status
= EfiLibInstallDriverBindingComponentName2 (
1135 &gUSBMassDriverBinding
,
1137 &gUsbMassStorageComponentName
,
1138 &gUsbMassStorageComponentName2
1140 ASSERT_EFI_ERROR (Status
);