X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FBus%2FUsb%2FUsbMassStorageDxe%2FUsbMassImpl.c;h=8c27e18cdb8754151221d8a00ed943267a9953a2;hp=f440e9fd7c5f78820afbce67ed165630a94a26c3;hb=9d510e61fceee7b92955ef9a3c20343752d8ce3f;hpb=15cc67e616cad2dad3d3b6f9ba1cba856b5de414
diff --git a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassImpl.c b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassImpl.c
index f440e9fd7c..8c27e18cdb 100644
--- a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassImpl.c
+++ b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassImpl.c
@@ -1,22 +1,16 @@
/** @file
USB Mass Storage Driver that manages USB Mass Storage Device and produces Block I/O Protocol.
-Copyright (c) 2007 - 2008, Intel Corporation. All rights reserved.
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent
**/
-#include "UsbMassImpl.h"
+#include "UsbMass.h"
#define USB_MASS_TRANSPORT_COUNT 3
//
-// Array of USB transport interfaces.
+// Array of USB transport interfaces.
//
USB_MASS_TRANSPORT *mUsbMassTransport[USB_MASS_TRANSPORT_COUNT] = {
&mUsbCbi0Transport,
@@ -36,7 +30,7 @@ EFI_DRIVER_BINDING_PROTOCOL gUSBMassDriverBinding = {
/**
Reset the block device.
- This function implements EFI_BLOCK_IO_PROTOCOL.Reset().
+ This function implements EFI_BLOCK_IO_PROTOCOL.Reset().
It resets the block device hardware.
ExtendedVerification is ignored in this implementation.
@@ -60,10 +54,10 @@ UsbMassReset (
EFI_STATUS Status;
//
- // Raise TPL to TPL_NOTIFY to serialize all its operations
+ // Raise TPL to TPL_CALLBACK to serialize all its operations
// to protect shared data structures.
//
- OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
UsbMass = USB_MASS_DEVICE_FROM_BLOCK_IO (This);
Status = UsbMass->Transport->Reset (UsbMass->Context, ExtendedVerification);
@@ -76,7 +70,7 @@ UsbMassReset (
/**
Reads the requested number of blocks from the device.
- This function implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks().
+ This function implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks().
It reads the requested number of blocks from the device.
All the blocks are read, or an error is returned.
@@ -114,17 +108,10 @@ UsbMassReadBlocks (
UINTN TotalBlock;
//
- // First, validate the parameters
- //
- if ((Buffer == NULL) || (BufferSize == 0)) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Raise TPL to TPL_NOTIFY to serialize all its operations
+ // Raise TPL to TPL_CALLBACK to serialize all its operations
// to protect shared data structures.
//
- OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
UsbMass = USB_MASS_DEVICE_FROM_BLOCK_IO (This);
Media = &UsbMass->BlockIoMedia;
@@ -140,6 +127,26 @@ UsbMassReadBlocks (
}
}
+ if (!(Media->MediaPresent)) {
+ Status = EFI_NO_MEDIA;
+ goto ON_EXIT;
+ }
+
+ if (MediaId != Media->MediaId) {
+ Status = EFI_MEDIA_CHANGED;
+ goto ON_EXIT;
+ }
+
+ if (BufferSize == 0) {
+ Status = EFI_SUCCESS;
+ goto ON_EXIT;
+ }
+
+ if (Buffer == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
//
// BufferSize must be a multiple of the intrinsic block size of the device.
//
@@ -158,17 +165,12 @@ UsbMassReadBlocks (
goto ON_EXIT;
}
- if (!(Media->MediaPresent)) {
- Status = EFI_NO_MEDIA;
- goto ON_EXIT;
- }
-
- if (MediaId != Media->MediaId) {
- Status = EFI_MEDIA_CHANGED;
- goto ON_EXIT;
+ if (UsbMass->Cdb16Byte) {
+ Status = UsbBootReadWriteBlocks16 (UsbMass, FALSE, Lba, TotalBlock, Buffer);
+ } else {
+ Status = UsbBootReadWriteBlocks (UsbMass, FALSE, (UINT32) Lba, TotalBlock, Buffer);
}
- Status = UsbBootReadBlocks (UsbMass, (UINT32) Lba, TotalBlock, Buffer);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "UsbMassReadBlocks: UsbBootReadBlocks (%r) -> Reset\n", Status));
UsbMassReset (This, TRUE);
@@ -183,7 +185,7 @@ ON_EXIT:
/**
Writes a specified number of blocks to the device.
- This function implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks().
+ This function implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks().
It writes a specified number of blocks to the device.
All blocks are written, or an error is returned.
@@ -222,17 +224,10 @@ UsbMassWriteBlocks (
UINTN TotalBlock;
//
- // First, validate the parameters
- //
- if ((Buffer == NULL) || (BufferSize == 0)) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Raise TPL to TPL_NOTIFY to serialize all its operations
+ // Raise TPL to TPL_CALLBACK to serialize all its operations
// to protect shared data structures.
//
- OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
UsbMass = USB_MASS_DEVICE_FROM_BLOCK_IO (This);
Media = &UsbMass->BlockIoMedia;
@@ -248,6 +243,26 @@ UsbMassWriteBlocks (
}
}
+ if (!(Media->MediaPresent)) {
+ Status = EFI_NO_MEDIA;
+ goto ON_EXIT;
+ }
+
+ if (MediaId != Media->MediaId) {
+ Status = EFI_MEDIA_CHANGED;
+ goto ON_EXIT;
+ }
+
+ if (BufferSize == 0) {
+ Status = EFI_SUCCESS;
+ goto ON_EXIT;
+ }
+
+ if (Buffer == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
//
// BufferSize must be a multiple of the intrinsic block size of the device.
//
@@ -266,21 +281,16 @@ UsbMassWriteBlocks (
goto ON_EXIT;
}
- if (!(Media->MediaPresent)) {
- Status = EFI_NO_MEDIA;
- goto ON_EXIT;
- }
-
- if (MediaId != Media->MediaId) {
- Status = EFI_MEDIA_CHANGED;
- goto ON_EXIT;
- }
-
//
// Try to write the data even the device is marked as ReadOnly,
// and clear the status should the write succeed.
//
- Status = UsbBootWriteBlocks (UsbMass, (UINT32) Lba, TotalBlock, Buffer);
+ if (UsbMass->Cdb16Byte) {
+ Status = UsbBootReadWriteBlocks16 (UsbMass, TRUE, Lba, TotalBlock, Buffer);
+ } else {
+ Status = UsbBootReadWriteBlocks (UsbMass, TRUE, (UINT32) Lba, TotalBlock, Buffer);
+ }
+
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "UsbMassWriteBlocks: UsbBootWriteBlocks (%r) -> Reset\n", Status));
UsbMassReset (This, TRUE);
@@ -330,7 +340,6 @@ UsbMassInitMedia (
{
EFI_BLOCK_IO_MEDIA *Media;
EFI_STATUS Status;
- UINTN Index;
Media = &UsbMass->BlockIoMedia;
@@ -345,25 +354,15 @@ UsbMassInitMedia (
Media->IoAlign = 0;
Media->MediaId = 1;
- //
- // Some device may spend several seconds before it is ready.
- // Try several times before giving up. Wait 5s at most.
- //
- Status = EFI_SUCCESS;
-
- for (Index = 0; Index < USB_BOOT_INIT_MEDIA_RETRY; Index++) {
-
- Status = UsbBootGetParams (UsbMass);
- if ((Status != EFI_MEDIA_CHANGED) && (Status != EFI_NOT_READY) && (Status != EFI_TIMEOUT)) {
- break;
- }
-
- Status = UsbBootIsUnitReady (UsbMass);
- if (EFI_ERROR (Status)) {
- gBS->Stall (USB_BOOT_RETRY_UNIT_READY_STALL * (Index + 1));
- }
+ Status = UsbBootGetParams (UsbMass);
+ DEBUG ((DEBUG_INFO, "UsbMassInitMedia: UsbBootGetParams (%r)\n", Status));
+ if (Status == EFI_MEDIA_CHANGED) {
+ //
+ // Some USB storage devices may report MEDIA_CHANGED sense key when hot-plugged.
+ // Treat it as SUCCESS
+ //
+ Status = EFI_SUCCESS;
}
-
return Status;
}
@@ -397,7 +396,7 @@ UsbMassInitTransport (
EFI_USB_INTERFACE_DESCRIPTOR Interface;
UINT8 Index;
EFI_STATUS Status;
-
+
Status = gBS->OpenProtocol (
Controller,
&gEfiUsbIoProtocolGuid,
@@ -410,12 +409,12 @@ UsbMassInitTransport (
if (EFI_ERROR (Status)) {
return Status;
}
-
+
Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
-
+
Status = EFI_UNSUPPORTED;
//
@@ -438,7 +437,7 @@ UsbMassInitTransport (
}
//
- // For BOT device, try to get its max LUN.
+ // For BOT device, try to get its max LUN.
// If max LUN is 0, then it is a non-lun device.
// Otherwise, it is a multi-lun device.
//
@@ -453,7 +452,7 @@ ON_EXIT:
This->DriverBindingHandle,
Controller
);
- return Status;
+ return Status;
}
/**
@@ -467,8 +466,7 @@ ON_EXIT:
@param MaxLun The max LUN number.
@retval EFI_SUCCESS At least one LUN is initialized successfully.
- @retval EFI_OUT_OF_RESOURCES Out of resource while creating device path node.
- @retval Other Initialization fails.
+ @retval EFI_NOT_FOUND Fail to initialize any of multiple LUNs.
**/
EFI_STATUS
@@ -486,17 +484,19 @@ UsbMassInitMultiLun (
DEVICE_LOGICAL_UNIT_DEVICE_PATH LunNode;
UINT8 Index;
EFI_STATUS Status;
+ EFI_STATUS ReturnStatus;
ASSERT (MaxLun > 0);
+ ReturnStatus = EFI_NOT_FOUND;
- for (Index = 0; Index <= MaxLun; Index++) {
+ for (Index = 0; Index <= MaxLun; Index++) {
DEBUG ((EFI_D_INFO, "UsbMassInitMultiLun: Start to initialize No.%d logic unit\n", Index));
-
+
UsbIo = NULL;
UsbMass = AllocateZeroPool (sizeof (USB_MASS_DEVICE));
ASSERT (UsbMass != NULL);
-
+
UsbMass->Signature = USB_MASS_SIGNATURE;
UsbMass->UsbIo = UsbIo;
UsbMass->BlockIo.Media = &UsbMass->BlockIoMedia;
@@ -508,26 +508,15 @@ UsbMassInitMultiLun (
UsbMass->Transport = Transport;
UsbMass->Context = Context;
UsbMass->Lun = Index;
-
+
//
// Initialize the media parameter data for EFI_BLOCK_IO_MEDIA of Block I/O Protocol.
//
Status = UsbMassInitMedia (UsbMass);
- if (!EFI_ERROR (Status)) {
- //
- // According to USB Mass Storage Specification for Bootability, only following
- // 4 Peripheral Device Types are in spec.
- //
- if ((UsbMass->Pdt != USB_PDT_DIRECT_ACCESS) &&
- (UsbMass->Pdt != USB_PDT_CDROM) &&
- (UsbMass->Pdt != USB_PDT_OPTICAL) &&
- (UsbMass->Pdt != USB_PDT_SIMPLE_DIRECT)) {
- DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: Found an unsupported peripheral type[%d]\n", UsbMass->Pdt));
- goto ON_ERROR;
- }
- } else if (Status != EFI_NO_MEDIA){
+ if ((EFI_ERROR (Status)) && (Status != EFI_NO_MEDIA)) {
DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: UsbMassInitMedia (%r)\n", Status));
- goto ON_ERROR;
+ FreePool (UsbMass);
+ continue;
}
//
@@ -536,18 +525,20 @@ UsbMassInitMultiLun (
LunNode.Header.Type = MESSAGING_DEVICE_PATH;
LunNode.Header.SubType = MSG_DEVICE_LOGICAL_UNIT_DP;
LunNode.Lun = UsbMass->Lun;
-
+
SetDevicePathNodeLength (&LunNode.Header, sizeof (LunNode));
-
+
UsbMass->DevicePath = AppendDevicePathNode (DevicePath, &LunNode.Header);
-
+
if (UsbMass->DevicePath == NULL) {
DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: failed to create device logic unit device path\n"));
-
Status = EFI_OUT_OF_RESOURCES;
- goto ON_ERROR;
+ FreePool (UsbMass);
+ continue;
}
+ InitializeDiskInfo (UsbMass);
+
//
// Create a new handle for each LUN, and install Block I/O Protocol and Device Path Protocol.
//
@@ -557,12 +548,16 @@ UsbMassInitMultiLun (
UsbMass->DevicePath,
&gEfiBlockIoProtocolGuid,
&UsbMass->BlockIo,
+ &gEfiDiskInfoProtocolGuid,
+ &UsbMass->DiskInfo,
NULL
);
-
+
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: InstallMultipleProtocolInterfaces (%r)\n", Status));
- goto ON_ERROR;
+ FreePool (UsbMass->DevicePath);
+ FreePool (UsbMass);
+ continue;
}
//
@@ -585,40 +580,19 @@ UsbMassInitMultiLun (
UsbMass->DevicePath,
&gEfiBlockIoProtocolGuid,
&UsbMass->BlockIo,
+ &gEfiDiskInfoProtocolGuid,
+ &UsbMass->DiskInfo,
NULL
);
- goto ON_ERROR;
- }
-
- DEBUG ((EFI_D_INFO, "UsbMassInitMultiLun: Success to initialize No.%d logic unit\n", Index));
- }
-
- return EFI_SUCCESS;
-
-ON_ERROR:
- if (UsbMass != NULL) {
- if (UsbMass->DevicePath != NULL) {
FreePool (UsbMass->DevicePath);
+ FreePool (UsbMass);
+ continue;
}
- FreePool (UsbMass);
- }
- if (UsbIo != NULL) {
- gBS->CloseProtocol (
- Controller,
- &gEfiUsbIoProtocolGuid,
- This->DriverBindingHandle,
- UsbMass->Controller
- );
+ ReturnStatus = EFI_SUCCESS;
+ DEBUG ((EFI_D_INFO, "UsbMassInitMultiLun: Success to initialize No.%d logic unit\n", Index));
}
- //
- // Return EFI_SUCCESS if at least one LUN is initialized successfully.
- //
- if (Index > 0) {
- return EFI_SUCCESS;
- } else {
- return Status;
- }
+ return ReturnStatus;
}
/**
@@ -662,7 +636,7 @@ UsbMassInitNonLun (
DEBUG ((EFI_D_ERROR, "UsbMassInitNonLun: OpenUsbIoProtocol By Driver (%r)\n", Status));
goto ON_ERROR;
}
-
+
UsbMass->Signature = USB_MASS_SIGNATURE;
UsbMass->Controller = Controller;
UsbMass->UsbIo = UsbIo;
@@ -674,33 +648,25 @@ UsbMassInitNonLun (
UsbMass->OpticalStorage = FALSE;
UsbMass->Transport = Transport;
UsbMass->Context = Context;
-
+
//
// Initialize the media parameter data for EFI_BLOCK_IO_MEDIA of Block I/O Protocol.
//
Status = UsbMassInitMedia (UsbMass);
- if (!EFI_ERROR (Status)) {
- //
- // According to USB Mass Storage Specification for Bootability, only following
- // 4 Peripheral Device Types are in spec.
- //
- if ((UsbMass->Pdt != USB_PDT_DIRECT_ACCESS) &&
- (UsbMass->Pdt != USB_PDT_CDROM) &&
- (UsbMass->Pdt != USB_PDT_OPTICAL) &&
- (UsbMass->Pdt != USB_PDT_SIMPLE_DIRECT)) {
- DEBUG ((EFI_D_ERROR, "UsbMassInitNonLun: Found an unsupported peripheral type[%d]\n", UsbMass->Pdt));
- goto ON_ERROR;
- }
- } else if (Status != EFI_NO_MEDIA){
+ if ((EFI_ERROR (Status)) && (Status != EFI_NO_MEDIA)) {
DEBUG ((EFI_D_ERROR, "UsbMassInitNonLun: UsbMassInitMedia (%r)\n", Status));
goto ON_ERROR;
}
-
- Status = gBS->InstallProtocolInterface (
+
+ InitializeDiskInfo (UsbMass);
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
&Controller,
&gEfiBlockIoProtocolGuid,
- EFI_NATIVE_INTERFACE,
- &UsbMass->BlockIo
+ &UsbMass->BlockIo,
+ &gEfiDiskInfoProtocolGuid,
+ &UsbMass->DiskInfo,
+ NULL
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
@@ -720,7 +686,7 @@ ON_ERROR:
Controller
);
}
- return Status;
+ return Status;
}
@@ -832,7 +798,7 @@ USBMassDriverBindingStart (
VOID *Context;
UINT8 MaxLun;
EFI_STATUS Status;
- EFI_USB_IO_PROTOCOL *UsbIo;
+ EFI_USB_IO_PROTOCOL *UsbIo;
EFI_TPL OldTpl;
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
@@ -852,7 +818,7 @@ USBMassDriverBindingStart (
// Initialize data for device that does not support multiple LUNSs.
//
Status = UsbMassInitNonLun (This, Controller, Transport, Context);
- if (EFI_ERROR (Status)) {
+ if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: UsbMassInitNonLun (%r)\n", Status));
}
} else {
@@ -867,7 +833,7 @@ USBMassDriverBindingStart (
Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
-
+
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: OpenDevicePathProtocol By Driver (%r)\n", Status));
goto Exit;
@@ -881,7 +847,7 @@ USBMassDriverBindingStart (
Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
-
+
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: OpenUsbIoProtocol By Driver (%r)\n", Status));
gBS->CloseProtocol (
@@ -894,7 +860,7 @@ USBMassDriverBindingStart (
}
//
- // Initialize data for device that supports multiple LUNSs.
+ // Initialize data for device that supports multiple LUNs.
// EFI_SUCCESS is returned if at least 1 LUN is initialized successfully.
//
Status = UsbMassInitMultiLun (This, Controller, Transport, Context, DevicePath, MaxLun);
@@ -969,7 +935,7 @@ USBMassDriverBindingStop (
Controller,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
-
+
if (EFI_ERROR(Status)) {
//
// This is a 2nd type handle(multi-lun root), it needs to close devicepath
@@ -990,43 +956,46 @@ USBMassDriverBindingStop (
DEBUG ((EFI_D_INFO, "Success to stop multi-lun root handle\n"));
return EFI_SUCCESS;
}
-
+
//
// This is a 1st type handle(non-multi-lun), which only needs to uninstall
// Block I/O Protocol, close USB I/O Protocol and free mass device.
//
UsbMass = USB_MASS_DEVICE_FROM_BLOCK_IO (BlockIo);
-
+
//
// Uninstall Block I/O protocol from the device handle,
// then call the transport protocol to stop itself.
//
- Status = gBS->UninstallProtocolInterface (
+ Status = gBS->UninstallMultipleProtocolInterfaces (
Controller,
&gEfiBlockIoProtocolGuid,
- &UsbMass->BlockIo
+ &UsbMass->BlockIo,
+ &gEfiDiskInfoProtocolGuid,
+ &UsbMass->DiskInfo,
+ NULL
);
if (EFI_ERROR (Status)) {
return Status;
}
-
+
gBS->CloseProtocol (
Controller,
&gEfiUsbIoProtocolGuid,
This->DriverBindingHandle,
Controller
);
-
+
UsbMass->Transport->CleanUp (UsbMass->Context);
FreePool (UsbMass);
-
+
DEBUG ((EFI_D_INFO, "Success to stop non-multi-lun root handle\n"));
return EFI_SUCCESS;
- }
+ }
//
// This is a 3rd type handle(multi-lun), which needs uninstall
- // Block I/O Protocol and Device Path Protocol, close USB I/O Protocol and
+ // Block I/O Protocol and Device Path Protocol, close USB I/O Protocol and
// free mass device for all children.
//
AllChildrenStopped = TRUE;
@@ -1055,23 +1024,25 @@ USBMassDriverBindingStop (
This->DriverBindingHandle,
ChildHandleBuffer[Index]
);
-
+
Status = gBS->UninstallMultipleProtocolInterfaces (
ChildHandleBuffer[Index],
&gEfiDevicePathProtocolGuid,
UsbMass->DevicePath,
&gEfiBlockIoProtocolGuid,
&UsbMass->BlockIo,
+ &gEfiDiskInfoProtocolGuid,
+ &UsbMass->DiskInfo,
NULL
);
-
+
if (EFI_ERROR (Status)) {
//
// Fail to uninstall Block I/O Protocol and Device Path Protocol, so re-open USB I/O Protocol by child.
//
AllChildrenStopped = FALSE;
DEBUG ((EFI_D_ERROR, "Fail to stop No.%d multi-lun child handle when uninstalling blockio and devicepath\n", (UINT32)Index));
-
+
gBS->OpenProtocol (
Controller,
&gEfiUsbIoProtocolGuid,
@@ -1094,7 +1065,7 @@ USBMassDriverBindingStop (
if (!AllChildrenStopped) {
return EFI_DEVICE_ERROR;
}
-
+
DEBUG ((EFI_D_INFO, "Success to stop all %d multi-lun children handles\n", (UINT32) NumberOfChildren));
return EFI_SUCCESS;
}