/** @file\r
USB Mass Storage Driver that manages USB Mass Storage Device and produces Block I/O Protocol.\r
\r
-Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
\r
#define USB_MASS_TRANSPORT_COUNT 3\r
//\r
-// Array of USB transport interfaces. \r
+// Array of USB transport interfaces.\r
//\r
USB_MASS_TRANSPORT *mUsbMassTransport[USB_MASS_TRANSPORT_COUNT] = {\r
&mUsbCbi0Transport,\r
/**\r
Reset the block device.\r
\r
- This function implements EFI_BLOCK_IO_PROTOCOL.Reset(). \r
+ This function implements EFI_BLOCK_IO_PROTOCOL.Reset().\r
It resets the block device hardware.\r
ExtendedVerification is ignored in this implementation.\r
\r
EFI_STATUS Status;\r
\r
//\r
- // Raise TPL to TPL_NOTIFY to serialize all its operations\r
+ // Raise TPL to TPL_CALLBACK to serialize all its operations\r
// to protect shared data structures.\r
//\r
- OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
\r
UsbMass = USB_MASS_DEVICE_FROM_BLOCK_IO (This);\r
Status = UsbMass->Transport->Reset (UsbMass->Context, ExtendedVerification);\r
/**\r
Reads the requested number of blocks from the device.\r
\r
- This function implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks(). \r
+ This function implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks().\r
It reads the requested number of blocks from the device.\r
All the blocks are read, or an error is returned.\r
\r
UINTN TotalBlock;\r
\r
//\r
- // Raise TPL to TPL_NOTIFY to serialize all its operations\r
+ // Raise TPL to TPL_CALLBACK to serialize all its operations\r
// to protect shared data structures.\r
//\r
- OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
UsbMass = USB_MASS_DEVICE_FROM_BLOCK_IO (This);\r
Media = &UsbMass->BlockIoMedia;\r
\r
goto ON_EXIT;\r
}\r
\r
- Status = UsbBootReadBlocks (UsbMass, (UINT32) Lba, TotalBlock, Buffer);\r
+ if (UsbMass->Cdb16Byte) {\r
+ Status = UsbBootReadWriteBlocks16 (UsbMass, FALSE, Lba, TotalBlock, Buffer);\r
+ } else {\r
+ Status = UsbBootReadWriteBlocks (UsbMass, FALSE, (UINT32) Lba, TotalBlock, Buffer);\r
+ }\r
+\r
if (EFI_ERROR (Status)) {\r
DEBUG ((EFI_D_ERROR, "UsbMassReadBlocks: UsbBootReadBlocks (%r) -> Reset\n", Status));\r
UsbMassReset (This, TRUE);\r
/**\r
Writes a specified number of blocks to the device.\r
\r
- This function implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks(). \r
+ This function implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks().\r
It writes a specified number of blocks to the device.\r
All blocks are written, or an error is returned.\r
\r
UINTN TotalBlock;\r
\r
//\r
- // Raise TPL to TPL_NOTIFY to serialize all its operations\r
+ // Raise TPL to TPL_CALLBACK to serialize all its operations\r
// to protect shared data structures.\r
//\r
- OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
UsbMass = USB_MASS_DEVICE_FROM_BLOCK_IO (This);\r
Media = &UsbMass->BlockIoMedia;\r
\r
// Try to write the data even the device is marked as ReadOnly,\r
// and clear the status should the write succeed.\r
//\r
- Status = UsbBootWriteBlocks (UsbMass, (UINT32) Lba, TotalBlock, Buffer);\r
+ if (UsbMass->Cdb16Byte) {\r
+ Status = UsbBootReadWriteBlocks16 (UsbMass, TRUE, Lba, TotalBlock, Buffer);\r
+ } else {\r
+ Status = UsbBootReadWriteBlocks (UsbMass, TRUE, (UINT32) Lba, TotalBlock, Buffer);\r
+ }\r
+\r
if (EFI_ERROR (Status)) {\r
DEBUG ((EFI_D_ERROR, "UsbMassWriteBlocks: UsbBootWriteBlocks (%r) -> Reset\n", Status));\r
UsbMassReset (This, TRUE);\r
Media->MediaId = 1;\r
\r
Status = UsbBootGetParams (UsbMass);\r
+ DEBUG ((DEBUG_INFO, "UsbMassInitMedia: UsbBootGetParams (%r)\n", Status));\r
+ if (Status == EFI_MEDIA_CHANGED) {\r
+ //\r
+ // Some USB storage devices may report MEDIA_CHANGED sense key when hot-plugged.\r
+ // Treat it as SUCCESS\r
+ //\r
+ Status = EFI_SUCCESS;\r
+ }\r
return Status;\r
}\r
\r
EFI_USB_INTERFACE_DESCRIPTOR Interface;\r
UINT8 Index;\r
EFI_STATUS Status;\r
- \r
+\r
Status = gBS->OpenProtocol (\r
Controller,\r
&gEfiUsbIoProtocolGuid,\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
- \r
+\r
Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface);\r
if (EFI_ERROR (Status)) {\r
goto ON_EXIT;\r
}\r
- \r
+\r
Status = EFI_UNSUPPORTED;\r
\r
//\r
}\r
\r
//\r
- // For BOT device, try to get its max LUN. \r
+ // For BOT device, try to get its max LUN.\r
// If max LUN is 0, then it is a non-lun device.\r
// Otherwise, it is a multi-lun device.\r
//\r
This->DriverBindingHandle,\r
Controller\r
);\r
- return Status; \r
+ return Status;\r
}\r
\r
/**\r
@param MaxLun The max LUN number.\r
\r
@retval EFI_SUCCESS At least one LUN is initialized successfully.\r
- @retval EFI_OUT_OF_RESOURCES Out of resource while creating device path node.\r
- @retval Other Initialization fails.\r
+ @retval EFI_NOT_FOUND Fail to initialize any of multiple LUNs.\r
\r
**/\r
EFI_STATUS\r
DEVICE_LOGICAL_UNIT_DEVICE_PATH LunNode;\r
UINT8 Index;\r
EFI_STATUS Status;\r
+ EFI_STATUS ReturnStatus;\r
\r
ASSERT (MaxLun > 0);\r
+ ReturnStatus = EFI_NOT_FOUND;\r
\r
- for (Index = 0; Index <= MaxLun; Index++) { \r
+ for (Index = 0; Index <= MaxLun; Index++) {\r
\r
DEBUG ((EFI_D_INFO, "UsbMassInitMultiLun: Start to initialize No.%d logic unit\n", Index));\r
- \r
+\r
UsbIo = NULL;\r
UsbMass = AllocateZeroPool (sizeof (USB_MASS_DEVICE));\r
ASSERT (UsbMass != NULL);\r
- \r
+\r
UsbMass->Signature = USB_MASS_SIGNATURE;\r
UsbMass->UsbIo = UsbIo;\r
UsbMass->BlockIo.Media = &UsbMass->BlockIoMedia;\r
UsbMass->Transport = Transport;\r
UsbMass->Context = Context;\r
UsbMass->Lun = Index;\r
- \r
+\r
//\r
// Initialize the media parameter data for EFI_BLOCK_IO_MEDIA of Block I/O Protocol.\r
//\r
Status = UsbMassInitMedia (UsbMass);\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // According to USB Mass Storage Specification for Bootability, only following\r
- // 4 Peripheral Device Types are in spec.\r
- //\r
- if ((UsbMass->Pdt != USB_PDT_DIRECT_ACCESS) && \r
- (UsbMass->Pdt != USB_PDT_CDROM) &&\r
- (UsbMass->Pdt != USB_PDT_OPTICAL) && \r
- (UsbMass->Pdt != USB_PDT_SIMPLE_DIRECT)) {\r
- DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: Found an unsupported peripheral type[%d]\n", UsbMass->Pdt));\r
- goto ON_ERROR;\r
- }\r
- } else if (Status != EFI_NO_MEDIA){\r
+ if ((EFI_ERROR (Status)) && (Status != EFI_NO_MEDIA)) {\r
DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: UsbMassInitMedia (%r)\n", Status));\r
- goto ON_ERROR;\r
+ FreePool (UsbMass);\r
+ continue;\r
}\r
\r
//\r
LunNode.Header.Type = MESSAGING_DEVICE_PATH;\r
LunNode.Header.SubType = MSG_DEVICE_LOGICAL_UNIT_DP;\r
LunNode.Lun = UsbMass->Lun;\r
- \r
+\r
SetDevicePathNodeLength (&LunNode.Header, sizeof (LunNode));\r
- \r
+\r
UsbMass->DevicePath = AppendDevicePathNode (DevicePath, &LunNode.Header);\r
- \r
+\r
if (UsbMass->DevicePath == NULL) {\r
DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: failed to create device logic unit device path\n"));\r
- \r
Status = EFI_OUT_OF_RESOURCES;\r
- goto ON_ERROR;\r
+ FreePool (UsbMass);\r
+ continue;\r
}\r
\r
InitializeDiskInfo (UsbMass);\r
&UsbMass->DiskInfo,\r
NULL\r
);\r
- \r
+\r
if (EFI_ERROR (Status)) {\r
DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: InstallMultipleProtocolInterfaces (%r)\n", Status));\r
- goto ON_ERROR;\r
+ FreePool (UsbMass->DevicePath);\r
+ FreePool (UsbMass);\r
+ continue;\r
}\r
\r
//\r
&UsbMass->DiskInfo,\r
NULL\r
);\r
- goto ON_ERROR;\r
- }\r
- \r
- DEBUG ((EFI_D_INFO, "UsbMassInitMultiLun: Success to initialize No.%d logic unit\n", Index));\r
- }\r
- \r
- return EFI_SUCCESS;\r
-\r
-ON_ERROR:\r
- if (UsbMass != NULL) {\r
- if (UsbMass->DevicePath != NULL) {\r
FreePool (UsbMass->DevicePath);\r
+ FreePool (UsbMass);\r
+ continue;\r
}\r
- FreePool (UsbMass);\r
- }\r
- if (UsbIo != NULL) {\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiUsbIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- UsbMass->Controller\r
- );\r
+ ReturnStatus = EFI_SUCCESS;\r
+ DEBUG ((EFI_D_INFO, "UsbMassInitMultiLun: Success to initialize No.%d logic unit\n", Index));\r
}\r
\r
- //\r
- // Return EFI_SUCCESS if at least one LUN is initialized successfully.\r
- //\r
- if (Index > 0) {\r
- return EFI_SUCCESS; \r
- } else {\r
- return Status;\r
- } \r
+ return ReturnStatus;\r
}\r
\r
/**\r
DEBUG ((EFI_D_ERROR, "UsbMassInitNonLun: OpenUsbIoProtocol By Driver (%r)\n", Status));\r
goto ON_ERROR;\r
}\r
- \r
+\r
UsbMass->Signature = USB_MASS_SIGNATURE;\r
UsbMass->Controller = Controller;\r
UsbMass->UsbIo = UsbIo;\r
UsbMass->OpticalStorage = FALSE;\r
UsbMass->Transport = Transport;\r
UsbMass->Context = Context;\r
- \r
+\r
//\r
// Initialize the media parameter data for EFI_BLOCK_IO_MEDIA of Block I/O Protocol.\r
//\r
Status = UsbMassInitMedia (UsbMass);\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // According to USB Mass Storage Specification for Bootability, only following\r
- // 4 Peripheral Device Types are in spec.\r
- //\r
- if ((UsbMass->Pdt != USB_PDT_DIRECT_ACCESS) && \r
- (UsbMass->Pdt != USB_PDT_CDROM) &&\r
- (UsbMass->Pdt != USB_PDT_OPTICAL) && \r
- (UsbMass->Pdt != USB_PDT_SIMPLE_DIRECT)) {\r
- DEBUG ((EFI_D_ERROR, "UsbMassInitNonLun: Found an unsupported peripheral type[%d]\n", UsbMass->Pdt));\r
- goto ON_ERROR;\r
- }\r
- } else if (Status != EFI_NO_MEDIA){\r
+ if ((EFI_ERROR (Status)) && (Status != EFI_NO_MEDIA)) {\r
DEBUG ((EFI_D_ERROR, "UsbMassInitNonLun: UsbMassInitMedia (%r)\n", Status));\r
goto ON_ERROR;\r
}\r
- \r
+\r
InitializeDiskInfo (UsbMass);\r
\r
Status = gBS->InstallMultipleProtocolInterfaces (\r
Controller\r
);\r
}\r
- return Status; \r
+ return Status;\r
}\r
\r
\r
VOID *Context;\r
UINT8 MaxLun;\r
EFI_STATUS Status;\r
- EFI_USB_IO_PROTOCOL *UsbIo; \r
+ EFI_USB_IO_PROTOCOL *UsbIo;\r
EFI_TPL OldTpl;\r
\r
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
// Initialize data for device that does not support multiple LUNSs.\r
//\r
Status = UsbMassInitNonLun (This, Controller, Transport, Context);\r
- if (EFI_ERROR (Status)) { \r
+ if (EFI_ERROR (Status)) {\r
DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: UsbMassInitNonLun (%r)\n", Status));\r
}\r
} else {\r
Controller,\r
EFI_OPEN_PROTOCOL_BY_DRIVER\r
);\r
- \r
+\r
if (EFI_ERROR (Status)) {\r
DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: OpenDevicePathProtocol By Driver (%r)\n", Status));\r
goto Exit;\r
Controller,\r
EFI_OPEN_PROTOCOL_BY_DRIVER\r
);\r
- \r
+\r
if (EFI_ERROR (Status)) {\r
DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: OpenUsbIoProtocol By Driver (%r)\n", Status));\r
gBS->CloseProtocol (\r
}\r
\r
//\r
- // Initialize data for device that supports multiple LUNSs.\r
+ // Initialize data for device that supports multiple LUNs.\r
// EFI_SUCCESS is returned if at least 1 LUN is initialized successfully.\r
//\r
Status = UsbMassInitMultiLun (This, Controller, Transport, Context, DevicePath, MaxLun);\r
Controller,\r
EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
);\r
- \r
+\r
if (EFI_ERROR(Status)) {\r
//\r
// This is a 2nd type handle(multi-lun root), it needs to close devicepath\r
DEBUG ((EFI_D_INFO, "Success to stop multi-lun root handle\n"));\r
return EFI_SUCCESS;\r
}\r
- \r
+\r
//\r
// This is a 1st type handle(non-multi-lun), which only needs to uninstall\r
// Block I/O Protocol, close USB I/O Protocol and free mass device.\r
//\r
UsbMass = USB_MASS_DEVICE_FROM_BLOCK_IO (BlockIo);\r
- \r
+\r
//\r
// Uninstall Block I/O protocol from the device handle,\r
// then call the transport protocol to stop itself.\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
- \r
+\r
gBS->CloseProtocol (\r
Controller,\r
&gEfiUsbIoProtocolGuid,\r
This->DriverBindingHandle,\r
Controller\r
);\r
- \r
+\r
UsbMass->Transport->CleanUp (UsbMass->Context);\r
FreePool (UsbMass);\r
- \r
+\r
DEBUG ((EFI_D_INFO, "Success to stop non-multi-lun root handle\n"));\r
return EFI_SUCCESS;\r
- } \r
+ }\r
\r
//\r
// This is a 3rd type handle(multi-lun), which needs uninstall\r
- // Block I/O Protocol and Device Path Protocol, close USB I/O Protocol and \r
+ // Block I/O Protocol and Device Path Protocol, close USB I/O Protocol and\r
// free mass device for all children.\r
//\r
AllChildrenStopped = TRUE;\r
This->DriverBindingHandle,\r
ChildHandleBuffer[Index]\r
);\r
- \r
+\r
Status = gBS->UninstallMultipleProtocolInterfaces (\r
ChildHandleBuffer[Index],\r
&gEfiDevicePathProtocolGuid,\r
&UsbMass->DiskInfo,\r
NULL\r
);\r
- \r
+\r
if (EFI_ERROR (Status)) {\r
//\r
// Fail to uninstall Block I/O Protocol and Device Path Protocol, so re-open USB I/O Protocol by child.\r
//\r
AllChildrenStopped = FALSE;\r
DEBUG ((EFI_D_ERROR, "Fail to stop No.%d multi-lun child handle when uninstalling blockio and devicepath\n", (UINT32)Index));\r
- \r
+\r
gBS->OpenProtocol (\r
Controller,\r
&gEfiUsbIoProtocolGuid,\r
if (!AllChildrenStopped) {\r
return EFI_DEVICE_ERROR;\r
}\r
- \r
+\r
DEBUG ((EFI_D_INFO, "Success to stop all %d multi-lun children handles\n", (UINT32) NumberOfChildren));\r
return EFI_SUCCESS;\r
}\r