+++ /dev/null
-/*++\r
-\r
-Copyright (c) 2006 - 2007, Intel Corporation\r
-All rights reserved. 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
-\r
-Module Name:\r
-\r
- UsbMassStorage.c\r
-\r
-Abstract:\r
-\r
- USB Mass Storage Driver\r
-\r
-Revision History\r
-\r
---*/\r
-\r
-#include "UsbMassStorage.h"\r
-#include "UsbMassStorageHelper.h"\r
-\r
-//\r
-// Block I/O Protocol Interface\r
-//\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-USBFloppyReset (\r
- IN EFI_BLOCK_IO_PROTOCOL *This,\r
- IN BOOLEAN ExtendedVerification\r
- );\r
-\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-USBFloppyReadBlocks (\r
- IN EFI_BLOCK_IO_PROTOCOL *This,\r
- IN UINT32 MediaId,\r
- IN EFI_LBA LBA,\r
- IN UINTN BufferSize,\r
- OUT VOID *Buffer\r
- );\r
-\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-USBFloppyWriteBlocks (\r
- IN EFI_BLOCK_IO_PROTOCOL *This,\r
- IN UINT32 MediaId,\r
- IN EFI_LBA LBA,\r
- IN UINTN BufferSize,\r
- IN VOID *Buffer\r
- );\r
-\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-USBFloppyFlushBlocks (\r
- IN EFI_BLOCK_IO_PROTOCOL *This\r
- );\r
-\r
-//\r
-// USB Floppy Driver Global Variables\r
-//\r
-EFI_DRIVER_BINDING_PROTOCOL gUSBFloppyDriverBinding = {\r
- USBFloppyDriverBindingSupported,\r
- USBFloppyDriverBindingStart,\r
- USBFloppyDriverBindingStop,\r
- 0xa,\r
- NULL,\r
- NULL\r
-};\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-USBFloppyDriverBindingSupported (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Test to see if this driver supports ControllerHandle. Any ControllerHandle\r
- that has UsbHcProtocol installed will be supported.\r
-\r
- Arguments:\r
- This - Protocol instance pointer.\r
- Controller - Handle of device to test\r
- RemainingDevicePath - Not used\r
-\r
- Returns:\r
- EFI_SUCCESS - This driver supports this device.\r
- EFI_UNSUPPORTED - This driver does not support this device.\r
-\r
---*/\r
-{\r
- EFI_STATUS OpenStatus;\r
- EFI_USB_ATAPI_PROTOCOL *AtapiProtocol;\r
-\r
- //\r
- // check whether EFI_USB_ATAPI_PROTOCOL exists, if it does,\r
- // then the controller must be a USB Mass Storage Controller\r
- //\r
- OpenStatus = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiUsbAtapiProtocolGuid,\r
- (VOID **) &AtapiProtocol,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER\r
- );\r
- if (EFI_ERROR (OpenStatus)) {\r
- return OpenStatus;\r
- }\r
-\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiUsbAtapiProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-USBFloppyDriverBindingStart (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Starting the Usb Bus Driver\r
-\r
- Arguments:\r
- This - Protocol instance pointer.\r
- Controller - Handle of device to test\r
- RemainingDevicePath - Not used\r
-\r
- Returns:\r
- EFI_SUCCESS - This driver supports this device.\r
- EFI_UNSUPPORTED - This driver does not support this device.\r
- EFI_DEVICE_ERROR - This driver cannot be started due to device\r
- Error\r
- EFI_OUT_OF_RESOURCES- Can't allocate memory resources\r
- EFI_ALREADY_STARTED - Thios driver has been started\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- EFI_USB_ATAPI_PROTOCOL *AtapiProtocol;\r
- USB_FLOPPY_DEV *UsbFloppyDevice;\r
-\r
- UsbFloppyDevice = NULL;\r
- //\r
- // Check whether Usb Atapi Protocol attached on the controller handle.\r
- //\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiUsbAtapiProtocolGuid,\r
- (VOID **) &AtapiProtocol,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- Status = gBS->AllocatePool (\r
- EfiBootServicesData,\r
- sizeof (USB_FLOPPY_DEV),\r
- (VOID **) &UsbFloppyDevice\r
- );\r
- if (EFI_ERROR (Status)) {\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiUsbAtapiProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
- return Status;\r
- }\r
-\r
- ZeroMem (UsbFloppyDevice, sizeof (USB_FLOPPY_DEV));\r
-\r
- UsbFloppyDevice->Handle = Controller;\r
- UsbFloppyDevice->BlkIo.Media = &UsbFloppyDevice->BlkMedia;\r
- UsbFloppyDevice->Signature = USB_FLOPPY_DEV_SIGNATURE;\r
- UsbFloppyDevice->BlkIo.Reset = USBFloppyReset;\r
- UsbFloppyDevice->BlkIo.ReadBlocks = USBFloppyReadBlocks;\r
- UsbFloppyDevice->BlkIo.WriteBlocks = USBFloppyWriteBlocks;\r
- UsbFloppyDevice->BlkIo.FlushBlocks = USBFloppyFlushBlocks;\r
- UsbFloppyDevice->AtapiProtocol = AtapiProtocol;\r
-\r
- //\r
- // Identify drive type and retrieve media information.\r
- //\r
- Status = USBFloppyIdentify (UsbFloppyDevice);\r
- if (EFI_ERROR (Status)) {\r
- if (UsbFloppyDevice->SenseData != NULL) {\r
- gBS->FreePool (UsbFloppyDevice->SenseData);\r
- }\r
-\r
- gBS->FreePool (UsbFloppyDevice);\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiUsbAtapiProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
- return Status;\r
- }\r
- //\r
- // Install Block I/O protocol for the usb floppy device.\r
- //\r
- Status = gBS->InstallProtocolInterface (\r
- &Controller,\r
- &gEfiBlockIoProtocolGuid,\r
- EFI_NATIVE_INTERFACE,\r
- &UsbFloppyDevice->BlkIo\r
- );\r
- if (EFI_ERROR (Status)) {\r
- if (UsbFloppyDevice->SenseData != NULL) {\r
- gBS->FreePool (UsbFloppyDevice->SenseData);\r
- }\r
-\r
- gBS->FreePool (UsbFloppyDevice);\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiUsbAtapiProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
- return Status;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-\r
-}\r
-\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-USBFloppyDriverBindingStop (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN UINTN NumberOfChildren,\r
- IN EFI_HANDLE *ChildHandleBuffer\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Stop this driver on ControllerHandle. Support stoping any child handles\r
- created by this driver.\r
-\r
- Arguments:\r
- This - Protocol instance pointer.\r
- Controller - Handle of device to stop driver on\r
- NumberOfChildren - Number of Children in the ChildHandleBuffer\r
- ChildHandleBuffer - List of handles for the children we need to stop.\r
-\r
- Returns:\r
- EFI_SUCCESS\r
- EFI_DEVICE_ERROR\r
- others\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- USB_FLOPPY_DEV *UsbFloppyDevice;\r
- EFI_BLOCK_IO_PROTOCOL *BlkIo;\r
-\r
- //\r
- // First find USB_FLOPPY_DEV\r
- //\r
- gBS->OpenProtocol (\r
- Controller,\r
- &gEfiBlockIoProtocolGuid,\r
- (VOID **) &BlkIo,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
-\r
- UsbFloppyDevice = USB_FLOPPY_DEV_FROM_THIS (BlkIo);\r
-\r
- //\r
- // Uninstall Block I/O protocol from the device handle\r
- //\r
- Status = gBS->UninstallProtocolInterface (\r
- Controller,\r
- &gEfiBlockIoProtocolGuid,\r
- &UsbFloppyDevice->BlkIo\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- //\r
- // Stop using EFI_USB_ATAPI_PROTOCOL\r
- //\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiUsbAtapiProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
-\r
- if (UsbFloppyDevice->SenseData != NULL) {\r
- gBS->FreePool (UsbFloppyDevice->SenseData);\r
- }\r
-\r
- gBS->FreePool (UsbFloppyDevice);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-USBFloppyReset (\r
- IN EFI_BLOCK_IO_PROTOCOL *This,\r
- IN BOOLEAN ExtendedVerification\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Implements EFI_BLOCK_IO_PROTOCOL.Reset() function.\r
-\r
- Arguments:\r
- This The EFI_BLOCK_IO_PROTOCOL instance.\r
- ExtendedVerification\r
- Indicates that the driver may perform a more exhaustive\r
- verification operation of the device during reset.\r
- (This parameter is ingored in this driver.)\r
-\r
- Returns:\r
- EFI_SUCCESS - Success\r
---*/\r
-{\r
- USB_FLOPPY_DEV *UsbFloppyDevice;\r
- EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;\r
- EFI_STATUS Status;\r
- EFI_TPL OldTpl;\r
-\r
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
-\r
- UsbFloppyDevice = USB_FLOPPY_DEV_FROM_THIS (This);\r
-\r
- UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;\r
-\r
- //\r
- // directly calling EFI_USB_ATAPI_PROTOCOL.Reset() to implement reset.\r
- //\r
- Status = UsbAtapiInterface->UsbAtapiReset (UsbAtapiInterface, ExtendedVerification);\r
-\r
- gBS->RestoreTPL (OldTpl);\r
-\r
- return Status;\r
-}\r
-\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-USBFloppyReadBlocks (\r
- IN EFI_BLOCK_IO_PROTOCOL *This,\r
- IN UINT32 MediaId,\r
- IN EFI_LBA LBA,\r
- IN UINTN BufferSize,\r
- OUT VOID *Buffer\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks() function.\r
-\r
- Arguments:\r
- This The EFI_BLOCK_IO_PROTOCOL instance.\r
- MediaId The media id that the read request is for.\r
- LBA The starting logical block address to read from on the device.\r
- BufferSize\r
- The size of the Buffer in bytes. This must be a multiple of\r
- the intrinsic block size of the device.\r
- Buffer A pointer to the destination buffer for the data. The caller\r
- is responsible for either having implicit or explicit ownership\r
- of the buffer.\r
-\r
- Returns:\r
- EFI_INVALID_PARAMETER - Parameter is error\r
- EFI_SUCCESS - Success\r
- EFI_DEVICE_ERROR - Hardware Error\r
- EFI_NO_MEDIA - No media\r
- EFI_MEDIA_CHANGED - Media Change\r
- EFI_BAD_BUFFER_SIZE - Buffer size is bad\r
- --*/\r
-{\r
- USB_FLOPPY_DEV *UsbFloppyDevice;\r
- EFI_STATUS Status;\r
- EFI_BLOCK_IO_MEDIA *Media;\r
- UINTN BlockSize;\r
- UINTN NumberOfBlocks;\r
- BOOLEAN MediaChange;\r
- EFI_TPL OldTpl;\r
-\r
- Status = EFI_SUCCESS;\r
- MediaChange = FALSE;\r
- UsbFloppyDevice = USB_FLOPPY_DEV_FROM_THIS (This);\r
-\r
- //\r
- // Check parameters\r
- //\r
- if (Buffer == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (BufferSize == 0) {\r
- return EFI_SUCCESS;\r
- }\r
-\r
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
-\r
- UsbFloppyTestUnitReady (UsbFloppyDevice);\r
-\r
- Status = UsbFloppyDetectMedia (UsbFloppyDevice, &MediaChange);\r
- if (EFI_ERROR (Status)) {\r
-\r
- Status = EFI_DEVICE_ERROR;\r
- goto Done;\r
- }\r
-\r
- if (MediaChange) {\r
- gBS->ReinstallProtocolInterface (\r
- UsbFloppyDevice->Handle,\r
- &gEfiBlockIoProtocolGuid,\r
- &UsbFloppyDevice->BlkIo,\r
- &UsbFloppyDevice->BlkIo\r
- );\r
- }\r
-\r
- Media = UsbFloppyDevice->BlkIo.Media;\r
- BlockSize = Media->BlockSize;\r
- NumberOfBlocks = BufferSize / BlockSize;\r
-\r
- if (!(Media->MediaPresent)) {\r
- Status = EFI_NO_MEDIA;\r
- goto Done;\r
- }\r
-\r
- if (MediaId != Media->MediaId) {\r
- Status = EFI_MEDIA_CHANGED;\r
- goto Done;\r
- }\r
-\r
- if (BufferSize % BlockSize != 0) {\r
- Status = EFI_BAD_BUFFER_SIZE;\r
- goto Done;\r
- }\r
-\r
- if (LBA > Media->LastBlock) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Done;\r
- }\r
-\r
- if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Done;\r
- }\r
-\r
- if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Done;\r
- }\r
-\r
- while (NumberOfBlocks > 0) {\r
-\r
- if (NumberOfBlocks > BLOCK_UNIT) {\r
- Status = USBFloppyRead10 (UsbFloppyDevice, Buffer, LBA, BLOCK_UNIT);\r
- } else {\r
- Status = USBFloppyRead10 (UsbFloppyDevice, Buffer, LBA, NumberOfBlocks);\r
- }\r
-\r
- if (EFI_ERROR (Status)) {\r
- This->Reset (This, TRUE);\r
- Status = EFI_DEVICE_ERROR;\r
- goto Done;\r
- }\r
-\r
- if (NumberOfBlocks > BLOCK_UNIT) {\r
- NumberOfBlocks -= BLOCK_UNIT;\r
- LBA += BLOCK_UNIT;\r
- Buffer = (UINT8 *) Buffer + This->Media->BlockSize * BLOCK_UNIT;\r
- } else {\r
- NumberOfBlocks -= NumberOfBlocks;\r
- LBA += NumberOfBlocks;\r
- Buffer = (UINT8 *) Buffer + This->Media->BlockSize * NumberOfBlocks;\r
- }\r
- }\r
-\r
- Done:\r
- gBS->RestoreTPL (OldTpl);\r
- return Status;\r
-}\r
-\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-USBFloppyWriteBlocks (\r
- IN EFI_BLOCK_IO_PROTOCOL *This,\r
- IN UINT32 MediaId,\r
- IN EFI_LBA LBA,\r
- IN UINTN BufferSize,\r
- IN VOID *Buffer\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks() function.\r
-\r
- Arguments:\r
- This The EFI_BLOCK_IO_PROTOCOL instance.\r
- MediaId The media id that the write request is for.\r
- LBA The starting logical block address to be written.\r
- The caller is responsible for writing to only\r
- legitimate locations.\r
- BufferSize\r
- The size of the Buffer in bytes. This must be a multiple of\r
- the intrinsic block size of the device.\r
- Buffer A pointer to the source buffer for the data. The caller\r
- is responsible for either having implicit or explicit ownership\r
- of the buffer.\r
-\r
- Returns:\r
- EFI_INVALID_PARAMETER - Parameter is error\r
- EFI_SUCCESS - Success\r
- EFI_DEVICE_ERROR - Hardware Error\r
- EFI_NO_MEDIA - No media\r
- EFI_MEDIA_CHANGED - Media Change\r
- EFI_BAD_BUFFER_SIZE - Buffer size is bad\r
-\r
---*/\r
-{\r
- USB_FLOPPY_DEV *UsbFloppyDevice;\r
- EFI_STATUS Status;\r
- EFI_BLOCK_IO_MEDIA *Media;\r
- UINTN BlockSize;\r
- UINTN NumberOfBlocks;\r
- BOOLEAN MediaChange;\r
- EFI_TPL OldTpl;\r
-\r
- Status = EFI_SUCCESS;\r
- MediaChange = FALSE;\r
-\r
- UsbFloppyDevice = USB_FLOPPY_DEV_FROM_THIS (This);\r
-\r
- //\r
- // Check parameters\r
- //\r
- if (Buffer == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (BufferSize == 0) {\r
- return EFI_SUCCESS;\r
- }\r
-\r
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
-\r
- UsbFloppyTestUnitReady (UsbFloppyDevice);\r
-\r
- Status = UsbFloppyDetectMedia (UsbFloppyDevice, &MediaChange);\r
- if (EFI_ERROR (Status)) {\r
-\r
- Status = EFI_DEVICE_ERROR;\r
- goto Done;\r
- }\r
-\r
- if (MediaChange) {\r
- gBS->ReinstallProtocolInterface (\r
- UsbFloppyDevice->Handle,\r
- &gEfiBlockIoProtocolGuid,\r
- &UsbFloppyDevice->BlkIo,\r
- &UsbFloppyDevice->BlkIo\r
- );\r
- }\r
-\r
- Media = UsbFloppyDevice->BlkIo.Media;\r
- BlockSize = Media->BlockSize;\r
- NumberOfBlocks = BufferSize / BlockSize;\r
-\r
- if (!(Media->MediaPresent)) {\r
- Status = EFI_NO_MEDIA;\r
- goto Done;\r
- }\r
-\r
- if (MediaId != Media->MediaId) {\r
- Status = EFI_MEDIA_CHANGED;\r
- goto Done;\r
- }\r
-\r
- if (BufferSize % BlockSize != 0) {\r
- Status = EFI_BAD_BUFFER_SIZE;\r
- goto Done;\r
- }\r
-\r
- if (LBA > Media->LastBlock) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Done;\r
- }\r
-\r
- if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Done;\r
- }\r
-\r
- if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Done;\r
- }\r
-\r
- if (UsbFloppyDevice->BlkMedia.ReadOnly) {\r
- Status = EFI_WRITE_PROTECTED;\r
- goto Done;\r
- }\r
-\r
- while (NumberOfBlocks > 0) {\r
-\r
- if (NumberOfBlocks > BLOCK_UNIT) {\r
- Status = USBFloppyWrite10 (UsbFloppyDevice, Buffer, LBA, BLOCK_UNIT);\r
- } else {\r
- Status = USBFloppyWrite10 (UsbFloppyDevice, Buffer, LBA, NumberOfBlocks);\r
- }\r
-\r
- if (EFI_ERROR (Status)) {\r
- This->Reset (This, TRUE);\r
- Status = EFI_DEVICE_ERROR;\r
- goto Done;\r
- }\r
-\r
- if (NumberOfBlocks > BLOCK_UNIT) {\r
- NumberOfBlocks -= BLOCK_UNIT;\r
- LBA += BLOCK_UNIT;\r
- Buffer = (UINT8 *) Buffer + This->Media->BlockSize * BLOCK_UNIT;\r
- } else {\r
- NumberOfBlocks -= NumberOfBlocks;\r
- LBA += NumberOfBlocks;\r
- Buffer = (UINT8 *) Buffer + This->Media->BlockSize * NumberOfBlocks;\r
- }\r
- }\r
-\r
-Done:\r
- gBS->RestoreTPL (OldTpl);\r
- return Status;\r
-}\r
-\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-USBFloppyFlushBlocks (\r
- IN EFI_BLOCK_IO_PROTOCOL *This\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Implements EFI_BLOCK_IO_PROTOCOL.FlushBlocks() function.\r
- (In this driver, this function just returns EFI_SUCCESS.)\r
-\r
- Arguments:\r
- This The EFI_BLOCK_IO_PROTOCOL instance.\r
-\r
- Returns:\r
- EFI_SUCCESS - Success\r
---*/\r
-{\r
- return EFI_SUCCESS;\r
-}\r