2 USB Mass Storage Driver that manages USB Mass Storage Device and produces Block I/O Protocol.
4 Copyright (c) 2007 - 2008, Intel Corporation
5 All rights reserved. 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 // First, validate the parameters
119 if ((Buffer
== NULL
) || (BufferSize
== 0)) {
120 return EFI_INVALID_PARAMETER
;
124 // Raise TPL to TPL_NOTIFY to serialize all its operations
125 // to protect shared data structures.
127 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
128 UsbMass
= USB_MASS_DEVICE_FROM_BLOCK_IO (This
);
129 Media
= &UsbMass
->BlockIoMedia
;
132 // If it is a removable media, such as CD-Rom or Usb-Floppy,
133 // need to detect the media before each read/write. While some of
134 // Usb-Flash is marked as removable media.
136 if (Media
->RemovableMedia
) {
137 Status
= UsbBootDetectMedia (UsbMass
);
138 if (EFI_ERROR (Status
)) {
144 // BufferSize must be a multiple of the intrinsic block size of the device.
146 if ((BufferSize
% Media
->BlockSize
) != 0) {
147 Status
= EFI_BAD_BUFFER_SIZE
;
151 TotalBlock
= BufferSize
/ Media
->BlockSize
;
154 // Make sure the range to read is valid.
156 if (Lba
+ TotalBlock
- 1 > Media
->LastBlock
) {
157 Status
= EFI_INVALID_PARAMETER
;
161 if (!(Media
->MediaPresent
)) {
162 Status
= EFI_NO_MEDIA
;
166 if (MediaId
!= Media
->MediaId
) {
167 Status
= EFI_MEDIA_CHANGED
;
171 Status
= UsbBootReadBlocks (UsbMass
, (UINT32
) Lba
, TotalBlock
, Buffer
);
172 if (EFI_ERROR (Status
)) {
173 DEBUG ((EFI_D_ERROR
, "UsbMassReadBlocks: UsbBootReadBlocks (%r) -> Reset\n", Status
));
174 UsbMassReset (This
, TRUE
);
178 gBS
->RestoreTPL (OldTpl
);
184 Writes a specified number of blocks to the device.
186 This function implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks().
187 It writes a specified number of blocks to the device.
188 All blocks are written, or an error is returned.
190 @param This Indicates a pointer to the calling context.
191 @param MediaId The media ID that the write request is for.
192 @param Lba The starting logical block address to be written.
193 @param BufferSize The size of the Buffer in bytes.
194 This must be a multiple of the intrinsic block size of the device.
195 @param Buffer Pointer to the source buffer for the data.
197 @retval EFI_SUCCESS The data were written correctly to the device.
198 @retval EFI_WRITE_PROTECTED The device cannot be written to.
199 @retval EFI_NO_MEDIA There is no media in the device.
200 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
201 @retval EFI_DEVICE_ERROR The device reported an error while attempting to perform the write operation.
202 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the intrinsic
203 block size of the device.
204 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
205 or the buffer is not on proper alignment.
211 IN EFI_BLOCK_IO_PROTOCOL
*This
,
218 USB_MASS_DEVICE
*UsbMass
;
219 EFI_BLOCK_IO_MEDIA
*Media
;
225 // First, validate the parameters
227 if ((Buffer
== NULL
) || (BufferSize
== 0)) {
228 return EFI_INVALID_PARAMETER
;
232 // Raise TPL to TPL_NOTIFY to serialize all its operations
233 // to protect shared data structures.
235 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
236 UsbMass
= USB_MASS_DEVICE_FROM_BLOCK_IO (This
);
237 Media
= &UsbMass
->BlockIoMedia
;
240 // If it is a removable media, such as CD-Rom or Usb-Floppy,
241 // need to detect the media before each read/write. Some of
242 // USB Flash is marked as removable media.
244 if (Media
->RemovableMedia
) {
245 Status
= UsbBootDetectMedia (UsbMass
);
246 if (EFI_ERROR (Status
)) {
252 // BufferSize must be a multiple of the intrinsic block size of the device.
254 if ((BufferSize
% Media
->BlockSize
) != 0) {
255 Status
= EFI_BAD_BUFFER_SIZE
;
259 TotalBlock
= BufferSize
/ Media
->BlockSize
;
262 // Make sure the range to write is valid.
264 if (Lba
+ TotalBlock
- 1 > Media
->LastBlock
) {
265 Status
= EFI_INVALID_PARAMETER
;
269 if (!(Media
->MediaPresent
)) {
270 Status
= EFI_NO_MEDIA
;
274 if (MediaId
!= Media
->MediaId
) {
275 Status
= EFI_MEDIA_CHANGED
;
280 // Try to write the data even the device is marked as ReadOnly,
281 // and clear the status should the write succeed.
283 Status
= UsbBootWriteBlocks (UsbMass
, (UINT32
) Lba
, TotalBlock
, Buffer
);
284 if (EFI_ERROR (Status
)) {
285 DEBUG ((EFI_D_ERROR
, "UsbMassWriteBlocks: UsbBootWriteBlocks (%r) -> Reset\n", Status
));
286 UsbMassReset (This
, TRUE
);
290 gBS
->RestoreTPL (OldTpl
);
295 Flushes all modified data to a physical block device.
297 This function implements EFI_BLOCK_IO_PROTOCOL.FlushBlocks().
298 USB mass storage device doesn't support write cache,
299 so return EFI_SUCCESS directly.
301 @param This Indicates a pointer to the calling context.
303 @retval EFI_SUCCESS All outstanding data were written correctly to the device.
304 @retval EFI_DEVICE_ERROR The device reported an error while attempting to write data.
305 @retval EFI_NO_MEDIA There is no media in the device.
311 IN EFI_BLOCK_IO_PROTOCOL
*This
318 Initialize the media parameter data for EFI_BLOCK_IO_MEDIA of Block I/O Protocol.
320 @param UsbMass The USB mass storage device
322 @retval EFI_SUCCESS The media parameters are updated successfully.
323 @retval Others Failed to get the media parameters.
328 IN USB_MASS_DEVICE
*UsbMass
331 EFI_BLOCK_IO_MEDIA
*Media
;
335 Media
= &UsbMass
->BlockIoMedia
;
338 // Fields of EFI_BLOCK_IO_MEDIA are defined in UEFI 2.0 spec,
339 // section for Block I/O Protocol.
341 Media
->MediaPresent
= FALSE
;
342 Media
->LogicalPartition
= FALSE
;
343 Media
->ReadOnly
= FALSE
;
344 Media
->WriteCaching
= FALSE
;
349 // Some device may spend several seconds before it is ready.
350 // Try several times before giving up. Wait 5s at most.
352 Status
= EFI_SUCCESS
;
354 for (Index
= 0; Index
< USB_BOOT_INIT_MEDIA_RETRY
; Index
++) {
356 Status
= UsbBootGetParams (UsbMass
);
357 if ((Status
!= EFI_MEDIA_CHANGED
) && (Status
!= EFI_NOT_READY
) && (Status
!= EFI_TIMEOUT
)) {
361 Status
= UsbBootIsUnitReady (UsbMass
);
362 if (EFI_ERROR (Status
)) {
363 gBS
->Stall (USB_BOOT_RETRY_UNIT_READY_STALL
* (Index
+ 1));
371 Initilize the USB Mass Storage transport.
373 This function tries to find the matching USB Mass Storage transport
374 protocol for USB device. If found, initializes the matching transport.
376 @param This The USB mass driver's driver binding.
377 @param Controller The device to test.
378 @param Transport The pointer to pointer to USB_MASS_TRANSPORT.
379 @param Context The parameter for USB_MASS_DEVICE.Context.
380 @param MaxLun Get the MaxLun if is BOT dev.
382 @retval EFI_SUCCESS The initialization is successful.
383 @retval EFI_UNSUPPORTED No matching transport protocol is found.
384 @retval Others Failed to initialize dev.
388 UsbMassInitTransport (
389 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
390 IN EFI_HANDLE Controller
,
391 OUT USB_MASS_TRANSPORT
**Transport
,
396 EFI_USB_IO_PROTOCOL
*UsbIo
;
397 EFI_USB_INTERFACE_DESCRIPTOR Interface
;
401 Status
= gBS
->OpenProtocol (
403 &gEfiUsbIoProtocolGuid
,
405 This
->DriverBindingHandle
,
407 EFI_OPEN_PROTOCOL_BY_DRIVER
410 if (EFI_ERROR (Status
)) {
414 Status
= UsbIo
->UsbGetInterfaceDescriptor (UsbIo
, &Interface
);
415 if (EFI_ERROR (Status
)) {
419 Status
= EFI_UNSUPPORTED
;
422 // Traverse the USB_MASS_TRANSPORT arrary and try to find the
423 // matching transport protocol.
424 // If not found, return EFI_UNSUPPORTED.
425 // If found, execute USB_MASS_TRANSPORT.Init() to initialize the transport context.
427 for (Index
= 0; Index
< USB_MASS_TRANSPORT_COUNT
; Index
++) {
428 *Transport
= mUsbMassTransport
[Index
];
430 if (Interface
.InterfaceProtocol
== (*Transport
)->Protocol
) {
431 Status
= (*Transport
)->Init (UsbIo
, Context
);
436 if (EFI_ERROR (Status
)) {
441 // For BOT device, try to get its max LUN.
442 // If max LUN is 0, then it is a non-lun device.
443 // Otherwise, it is a multi-lun device.
445 if ((*Transport
)->Protocol
== USB_MASS_STORE_BOT
) {
446 (*Transport
)->GetMaxLun (*Context
, MaxLun
);
452 &gEfiUsbIoProtocolGuid
,
453 This
->DriverBindingHandle
,
460 Initialize data for device that supports multiple LUNSs.
462 @param This The Driver Binding Protocol instance.
463 @param Controller The device to initialize.
464 @param Transport Pointer to USB_MASS_TRANSPORT.
465 @param Context Parameter for USB_MASS_DEVICE.Context.
466 @param DevicePath The remaining device path.
467 @param MaxLun The max LUN number.
469 @retval EFI_SUCCESS At least one LUN is initialized successfully.
470 @retval EFI_OUT_OF_RESOURCES Out of resource while creating device path node.
471 @retval Other Initialization fails.
475 UsbMassInitMultiLun (
476 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
477 IN EFI_HANDLE Controller
,
478 IN USB_MASS_TRANSPORT
*Transport
,
480 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
484 USB_MASS_DEVICE
*UsbMass
;
485 EFI_USB_IO_PROTOCOL
*UsbIo
;
486 DEVICE_LOGICAL_UNIT_DEVICE_PATH LunNode
;
492 for (Index
= 0; Index
<= MaxLun
; Index
++) {
494 DEBUG ((EFI_D_INFO
, "UsbMassInitMultiLun: Start to initialize No.%d logic unit\n", Index
));
497 UsbMass
= AllocateZeroPool (sizeof (USB_MASS_DEVICE
));
498 ASSERT (UsbMass
!= NULL
);
500 UsbMass
->Signature
= USB_MASS_SIGNATURE
;
501 UsbMass
->UsbIo
= UsbIo
;
502 UsbMass
->BlockIo
.Media
= &UsbMass
->BlockIoMedia
;
503 UsbMass
->BlockIo
.Reset
= UsbMassReset
;
504 UsbMass
->BlockIo
.ReadBlocks
= UsbMassReadBlocks
;
505 UsbMass
->BlockIo
.WriteBlocks
= UsbMassWriteBlocks
;
506 UsbMass
->BlockIo
.FlushBlocks
= UsbMassFlushBlocks
;
507 UsbMass
->OpticalStorage
= FALSE
;
508 UsbMass
->Transport
= Transport
;
509 UsbMass
->Context
= Context
;
510 UsbMass
->Lun
= Index
;
513 // Initialize the media parameter data for EFI_BLOCK_IO_MEDIA of Block I/O Protocol.
515 Status
= UsbMassInitMedia (UsbMass
);
516 if (!EFI_ERROR (Status
)) {
518 // According to USB Mass Storage Specification for Bootability, only following
519 // 4 Peripheral Device Types are in spec.
521 if ((UsbMass
->Pdt
!= USB_PDT_DIRECT_ACCESS
) &&
522 (UsbMass
->Pdt
!= USB_PDT_CDROM
) &&
523 (UsbMass
->Pdt
!= USB_PDT_OPTICAL
) &&
524 (UsbMass
->Pdt
!= USB_PDT_SIMPLE_DIRECT
)) {
525 DEBUG ((EFI_D_ERROR
, "UsbMassInitMultiLun: Found an unsupported peripheral type[%d]\n", UsbMass
->Pdt
));
528 } else if (Status
!= EFI_NO_MEDIA
){
529 DEBUG ((EFI_D_ERROR
, "UsbMassInitMultiLun: UsbMassInitMedia (%r)\n", Status
));
534 // Create a device path node for device logic unit, and append it.
536 LunNode
.Header
.Type
= MESSAGING_DEVICE_PATH
;
537 LunNode
.Header
.SubType
= MSG_DEVICE_LOGICAL_UNIT_DP
;
538 LunNode
.Lun
= UsbMass
->Lun
;
540 SetDevicePathNodeLength (&LunNode
.Header
, sizeof (LunNode
));
542 UsbMass
->DevicePath
= AppendDevicePathNode (DevicePath
, &LunNode
.Header
);
544 if (UsbMass
->DevicePath
== NULL
) {
545 DEBUG ((EFI_D_ERROR
, "UsbMassInitMultiLun: failed to create device logic unit device path\n"));
547 Status
= EFI_OUT_OF_RESOURCES
;
552 // Create a new handle for each LUN, and install Block I/O Protocol and Device Path Protocol.
554 Status
= gBS
->InstallMultipleProtocolInterfaces (
555 &UsbMass
->Controller
,
556 &gEfiDevicePathProtocolGuid
,
558 &gEfiBlockIoProtocolGuid
,
563 if (EFI_ERROR (Status
)) {
564 DEBUG ((EFI_D_ERROR
, "UsbMassInitMultiLun: InstallMultipleProtocolInterfaces (%r)\n", Status
));
569 // Open USB I/O Protocol by child to setup a parent-child relationship.
571 Status
= gBS
->OpenProtocol (
573 &gEfiUsbIoProtocolGuid
,
575 This
->DriverBindingHandle
,
577 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
580 if (EFI_ERROR (Status
)) {
581 DEBUG ((EFI_D_ERROR
, "UsbMassInitMultiLun: OpenUsbIoProtocol By Child (%r)\n", Status
));
582 gBS
->UninstallMultipleProtocolInterfaces (
583 &UsbMass
->Controller
,
584 &gEfiDevicePathProtocolGuid
,
586 &gEfiBlockIoProtocolGuid
,
593 DEBUG ((EFI_D_INFO
, "UsbMassInitMultiLun: Success to initialize No.%d logic unit\n", Index
));
599 if (UsbMass
!= NULL
) {
600 if (UsbMass
->DevicePath
!= NULL
) {
601 FreePool (UsbMass
->DevicePath
);
608 &gEfiUsbIoProtocolGuid
,
609 This
->DriverBindingHandle
,
615 // Return EFI_SUCCESS if at least one LUN is initialized successfully.
625 Initialize data for device that does not support multiple LUNSs.
627 @param This The Driver Binding Protocol instance.
628 @param Controller The device to initialize.
629 @param Transport Pointer to USB_MASS_TRANSPORT.
630 @param Context Parameter for USB_MASS_DEVICE.Context.
632 @retval EFI_SUCCESS Initialization succeeds.
633 @retval Other Initialization fails.
638 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
639 IN EFI_HANDLE Controller
,
640 IN USB_MASS_TRANSPORT
*Transport
,
644 USB_MASS_DEVICE
*UsbMass
;
645 EFI_USB_IO_PROTOCOL
*UsbIo
;
649 UsbMass
= AllocateZeroPool (sizeof (USB_MASS_DEVICE
));
650 ASSERT (UsbMass
!= NULL
);
652 Status
= gBS
->OpenProtocol (
654 &gEfiUsbIoProtocolGuid
,
656 This
->DriverBindingHandle
,
658 EFI_OPEN_PROTOCOL_BY_DRIVER
661 if (EFI_ERROR (Status
)) {
662 DEBUG ((EFI_D_ERROR
, "UsbMassInitNonLun: OpenUsbIoProtocol By Driver (%r)\n", Status
));
666 UsbMass
->Signature
= USB_MASS_SIGNATURE
;
667 UsbMass
->Controller
= Controller
;
668 UsbMass
->UsbIo
= UsbIo
;
669 UsbMass
->BlockIo
.Media
= &UsbMass
->BlockIoMedia
;
670 UsbMass
->BlockIo
.Reset
= UsbMassReset
;
671 UsbMass
->BlockIo
.ReadBlocks
= UsbMassReadBlocks
;
672 UsbMass
->BlockIo
.WriteBlocks
= UsbMassWriteBlocks
;
673 UsbMass
->BlockIo
.FlushBlocks
= UsbMassFlushBlocks
;
674 UsbMass
->OpticalStorage
= FALSE
;
675 UsbMass
->Transport
= Transport
;
676 UsbMass
->Context
= Context
;
679 // Initialize the media parameter data for EFI_BLOCK_IO_MEDIA of Block I/O Protocol.
681 Status
= UsbMassInitMedia (UsbMass
);
682 if (!EFI_ERROR (Status
)) {
684 // According to USB Mass Storage Specification for Bootability, only following
685 // 4 Peripheral Device Types are in spec.
687 if ((UsbMass
->Pdt
!= USB_PDT_DIRECT_ACCESS
) &&
688 (UsbMass
->Pdt
!= USB_PDT_CDROM
) &&
689 (UsbMass
->Pdt
!= USB_PDT_OPTICAL
) &&
690 (UsbMass
->Pdt
!= USB_PDT_SIMPLE_DIRECT
)) {
691 DEBUG ((EFI_D_ERROR
, "UsbMassInitNonLun: Found an unsupported peripheral type[%d]\n", UsbMass
->Pdt
));
694 } else if (Status
!= EFI_NO_MEDIA
){
695 DEBUG ((EFI_D_ERROR
, "UsbMassInitNonLun: UsbMassInitMedia (%r)\n", Status
));
699 Status
= gBS
->InstallProtocolInterface (
701 &gEfiBlockIoProtocolGuid
,
702 EFI_NATIVE_INTERFACE
,
705 if (EFI_ERROR (Status
)) {
712 if (UsbMass
!= NULL
) {
718 &gEfiUsbIoProtocolGuid
,
719 This
->DriverBindingHandle
,
728 Check whether the controller is a supported USB mass storage.
730 @param This The USB mass storage driver binding protocol.
731 @param Controller The controller handle to check.
732 @param RemainingDevicePath The remaining device path.
734 @retval EFI_SUCCESS The driver supports this controller.
735 @retval other This device isn't supported.
740 USBMassDriverBindingSupported (
741 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
742 IN EFI_HANDLE Controller
,
743 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
746 EFI_USB_IO_PROTOCOL
*UsbIo
;
747 EFI_USB_INTERFACE_DESCRIPTOR Interface
;
748 USB_MASS_TRANSPORT
*Transport
;
752 Status
= gBS
->OpenProtocol (
754 &gEfiUsbIoProtocolGuid
,
756 This
->DriverBindingHandle
,
758 EFI_OPEN_PROTOCOL_BY_DRIVER
760 if (EFI_ERROR (Status
)) {
765 // Get the interface descriptor to check the USB class and find a transport
768 Status
= UsbIo
->UsbGetInterfaceDescriptor (UsbIo
, &Interface
);
769 if (EFI_ERROR (Status
)) {
773 Status
= EFI_UNSUPPORTED
;
775 if (Interface
.InterfaceClass
!= USB_MASS_STORE_CLASS
) {
780 // Traverse the USB_MASS_TRANSPORT arrary and try to find the
781 // matching transport method.
782 // If not found, return EFI_UNSUPPORTED.
783 // If found, execute USB_MASS_TRANSPORT.Init() to initialize the transport context.
785 for (Index
= 0; Index
< USB_MASS_TRANSPORT_COUNT
; Index
++) {
786 Transport
= mUsbMassTransport
[Index
];
787 if (Interface
.InterfaceProtocol
== Transport
->Protocol
) {
788 Status
= Transport
->Init (UsbIo
, NULL
);
796 &gEfiUsbIoProtocolGuid
,
797 This
->DriverBindingHandle
,
805 Starts the USB mass storage device with this driver.
807 This function consumes USB I/O Portocol, intializes USB mass storage device,
808 installs Block I/O Protocol, and submits Asynchronous Interrupt
809 Transfer to manage the USB mass storage device.
811 @param This The USB mass storage driver binding protocol.
812 @param Controller The USB mass storage device to start on
813 @param RemainingDevicePath The remaining device path.
815 @retval EFI_SUCCESS This driver supports this device.
816 @retval EFI_UNSUPPORTED This driver does not support this device.
817 @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.
818 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
819 @retval EFI_ALREADY_STARTED This driver has been started.
824 USBMassDriverBindingStart (
825 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
826 IN EFI_HANDLE Controller
,
827 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
830 USB_MASS_TRANSPORT
*Transport
;
831 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
835 EFI_USB_IO_PROTOCOL
*UsbIo
;
841 Status
= UsbMassInitTransport (This
, Controller
, &Transport
, &Context
, &MaxLun
);
843 if (EFI_ERROR (Status
)) {
844 DEBUG ((EFI_D_ERROR
, "USBMassDriverBindingStart: UsbMassInitTransport (%r)\n", Status
));
849 // Initialize data for device that does not support multiple LUNSs.
851 Status
= UsbMassInitNonLun (This
, Controller
, Transport
, Context
);
852 if (EFI_ERROR (Status
)) {
853 DEBUG ((EFI_D_ERROR
, "USBMassDriverBindingStart: UsbMassInitNonLun (%r)\n", Status
));
857 // Open device path to prepare for appending Device Logic Unit node.
859 Status
= gBS
->OpenProtocol (
861 &gEfiDevicePathProtocolGuid
,
862 (VOID
**) &DevicePath
,
863 This
->DriverBindingHandle
,
865 EFI_OPEN_PROTOCOL_BY_DRIVER
868 if (EFI_ERROR (Status
)) {
869 DEBUG ((EFI_D_ERROR
, "USBMassDriverBindingStart: OpenDevicePathProtocol By Driver (%r)\n", Status
));
873 Status
= gBS
->OpenProtocol (
875 &gEfiUsbIoProtocolGuid
,
877 This
->DriverBindingHandle
,
879 EFI_OPEN_PROTOCOL_BY_DRIVER
882 if (EFI_ERROR (Status
)) {
883 DEBUG ((EFI_D_ERROR
, "USBMassDriverBindingStart: OpenUsbIoProtocol By Driver (%r)\n", Status
));
886 &gEfiDevicePathProtocolGuid
,
887 This
->DriverBindingHandle
,
894 // Initialize data for device that supports multiple LUNSs.
895 // EFI_SUCCESS is returned if at least 1 LUN is initialized successfully.
897 Status
= UsbMassInitMultiLun (This
, Controller
, Transport
, Context
, DevicePath
, MaxLun
);
898 if (EFI_ERROR (Status
)) {
901 &gEfiDevicePathProtocolGuid
,
902 This
->DriverBindingHandle
,
907 &gEfiUsbIoProtocolGuid
,
908 This
->DriverBindingHandle
,
911 DEBUG ((EFI_D_ERROR
, "USBMassDriverBindingStart: UsbMassInitMultiLun (%r) with Maxlun=%d\n", Status
, MaxLun
));
919 Stop controlling the device.
921 @param This The USB mass storage driver binding
922 @param Controller The device controller controlled by the driver.
923 @param NumberOfChildren The number of children of this device
924 @param ChildHandleBuffer The buffer of children handle.
926 @retval EFI_SUCCESS The driver stopped from controlling the device.
927 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
928 @retval EFI_UNSUPPORTED Block I/O Protocol is not installed on Controller.
929 @retval Others Failed to stop the driver
934 USBMassDriverBindingStop (
935 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
936 IN EFI_HANDLE Controller
,
937 IN UINTN NumberOfChildren
,
938 IN EFI_HANDLE
*ChildHandleBuffer
942 USB_MASS_DEVICE
*UsbMass
;
943 EFI_USB_IO_PROTOCOL
*UsbIo
;
944 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
946 BOOLEAN AllChildrenStopped
;
949 // This is a bus driver stop function since multi-lun is supported.
950 // There are three kinds of device handles that might be passed:
951 // 1st is a handle with USB I/O & Block I/O installed (non-multi-lun)
952 // 2nd is a handle with Device Path & USB I/O installed (multi-lun root)
953 // 3rd is a handle with Device Path & USB I/O & Block I/O installed (multi-lun).
955 if (NumberOfChildren
== 0) {
957 // A handle without any children, might be 1st and 2nd type.
959 Status
= gBS
->OpenProtocol (
961 &gEfiBlockIoProtocolGuid
,
963 This
->DriverBindingHandle
,
965 EFI_OPEN_PROTOCOL_GET_PROTOCOL
968 if (EFI_ERROR(Status
)) {
970 // This is a 2nd type handle(multi-lun root), it needs to close devicepath
971 // and usbio protocol.
975 &gEfiDevicePathProtocolGuid
,
976 This
->DriverBindingHandle
,
981 &gEfiUsbIoProtocolGuid
,
982 This
->DriverBindingHandle
,
985 DEBUG ((EFI_D_INFO
, "Success to stop multi-lun root handle\n"));
990 // This is a 1st type handle(non-multi-lun), which only needs to uninstall
991 // Block I/O Protocol, close USB I/O Protocol and free mass device.
993 UsbMass
= USB_MASS_DEVICE_FROM_BLOCK_IO (BlockIo
);
996 // Uninstall Block I/O protocol from the device handle,
997 // then call the transport protocol to stop itself.
999 Status
= gBS
->UninstallProtocolInterface (
1001 &gEfiBlockIoProtocolGuid
,
1004 if (EFI_ERROR (Status
)) {
1008 gBS
->CloseProtocol (
1010 &gEfiUsbIoProtocolGuid
,
1011 This
->DriverBindingHandle
,
1015 UsbMass
->Transport
->CleanUp (UsbMass
->Context
);
1018 DEBUG ((EFI_D_INFO
, "Success to stop non-multi-lun root handle\n"));
1023 // This is a 3rd type handle(multi-lun), which needs uninstall
1024 // Block I/O Protocol and Device Path Protocol, close USB I/O Protocol and
1025 // free mass device for all children.
1027 AllChildrenStopped
= TRUE
;
1029 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
1031 Status
= gBS
->OpenProtocol (
1032 ChildHandleBuffer
[Index
],
1033 &gEfiBlockIoProtocolGuid
,
1035 This
->DriverBindingHandle
,
1037 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1039 if (EFI_ERROR (Status
)) {
1040 AllChildrenStopped
= FALSE
;
1041 DEBUG ((EFI_D_ERROR
, "Fail to stop No.%d multi-lun child handle when opening blockio\n", (UINT32
)Index
));
1045 UsbMass
= USB_MASS_DEVICE_FROM_BLOCK_IO (BlockIo
);
1047 gBS
->CloseProtocol (
1049 &gEfiUsbIoProtocolGuid
,
1050 This
->DriverBindingHandle
,
1051 ChildHandleBuffer
[Index
]
1054 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1055 ChildHandleBuffer
[Index
],
1056 &gEfiDevicePathProtocolGuid
,
1057 UsbMass
->DevicePath
,
1058 &gEfiBlockIoProtocolGuid
,
1063 if (EFI_ERROR (Status
)) {
1065 // Fail to uninstall Block I/O Protocol and Device Path Protocol, so re-open USB I/O Protocol by child.
1067 AllChildrenStopped
= FALSE
;
1068 DEBUG ((EFI_D_ERROR
, "Fail to stop No.%d multi-lun child handle when uninstalling blockio and devicepath\n", (UINT32
)Index
));
1072 &gEfiUsbIoProtocolGuid
,
1074 This
->DriverBindingHandle
,
1075 ChildHandleBuffer
[Index
],
1076 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1080 // Succeed to stop this multi-lun handle, so go on with next child.
1082 if (((Index
+ 1) == NumberOfChildren
) && AllChildrenStopped
) {
1083 UsbMass
->Transport
->CleanUp (UsbMass
->Context
);
1089 if (!AllChildrenStopped
) {
1090 return EFI_DEVICE_ERROR
;
1093 DEBUG ((EFI_D_INFO
, "Success to stop all %d multi-lun children handles\n", (UINT32
) NumberOfChildren
));
1098 Entrypoint of USB Mass Storage Driver.
1100 This function is the entrypoint of USB Mass Storage Driver. It installs Driver Binding
1101 Protocol together with Component Name Protocols.
1103 @param ImageHandle The firmware allocated handle for the EFI image.
1104 @param SystemTable A pointer to the EFI System Table.
1106 @retval EFI_SUCCESS The entry point is executed successfully.
1111 USBMassStorageEntryPoint (
1112 IN EFI_HANDLE ImageHandle
,
1113 IN EFI_SYSTEM_TABLE
*SystemTable
1119 // Install driver binding protocol
1121 Status
= EfiLibInstallDriverBindingComponentName2 (
1124 &gUSBMassDriverBinding
,
1126 &gUsbMassStorageComponentName
,
1127 &gUsbMassStorageComponentName2
1129 ASSERT_EFI_ERROR (Status
);