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; }