mirror of https://github.com/acidanthera/audk.git
Code scrub for USB Mass Storage Driver.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@7243 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
cdfdbb970a
commit
d80ed2a76e
|
@ -37,10 +37,10 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
#include <Library/MemoryAllocationLib.h>
|
#include <Library/MemoryAllocationLib.h>
|
||||||
#include <Library/DevicePathLib.h>
|
#include <Library/DevicePathLib.h>
|
||||||
|
|
||||||
#define USB_IS_IN_ENDPOINT(EndPointAddr) (((EndPointAddr) & 0x80) == 0x80)
|
#define USB_IS_IN_ENDPOINT(EndPointAddr) (((EndPointAddr) & BIT7) == BIT7)
|
||||||
#define USB_IS_OUT_ENDPOINT(EndPointAddr) (((EndPointAddr) & 0x80) == 0)
|
#define USB_IS_OUT_ENDPOINT(EndPointAddr) (((EndPointAddr) & BIT7) == 0)
|
||||||
#define USB_IS_BULK_ENDPOINT(Attribute) (((Attribute) & 0x03) == 0x02)
|
#define USB_IS_BULK_ENDPOINT(Attribute) (((Attribute) & (BIT0 | BIT1)) == USB_ENDPOINT_BULK)
|
||||||
#define USB_IS_INTERRUPT_ENDPOINT(Attribute) (((Attribute) & 0x03) == 0x03)
|
#define USB_IS_INTERRUPT_ENDPOINT(Attribute) (((Attribute) & (BIT0 | BIT1)) == USB_ENDPOINT_INTERRUPT)
|
||||||
#define USB_IS_ERROR(Result, Error) (((Result) & (Error)) != 0)
|
#define USB_IS_ERROR(Result, Error) (((Result) & (Error)) != 0)
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -52,19 +52,19 @@ typedef enum {
|
||||||
//
|
//
|
||||||
// Usb mass storage subclass code, specify the command set used.
|
// Usb mass storage subclass code, specify the command set used.
|
||||||
//
|
//
|
||||||
USB_MASS_STORE_RBC = 0x01, // Reduced Block Commands
|
USB_MASS_STORE_RBC = 0x01, ///< Reduced Block Commands
|
||||||
USB_MASS_STORE_8020I = 0x02, // SFF-8020i, typically a CD/DVD device
|
USB_MASS_STORE_8020I = 0x02, ///< SFF-8020i, typically a CD/DVD device
|
||||||
USB_MASS_STORE_QIC = 0x03, // Typically a tape device
|
USB_MASS_STORE_QIC = 0x03, ///< Typically a tape device
|
||||||
USB_MASS_STORE_UFI = 0x04, // Typically a floppy disk driver device
|
USB_MASS_STORE_UFI = 0x04, ///< Typically a floppy disk driver device
|
||||||
USB_MASS_STORE_8070I = 0x05, // SFF-8070i, typically a floppy disk driver device.
|
USB_MASS_STORE_8070I = 0x05, ///< SFF-8070i, typically a floppy disk driver device.
|
||||||
USB_MASS_STORE_SCSI = 0x06, // SCSI transparent command set
|
USB_MASS_STORE_SCSI = 0x06, ///< SCSI transparent command set
|
||||||
|
|
||||||
//
|
//
|
||||||
// Usb mass storage protocol code, specify the transport protocol
|
// Usb mass storage protocol code, specify the transport protocol
|
||||||
//
|
//
|
||||||
USB_MASS_STORE_CBI0 = 0x00, // CBI protocol with command completion interrupt
|
USB_MASS_STORE_CBI0 = 0x00, ///< CBI protocol with command completion interrupt
|
||||||
USB_MASS_STORE_CBI1 = 0x01, // CBI protocol without command completion interrupt
|
USB_MASS_STORE_CBI1 = 0x01, ///< CBI protocol without command completion interrupt
|
||||||
USB_MASS_STORE_BOT = 0x50, // Bulk-Only Transport
|
USB_MASS_STORE_BOT = 0x50, ///< Bulk-Only Transport
|
||||||
|
|
||||||
USB_MASS_1_MILLISECOND = 1000,
|
USB_MASS_1_MILLISECOND = 1000,
|
||||||
USB_MASS_1_SECOND = 1000 * USB_MASS_1_MILLISECOND,
|
USB_MASS_1_SECOND = 1000 * USB_MASS_1_MILLISECOND,
|
||||||
|
@ -111,25 +111,25 @@ EFI_STATUS
|
||||||
|
|
||||||
typedef
|
typedef
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
(*USB_MASS_FINI) (
|
(*USB_MASS_CLEAN_UP) (
|
||||||
IN VOID *Context
|
IN VOID *Context
|
||||||
);
|
);
|
||||||
|
|
||||||
//
|
///
|
||||||
// This structure contains information necessary to select the
|
/// This structure contains information necessary to select the
|
||||||
// proper transport protocol. The mass storage class defines
|
/// proper transport protocol. The mass storage class defines
|
||||||
// two transport protocols. One is the CBI, and the other is BOT.
|
/// two transport protocols. One is the CBI, and the other is BOT.
|
||||||
// CBI is being obseleted. The design is made modular by this
|
/// CBI is being obseleted. The design is made modular by this
|
||||||
// structure so that the CBI protocol can be easily removed when
|
/// structure so that the CBI protocol can be easily removed when
|
||||||
// it is no longer necessary.
|
/// it is no longer necessary.
|
||||||
//
|
///
|
||||||
typedef struct {
|
typedef struct {
|
||||||
UINT8 Protocol;
|
UINT8 Protocol;
|
||||||
USB_MASS_INIT_TRANSPORT Init; // Initialize the mass storage transport protocol
|
USB_MASS_INIT_TRANSPORT Init; ///< Initialize the mass storage transport protocol
|
||||||
USB_MASS_EXEC_COMMAND ExecCommand; // Transport command to the device then get result
|
USB_MASS_EXEC_COMMAND ExecCommand; ///< Transport command to the device then get result
|
||||||
USB_MASS_RESET Reset; // Reset the device
|
USB_MASS_RESET Reset; ///< Reset the device
|
||||||
USB_MASS_GET_MAX_LUN GetMaxLun; // Get max lun, only for bot
|
USB_MASS_GET_MAX_LUN GetMaxLun; ///< Get max lun, only for bot
|
||||||
USB_MASS_FINI Fini; // Clean up the resources.
|
USB_MASS_CLEAN_UP CleanUp; ///< Clean up the resources.
|
||||||
} USB_MASS_TRANSPORT;
|
} USB_MASS_TRANSPORT;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
/** @file
|
/** @file
|
||||||
|
Implementation of the command set of USB Mass Storage Specification
|
||||||
This file implement the command set of "USB Mass Storage Specification
|
for Bootability, Revision 1.0.
|
||||||
for Bootability".
|
|
||||||
|
|
||||||
Copyright (c) 2007 - 2008, Intel Corporation
|
Copyright (c) 2007 - 2008, Intel Corporation
|
||||||
All rights reserved. This program and the accompanying materials
|
All rights reserved. This program and the accompanying materials
|
||||||
|
@ -16,96 +15,12 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
#include "UsbMassImpl.h"
|
#include "UsbMassImpl.h"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Return the current TPL.
|
Execute REQUEST SENSE Command to retrieve sense data from device.
|
||||||
|
|
||||||
@return Current TPL.
|
@param UsbMass The device whose sense data is requested.
|
||||||
|
|
||||||
**/
|
@retval EFI_SUCCESS The command is excuted successfully.
|
||||||
EFI_TPL
|
|
||||||
UsbGetCurrentTpl (
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
|
||||||
EFI_TPL Tpl;
|
|
||||||
|
|
||||||
Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
|
|
||||||
gBS->RestoreTPL (Tpl);
|
|
||||||
|
|
||||||
return Tpl;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Read an UINT32 from the buffer to avoid byte alignment problems, then
|
|
||||||
convert that to the little endia. The USB mass storage bootability spec
|
|
||||||
use big endia.
|
|
||||||
|
|
||||||
@param Buf The buffer contains the first byte of the UINT32
|
|
||||||
in big endia.
|
|
||||||
|
|
||||||
@return The UINT32 value read from the buffer in little endia.
|
|
||||||
|
|
||||||
**/
|
|
||||||
UINT32
|
|
||||||
UsbBootGetUint32 (
|
|
||||||
IN UINT8 *Buf
|
|
||||||
)
|
|
||||||
{
|
|
||||||
UINT32 Value;
|
|
||||||
|
|
||||||
CopyMem (&Value, Buf, sizeof (UINT32));
|
|
||||||
return USB_BOOT_SWAP32 (Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Put an UINT32 in little endia to the buffer. The data is converted to
|
|
||||||
big endia before writing.
|
|
||||||
|
|
||||||
@param Buf The buffer to write data to.
|
|
||||||
@param Data32 The data to write.
|
|
||||||
|
|
||||||
@return None.
|
|
||||||
|
|
||||||
**/
|
|
||||||
VOID
|
|
||||||
UsbBootPutUint32 (
|
|
||||||
IN UINT8 *Buf,
|
|
||||||
IN UINT32 Data32
|
|
||||||
)
|
|
||||||
{
|
|
||||||
Data32 = USB_BOOT_SWAP32 (Data32);
|
|
||||||
CopyMem (Buf, &Data32, sizeof (UINT32));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Put an UINT16 in little endia to the buffer. The data is converted to
|
|
||||||
big endia before writing.
|
|
||||||
|
|
||||||
@param Buf The buffer to write data to.
|
|
||||||
@param Data16 The data to write.
|
|
||||||
|
|
||||||
@return None.
|
|
||||||
|
|
||||||
**/
|
|
||||||
VOID
|
|
||||||
UsbBootPutUint16 (
|
|
||||||
IN UINT8 *Buf,
|
|
||||||
IN UINT16 Data16
|
|
||||||
)
|
|
||||||
{
|
|
||||||
Data16 = (UINT16) (USB_BOOT_SWAP16 (Data16));
|
|
||||||
CopyMem (Buf, &Data16, sizeof (UINT16));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Request sense information via sending Request Sense
|
|
||||||
Packet Command.
|
|
||||||
|
|
||||||
@param UsbMass The device to be requested sense data.
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS The command is excuted OK.
|
|
||||||
@retval EFI_DEVICE_ERROR Failed to request sense.
|
@retval EFI_DEVICE_ERROR Failed to request sense.
|
||||||
@retval EFI_NO_RESPONSE The device media doesn't response this request.
|
@retval EFI_NO_RESPONSE The device media doesn't response this request.
|
||||||
@retval EFI_INVALID_PARAMETER The command has some invalid parameters.
|
@retval EFI_INVALID_PARAMETER The command has some invalid parameters.
|
||||||
|
@ -128,7 +43,7 @@ UsbBootRequestSense (
|
||||||
Transport = UsbMass->Transport;
|
Transport = UsbMass->Transport;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Request the sense data from the device if command failed
|
// Request the sense data from the device
|
||||||
//
|
//
|
||||||
ZeroMem (&SenseCmd, sizeof (USB_BOOT_REQUEST_SENSE_CMD));
|
ZeroMem (&SenseCmd, sizeof (USB_BOOT_REQUEST_SENSE_CMD));
|
||||||
ZeroMem (&SenseData, sizeof (USB_BOOT_REQUEST_SENSE_DATA));
|
ZeroMem (&SenseData, sizeof (USB_BOOT_REQUEST_SENSE_DATA));
|
||||||
|
@ -154,7 +69,8 @@ UsbBootRequestSense (
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Interpret the sense data and update the media status if necessary.
|
// If sense data is retrieved successfully, interpret the sense data
|
||||||
|
// and update the media status if necessary.
|
||||||
//
|
//
|
||||||
Media = &UsbMass->BlockIoMedia;
|
Media = &UsbMass->BlockIoMedia;
|
||||||
|
|
||||||
|
@ -174,10 +90,10 @@ UsbBootRequestSense (
|
||||||
case USB_BOOT_SENSE_NOT_READY:
|
case USB_BOOT_SENSE_NOT_READY:
|
||||||
Status = EFI_DEVICE_ERROR;
|
Status = EFI_DEVICE_ERROR;
|
||||||
if (SenseData.ASC == USB_BOOT_ASC_NO_MEDIA) {
|
if (SenseData.ASC == USB_BOOT_ASC_NO_MEDIA) {
|
||||||
Media->MediaPresent = FALSE;
|
Media->MediaPresent = FALSE;
|
||||||
Status = EFI_NO_MEDIA;
|
Status = EFI_NO_MEDIA;
|
||||||
} else if (SenseData.ASC == USB_BOOT_ASC_NOT_READY) {
|
} else if (SenseData.ASC == USB_BOOT_ASC_NOT_READY) {
|
||||||
Status = EFI_NOT_READY;
|
Status = EFI_NOT_READY;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -189,16 +105,16 @@ UsbBootRequestSense (
|
||||||
Status = EFI_DEVICE_ERROR;
|
Status = EFI_DEVICE_ERROR;
|
||||||
if (SenseData.ASC == USB_BOOT_ASC_MEDIA_CHANGE) {
|
if (SenseData.ASC == USB_BOOT_ASC_MEDIA_CHANGE) {
|
||||||
//
|
//
|
||||||
// If MediaChange, reset ReadOnly and new MediId
|
// If MediaChange, reset ReadOnly and new MediaId
|
||||||
//
|
//
|
||||||
Status = EFI_MEDIA_CHANGED;
|
Status = EFI_MEDIA_CHANGED;
|
||||||
Media->ReadOnly = FALSE;
|
Media->ReadOnly = FALSE;
|
||||||
Media->MediaId++;
|
Media->MediaId++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case USB_BOOT_SNESE_DATA_PROTECT:
|
case USB_BOOT_SENSE_DATA_PROTECT:
|
||||||
Status = EFI_WRITE_PROTECTED;
|
Status = EFI_WRITE_PROTECTED;
|
||||||
Media->ReadOnly = TRUE;
|
Media->ReadOnly = TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -219,9 +135,11 @@ UsbBootRequestSense (
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Execute the USB mass storage bootability commands. If execution
|
Execute the USB mass storage bootability commands.
|
||||||
failed, retrieve the error by REQUEST_SENSE then update the device's
|
|
||||||
status, such as ReadyOnly.
|
This function executes the USB mass storage bootability commands.
|
||||||
|
If execution failed, retrieve the error by REQUEST_SENSE, then
|
||||||
|
update the device's status, such as ReadyOnly.
|
||||||
|
|
||||||
@param UsbMass The device to issue commands to
|
@param UsbMass The device to issue commands to
|
||||||
@param Cmd The command to execute
|
@param Cmd The command to execute
|
||||||
|
@ -231,11 +149,8 @@ UsbBootRequestSense (
|
||||||
@param DataLen The length of expected data
|
@param DataLen The length of expected data
|
||||||
@param Timeout The timeout used to transfer
|
@param Timeout The timeout used to transfer
|
||||||
|
|
||||||
@retval EFI_SUCCESS The command is excuted OK
|
@retval EFI_SUCCESS Command is excuted successfully
|
||||||
@retval EFI_DEVICE_ERROR Failed to request sense
|
@retval Others Command execution failed.
|
||||||
@retval EFI_INVALID_PARAMETER The command has some invalid parameters
|
|
||||||
@retval EFI_WRITE_PROTECTED The device is write protected
|
|
||||||
@retval EFI_MEDIA_CHANGED The device media has been changed
|
|
||||||
|
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
|
@ -266,25 +181,31 @@ UsbBootExecCmd (
|
||||||
&CmdResult
|
&CmdResult
|
||||||
);
|
);
|
||||||
//
|
//
|
||||||
// ExecCommand return success and get the right CmdResult means
|
// If ExecCommand() returns no error and CmdResult is success,
|
||||||
// the commnad transfer is OK.
|
// then the commnad transfer is successful.
|
||||||
//
|
//
|
||||||
if ((CmdResult == USB_MASS_CMD_SUCCESS) && !EFI_ERROR(Status)) {
|
if ((CmdResult == USB_MASS_CMD_SUCCESS) && !EFI_ERROR (Status)) {
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG ((EFI_D_INFO, "UsbBootExecCmd: Fail to Exec 0x%x Cmd /w %r\n",
|
DEBUG ((EFI_D_INFO, "UsbBootExecCmd: Fail to Exec 0x%x Cmd /w %r\n",
|
||||||
*(UINT8 *)Cmd ,Status));
|
*(UINT8 *)Cmd ,Status));
|
||||||
|
|
||||||
|
//
|
||||||
|
// If command execution failed, then retrieve error info via sense request.
|
||||||
|
//
|
||||||
return UsbBootRequestSense (UsbMass);
|
return UsbBootRequestSense (UsbMass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Execute the USB mass storage bootability commands. If execution
|
Execute the USB mass storage bootability commands with retrial.
|
||||||
failed, retrieve the error by REQUEST_SENSE then update the device's
|
|
||||||
status, such as ReadyOnly.
|
|
||||||
|
|
||||||
|
This function executes USB mass storage bootability commands.
|
||||||
|
If the device isn't ready, wait for it. If the device is ready
|
||||||
|
and error occurs, retry the command again until it exceeds the
|
||||||
|
limit of retrial times.
|
||||||
|
|
||||||
@param UsbMass The device to issue commands to
|
@param UsbMass The device to issue commands to
|
||||||
@param Cmd The command to execute
|
@param Cmd The command to execute
|
||||||
@param CmdLen The length of the command
|
@param CmdLen The length of the command
|
||||||
|
@ -293,11 +214,9 @@ UsbBootExecCmd (
|
||||||
@param DataLen The length of expected data
|
@param DataLen The length of expected data
|
||||||
@param Timeout The timeout used to transfer
|
@param Timeout The timeout used to transfer
|
||||||
|
|
||||||
@retval EFI_SUCCESS The command is excuted OK
|
@retval EFI_SUCCESS The command is executed successfully.
|
||||||
@retval EFI_DEVICE_ERROR Failed to request sense
|
@retval EFI_MEDIA_CHANGED The device media has been changed.
|
||||||
@retval EFI_INVALID_PARAMETER The command has some invalid parameters
|
@retval Others Command execution failed after retrial.
|
||||||
@retval EFI_WRITE_PROTECTED The device is write protected
|
|
||||||
@retval EFI_MEDIA_CHANGED The device media has been changed
|
|
||||||
|
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
|
@ -312,18 +231,12 @@ UsbBootExecCmdWithRetry (
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
INT16 Index;
|
UINTN Retry;
|
||||||
|
|
||||||
//
|
|
||||||
// If the device isn't ready, wait some time. If the device is ready,
|
|
||||||
// retry the command again.
|
|
||||||
//
|
|
||||||
Status = EFI_SUCCESS;
|
Status = EFI_SUCCESS;
|
||||||
|
|
||||||
for (Index = 0; Index < USB_BOOT_COMMAND_RETRY; Index++) {
|
for (Retry = 0; Retry < USB_BOOT_COMMAND_RETRY; Retry++) {
|
||||||
//
|
|
||||||
// Execute the command with an increasingly larger timeout value.
|
|
||||||
//
|
|
||||||
Status = UsbBootExecCmd (
|
Status = UsbBootExecCmd (
|
||||||
UsbMass,
|
UsbMass,
|
||||||
Cmd,
|
Cmd,
|
||||||
|
@ -333,15 +246,14 @@ UsbBootExecCmdWithRetry (
|
||||||
DataLen,
|
DataLen,
|
||||||
Timeout
|
Timeout
|
||||||
);
|
);
|
||||||
if (Status == EFI_SUCCESS ||
|
if (Status == EFI_SUCCESS || Status == EFI_MEDIA_CHANGED) {
|
||||||
Status == EFI_MEDIA_CHANGED) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// Need retry once more, so reset index
|
// If the device isn't ready, just wait for it without limit on retrial times.
|
||||||
//
|
//
|
||||||
if (Status == EFI_NOT_READY) {
|
if (Status == EFI_NOT_READY) {
|
||||||
Index = 0;
|
Retry = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -350,12 +262,11 @@ UsbBootExecCmdWithRetry (
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Use the TEST UNIT READY command to check whether it is ready.
|
Execute TEST UNIT READY command to check if the device is ready.
|
||||||
If it is ready, update the parameters.
|
|
||||||
|
|
||||||
@param UsbMass The device to test
|
@param UsbMass The device to test
|
||||||
|
|
||||||
@retval EFI_SUCCESS The device is ready and parameters are updated.
|
@retval EFI_SUCCESS The device is ready.
|
||||||
@retval Others Device not ready.
|
@retval Others Device not ready.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
@ -384,13 +295,13 @@ UsbBootIsUnitReady (
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Inquiry Command requests that information regrarding parameters of
|
Execute INQUIRY Command to request information regarding parameters of
|
||||||
the Device be sent to the Host.
|
the device be sent to the host computer.
|
||||||
|
|
||||||
@param UsbMass The device to inquiry.
|
@param UsbMass The device to inquire.
|
||||||
|
|
||||||
@retval EFI_SUCCESS The device is ready and parameters are updated.
|
@retval EFI_SUCCESS INQUIRY Command is executed successfully.
|
||||||
@retval Others Device not ready.
|
@retval Others INQUIRY Command is not executed successfully.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
|
@ -405,9 +316,6 @@ UsbBootInquiry (
|
||||||
|
|
||||||
Media = &(UsbMass->BlockIoMedia);
|
Media = &(UsbMass->BlockIoMedia);
|
||||||
|
|
||||||
//
|
|
||||||
// Use the Inquiry command to get the RemovableMedia setting.
|
|
||||||
//
|
|
||||||
ZeroMem (&InquiryCmd, sizeof (USB_BOOT_INQUIRY_CMD));
|
ZeroMem (&InquiryCmd, sizeof (USB_BOOT_INQUIRY_CMD));
|
||||||
ZeroMem (&InquiryData, sizeof (USB_BOOT_INQUIRY_DATA));
|
ZeroMem (&InquiryData, sizeof (USB_BOOT_INQUIRY_DATA));
|
||||||
|
|
||||||
|
@ -428,10 +336,14 @@ UsbBootInquiry (
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get information from PDT (Peripheral Device Type) field and Removable Medium Bit
|
||||||
|
// from the inquiry data.
|
||||||
|
//
|
||||||
UsbMass->Pdt = (UINT8) (USB_BOOT_PDT (InquiryData.Pdt));
|
UsbMass->Pdt = (UINT8) (USB_BOOT_PDT (InquiryData.Pdt));
|
||||||
Media->RemovableMedia = (BOOLEAN) (USB_BOOT_REMOVABLE (InquiryData.Removable));
|
Media->RemovableMedia = (BOOLEAN) (USB_BOOT_REMOVABLE (InquiryData.Removable));
|
||||||
//
|
//
|
||||||
// Default value 512 Bytes, in case no media present at first time
|
// Set block size to the default value of 512 Bytes, in case no media is present at first time.
|
||||||
//
|
//
|
||||||
Media->BlockSize = 0x0200;
|
Media->BlockSize = 0x0200;
|
||||||
|
|
||||||
|
@ -440,17 +352,18 @@ UsbBootInquiry (
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Get the capacity of the USB mass storage media, including
|
Execute READ CAPACITY command to request information regarding
|
||||||
the presentation, block size, and last block number. This
|
the capacity of the installed medium of the device.
|
||||||
function is used to get the disk parameters at the start if
|
|
||||||
it is a non-removable media or to detect the media if it is
|
This function executes READ CAPACITY command to get the capacity
|
||||||
removable.
|
of the USB mass storage media, including the presence, block size,
|
||||||
|
and last block number.
|
||||||
|
|
||||||
@param UsbMass The device to retireve disk gemotric.
|
@param UsbMass The device to retireve disk gemotric.
|
||||||
|
|
||||||
@retval EFI_SUCCESS The disk gemotric is successfully retrieved.
|
@retval EFI_SUCCESS The disk geometry is successfully retrieved.
|
||||||
@retval EFI_DEVICE_ERROR Something is inconsistent with the disk gemotric.
|
@retval EFI_NOT_READY The returned block size is zero.
|
||||||
@retval Other Read capacity request fails.
|
@retval Other READ CAPACITY command execution failed.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
|
@ -465,9 +378,6 @@ UsbBootReadCapacity (
|
||||||
|
|
||||||
Media = &UsbMass->BlockIoMedia;
|
Media = &UsbMass->BlockIoMedia;
|
||||||
|
|
||||||
//
|
|
||||||
// Use the READ CAPACITY command to get the block length and last blockno
|
|
||||||
//
|
|
||||||
ZeroMem (&CapacityCmd, sizeof (USB_BOOT_READ_CAPACITY_CMD));
|
ZeroMem (&CapacityCmd, sizeof (USB_BOOT_READ_CAPACITY_CMD));
|
||||||
ZeroMem (&CapacityData, sizeof (USB_BOOT_READ_CAPACITY_DATA));
|
ZeroMem (&CapacityData, sizeof (USB_BOOT_READ_CAPACITY_DATA));
|
||||||
|
|
||||||
|
@ -487,9 +397,13 @@ UsbBootReadCapacity (
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get the information on media presence, block size, and last block number
|
||||||
|
// from READ CAPACITY data.
|
||||||
|
//
|
||||||
Media->MediaPresent = TRUE;
|
Media->MediaPresent = TRUE;
|
||||||
Media->LastBlock = UsbBootGetUint32 (CapacityData.LastLba);
|
Media->LastBlock = SwapBytes32 (ReadUnaligned32 ((CONST UINT32 *) CapacityData.LastLba));
|
||||||
Media->BlockSize = UsbBootGetUint32 (CapacityData.BlockLen);
|
Media->BlockSize = SwapBytes32 (ReadUnaligned32 ((CONST UINT32 *) CapacityData.BlockLen));
|
||||||
|
|
||||||
if (Media->BlockSize == 0) {
|
if (Media->BlockSize == 0) {
|
||||||
return EFI_NOT_READY;
|
return EFI_NOT_READY;
|
||||||
|
@ -502,13 +416,12 @@ UsbBootReadCapacity (
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Retrieves mode sense information via sending Mode Sense
|
Retrieves SCSI mode sense information via MODE SENSE(6) command.
|
||||||
Packet Command.
|
|
||||||
|
|
||||||
@param UsbMass The USB_FLOPPY_DEV instance.
|
@param UsbMass The device whose sense data is requested.
|
||||||
|
|
||||||
@retval EFI_SUCCESS Success
|
@retval EFI_SUCCESS SCSI mode sense information retrieved successfully.
|
||||||
@retval Other Execute Request command fails.
|
@retval Other Command execution failed.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
|
@ -527,7 +440,7 @@ UsbScsiModeSense (
|
||||||
ZeroMem (&ModeParaHeader, sizeof (USB_SCSI_MODE_SENSE6_PARA_HEADER));
|
ZeroMem (&ModeParaHeader, sizeof (USB_SCSI_MODE_SENSE6_PARA_HEADER));
|
||||||
|
|
||||||
//
|
//
|
||||||
// ModeSense6 command is defined in [SCSI2Spec-Page151]
|
// MODE SENSE(6) command is defined in Section 8.2.10 of SCSI-2 Spec
|
||||||
//
|
//
|
||||||
ModeSenseCmd.OpCode = USB_SCSI_MODE_SENSE6_OPCODE;
|
ModeSenseCmd.OpCode = USB_SCSI_MODE_SENSE6_OPCODE;
|
||||||
ModeSenseCmd.Lun = (UINT8) USB_BOOT_LUN (UsbMass->Lun);
|
ModeSenseCmd.Lun = (UINT8) USB_BOOT_LUN (UsbMass->Lun);
|
||||||
|
@ -545,11 +458,12 @@ UsbScsiModeSense (
|
||||||
);
|
);
|
||||||
|
|
||||||
//
|
//
|
||||||
// ModeSense(6) is used to get the information of WriteProtected. While only some of
|
// Format of device-specific parameter byte of the mode parameter header is defined in
|
||||||
// devices support this command, so have a try here.
|
// Section 8.2.10 of SCSI-2 Spec.
|
||||||
|
// BIT7 of this byte is indicates whether the medium is write protected.
|
||||||
//
|
//
|
||||||
if (!EFI_ERROR (Status)) {
|
if (!EFI_ERROR (Status)) {
|
||||||
Media->ReadOnly = (BOOLEAN) (((ModeParaHeader.DevicePara & 0x80) != 0) ? TRUE : FALSE);
|
Media->ReadOnly = (BOOLEAN) ((ModeParaHeader.DevicePara & BIT7) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
|
@ -557,17 +471,18 @@ UsbScsiModeSense (
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Get the parameters for the USB mass storage media, including
|
Get the parameters for the USB mass storage media.
|
||||||
the RemovableMedia, block size, and last block number. This
|
|
||||||
function is used both to initialize the media during the
|
|
||||||
DriverBindingStart and to re-initialize it when the media is
|
|
||||||
changed. Althought the RemoveableMedia is unlikely to change,
|
|
||||||
I include it here.
|
|
||||||
|
|
||||||
@param UsbMass The device to retireve disk gemotric.
|
This function get the parameters for the USB mass storage media,
|
||||||
|
It is used both to initialize the media during the Start() phase
|
||||||
|
of Driver Binding Protocol and to re-initialize it when the media is
|
||||||
|
changed. Althought the RemoveableMedia is unlikely to change,
|
||||||
|
it is also included here.
|
||||||
|
|
||||||
|
@param UsbMass The device to retrieve disk gemotric.
|
||||||
|
|
||||||
@retval EFI_SUCCESS The disk gemotric is successfully retrieved.
|
@retval EFI_SUCCESS The disk gemotric is successfully retrieved.
|
||||||
@retval Other Get the parameters failed.
|
@retval Other Failed to get the parameters.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
|
@ -589,7 +504,7 @@ UsbBootGetParams (
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Don't use the Removable bit in inquirydata to test whether the media
|
// Don't use the Removable bit in inquiry data to test whether the media
|
||||||
// is removable because many flash disks wrongly set this bit.
|
// is removable because many flash disks wrongly set this bit.
|
||||||
//
|
//
|
||||||
if ((UsbMass->Pdt == USB_PDT_CDROM) || (UsbMass->Pdt == USB_PDT_OPTICAL)) {
|
if ((UsbMass->Pdt == USB_PDT_CDROM) || (UsbMass->Pdt == USB_PDT_OPTICAL)) {
|
||||||
|
@ -620,12 +535,11 @@ UsbBootGetParams (
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Detect whether the removable media is present and whether it has changed.
|
Detect whether the removable media is present and whether it has changed.
|
||||||
The Non-removable media doesn't need it.
|
|
||||||
|
|
||||||
@param UsbMass The device to retireve disk gemotric.
|
@param UsbMass The device to check.
|
||||||
|
|
||||||
@retval EFI_SUCCESS The disk gemotric is successfully retrieved.
|
@retval EFI_SUCCESS The media status is successfully checked.
|
||||||
@retval Other Decect media fails.
|
@retval Other Failed to detect media.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
|
@ -641,27 +555,22 @@ UsbBootDetectMedia (
|
||||||
|
|
||||||
Media = &UsbMass->BlockIoMedia;
|
Media = &UsbMass->BlockIoMedia;
|
||||||
|
|
||||||
CopyMem (
|
CopyMem (&OldMedia, &(UsbMass->BlockIoMedia), sizeof (EFI_BLOCK_IO_MEDIA));
|
||||||
&OldMedia,
|
|
||||||
&(UsbMass->BlockIoMedia),
|
|
||||||
sizeof (EFI_BLOCK_IO_MEDIA)
|
|
||||||
);
|
|
||||||
|
|
||||||
CmdSet = ((EFI_USB_INTERFACE_DESCRIPTOR *) (UsbMass->Context))->InterfaceSubClass;
|
CmdSet = ((EFI_USB_INTERFACE_DESCRIPTOR *) (UsbMass->Context))->InterfaceSubClass;
|
||||||
|
|
||||||
Status = UsbBootIsUnitReady (UsbMass);
|
Status = UsbBootIsUnitReady (UsbMass);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
DEBUG ((EFI_D_ERROR, "UsbBootDetectMedia: UsbBootIsUnitReady (%r)\n", Status));
|
|
||||||
goto ON_ERROR;
|
goto ON_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((UsbMass->Pdt != USB_PDT_CDROM) && (CmdSet == USB_MASS_STORE_SCSI)) {
|
if ((UsbMass->Pdt != USB_PDT_CDROM) && (CmdSet == USB_MASS_STORE_SCSI)) {
|
||||||
//
|
//
|
||||||
// ModeSense is required for the device with PDT of 0x00/0x07/0x0E,
|
// MODE SENSE is required for the device with PDT of 0x00/0x07/0x0E,
|
||||||
// which is from [MassStorageBootabilitySpec-Page7].
|
// according to Section 4 of USB Mass Storage Specification for Bootability.
|
||||||
// ModeSense(10) is useless here, while ModeSense(6) defined in SCSI
|
// MODE SENSE(10) is useless here, while MODE SENSE(6) defined in SCSI
|
||||||
// could get the information of WriteProtected.
|
// could get the information of Write Protected.
|
||||||
// Since not all device support this command, so skip if fail.
|
// Since not all device support this command, skip if fail.
|
||||||
//
|
//
|
||||||
UsbScsiModeSense (UsbMass);
|
UsbScsiModeSense (UsbMass);
|
||||||
}
|
}
|
||||||
|
@ -676,7 +585,7 @@ UsbBootDetectMedia (
|
||||||
|
|
||||||
ON_ERROR:
|
ON_ERROR:
|
||||||
//
|
//
|
||||||
// Detect whether it is necessary to reinstall the BlockIO
|
// Detect whether it is necessary to reinstall the Block I/O Protocol.
|
||||||
//
|
//
|
||||||
// MediaId may change in RequestSense for MediaChanged
|
// MediaId may change in RequestSense for MediaChanged
|
||||||
// MediaPresent may change in RequestSense for NoMedia
|
// MediaPresent may change in RequestSense for NoMedia
|
||||||
|
@ -689,9 +598,11 @@ ON_ERROR:
|
||||||
(Media->BlockSize != OldMedia.BlockSize) ||
|
(Media->BlockSize != OldMedia.BlockSize) ||
|
||||||
(Media->LastBlock != OldMedia.LastBlock)) {
|
(Media->LastBlock != OldMedia.LastBlock)) {
|
||||||
|
|
||||||
OldTpl = UsbGetCurrentTpl ();
|
//
|
||||||
DEBUG ((EFI_D_ERROR, "UsbBootDetectMedia: TPL before reinstall BlockIoProtocol is %d\n", (UINT32)OldTpl));
|
// This function is called by Block I/O Protocol APIs, which run at TPL_NOTIFY.
|
||||||
|
// Here we temporarily restore TPL to TPL_CALLBACK to invoke ReinstallProtocolInterface().
|
||||||
|
//
|
||||||
|
OldTpl = EfiGetCurrentTpl ();
|
||||||
gBS->RestoreTPL (TPL_CALLBACK);
|
gBS->RestoreTPL (TPL_CALLBACK);
|
||||||
|
|
||||||
gBS->ReinstallProtocolInterface (
|
gBS->ReinstallProtocolInterface (
|
||||||
|
@ -701,16 +612,14 @@ ON_ERROR:
|
||||||
&UsbMass->BlockIo
|
&UsbMass->BlockIo
|
||||||
);
|
);
|
||||||
|
|
||||||
DEBUG ((EFI_D_ERROR, "UsbBootDetectMedia: TPL after reinstall is %d\n", (UINT32)UsbGetCurrentTpl()));
|
ASSERT (EfiGetCurrentTpl () == TPL_CALLBACK);
|
||||||
ASSERT (UsbGetCurrentTpl () == TPL_CALLBACK);
|
|
||||||
|
|
||||||
gBS->RaiseTPL (OldTpl);
|
gBS->RaiseTPL (OldTpl);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Update MediaId after reinstall BLOCK_IO_PROTOCOL
|
// Update MediaId after reinstalling Block I/O Protocol.
|
||||||
//
|
//
|
||||||
if (Media->MediaPresent != OldMedia.MediaPresent) {
|
if (Media->MediaPresent != OldMedia.MediaPresent) {
|
||||||
if (Media->MediaPresent == TRUE) {
|
if (Media->MediaPresent) {
|
||||||
Media->MediaId = 1;
|
Media->MediaId = 1;
|
||||||
} else {
|
} else {
|
||||||
Media->MediaId = 0;
|
Media->MediaId = 0;
|
||||||
|
@ -779,8 +688,8 @@ UsbBootReadBlocks (
|
||||||
|
|
||||||
ReadCmd.OpCode = USB_BOOT_READ10_OPCODE;
|
ReadCmd.OpCode = USB_BOOT_READ10_OPCODE;
|
||||||
ReadCmd.Lun = (UINT8) (USB_BOOT_LUN (UsbMass->Lun));
|
ReadCmd.Lun = (UINT8) (USB_BOOT_LUN (UsbMass->Lun));
|
||||||
UsbBootPutUint32 (ReadCmd.Lba, Lba);
|
WriteUnaligned32 ((UINT32 *) ReadCmd.Lba, SwapBytes32 (Lba));
|
||||||
UsbBootPutUint16 (ReadCmd.TransferLen, Count);
|
WriteUnaligned16 ((UINT16 *) ReadCmd.TransferLen, SwapBytes16 (Count));
|
||||||
|
|
||||||
Status = UsbBootExecCmdWithRetry (
|
Status = UsbBootExecCmdWithRetry (
|
||||||
UsbMass,
|
UsbMass,
|
||||||
|
@ -810,7 +719,7 @@ UsbBootReadBlocks (
|
||||||
@param UsbMass The USB mass storage device to write to
|
@param UsbMass The USB mass storage device to write to
|
||||||
@param Lba The start block number
|
@param Lba The start block number
|
||||||
@param TotalBlock Total block number to write
|
@param TotalBlock Total block number to write
|
||||||
@param Buffer The buffer to write to
|
@param Buffer Pointer to the source buffer for the data.
|
||||||
|
|
||||||
@retval EFI_SUCCESS Data are written into the buffer
|
@retval EFI_SUCCESS Data are written into the buffer
|
||||||
@retval Others Failed to write all the data
|
@retval Others Failed to write all the data
|
||||||
|
@ -821,7 +730,7 @@ UsbBootWriteBlocks (
|
||||||
IN USB_MASS_DEVICE *UsbMass,
|
IN USB_MASS_DEVICE *UsbMass,
|
||||||
IN UINT32 Lba,
|
IN UINT32 Lba,
|
||||||
IN UINTN TotalBlock,
|
IN UINTN TotalBlock,
|
||||||
OUT UINT8 *Buffer
|
IN UINT8 *Buffer
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
USB_BOOT_WRITE10_CMD WriteCmd;
|
USB_BOOT_WRITE10_CMD WriteCmd;
|
||||||
|
@ -855,8 +764,8 @@ UsbBootWriteBlocks (
|
||||||
|
|
||||||
WriteCmd.OpCode = USB_BOOT_WRITE10_OPCODE;
|
WriteCmd.OpCode = USB_BOOT_WRITE10_OPCODE;
|
||||||
WriteCmd.Lun = (UINT8) (USB_BOOT_LUN (UsbMass->Lun));
|
WriteCmd.Lun = (UINT8) (USB_BOOT_LUN (UsbMass->Lun));
|
||||||
UsbBootPutUint32 (WriteCmd.Lba, Lba);
|
WriteUnaligned32 ((UINT32 *) WriteCmd.Lba, SwapBytes32 (Lba));
|
||||||
UsbBootPutUint16 (WriteCmd.TransferLen, Count);
|
WriteUnaligned16 ((UINT16 *) WriteCmd.TransferLen, SwapBytes16 (Count));
|
||||||
|
|
||||||
Status = UsbBootExecCmdWithRetry (
|
Status = UsbBootExecCmdWithRetry (
|
||||||
UsbMass,
|
UsbMass,
|
||||||
|
@ -881,14 +790,13 @@ UsbBootWriteBlocks (
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Use the USB clear feature control transfer to clear the endpoint
|
Use the USB clear feature control transfer to clear the endpoint stall condition.
|
||||||
stall condition.
|
|
||||||
|
|
||||||
@param UsbIo The USB IO protocol to use
|
@param UsbIo The USB I/O Protocol instance
|
||||||
@param EndpointAddr The endpoint to clear stall for
|
@param EndpointAddr The endpoint to clear stall for
|
||||||
|
|
||||||
@retval EFI_SUCCESS The endpoint stall condtion is clear
|
@retval EFI_SUCCESS The endpoint stall condition is cleared.
|
||||||
@retval Others Failed to clear the endpoint stall condtion
|
@retval Others Failed to clear the endpoint stall condition.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
/** @file
|
/** @file
|
||||||
|
Definition of the command set of USB Mass Storage Specification
|
||||||
|
for Bootability, Revision 1.0.
|
||||||
|
|
||||||
Copyright (c) 2007, Intel Corporation
|
Copyright (c) 2007 - 2008, Intel Corporation
|
||||||
All rights reserved. This program and the accompanying materials
|
All rights reserved. This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
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
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
|
@ -9,18 +11,6 @@ http://opensource.org/licenses/bsd-license.php
|
||||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
Module Name:
|
|
||||||
|
|
||||||
UsbMassBoot.h
|
|
||||||
|
|
||||||
Abstract:
|
|
||||||
|
|
||||||
The definition of command and data of the USB mass storage for
|
|
||||||
bootability command set.
|
|
||||||
|
|
||||||
Revision History
|
|
||||||
|
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#ifndef _EFI_USB_MASS_BOOT_H_
|
#ifndef _EFI_USB_MASS_BOOT_H_
|
||||||
|
@ -28,13 +18,11 @@ Revision History
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
//
|
//
|
||||||
// The opcodes of various usb boot commands:
|
// The opcodes of various USB boot commands:
|
||||||
// INQUIRY/REQUEST_SENSE are "No Timeout Commands" as specified
|
// INQUIRY/REQUEST_SENSE are "No Timeout Commands" as specified
|
||||||
// by MMC command set. Others are "Group 1 Timeout Commands". That
|
// by Multi-Media Commands (MMC) set.
|
||||||
// is they should be retried if driver is ready.
|
// Others are "Group 1 Timeout Commands". That is,
|
||||||
// We can't use the Peripheral Device Type in Inquiry data to
|
// they should be retried if driver is ready.
|
||||||
// determine the timeout used. For example, both floppy and flash
|
|
||||||
// are likely set their PDT to 0, or Direct Access Device.
|
|
||||||
//
|
//
|
||||||
USB_BOOT_INQUIRY_OPCODE = 0x12,
|
USB_BOOT_INQUIRY_OPCODE = 0x12,
|
||||||
USB_BOOT_REQUEST_SENSE_OPCODE = 0x03,
|
USB_BOOT_REQUEST_SENSE_OPCODE = 0x03,
|
||||||
|
@ -50,19 +38,19 @@ typedef enum {
|
||||||
// The Sense Key part of the sense data. Sense data has three levels:
|
// The Sense Key part of the sense data. Sense data has three levels:
|
||||||
// Sense key, Additional Sense Code and Additional Sense Code Qualifier
|
// Sense key, Additional Sense Code and Additional Sense Code Qualifier
|
||||||
//
|
//
|
||||||
USB_BOOT_SENSE_NO_SENSE = 0x00, // No sense key
|
USB_BOOT_SENSE_NO_SENSE = 0x00, ///< No sense key
|
||||||
USB_BOOT_SENSE_RECOVERED = 0x01, // Last command succeed with recovery actions
|
USB_BOOT_SENSE_RECOVERED = 0x01, ///< Last command succeed with recovery actions
|
||||||
USB_BOOT_SENSE_NOT_READY = 0x02, // Device not ready
|
USB_BOOT_SENSE_NOT_READY = 0x02, ///< Device not ready
|
||||||
USB_BOOT_SNESE_MEDIUM_ERROR = 0X03, // Failed probably because flaw in the media
|
USB_BOOT_SNESE_MEDIUM_ERROR = 0X03, ///< Failed probably because flaw in the media
|
||||||
USB_BOOT_SENSE_HARDWARE_ERROR = 0X04, // Non-recoverable hardware failure
|
USB_BOOT_SENSE_HARDWARE_ERROR = 0X04, ///< Non-recoverable hardware failure
|
||||||
USB_BOOT_SENSE_ILLEGAL_REQUEST = 0X05, // Illegal parameters in the request
|
USB_BOOT_SENSE_ILLEGAL_REQUEST = 0X05, ///< Illegal parameters in the request
|
||||||
USB_BOOT_SENSE_UNIT_ATTENTION = 0X06, // Removable medium may have been changed
|
USB_BOOT_SENSE_UNIT_ATTENTION = 0X06, ///< Removable medium may have been changed
|
||||||
USB_BOOT_SNESE_DATA_PROTECT = 0X07, // Write protected
|
USB_BOOT_SENSE_DATA_PROTECT = 0X07, ///< Write protected
|
||||||
USB_BOOT_SENSE_BLANK_CHECK = 0X08, // Blank/non-blank medium while reading/writing
|
USB_BOOT_SENSE_BLANK_CHECK = 0X08, ///< Blank/non-blank medium while reading/writing
|
||||||
USB_BOOT_SENSE_VENDOR = 0X09, // Vendor specific sense key
|
USB_BOOT_SENSE_VENDOR = 0X09, ///< Vendor specific sense key
|
||||||
USB_BOOT_SENSE_ABORTED = 0X0B, // Command aborted by the device
|
USB_BOOT_SENSE_ABORTED = 0X0B, ///< Command aborted by the device
|
||||||
USB_BOOT_SENSE_VOLUME_OVERFLOW = 0x0D, // Partition overflow
|
USB_BOOT_SENSE_VOLUME_OVERFLOW = 0x0D, ///< Partition overflow
|
||||||
USB_BOOT_SENSE_MISCOMPARE = 0x0E, // Source data mis-match while verfying.
|
USB_BOOT_SENSE_MISCOMPARE = 0x0E, ///< Source data mis-match while verfying.
|
||||||
|
|
||||||
USB_BOOT_ASC_NOT_READY = 0x04,
|
USB_BOOT_ASC_NOT_READY = 0x04,
|
||||||
USB_BOOT_ASC_NO_MEDIA = 0x3A,
|
USB_BOOT_ASC_NO_MEDIA = 0x3A,
|
||||||
|
@ -71,10 +59,10 @@ typedef enum {
|
||||||
//
|
//
|
||||||
// Supported PDT codes, or Peripheral Device Type
|
// Supported PDT codes, or Peripheral Device Type
|
||||||
//
|
//
|
||||||
USB_PDT_DIRECT_ACCESS = 0x00, // Direct access device
|
USB_PDT_DIRECT_ACCESS = 0x00, ///< Direct access device
|
||||||
USB_PDT_CDROM = 0x05, // CDROM
|
USB_PDT_CDROM = 0x05, ///< CDROM
|
||||||
USB_PDT_OPTICAL = 0x07, // Non-CD optical disks
|
USB_PDT_OPTICAL = 0x07, ///< Non-CD optical disks
|
||||||
USB_PDT_SIMPLE_DIRECT = 0x0E, // Simplified direct access device
|
USB_PDT_SIMPLE_DIRECT = 0x0E, ///< Simplified direct access device
|
||||||
|
|
||||||
//
|
//
|
||||||
// Other parameters, Max carried size is 512B * 128 = 64KB
|
// Other parameters, Max carried size is 512B * 128 = 64KB
|
||||||
|
@ -99,7 +87,6 @@ typedef enum {
|
||||||
// USB CD-Rom and iPod devices are much slower than USB key when reponse
|
// USB CD-Rom and iPod devices are much slower than USB key when reponse
|
||||||
// most of commands, So we set 5s as timeout here.
|
// most of commands, So we set 5s as timeout here.
|
||||||
//
|
//
|
||||||
//
|
|
||||||
USB_BOOT_GENERAL_CMD_TIMEOUT = 5 * USB_MASS_1_SECOND
|
USB_BOOT_GENERAL_CMD_TIMEOUT = 5 * USB_MASS_1_SECOND
|
||||||
}USB_BOOT_OPTCODE;
|
}USB_BOOT_OPTCODE;
|
||||||
|
|
||||||
|
@ -112,7 +99,7 @@ typedef enum {
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
typedef struct {
|
typedef struct {
|
||||||
UINT8 OpCode;
|
UINT8 OpCode;
|
||||||
UINT8 Lun; // Lun (high 3 bits)
|
UINT8 Lun; ///< Lun (high 3 bits)
|
||||||
UINT8 Reserved0[2];
|
UINT8 Reserved0[2];
|
||||||
UINT8 AllocLen;
|
UINT8 AllocLen;
|
||||||
UINT8 Reserved1;
|
UINT8 Reserved1;
|
||||||
|
@ -120,10 +107,10 @@ typedef struct {
|
||||||
} USB_BOOT_INQUIRY_CMD;
|
} USB_BOOT_INQUIRY_CMD;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
UINT8 Pdt; // Peripheral Device Type (low 5 bits)
|
UINT8 Pdt; ///< Peripheral Device Type (low 5 bits)
|
||||||
UINT8 Removable; // Removable Media (highest bit)
|
UINT8 Removable; ///< Removable Media (highest bit)
|
||||||
UINT8 Reserved0[2];
|
UINT8 Reserved0[2];
|
||||||
UINT8 AddLen; // Additional length
|
UINT8 AddLen; ///< Additional length
|
||||||
UINT8 Reserved1[3];
|
UINT8 Reserved1[3];
|
||||||
UINT8 VendorID[8];
|
UINT8 VendorID[8];
|
||||||
UINT8 ProductID[16];
|
UINT8 ProductID[16];
|
||||||
|
@ -170,10 +157,10 @@ typedef struct {
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
UINT8 OpCode;
|
UINT8 OpCode;
|
||||||
UINT8 Lun; // Lun (High 3 bits)
|
UINT8 Lun; ///< Lun (High 3 bits)
|
||||||
UINT8 Lba[4]; // Logical block address
|
UINT8 Lba[4]; ///< Logical block address
|
||||||
UINT8 Reserved0;
|
UINT8 Reserved0;
|
||||||
UINT8 TransferLen[2]; // Transfer length
|
UINT8 TransferLen[2]; ///< Transfer length
|
||||||
UINT8 Reserverd1;
|
UINT8 Reserverd1;
|
||||||
UINT8 Pad[2];
|
UINT8 Pad[2];
|
||||||
} USB_BOOT_READ10_CMD;
|
} USB_BOOT_READ10_CMD;
|
||||||
|
@ -190,9 +177,9 @@ typedef struct {
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
UINT8 OpCode;
|
UINT8 OpCode;
|
||||||
UINT8 Lun; // Lun (High 3 bits)
|
UINT8 Lun; ///< Lun (High 3 bits)
|
||||||
UINT8 Reserved0[2];
|
UINT8 Reserved0[2];
|
||||||
UINT8 AllocLen; // Allocation length
|
UINT8 AllocLen; ///< Allocation length
|
||||||
UINT8 Reserved1;
|
UINT8 Reserved1;
|
||||||
UINT8 Pad[6];
|
UINT8 Pad[6];
|
||||||
} USB_BOOT_REQUEST_SENSE_CMD;
|
} USB_BOOT_REQUEST_SENSE_CMD;
|
||||||
|
@ -200,12 +187,12 @@ typedef struct {
|
||||||
typedef struct {
|
typedef struct {
|
||||||
UINT8 ErrorCode;
|
UINT8 ErrorCode;
|
||||||
UINT8 Reserved0;
|
UINT8 Reserved0;
|
||||||
UINT8 SenseKey; // Sense key (low 4 bits)
|
UINT8 SenseKey; ///< Sense key (low 4 bits)
|
||||||
UINT8 Infor[4];
|
UINT8 Infor[4];
|
||||||
UINT8 AddLen; // Additional Sense length, 10
|
UINT8 AddLen; ///< Additional Sense length, 10
|
||||||
UINT8 Reserved1[4];
|
UINT8 Reserved1[4];
|
||||||
UINT8 ASC; // Additional Sense Code
|
UINT8 ASC; ///< Additional Sense Code
|
||||||
UINT8 ASCQ; // Additional Sense Code Qualifier
|
UINT8 ASCQ; ///< Additional Sense Code Qualifier
|
||||||
UINT8 Reserverd2[4];
|
UINT8 Reserverd2[4];
|
||||||
} USB_BOOT_REQUEST_SENSE_DATA;
|
} USB_BOOT_REQUEST_SENSE_DATA;
|
||||||
|
|
||||||
|
@ -234,22 +221,10 @@ typedef struct {
|
||||||
//
|
//
|
||||||
// Get the removable, PDT, and sense key bits from the command data
|
// Get the removable, PDT, and sense key bits from the command data
|
||||||
//
|
//
|
||||||
#define USB_BOOT_REMOVABLE(RmbByte) (((RmbByte) & 0x80) != 0)
|
#define USB_BOOT_REMOVABLE(RmbByte) (((RmbByte) & BIT7) != 0)
|
||||||
#define USB_BOOT_PDT(Pdt) ((Pdt) & 0x1f)
|
#define USB_BOOT_PDT(Pdt) ((Pdt) & 0x1f)
|
||||||
#define USB_BOOT_SENSE_KEY(Key) ((Key) & 0x0f)
|
#define USB_BOOT_SENSE_KEY(Key) ((Key) & 0x0f)
|
||||||
|
|
||||||
//
|
|
||||||
// Swap the byte sequence of a UINT32. Intel CPU uses little endian
|
|
||||||
// in UEFI environment, but USB boot uses big endian.
|
|
||||||
//
|
|
||||||
#define USB_BOOT_SWAP32(Data32) \
|
|
||||||
((((Data32) & 0x000000ff) << 24) | (((Data32) & 0xff000000) >> 24) | \
|
|
||||||
(((Data32) & 0x0000ff00) << 8) | (((Data32) & 0x00ff0000) >> 8))
|
|
||||||
|
|
||||||
#define USB_BOOT_SWAP16(Data16) \
|
|
||||||
((((Data16) & 0x00ff) << 8) | (((Data16) & 0xff00) >> 8))
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Get the parameters for the USB mass storage media, including
|
Get the parameters for the USB mass storage media, including
|
||||||
the RemovableMedia, block size, and last block number. This
|
the RemovableMedia, block size, and last block number. This
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/** @file
|
/** @file
|
||||||
|
Implementation of the USB mass storage Bulk-Only Transport protocol,
|
||||||
Implementation of the USB mass storage Bulk-Only Transport protocol.
|
according to USB Mass Storage Class Bulk-Only Transport, Revision 1.0.
|
||||||
|
|
||||||
Copyright (c) 2007 - 2008, Intel Corporation
|
Copyright (c) 2007 - 2008, Intel Corporation
|
||||||
All rights reserved. This program and the accompanying materials
|
All rights reserved. This program and the accompanying materials
|
||||||
|
@ -16,41 +16,36 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
#include "UsbMass.h"
|
#include "UsbMass.h"
|
||||||
#include "UsbMassBot.h"
|
#include "UsbMassBot.h"
|
||||||
|
|
||||||
/**
|
//
|
||||||
Reset the mass storage device by BOT protocol.
|
// Definition of USB BOT Transport Protocol
|
||||||
|
//
|
||||||
@param Context The context of the BOT protocol, that is,
|
USB_MASS_TRANSPORT mUsbBotTransport = {
|
||||||
USB_BOT_PROTOCOL.
|
USB_MASS_STORE_BOT,
|
||||||
@param ExtendedVerification The flag controlling the rule of reset dev.
|
UsbBotInit,
|
||||||
|
UsbBotExecCommand,
|
||||||
@retval EFI_SUCCESS The device is reset.
|
UsbBotResetDevice,
|
||||||
@retval Others Failed to reset the device..
|
UsbBotGetMaxLun,
|
||||||
|
UsbBotCleanUp
|
||||||
**/
|
};
|
||||||
EFI_STATUS
|
|
||||||
UsbBotResetDevice (
|
|
||||||
IN VOID *Context,
|
|
||||||
IN BOOLEAN ExtendedVerification
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Initialize the USB mass storage class BOT transport protocol.
|
Initializes USB BOT protocol.
|
||||||
|
|
||||||
|
This function initializes the USB mass storage class BOT protocol.
|
||||||
It will save its context which is a USB_BOT_PROTOCOL structure
|
It will save its context which is a USB_BOT_PROTOCOL structure
|
||||||
in the Context if Context isn't NULL.
|
in the Context if Context isn't NULL.
|
||||||
|
|
||||||
@param UsbIo The USB IO protocol to use
|
@param UsbIo The USB I/O Protocol instance
|
||||||
@param Context The variable to save the context to
|
@param Context The buffer to save the context to
|
||||||
|
|
||||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory
|
@retval EFI_SUCCESS The device is successfully initialized.
|
||||||
@retval EFI_UNSUPPORTED The transport protocol doesn't support the device.
|
@retval EFI_UNSUPPORTED The transport protocol doesn't support the device.
|
||||||
@retval EFI_SUCCESS The device is supported and protocol initialized.
|
@retval Other The USB BOT initialization fails.
|
||||||
@retval Other The UBS BOT initialization fails.
|
|
||||||
|
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
UsbBotInit (
|
UsbBotInit (
|
||||||
IN EFI_USB_IO_PROTOCOL * UsbIo,
|
IN EFI_USB_IO_PROTOCOL *UsbIo,
|
||||||
OUT VOID **Context OPTIONAL
|
OUT VOID **Context OPTIONAL
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
@ -61,25 +56,22 @@ UsbBotInit (
|
||||||
UINT8 Index;
|
UINT8 Index;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Allocate the BOT context, append two endpoint descriptors to it
|
// Allocate the BOT context for USB_BOT_PROTOCOL and two endpoint descriptors.
|
||||||
//
|
//
|
||||||
UsbBot = AllocateZeroPool (
|
UsbBot = AllocateZeroPool (
|
||||||
sizeof (USB_BOT_PROTOCOL) + 2 * sizeof (EFI_USB_ENDPOINT_DESCRIPTOR)
|
sizeof (USB_BOT_PROTOCOL) + 2 * sizeof (EFI_USB_ENDPOINT_DESCRIPTOR)
|
||||||
);
|
);
|
||||||
if (UsbBot == NULL) {
|
ASSERT (UsbBot != NULL);
|
||||||
return EFI_OUT_OF_RESOURCES;
|
|
||||||
}
|
|
||||||
|
|
||||||
UsbBot->UsbIo = UsbIo;
|
UsbBot->UsbIo = UsbIo;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the interface descriptor and validate that it
|
// Get the interface descriptor and validate that it
|
||||||
// is a USB MSC BOT interface.
|
// is a USB Mass Storage BOT interface.
|
||||||
//
|
//
|
||||||
Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &UsbBot->Interface);
|
Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &UsbBot->Interface);
|
||||||
|
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
DEBUG ((EFI_D_ERROR, "UsbBotInit: Get invalid BOT interface (%r)\n", Status));
|
|
||||||
goto ON_ERROR;
|
goto ON_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,14 +107,16 @@ UsbBotInit (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// If bulk-in or bulk-out endpoint is not found, report error.
|
||||||
|
//
|
||||||
if ((UsbBot->BulkInEndpoint == NULL) || (UsbBot->BulkOutEndpoint == NULL)) {
|
if ((UsbBot->BulkInEndpoint == NULL) || (UsbBot->BulkOutEndpoint == NULL)) {
|
||||||
DEBUG ((EFI_D_ERROR, "UsbBotInit: In/Out Endpoint invalid\n"));
|
|
||||||
Status = EFI_UNSUPPORTED;
|
Status = EFI_UNSUPPORTED;
|
||||||
goto ON_ERROR;
|
goto ON_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// The USB BOT protocol uses dCBWTag to match the CBW and CSW.
|
// The USB BOT protocol uses CBWTag to match the CBW and CSW.
|
||||||
//
|
//
|
||||||
UsbBot->CbwTag = 0x01;
|
UsbBot->CbwTag = 0x01;
|
||||||
|
|
||||||
|
@ -139,19 +133,22 @@ ON_ERROR:
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Send the command to the device using Bulk-Out endpoint.
|
Send the command to the device using Bulk-Out endpoint.
|
||||||
|
|
||||||
|
This function sends the command to the device using Bulk-Out endpoint.
|
||||||
|
BOT transfer is composed of three phases: Command, Data, and Status.
|
||||||
|
This is the Command phase.
|
||||||
|
|
||||||
@param UsbBot The USB BOT device
|
@param UsbBot The USB BOT device
|
||||||
@param Cmd The command to transfer to device
|
@param Cmd The command to transfer to device
|
||||||
@param CmdLen the length of the command
|
@param CmdLen The length of the command
|
||||||
@param DataDir The direction of the data
|
@param DataDir The direction of the data
|
||||||
@param TransLen The expected length of the data
|
@param TransLen The expected length of the data
|
||||||
@param Lun The number of logic unit
|
@param Lun The number of logic unit
|
||||||
|
|
||||||
@retval EFI_NOT_READY The device return NAK to the transfer
|
|
||||||
@retval EFI_SUCCESS The command is sent to the device.
|
@retval EFI_SUCCESS The command is sent to the device.
|
||||||
|
@retval EFI_NOT_READY The device return NAK to the transfer
|
||||||
@retval Others Failed to send the command to device
|
@retval Others Failed to send the command to device
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
@ -174,25 +171,24 @@ UsbBotSendCommand (
|
||||||
ASSERT ((CmdLen > 0) && (CmdLen <= USB_BOT_MAX_CMDLEN));
|
ASSERT ((CmdLen > 0) && (CmdLen <= USB_BOT_MAX_CMDLEN));
|
||||||
|
|
||||||
//
|
//
|
||||||
// Fill in the CSW. Only the first LUN is supported now.
|
// Fill in the Command Block Wrapper.
|
||||||
//
|
//
|
||||||
Cbw.Signature = USB_BOT_CBW_SIGNATURE;
|
Cbw.Signature = USB_BOT_CBW_SIGNATURE;
|
||||||
Cbw.Tag = UsbBot->CbwTag;
|
Cbw.Tag = UsbBot->CbwTag;
|
||||||
Cbw.DataLen = TransLen;
|
Cbw.DataLen = TransLen;
|
||||||
Cbw.Flag = (UINT8) ((DataDir == EfiUsbDataIn) ? 0x80 : 0);
|
Cbw.Flag = (UINT8) ((DataDir == EfiUsbDataIn) ? BIT7 : 0);
|
||||||
Cbw.Lun = Lun;
|
Cbw.Lun = Lun;
|
||||||
Cbw.CmdLen = CmdLen;
|
Cbw.CmdLen = CmdLen;
|
||||||
|
|
||||||
ZeroMem (Cbw.CmdBlock, USB_BOT_MAX_CMDLEN);
|
ZeroMem (Cbw.CmdBlock, USB_BOT_MAX_CMDLEN);
|
||||||
CopyMem (Cbw.CmdBlock, Cmd, CmdLen);
|
CopyMem (Cbw.CmdBlock, Cmd, CmdLen);
|
||||||
|
|
||||||
Result = 0;
|
Result = 0;
|
||||||
DataLen = sizeof (USB_BOT_CBW);
|
DataLen = sizeof (USB_BOT_CBW);
|
||||||
Timeout = USB_BOT_SEND_CBW_TIMEOUT / USB_MASS_1_MILLISECOND;
|
Timeout = USB_BOT_SEND_CBW_TIMEOUT / USB_MASS_1_MILLISECOND;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Use the UsbIo to send the command to the device. The default
|
// Use USB I/O Protocol to send the Command Block Wrapper to the device.
|
||||||
// time out is enough.
|
|
||||||
//
|
//
|
||||||
Status = UsbBot->UsbIo->UsbBulkTransfer (
|
Status = UsbBot->UsbIo->UsbBulkTransfer (
|
||||||
UsbBot->UsbIo,
|
UsbBot->UsbIo,
|
||||||
|
@ -202,12 +198,12 @@ UsbBotSendCommand (
|
||||||
Timeout,
|
Timeout,
|
||||||
&Result
|
&Result
|
||||||
);
|
);
|
||||||
//
|
|
||||||
// Respond to Bulk-Out endpoint stall with a Reset Recovery,
|
|
||||||
// see the spec section 5.3.1
|
|
||||||
//
|
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
if (USB_IS_ERROR (Result, EFI_USB_ERR_STALL) && DataDir == EfiUsbDataOut) {
|
if (USB_IS_ERROR (Result, EFI_USB_ERR_STALL) && DataDir == EfiUsbDataOut) {
|
||||||
|
//
|
||||||
|
// Respond to Bulk-Out endpoint stall with a Reset Recovery,
|
||||||
|
// according to section 5.3.1 of USB Mass Storage Class Bulk-Only Transport Spec, v1.0.
|
||||||
|
//
|
||||||
UsbBotResetDevice (UsbBot, FALSE);
|
UsbBotResetDevice (UsbBot, FALSE);
|
||||||
} else if (USB_IS_ERROR (Result, EFI_USB_ERR_NAK)) {
|
} else if (USB_IS_ERROR (Result, EFI_USB_ERR_NAK)) {
|
||||||
Status = EFI_NOT_READY;
|
Status = EFI_NOT_READY;
|
||||||
|
@ -219,8 +215,11 @@ UsbBotSendCommand (
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Transfer the data between the device and host. BOT transfer
|
Transfer the data between the device and host.
|
||||||
is composed of three phase, command, data, and status.
|
|
||||||
|
This function transfers the data between the device and host.
|
||||||
|
BOT transfer is composed of three phases: Command, Data, and Status.
|
||||||
|
This is the Data phase.
|
||||||
|
|
||||||
@param UsbBot The USB BOT device
|
@param UsbBot The USB BOT device
|
||||||
@param DataDir The direction of the data
|
@param DataDir The direction of the data
|
||||||
|
@ -229,6 +228,8 @@ UsbBotSendCommand (
|
||||||
@param Timeout The time to wait the command to complete
|
@param Timeout The time to wait the command to complete
|
||||||
|
|
||||||
@retval EFI_SUCCESS The data is transferred
|
@retval EFI_SUCCESS The data is transferred
|
||||||
|
@retval EFI_SUCCESS No data to transfer
|
||||||
|
@retval EFI_NOT_READY The device return NAK to the transfer
|
||||||
@retval Others Failed to transfer data
|
@retval Others Failed to transfer data
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
@ -246,7 +247,7 @@ UsbBotDataTransfer (
|
||||||
UINT32 Result;
|
UINT32 Result;
|
||||||
|
|
||||||
//
|
//
|
||||||
// It's OK if no data to transfer
|
// If no data to transfer, just return EFI_SUCCESS.
|
||||||
//
|
//
|
||||||
if ((DataDir == EfiUsbNoData) || (*TransLen == 0)) {
|
if ((DataDir == EfiUsbNoData) || (*TransLen == 0)) {
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
|
@ -273,9 +274,7 @@ UsbBotDataTransfer (
|
||||||
&Result
|
&Result
|
||||||
);
|
);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
DEBUG ((EFI_D_ERROR, "UsbBotDataTransfer: (%r)\n", Status));
|
|
||||||
if (USB_IS_ERROR (Result, EFI_USB_ERR_STALL)) {
|
if (USB_IS_ERROR (Result, EFI_USB_ERR_STALL)) {
|
||||||
DEBUG ((EFI_D_ERROR, "UsbBotDataTransfer: DataIn Stall\n"));
|
|
||||||
UsbClearEndpointStall (UsbBot->UsbIo, Endpoint->EndpointAddress);
|
UsbClearEndpointStall (UsbBot->UsbIo, Endpoint->EndpointAddress);
|
||||||
} else if (USB_IS_ERROR (Result, EFI_USB_ERR_NAK)) {
|
} else if (USB_IS_ERROR (Result, EFI_USB_ERR_NAK)) {
|
||||||
Status = EFI_NOT_READY;
|
Status = EFI_NOT_READY;
|
||||||
|
@ -287,19 +286,22 @@ UsbBotDataTransfer (
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Get the command execution status from device. BOT transfer is
|
Get the command execution status from device.
|
||||||
composed of three phase, command, data, and status.
|
|
||||||
This function return the transfer status of the BOT's CSW status,
|
|
||||||
and return the high level command execution result in Result. So
|
|
||||||
even it returns EFI_SUCCESS, the command may still have failed.
|
|
||||||
|
|
||||||
@param UsbBot The USB BOT device.
|
This function gets the command execution status from device.
|
||||||
@param TransLen The expected length of the data.
|
BOT transfer is composed of three phases: Command, Data, and Status.
|
||||||
@param CmdStatus The result of the command execution.
|
This is the Status phase.
|
||||||
|
|
||||||
@retval EFI_SUCCESS Command execute result is retrieved and in the
|
This function returns the transfer status of the BOT's CSW status,
|
||||||
Result.
|
and returns the high level command execution result in Result. So
|
||||||
@retval Other Failed to get status.
|
even if EFI_SUCCESS is returned, the command may still have failed.
|
||||||
|
|
||||||
|
@param UsbBot The USB BOT device.
|
||||||
|
@param TransLen The expected length of the data.
|
||||||
|
@param CmdStatus The result of the command execution.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Command execute result is retrieved and in the Result.
|
||||||
|
@retval Other Error occurred when trying to get status.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
|
@ -326,7 +328,7 @@ UsbBotGetStatus (
|
||||||
|
|
||||||
for (Index = 0; Index < USB_BOT_RECV_CSW_RETRY; Index++) {
|
for (Index = 0; Index < USB_BOT_RECV_CSW_RETRY; Index++) {
|
||||||
//
|
//
|
||||||
// Attemp to the read CSW from bulk in endpoint
|
// Attemp to the read Command Status Wrapper from bulk in endpoint
|
||||||
//
|
//
|
||||||
ZeroMem (&Csw, sizeof (USB_BOT_CSW));
|
ZeroMem (&Csw, sizeof (USB_BOT_CSW));
|
||||||
Result = 0;
|
Result = 0;
|
||||||
|
@ -340,9 +342,7 @@ UsbBotGetStatus (
|
||||||
&Result
|
&Result
|
||||||
);
|
);
|
||||||
if (EFI_ERROR(Status)) {
|
if (EFI_ERROR(Status)) {
|
||||||
DEBUG ((EFI_D_ERROR, "UsbBotGetStatus (%r)\n", Status));
|
|
||||||
if (USB_IS_ERROR (Result, EFI_USB_ERR_STALL)) {
|
if (USB_IS_ERROR (Result, EFI_USB_ERR_STALL)) {
|
||||||
DEBUG ((EFI_D_ERROR, "UsbBotGetStatus: DataIn Stall\n"));
|
|
||||||
UsbClearEndpointStall (UsbIo, Endpoint);
|
UsbClearEndpointStall (UsbIo, Endpoint);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
@ -350,24 +350,21 @@ UsbBotGetStatus (
|
||||||
|
|
||||||
if (Csw.Signature != USB_BOT_CSW_SIGNATURE) {
|
if (Csw.Signature != USB_BOT_CSW_SIGNATURE) {
|
||||||
//
|
//
|
||||||
// Invalid Csw need perform reset recovery
|
// CSW is invalid, so perform reset recovery
|
||||||
//
|
//
|
||||||
DEBUG ((EFI_D_ERROR, "UsbBotGetStatus: Device return a invalid signature\n"));
|
|
||||||
Status = UsbBotResetDevice (UsbBot, FALSE);
|
Status = UsbBotResetDevice (UsbBot, FALSE);
|
||||||
} else if (Csw.CmdStatus == USB_BOT_COMMAND_ERROR) {
|
} else if (Csw.CmdStatus == USB_BOT_COMMAND_ERROR) {
|
||||||
//
|
//
|
||||||
// Respond phase error need perform reset recovery
|
// Respond phase error also needs reset recovery
|
||||||
//
|
//
|
||||||
DEBUG ((EFI_D_ERROR, "UsbBotGetStatus: Device return a phase error\n"));
|
|
||||||
Status = UsbBotResetDevice (UsbBot, FALSE);
|
Status = UsbBotResetDevice (UsbBot, FALSE);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
*CmdStatus = Csw.CmdStatus;
|
*CmdStatus = Csw.CmdStatus;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
//The tag is increased even there is an error.
|
//The tag is increased even if there is an error.
|
||||||
//
|
//
|
||||||
UsbBot->CbwTag++;
|
UsbBot->CbwTag++;
|
||||||
|
|
||||||
|
@ -376,7 +373,7 @@ UsbBotGetStatus (
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Call the Usb mass storage class transport protocol to issue
|
Call the USB Mass Storage Class BOT protocol to issue
|
||||||
the command/data/status circle to execute the commands.
|
the command/data/status circle to execute the commands.
|
||||||
|
|
||||||
@param Context The context of the BOT protocol, that is,
|
@param Context The context of the BOT protocol, that is,
|
||||||
|
@ -390,7 +387,7 @@ UsbBotGetStatus (
|
||||||
@param Timeout The time to wait command
|
@param Timeout The time to wait command
|
||||||
@param CmdStatus The result of high level command execution
|
@param CmdStatus The result of high level command execution
|
||||||
|
|
||||||
@retval EFI_SUCCESS The command is executed OK, and result in CmdStatus
|
@retval EFI_SUCCESS The command is executed successfully.
|
||||||
@retval Other Failed to excute command
|
@retval Other Failed to excute command
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
@ -428,7 +425,7 @@ UsbBotExecCommand (
|
||||||
//
|
//
|
||||||
// Transfer the data. Don't return immediately even data transfer
|
// Transfer the data. Don't return immediately even data transfer
|
||||||
// failed. The host should attempt to receive the CSW no matter
|
// failed. The host should attempt to receive the CSW no matter
|
||||||
// whether it succeeds or failed.
|
// whether it succeeds or fails.
|
||||||
//
|
//
|
||||||
TransLen = (UINTN) DataLen;
|
TransLen = (UINTN) DataLen;
|
||||||
UsbBotDataTransfer (UsbBot, DataDir, Data, &TransLen, Timeout);
|
UsbBotDataTransfer (UsbBot, DataDir, Data, &TransLen, Timeout);
|
||||||
|
@ -451,11 +448,12 @@ UsbBotExecCommand (
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Reset the mass storage device by BOT protocol.
|
Reset the USB mass storage device by BOT protocol.
|
||||||
|
|
||||||
@param Context The context of the BOT protocol, that is,
|
@param Context The context of the BOT protocol, that is,
|
||||||
USB_BOT_PROTOCOL.
|
USB_BOT_PROTOCOL.
|
||||||
@param ExtendedVerification The flag controlling the rule of reset dev.
|
@param ExtendedVerification If FALSE, just issue Bulk-Only Mass Storage Reset request.
|
||||||
|
If TRUE, additionally reset parent hub port.
|
||||||
|
|
||||||
@retval EFI_SUCCESS The device is reset.
|
@retval EFI_SUCCESS The device is reset.
|
||||||
@retval Others Failed to reset the device..
|
@retval Others Failed to reset the device..
|
||||||
|
@ -464,7 +462,7 @@ UsbBotExecCommand (
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
UsbBotResetDevice (
|
UsbBotResetDevice (
|
||||||
IN VOID *Context,
|
IN VOID *Context,
|
||||||
IN BOOLEAN ExtendedVerification
|
IN BOOLEAN ExtendedVerification
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
USB_BOT_PROTOCOL *UsbBot;
|
USB_BOT_PROTOCOL *UsbBot;
|
||||||
|
@ -486,10 +484,10 @@ UsbBotResetDevice (
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Issue a class specific Bulk-Only Mass Storage Reset reqest.
|
// Issue a class specific Bulk-Only Mass Storage Reset request,
|
||||||
// See the spec section 3.1
|
// according to section 3.1 of USB Mass Storage Class Bulk-Only Transport Spec, v1.0.
|
||||||
//
|
//
|
||||||
Request.RequestType = 0x21; // Class, Interface, Host to Device
|
Request.RequestType = 0x21;
|
||||||
Request.Request = USB_BOT_RESET_REQUEST;
|
Request.Request = USB_BOT_RESET_REQUEST;
|
||||||
Request.Value = 0;
|
Request.Value = 0;
|
||||||
Request.Index = UsbBot->Interface.InterfaceNumber;
|
Request.Index = UsbBot->Interface.InterfaceNumber;
|
||||||
|
@ -507,14 +505,13 @@ UsbBotResetDevice (
|
||||||
);
|
);
|
||||||
|
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
DEBUG ((EFI_D_ERROR, "UsbBotResetDevice: (%r)\n", Status));
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// The device shall NAK the host's request until the reset is
|
// The device shall NAK the host's request until the reset is
|
||||||
// complete. We can use this to sync the device and host. For
|
// complete. We can use this to sync the device and host. For
|
||||||
// now just stall 100ms to wait the device.
|
// now just stall 100ms to wait for the device.
|
||||||
//
|
//
|
||||||
gBS->Stall (USB_BOT_RESET_DEVICE_STALL);
|
gBS->Stall (USB_BOT_RESET_DEVICE_STALL);
|
||||||
|
|
||||||
|
@ -523,25 +520,26 @@ UsbBotResetDevice (
|
||||||
//
|
//
|
||||||
UsbClearEndpointStall (UsbBot->UsbIo, UsbBot->BulkInEndpoint->EndpointAddress);
|
UsbClearEndpointStall (UsbBot->UsbIo, UsbBot->BulkInEndpoint->EndpointAddress);
|
||||||
UsbClearEndpointStall (UsbBot->UsbIo, UsbBot->BulkOutEndpoint->EndpointAddress);
|
UsbClearEndpointStall (UsbBot->UsbIo, UsbBot->BulkOutEndpoint->EndpointAddress);
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Get the max lun of mass storage device.
|
Get the max LUN (Logical Unit Number) of USB mass storage device.
|
||||||
|
|
||||||
@param Context The context of the BOT protocol, that is, USB_BOT_PROTOCOL
|
@param Context The context of the BOT protocol, that is, USB_BOT_PROTOCOL
|
||||||
@param MaxLun Return pointer to the max number of lun. Maxlun=1 means lun0 and
|
@param MaxLun Return pointer to the max number of LUN. (e.g. MaxLun=1 means LUN0 and
|
||||||
lun1 in all.
|
LUN1 in all.)
|
||||||
|
|
||||||
@retval EFI_SUCCESS Get max lun success.
|
@retval EFI_SUCCESS Max LUN is got successfully.
|
||||||
@retval Others Failed to execute this request.
|
@retval Others Fail to execute this request.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
UsbBotGetMaxLun (
|
UsbBotGetMaxLun (
|
||||||
IN VOID *Context,
|
IN VOID *Context,
|
||||||
IN UINT8 *MaxLun
|
OUT UINT8 *MaxLun
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
USB_BOT_PROTOCOL *UsbBot;
|
USB_BOT_PROTOCOL *UsbBot;
|
||||||
|
@ -556,9 +554,9 @@ UsbBotGetMaxLun (
|
||||||
|
|
||||||
//
|
//
|
||||||
// Issue a class specific Bulk-Only Mass Storage get max lun reqest.
|
// Issue a class specific Bulk-Only Mass Storage get max lun reqest.
|
||||||
// See the spec section 3.2
|
// according to section 3.2 of USB Mass Storage Class Bulk-Only Transport Spec, v1.0.
|
||||||
//
|
//
|
||||||
Request.RequestType = 0xA1; // Class, Interface, Device to Host
|
Request.RequestType = 0xA1;
|
||||||
Request.Request = USB_BOT_GETLUN_REQUEST;
|
Request.Request = USB_BOT_GETLUN_REQUEST;
|
||||||
Request.Value = 0;
|
Request.Value = 0;
|
||||||
Request.Index = UsbBot->Interface.InterfaceNumber;
|
Request.Index = UsbBot->Interface.InterfaceNumber;
|
||||||
|
@ -570,29 +568,24 @@ UsbBotGetMaxLun (
|
||||||
&Request,
|
&Request,
|
||||||
EfiUsbDataIn,
|
EfiUsbDataIn,
|
||||||
Timeout,
|
Timeout,
|
||||||
(VOID *)MaxLun,
|
(VOID *) MaxLun,
|
||||||
1,
|
1,
|
||||||
&Result
|
&Result
|
||||||
);
|
);
|
||||||
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
DEBUG ((EFI_D_ERROR, "UsbBotGetMaxLun: (%r)\n", Status));
|
|
||||||
}
|
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Clean up the resource used by this BOT protocol.
|
Clean up the resource used by this BOT protocol.
|
||||||
|
|
||||||
@param Context The context of the BOT protocol, that is,
|
@param Context The context of the BOT protocol, that is, USB_BOT_PROTOCOL.
|
||||||
USB_BOT_PROTOCOL.
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS The resource is cleaned up.
|
@retval EFI_SUCCESS The resource is cleaned up.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
UsbBotFini (
|
UsbBotCleanUp (
|
||||||
IN VOID *Context
|
IN VOID *Context
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
@ -600,13 +593,3 @@ UsbBotFini (
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
USB_MASS_TRANSPORT
|
|
||||||
mUsbBotTransport = {
|
|
||||||
USB_MASS_STORE_BOT,
|
|
||||||
UsbBotInit,
|
|
||||||
UsbBotExecCommand,
|
|
||||||
UsbBotResetDevice,
|
|
||||||
UsbBotGetMaxLun,
|
|
||||||
UsbBotFini
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
/** @file
|
/** @file
|
||||||
|
Definition for the USB mass storage Bulk-Only Transport protocol,
|
||||||
Defination for the USB mass storage Bulk-Only Transport protocol.
|
based on the "Universal Serial Bus Mass Storage Class Bulk-Only
|
||||||
This implementation is based on the "Universal Serial Bus Mass
|
Transport" Revision 1.0, September 31, 1999.
|
||||||
Storage Class Bulk-Only Transport" Revision 1.0, September 31, 1999.
|
|
||||||
|
|
||||||
Copyright (c) 2007 - 2008, Intel Corporation
|
Copyright (c) 2007 - 2008, Intel Corporation
|
||||||
All rights reserved. This program and the accompanying materials
|
All rights reserved. This program and the accompanying materials
|
||||||
|
@ -18,33 +17,35 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
#ifndef _EFI_USBMASS_BOT_H_
|
#ifndef _EFI_USBMASS_BOT_H_
|
||||||
#define _EFI_USBMASS_BOT_H_
|
#define _EFI_USBMASS_BOT_H_
|
||||||
|
|
||||||
|
extern USB_MASS_TRANSPORT mUsbBotTransport;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
//
|
//
|
||||||
// Usb Bulk-Only class specfic request
|
// Usb Bulk-Only class specfic request
|
||||||
//
|
//
|
||||||
USB_BOT_RESET_REQUEST = 0xFF, // Bulk-Only Mass Storage Reset
|
USB_BOT_RESET_REQUEST = 0xFF, ///< Bulk-Only Mass Storage Reset
|
||||||
USB_BOT_GETLUN_REQUEST = 0xFE, // Get Max Lun
|
USB_BOT_GETLUN_REQUEST = 0xFE, ///< Get Max Lun
|
||||||
USB_BOT_CBW_SIGNATURE = 0x43425355, // dCBWSignature, tag the packet as CBW
|
USB_BOT_CBW_SIGNATURE = 0x43425355, ///< dCBWSignature, tag the packet as CBW
|
||||||
USB_BOT_CSW_SIGNATURE = 0x53425355, // dCSWSignature, tag the packet as CSW
|
USB_BOT_CSW_SIGNATURE = 0x53425355, ///< dCSWSignature, tag the packet as CSW
|
||||||
USB_BOT_MAX_LUN = 0x0F, // Lun number is from 0 to 15
|
USB_BOT_MAX_LUN = 0x0F, ///< Lun number is from 0 to 15
|
||||||
USB_BOT_MAX_CMDLEN = 16, // Maxium number of command from command set
|
USB_BOT_MAX_CMDLEN = 16, ///< Maxium number of command from command set
|
||||||
|
|
||||||
//
|
//
|
||||||
// Usb BOT command block status values
|
// Usb BOT command block status values
|
||||||
//
|
//
|
||||||
USB_BOT_COMMAND_OK = 0x00, // Command passed, good status
|
USB_BOT_COMMAND_OK = 0x00, ///< Command passed, good status
|
||||||
USB_BOT_COMMAND_FAILED = 0x01, // Command failed
|
USB_BOT_COMMAND_FAILED = 0x01, ///< Command failed
|
||||||
USB_BOT_COMMAND_ERROR = 0x02, // Phase error, need to reset the device
|
USB_BOT_COMMAND_ERROR = 0x02, ///< Phase error, need to reset the device
|
||||||
|
|
||||||
//
|
//
|
||||||
// Usb Bot retry to get CSW, refers to specification[BOT10-5.3, it says 2 times]
|
// Usb Bot retry to get CSW, refers to specification[BOT10-5.3, it says 2 times]
|
||||||
//
|
//
|
||||||
USB_BOT_RECV_CSW_RETRY = 3,
|
USB_BOT_RECV_CSW_RETRY = 3,
|
||||||
|
|
||||||
//
|
//
|
||||||
// Usb Bot wait device reset complete, set by experience
|
// Usb Bot wait device reset complete, set by experience
|
||||||
//
|
//
|
||||||
USB_BOT_RESET_DEVICE_STALL = 100 * USB_MASS_1_MILLISECOND,
|
USB_BOT_RESET_DEVICE_STALL = 100 * USB_MASS_1_MILLISECOND,
|
||||||
|
|
||||||
//
|
//
|
||||||
// Usb Bot transport timeout, set by experience
|
// Usb Bot transport timeout, set by experience
|
||||||
|
@ -52,23 +53,25 @@ typedef enum {
|
||||||
USB_BOT_SEND_CBW_TIMEOUT = 3 * USB_MASS_1_SECOND,
|
USB_BOT_SEND_CBW_TIMEOUT = 3 * USB_MASS_1_SECOND,
|
||||||
USB_BOT_RECV_CSW_TIMEOUT = 3 * USB_MASS_1_SECOND,
|
USB_BOT_RECV_CSW_TIMEOUT = 3 * USB_MASS_1_SECOND,
|
||||||
USB_BOT_RESET_DEVICE_TIMEOUT = 3 * USB_MASS_1_SECOND
|
USB_BOT_RESET_DEVICE_TIMEOUT = 3 * USB_MASS_1_SECOND
|
||||||
}USB_BOT_SUBCLASS;
|
} USB_BOT_SUBCLASS;
|
||||||
|
|
||||||
//
|
|
||||||
// The CBW (Command Block Wrapper) and CSW (Command Status Wrapper)
|
|
||||||
// structures used by the Usb BOT protocol.
|
|
||||||
//
|
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
|
///
|
||||||
|
/// The CBW (Command Block Wrapper) structures used by the USB BOT protocol.
|
||||||
|
///
|
||||||
typedef struct {
|
typedef struct {
|
||||||
UINT32 Signature;
|
UINT32 Signature;
|
||||||
UINT32 Tag;
|
UINT32 Tag;
|
||||||
UINT32 DataLen; // Length of data between CBW and CSW
|
UINT32 DataLen; ///< Length of data between CBW and CSW
|
||||||
UINT8 Flag; // Bit 7, 0 ~ Data-Out, 1 ~ Data-In
|
UINT8 Flag; ///< Bit 7, 0 ~ Data-Out, 1 ~ Data-In
|
||||||
UINT8 Lun; // Lun number. Bits 0~3 are used
|
UINT8 Lun; ///< Lun number. Bits 0~3 are used
|
||||||
UINT8 CmdLen; // Length of the command. Bits 0~4 are used
|
UINT8 CmdLen; ///< Length of the command. Bits 0~4 are used
|
||||||
UINT8 CmdBlock[USB_BOT_MAX_CMDLEN];
|
UINT8 CmdBlock[USB_BOT_MAX_CMDLEN];
|
||||||
} USB_BOT_CBW;
|
} USB_BOT_CBW;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// The and CSW (Command Status Wrapper) structures used by the USB BOT protocol.
|
||||||
|
///
|
||||||
typedef struct {
|
typedef struct {
|
||||||
UINT32 Signature;
|
UINT32 Signature;
|
||||||
UINT32 Tag;
|
UINT32 Tag;
|
||||||
|
@ -77,11 +80,10 @@ typedef struct {
|
||||||
} USB_BOT_CSW;
|
} USB_BOT_CSW;
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
|
|
||||||
//
|
|
||||||
// Put Interface at the first field is to make it easy to get by Context, which
|
|
||||||
// could be BOT/CBI Protocol instance
|
|
||||||
//
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
//
|
||||||
|
// Put Interface at the first field to make it easy to distinguish BOT/CBI Protocol instance
|
||||||
|
//
|
||||||
EFI_USB_INTERFACE_DESCRIPTOR Interface;
|
EFI_USB_INTERFACE_DESCRIPTOR Interface;
|
||||||
EFI_USB_ENDPOINT_DESCRIPTOR *BulkInEndpoint;
|
EFI_USB_ENDPOINT_DESCRIPTOR *BulkInEndpoint;
|
||||||
EFI_USB_ENDPOINT_DESCRIPTOR *BulkOutEndpoint;
|
EFI_USB_ENDPOINT_DESCRIPTOR *BulkOutEndpoint;
|
||||||
|
@ -89,5 +91,105 @@ typedef struct {
|
||||||
EFI_USB_IO_PROTOCOL *UsbIo;
|
EFI_USB_IO_PROTOCOL *UsbIo;
|
||||||
} USB_BOT_PROTOCOL;
|
} USB_BOT_PROTOCOL;
|
||||||
|
|
||||||
extern USB_MASS_TRANSPORT mUsbBotTransport;
|
/**
|
||||||
|
Initializes USB BOT protocol.
|
||||||
|
|
||||||
|
This function initializes the USB mass storage class BOT protocol.
|
||||||
|
It will save its context which is a USB_BOT_PROTOCOL structure
|
||||||
|
in the Context if Context isn't NULL.
|
||||||
|
|
||||||
|
@param UsbIo The USB I/O Protocol instance
|
||||||
|
@param Context The buffer to save the context to
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The device is successfully initialized.
|
||||||
|
@retval EFI_UNSUPPORTED The transport protocol doesn't support the device.
|
||||||
|
@retval Other The USB BOT initialization fails.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
UsbBotInit (
|
||||||
|
IN EFI_USB_IO_PROTOCOL *UsbIo,
|
||||||
|
OUT VOID **Context OPTIONAL
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Call the USB Mass Storage Class BOT protocol to issue
|
||||||
|
the command/data/status circle to execute the commands.
|
||||||
|
|
||||||
|
@param Context The context of the BOT protocol, that is,
|
||||||
|
USB_BOT_PROTOCOL
|
||||||
|
@param Cmd The high level command
|
||||||
|
@param CmdLen The command length
|
||||||
|
@param DataDir The direction of the data transfer
|
||||||
|
@param Data The buffer to hold data
|
||||||
|
@param DataLen The length of the data
|
||||||
|
@param Lun The number of logic unit
|
||||||
|
@param Timeout The time to wait command
|
||||||
|
@param CmdStatus The result of high level command execution
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The command is executed successfully.
|
||||||
|
@retval Other Failed to excute command
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
UsbBotExecCommand (
|
||||||
|
IN VOID *Context,
|
||||||
|
IN VOID *Cmd,
|
||||||
|
IN UINT8 CmdLen,
|
||||||
|
IN EFI_USB_DATA_DIRECTION DataDir,
|
||||||
|
IN VOID *Data,
|
||||||
|
IN UINT32 DataLen,
|
||||||
|
IN UINT8 Lun,
|
||||||
|
IN UINT32 Timeout,
|
||||||
|
OUT UINT32 *CmdStatus
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Reset the USB mass storage device by BOT protocol.
|
||||||
|
|
||||||
|
@param Context The context of the BOT protocol, that is,
|
||||||
|
USB_BOT_PROTOCOL.
|
||||||
|
@param ExtendedVerification If FALSE, just issue Bulk-Only Mass Storage Reset request.
|
||||||
|
If TRUE, additionally reset parent hub port.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The device is reset.
|
||||||
|
@retval Others Failed to reset the device..
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
UsbBotResetDevice (
|
||||||
|
IN VOID *Context,
|
||||||
|
IN BOOLEAN ExtendedVerification
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the max LUN (Logical Unit Number) of USB mass storage device.
|
||||||
|
|
||||||
|
@param Context The context of the BOT protocol, that is, USB_BOT_PROTOCOL
|
||||||
|
@param MaxLun Return pointer to the max number of LUN. (e.g. MaxLun=1 means LUN0 and
|
||||||
|
LUN1 in all.)
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Max LUN is got successfully.
|
||||||
|
@retval Others Fail to execute this request.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
UsbBotGetMaxLun (
|
||||||
|
IN VOID *Context,
|
||||||
|
OUT UINT8 *MaxLun
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Clean up the resource used by this BOT protocol.
|
||||||
|
|
||||||
|
@param Context The context of the BOT protocol, that is, USB_BOT_PROTOCOL.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The resource is cleaned up.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
UsbBotCleanUp (
|
||||||
|
IN VOID *Context
|
||||||
|
);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/** @file
|
/** @file
|
||||||
|
Implementation of the USB mass storage Control/Bulk/Interrupt transport,
|
||||||
Implementation of the USB mass storage Control/Bulk/Interrupt transport.
|
according to USB Mass Storage Class Control/Bulk/Interrupt (CBI) Transport, Revision 1.1.
|
||||||
Notice: it is being obsoleted by the standard body in favor of the BOT
|
Notice: it is being obsoleted by the standard body in favor of the BOT
|
||||||
(Bulk-Only Transport).
|
(Bulk-Only Transport).
|
||||||
|
|
||||||
|
@ -18,37 +18,43 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
#include "UsbMass.h"
|
#include "UsbMass.h"
|
||||||
#include "UsbMassCbi.h"
|
#include "UsbMassCbi.h"
|
||||||
|
|
||||||
/**
|
//
|
||||||
Call the Usb mass storage class transport protocol to
|
// Definition of USB CBI0 Transport Protocol
|
||||||
reset the device. The reset is defined as a Non-Data
|
//
|
||||||
command. Don't use UsbCbiExecCommand to send the command
|
USB_MASS_TRANSPORT mUsbCbi0Transport = {
|
||||||
to device because that may introduce recursive loop.
|
USB_MASS_STORE_CBI0,
|
||||||
|
UsbCbiInit,
|
||||||
@param Context The USB CBI device protocol
|
UsbCbiExecCommand,
|
||||||
@param ExtendedVerification The flag controlling the rule of reset
|
UsbCbiResetDevice,
|
||||||
|
NULL,
|
||||||
@retval EFI_SUCCESS the device is reset
|
UsbCbiCleanUp
|
||||||
@retval Others Failed to reset the device
|
};
|
||||||
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
UsbCbiResetDevice (
|
|
||||||
IN VOID *Context,
|
|
||||||
IN BOOLEAN ExtendedVerification
|
|
||||||
);
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Definition of USB CBI1 Transport Protocol
|
||||||
|
//
|
||||||
|
USB_MASS_TRANSPORT mUsbCbi1Transport = {
|
||||||
|
USB_MASS_STORE_CBI1,
|
||||||
|
UsbCbiInit,
|
||||||
|
UsbCbiExecCommand,
|
||||||
|
UsbCbiResetDevice,
|
||||||
|
NULL,
|
||||||
|
UsbCbiCleanUp
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Initialize the USB mass storage class CBI transport protocol.
|
Initializes USB CBI protocol.
|
||||||
If Context isn't NULL, it will save its context in it.
|
|
||||||
|
|
||||||
@param UsbIo The USB IO to use
|
This function initializes the USB mass storage class CBI protocol.
|
||||||
@param Context The variable to save context in
|
It will save its context which is a USB_CBI_PROTOCOL structure
|
||||||
|
in the Context if Context isn't NULL.
|
||||||
|
|
||||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory
|
@param UsbIo The USB I/O Protocol instance
|
||||||
@retval EFI_UNSUPPORTED The device isn't supported
|
@param Context The buffer to save the context to
|
||||||
@retval EFI_SUCCESS The CBI protocol is initialized.
|
|
||||||
@retval Other The Usb cbi init failed.
|
@retval EFI_SUCCESS The device is successfully initialized.
|
||||||
|
@retval EFI_UNSUPPORTED The transport protocol doesn't support the device.
|
||||||
|
@retval Other The USB CBI initialization fails.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
|
@ -64,21 +70,18 @@ UsbCbiInit (
|
||||||
UINT8 Index;
|
UINT8 Index;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Allocate the CBI context
|
// Allocate the CBI context for USB_CBI_PROTOCOL and 3 endpoint descriptors.
|
||||||
//
|
//
|
||||||
UsbCbi = AllocateZeroPool (
|
UsbCbi = AllocateZeroPool (
|
||||||
sizeof (USB_CBI_PROTOCOL) + 3 * sizeof (EFI_USB_ENDPOINT_DESCRIPTOR)
|
sizeof (USB_CBI_PROTOCOL) + 3 * sizeof (EFI_USB_ENDPOINT_DESCRIPTOR)
|
||||||
);
|
);
|
||||||
|
ASSERT (UsbCbi != NULL);
|
||||||
if (UsbCbi == NULL) {
|
|
||||||
return EFI_OUT_OF_RESOURCES;
|
|
||||||
}
|
|
||||||
|
|
||||||
UsbCbi->UsbIo = UsbIo;
|
UsbCbi->UsbIo = UsbIo;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the interface descriptor and validate that it is a USB mass
|
// Get the interface descriptor and validate that it
|
||||||
// storage class CBI interface.
|
// is a USB Mass Storage CBI interface.
|
||||||
//
|
//
|
||||||
Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &UsbCbi->Interface);
|
Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &UsbCbi->Interface);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
|
@ -118,7 +121,6 @@ UsbCbiInit (
|
||||||
UsbCbi->BulkOutEndpoint = (EFI_USB_ENDPOINT_DESCRIPTOR *) (UsbCbi + 1) + 1;
|
UsbCbi->BulkOutEndpoint = (EFI_USB_ENDPOINT_DESCRIPTOR *) (UsbCbi + 1) + 1;
|
||||||
CopyMem(UsbCbi->BulkOutEndpoint, &EndPoint, sizeof (EndPoint));
|
CopyMem(UsbCbi->BulkOutEndpoint, &EndPoint, sizeof (EndPoint));
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (USB_IS_INTERRUPT_ENDPOINT (EndPoint.Attributes)) {
|
} else if (USB_IS_INTERRUPT_ENDPOINT (EndPoint.Attributes)) {
|
||||||
//
|
//
|
||||||
// Use the first interrupt endpoint if it is CBI0
|
// Use the first interrupt endpoint if it is CBI0
|
||||||
|
@ -132,10 +134,11 @@ UsbCbiInit (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((UsbCbi->BulkInEndpoint == NULL)
|
if ((UsbCbi->BulkInEndpoint == NULL) || (UsbCbi->BulkOutEndpoint == NULL)) {
|
||||||
|| (UsbCbi->BulkOutEndpoint == NULL)
|
Status = EFI_UNSUPPORTED;
|
||||||
|| ((Interface->InterfaceProtocol == USB_MASS_STORE_CBI0)
|
goto ON_ERROR;
|
||||||
&& (UsbCbi->InterruptEndpoint == NULL))) {
|
}
|
||||||
|
if ((Interface->InterfaceProtocol == USB_MASS_STORE_CBI0) && (UsbCbi->InterruptEndpoint == NULL)) {
|
||||||
Status = EFI_UNSUPPORTED;
|
Status = EFI_UNSUPPORTED;
|
||||||
goto ON_ERROR;
|
goto ON_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -145,6 +148,7 @@ UsbCbiInit (
|
||||||
} else {
|
} else {
|
||||||
gBS->FreePool (UsbCbi);
|
gBS->FreePool (UsbCbi);
|
||||||
}
|
}
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
|
|
||||||
ON_ERROR:
|
ON_ERROR:
|
||||||
|
@ -152,16 +156,18 @@ ON_ERROR:
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Send the command to the device using class specific control transfer.
|
Send the command to the device using class specific control transfer.
|
||||||
|
|
||||||
|
This function sends command to the device using class specific control transfer.
|
||||||
|
The CBI contains three phases: Command, Data, and Status. This is Command phase.
|
||||||
|
|
||||||
@param UsbCbi The USB CBI protocol
|
@param UsbCbi The USB CBI protocol
|
||||||
@param Cmd The high level command to transfer to device
|
@param Cmd The high level command to transfer to device
|
||||||
@param CmdLen The length of the command
|
@param CmdLen The length of the command
|
||||||
@param Timeout The time to wait the command to finish
|
@param Timeout The time to wait the command to finish
|
||||||
|
|
||||||
@retval EFI_SUCCESS The command is transferred to device
|
@retval EFI_SUCCESS The command is sent to the device.
|
||||||
@retval Others The command failed to transfer to device
|
@retval Others The command failed to transfer to device
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
@ -181,7 +187,7 @@ UsbCbiSendCommand (
|
||||||
|
|
||||||
//
|
//
|
||||||
// Fill in the device request, CBI use the "Accept Device-Specific
|
// Fill in the device request, CBI use the "Accept Device-Specific
|
||||||
// Cmd" (ADSC) class specific request to send commands
|
// Cmd" (ADSC) class specific request to send commands.
|
||||||
//
|
//
|
||||||
Request.RequestType = 0x21;
|
Request.RequestType = 0x21;
|
||||||
Request.Request = 0;
|
Request.Request = 0;
|
||||||
|
@ -194,7 +200,7 @@ UsbCbiSendCommand (
|
||||||
|
|
||||||
for (Retry = 0; Retry < USB_CBI_MAX_RETRY; Retry++) {
|
for (Retry = 0; Retry < USB_CBI_MAX_RETRY; Retry++) {
|
||||||
//
|
//
|
||||||
// Use the UsbIo to send the command to the device
|
// Use USB I/O Protocol to send the command to the device
|
||||||
//
|
//
|
||||||
TransStatus = 0;
|
TransStatus = 0;
|
||||||
DataLen = CmdLen;
|
DataLen = CmdLen;
|
||||||
|
@ -226,16 +232,20 @@ UsbCbiSendCommand (
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Transfer data between the device and host. The CBI contains three phase,
|
Transfer data between the device and host.
|
||||||
command, data, and status. This is data phase.
|
|
||||||
|
This function transfers data between the device and host.
|
||||||
|
The CBI contains three phases: Command, Data, and Status. This is Data phase.
|
||||||
|
|
||||||
@param UsbCbi The USB CBI device
|
@param UsbCbi The USB CBI device
|
||||||
@param DataDir The direction of the data transfer
|
@param DataDir The direction of the data transfer
|
||||||
@param Data The buffer to hold the data
|
@param Data The buffer to hold the data for input or output.
|
||||||
@param TransLen The expected transfer length
|
@param TransLen On input, the expected transfer length.
|
||||||
@param Timeout The time to wait the command to execute
|
On output, the length of data actually transferred.
|
||||||
|
@param Timeout The time to wait for the command to execute
|
||||||
|
|
||||||
@retval EFI_SUCCESS The data transfer succeeded
|
@retval EFI_SUCCESS The data transferred successfully.
|
||||||
|
@retval EFI_SUCCESS No data to transfer
|
||||||
@retval Others Failed to transfer all the data
|
@retval Others Failed to transfer all the data
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
@ -257,7 +267,7 @@ UsbCbiDataTransfer (
|
||||||
UINTN Retry;
|
UINTN Retry;
|
||||||
|
|
||||||
//
|
//
|
||||||
// It's OK if no data to transfer
|
// If no data to transfer, just return EFI_SUCCESS.
|
||||||
//
|
//
|
||||||
if ((DataDir == EfiUsbNoData) || (*TransLen == 0)) {
|
if ((DataDir == EfiUsbNoData) || (*TransLen == 0)) {
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
|
@ -279,7 +289,7 @@ UsbCbiDataTransfer (
|
||||||
Timeout = Timeout / USB_MASS_1_MILLISECOND;
|
Timeout = Timeout / USB_MASS_1_MILLISECOND;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Transfer the data, if the device returns NAK, retry it.
|
// Transfer the data with a loop. The length of data transferred once is restricted.
|
||||||
//
|
//
|
||||||
while (Remain > 0) {
|
while (Remain > 0) {
|
||||||
TransStatus = 0;
|
TransStatus = 0;
|
||||||
|
@ -302,15 +312,15 @@ UsbCbiDataTransfer (
|
||||||
if (TransStatus == EFI_USB_ERR_NAK) {
|
if (TransStatus == EFI_USB_ERR_NAK) {
|
||||||
//
|
//
|
||||||
// The device can NAK the host if either the data/buffer isn't
|
// The device can NAK the host if either the data/buffer isn't
|
||||||
// aviable or the command is in-progress. The data can be partly
|
// aviable or the command is in-progress.
|
||||||
// transferred. The transfer is aborted if several succssive data
|
// If data are partially transferred, we just ignore NAK and continue.
|
||||||
// transfer commands are NAKed.
|
// If all data have been transferred and status is NAK, then we retry for several times.
|
||||||
|
// If retry exceeds the USB_CBI_MAX_RETRY, then return error status.
|
||||||
//
|
//
|
||||||
if (Increment == 0) {
|
if (Increment == 0) {
|
||||||
if (++Retry > USB_CBI_MAX_RETRY) {
|
if (++Retry > USB_CBI_MAX_RETRY) {
|
||||||
goto ON_EXIT;
|
goto ON_EXIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Next += Increment;
|
Next += Increment;
|
||||||
Remain -= Increment;
|
Remain -= Increment;
|
||||||
|
@ -342,13 +352,15 @@ ON_EXIT:
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Get the result of high level command execution from interrupt
|
Gets the result of high level command execution from interrupt endpoint.
|
||||||
endpoint. This function returns the USB transfer status, and
|
|
||||||
put the high level command execution result in Result.
|
This function returns the USB transfer status, and put the high level
|
||||||
|
command execution result in Result.
|
||||||
|
The CBI contains three phases: Command, Data, and Status. This is Status phase.
|
||||||
|
|
||||||
@param UsbCbi The USB CBI protocol
|
@param UsbCbi The USB CBI protocol
|
||||||
@param Timeout The time to wait the command to execute
|
@param Timeout The time to wait for the command to execute
|
||||||
@param Result GC_TODO: add argument description
|
@param Result The result of the command execution.
|
||||||
|
|
||||||
@retval EFI_SUCCESS The high level command execution result is
|
@retval EFI_SUCCESS The high level command execution result is
|
||||||
retrieved in Result.
|
retrieved in Result.
|
||||||
|
@ -404,7 +416,7 @@ UsbCbiGetStatus (
|
||||||
/**
|
/**
|
||||||
Execute USB mass storage command through the CBI0/CBI1 transport protocol.
|
Execute USB mass storage command through the CBI0/CBI1 transport protocol.
|
||||||
|
|
||||||
@param Context The USB CBI device
|
@param Context The USB CBI Protocol.
|
||||||
@param Cmd The command to transfer to device
|
@param Cmd The command to transfer to device
|
||||||
@param CmdLen The length of the command
|
@param CmdLen The length of the command
|
||||||
@param DataDir The direction of data transfer
|
@param DataDir The direction of data transfer
|
||||||
|
@ -414,7 +426,7 @@ UsbCbiGetStatus (
|
||||||
@param Timeout The time to wait
|
@param Timeout The time to wait
|
||||||
@param CmdStatus The result of the command execution
|
@param CmdStatus The result of the command execution
|
||||||
|
|
||||||
@retval EFI_SUCCESS The command is executed OK and result in CmdStatus.
|
@retval EFI_SUCCESS The command is executed successfully.
|
||||||
@retval Other Failed to execute the command
|
@retval Other Failed to execute the command
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
@ -450,7 +462,7 @@ UsbCbiExecCommand (
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Transfer the data, return this status if no interrupt endpoint
|
// Transfer the data. Return this status if no interrupt endpoint
|
||||||
// is used to report the transfer status.
|
// is used to report the transfer status.
|
||||||
//
|
//
|
||||||
TransLen = (UINTN) DataLen;
|
TransLen = (UINTN) DataLen;
|
||||||
|
@ -462,12 +474,12 @@ UsbCbiExecCommand (
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the status, if that succeeds, interpret the result
|
// Get the status. If it succeeds, interpret the result.
|
||||||
//
|
//
|
||||||
Status = UsbCbiGetStatus (UsbCbi, Timeout, &Result);
|
Status = UsbCbiGetStatus (UsbCbi, Timeout, &Result);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
DEBUG ((EFI_D_ERROR, "UsbCbiExecCommand: UsbCbiGetStatus (%r)\n",Status));
|
DEBUG ((EFI_D_ERROR, "UsbCbiExecCommand: UsbCbiGetStatus (%r)\n",Status));
|
||||||
return EFI_DEVICE_ERROR;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UsbCbi->Interface.InterfaceSubClass == USB_MASS_STORE_UFI) {
|
if (UsbCbi->Interface.InterfaceSubClass == USB_MASS_STORE_UFI) {
|
||||||
|
@ -492,7 +504,8 @@ UsbCbiExecCommand (
|
||||||
|
|
||||||
case 0x02:
|
case 0x02:
|
||||||
//
|
//
|
||||||
// Phase Error, response with reset. Fall through to Fail.
|
// Phase Error, response with reset.
|
||||||
|
// No break here to fall through to "Fail".
|
||||||
//
|
//
|
||||||
UsbCbiResetDevice (UsbCbi, FALSE);
|
UsbCbiResetDevice (UsbCbi, FALSE);
|
||||||
|
|
||||||
|
@ -505,7 +518,7 @@ UsbCbiExecCommand (
|
||||||
|
|
||||||
case 0x03:
|
case 0x03:
|
||||||
//
|
//
|
||||||
// Persistent Fail, need to send REQUEST SENSE.
|
// Persistent Fail. Need to send REQUEST SENSE.
|
||||||
//
|
//
|
||||||
*CmdStatus = USB_MASS_CMD_PERSISTENT;
|
*CmdStatus = USB_MASS_CMD_PERSISTENT;
|
||||||
break;
|
break;
|
||||||
|
@ -517,16 +530,18 @@ UsbCbiExecCommand (
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Call the Usb mass storage class transport protocol to
|
Reset the USB mass storage device by CBI protocol.
|
||||||
reset the device. The reset is defined as a Non-Data
|
|
||||||
command. Don't use UsbCbiExecCommand to send the command
|
|
||||||
to device because that may introduce recursive loop.
|
|
||||||
|
|
||||||
@param Context The USB CBI device protocol
|
This function resets the USB mass storage device by CBI protocol.
|
||||||
@param ExtendedVerification The flag controlling the rule of reset
|
The reset is defined as a non-data command. Don't use UsbCbiExecCommand
|
||||||
|
to send the command to device because that may introduce recursive loop.
|
||||||
|
|
||||||
@retval EFI_SUCCESS the device is reset
|
@param Context The USB CBI protocol
|
||||||
@retval Others Failed to reset the device
|
@param ExtendedVerification The flag controlling the rule of reset.
|
||||||
|
Not used here.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The device is reset.
|
||||||
|
@retval Others Failed to reset the device.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
|
@ -562,17 +577,17 @@ UsbCbiResetDevice (
|
||||||
|
|
||||||
//
|
//
|
||||||
// Just retrieve the status and ignore that. Then stall
|
// Just retrieve the status and ignore that. Then stall
|
||||||
// 50ms to wait it complete
|
// 50ms to wait for it to complete.
|
||||||
//
|
//
|
||||||
UsbCbiGetStatus (UsbCbi, Timeout, &Result);
|
UsbCbiGetStatus (UsbCbi, Timeout, &Result);
|
||||||
gBS->Stall (USB_CBI_RESET_DEVICE_STALL);
|
gBS->Stall (USB_CBI_RESET_DEVICE_STALL);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Clear the Bulk-In and Bulk-Out stall condition and
|
// Clear the Bulk-In and Bulk-Out stall condition and init data toggle.
|
||||||
// init data toggle.
|
|
||||||
//
|
//
|
||||||
UsbClearEndpointStall (UsbCbi->UsbIo, UsbCbi->BulkInEndpoint->EndpointAddress);
|
UsbClearEndpointStall (UsbCbi->UsbIo, UsbCbi->BulkInEndpoint->EndpointAddress);
|
||||||
UsbClearEndpointStall (UsbCbi->UsbIo, UsbCbi->BulkOutEndpoint->EndpointAddress);
|
UsbClearEndpointStall (UsbCbi->UsbIo, UsbCbi->BulkOutEndpoint->EndpointAddress);
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -586,30 +601,10 @@ UsbCbiResetDevice (
|
||||||
|
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
UsbCbiFini (
|
UsbCbiCleanUp (
|
||||||
IN VOID *Context
|
IN VOID *Context
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
gBS->FreePool (Context);
|
gBS->FreePool (Context);
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
USB_MASS_TRANSPORT
|
|
||||||
mUsbCbi0Transport = {
|
|
||||||
USB_MASS_STORE_CBI0,
|
|
||||||
UsbCbiInit,
|
|
||||||
UsbCbiExecCommand,
|
|
||||||
UsbCbiResetDevice,
|
|
||||||
NULL,
|
|
||||||
UsbCbiFini
|
|
||||||
};
|
|
||||||
|
|
||||||
USB_MASS_TRANSPORT
|
|
||||||
mUsbCbi1Transport = {
|
|
||||||
USB_MASS_STORE_CBI1,
|
|
||||||
UsbCbiInit,
|
|
||||||
UsbCbiExecCommand,
|
|
||||||
UsbCbiResetDevice,
|
|
||||||
NULL,
|
|
||||||
UsbCbiFini
|
|
||||||
};
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/** @file
|
/** @file
|
||||||
|
Defination for the USB mass storage Control/Bulk/Interrupt (CBI) transport,
|
||||||
Defination for the USB mass storage Control/Bulk/Interrupt transport.
|
according to USB Mass Storage Class Control/Bulk/Interrupt (CBI) Transport, Revision 1.1.
|
||||||
|
|
||||||
Copyright (c) 2007 - 2008, Intel Corporation
|
Copyright (c) 2007 - 2008, Intel Corporation
|
||||||
All rights reserved. This program and the accompanying materials
|
All rights reserved. This program and the accompanying materials
|
||||||
|
@ -16,31 +16,33 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
#ifndef _EFI_USBMASS_CBI_H_
|
#ifndef _EFI_USBMASS_CBI_H_
|
||||||
#define _EFI_USBMASS_CBI_H_
|
#define _EFI_USBMASS_CBI_H_
|
||||||
|
|
||||||
|
extern USB_MASS_TRANSPORT mUsbCbi0Transport;
|
||||||
|
extern USB_MASS_TRANSPORT mUsbCbi1Transport;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
USB_CBI_MAX_PACKET_NUM = 16,
|
USB_CBI_MAX_PACKET_NUM = 16,
|
||||||
USB_CBI_RESET_CMD_LEN = 12,
|
USB_CBI_RESET_CMD_LEN = 12,
|
||||||
|
|
||||||
//
|
//
|
||||||
// Usb Cbi retry C/B/I transport times, set by experience
|
// USB CBI retry C/B/I transport times, set by experience
|
||||||
//
|
//
|
||||||
USB_CBI_MAX_RETRY = 3,
|
USB_CBI_MAX_RETRY = 3,
|
||||||
|
|
||||||
//
|
//
|
||||||
// Usb Cbi wait device reset complete, set by experience
|
// Time to wait for USB CBI reset to complete, set by experience
|
||||||
//
|
//
|
||||||
USB_CBI_RESET_DEVICE_STALL = 50 * USB_MASS_1_MILLISECOND,
|
USB_CBI_RESET_DEVICE_STALL = 50 * USB_MASS_1_MILLISECOND,
|
||||||
|
|
||||||
//
|
//
|
||||||
// Usb Cbi transport timeout, set by experience
|
// USB CBI transport timeout, set by experience
|
||||||
//
|
//
|
||||||
USB_CBI_RESET_DEVICE_TIMEOUT = 1 * USB_MASS_1_SECOND
|
USB_CBI_RESET_DEVICE_TIMEOUT = 1 * USB_MASS_1_SECOND
|
||||||
}USB_CBI_DATA;
|
} USB_CBI_DATA;
|
||||||
|
|
||||||
//
|
|
||||||
// Put Interface at the first field is to make it easy to get by Context, which
|
|
||||||
// could be BOT/CBI Protocol instance
|
|
||||||
//
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
//
|
||||||
|
// Put Interface at the first field to make it easy to distinguish BOT/CBI Protocol instance
|
||||||
|
//
|
||||||
EFI_USB_INTERFACE_DESCRIPTOR Interface;
|
EFI_USB_INTERFACE_DESCRIPTOR Interface;
|
||||||
EFI_USB_ENDPOINT_DESCRIPTOR *BulkInEndpoint;
|
EFI_USB_ENDPOINT_DESCRIPTOR *BulkInEndpoint;
|
||||||
EFI_USB_ENDPOINT_DESCRIPTOR *BulkOutEndpoint;
|
EFI_USB_ENDPOINT_DESCRIPTOR *BulkOutEndpoint;
|
||||||
|
@ -55,6 +57,89 @@ typedef struct {
|
||||||
} USB_CBI_STATUS;
|
} USB_CBI_STATUS;
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
|
|
||||||
extern USB_MASS_TRANSPORT mUsbCbi0Transport;
|
/**
|
||||||
extern USB_MASS_TRANSPORT mUsbCbi1Transport;
|
Initializes USB CBI protocol.
|
||||||
|
|
||||||
|
This function initializes the USB mass storage class CBI protocol.
|
||||||
|
It will save its context which is a USB_CBI_PROTOCOL structure
|
||||||
|
in the Context if Context isn't NULL.
|
||||||
|
|
||||||
|
@param UsbIo The USB I/O Protocol instance
|
||||||
|
@param Context The buffer to save the context to
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The device is successfully initialized.
|
||||||
|
@retval EFI_UNSUPPORTED The transport protocol doesn't support the device.
|
||||||
|
@retval Other The USB CBI initialization fails.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
UsbCbiInit (
|
||||||
|
IN EFI_USB_IO_PROTOCOL *UsbIo,
|
||||||
|
OUT VOID **Context OPTIONAL
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Execute USB mass storage command through the CBI0/CBI1 transport protocol.
|
||||||
|
|
||||||
|
@param Context The USB CBI Protocol.
|
||||||
|
@param Cmd The command to transfer to device
|
||||||
|
@param CmdLen The length of the command
|
||||||
|
@param DataDir The direction of data transfer
|
||||||
|
@param Data The buffer to hold the data
|
||||||
|
@param DataLen The length of the buffer
|
||||||
|
@param Lun Should be 0, this field for bot only
|
||||||
|
@param Timeout The time to wait
|
||||||
|
@param CmdStatus The result of the command execution
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The command is executed successfully.
|
||||||
|
@retval Other Failed to execute the command
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
UsbCbiExecCommand (
|
||||||
|
IN VOID *Context,
|
||||||
|
IN VOID *Cmd,
|
||||||
|
IN UINT8 CmdLen,
|
||||||
|
IN EFI_USB_DATA_DIRECTION DataDir,
|
||||||
|
IN VOID *Data,
|
||||||
|
IN UINT32 DataLen,
|
||||||
|
IN UINT8 Lun,
|
||||||
|
IN UINT32 Timeout,
|
||||||
|
OUT UINT32 *CmdStatus
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Reset the USB mass storage device by CBI protocol.
|
||||||
|
|
||||||
|
This function resets the USB mass storage device by CBI protocol.
|
||||||
|
The reset is defined as a non-data command. Don't use UsbCbiExecCommand
|
||||||
|
to send the command to device because that may introduce recursive loop.
|
||||||
|
|
||||||
|
@param Context The USB CBI protocol
|
||||||
|
@param ExtendedVerification The flag controlling the rule of reset.
|
||||||
|
Not used here.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The device is reset.
|
||||||
|
@retval Others Failed to reset the device.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
UsbCbiResetDevice (
|
||||||
|
IN VOID *Context,
|
||||||
|
IN BOOLEAN ExtendedVerification
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Clean up the CBI protocol's resource.
|
||||||
|
|
||||||
|
@param Context The instance of CBI protocol.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The resource is cleaned up.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
UsbCbiCleanUp (
|
||||||
|
IN VOID *Context
|
||||||
|
);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
/** @file
|
/** @file
|
||||||
|
USB Mass Storage Driver that manages USB Mass Storage Device and produces Block I/O Protocol.
|
||||||
The implementation of USB mass storage class device driver.
|
|
||||||
The command set supported is "USB Mass Storage Specification
|
|
||||||
for Bootability".
|
|
||||||
|
|
||||||
Copyright (c) 2007 - 2008, Intel Corporation
|
Copyright (c) 2007 - 2008, Intel Corporation
|
||||||
All rights reserved. This program and the accompanying materials
|
All rights reserved. This program and the accompanying materials
|
||||||
|
@ -17,6 +14,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
#include "UsbMassImpl.h"
|
#include "UsbMassImpl.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// Array of USB transport interfaces.
|
||||||
|
//
|
||||||
USB_MASS_TRANSPORT *mUsbMassTransport[] = {
|
USB_MASS_TRANSPORT *mUsbMassTransport[] = {
|
||||||
&mUsbCbi0Transport,
|
&mUsbCbi0Transport,
|
||||||
&mUsbCbi1Transport,
|
&mUsbCbi1Transport,
|
||||||
|
@ -24,14 +24,28 @@ USB_MASS_TRANSPORT *mUsbMassTransport[] = {
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
EFI_DRIVER_BINDING_PROTOCOL gUSBMassDriverBinding = {
|
||||||
|
USBMassDriverBindingSupported,
|
||||||
|
USBMassDriverBindingStart,
|
||||||
|
USBMassDriverBindingStop,
|
||||||
|
0x11,
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Reset the block device. ExtendedVerification is ignored for this.
|
Reset the block device.
|
||||||
|
|
||||||
@param This The BLOCK IO protocol
|
This function implements EFI_BLOCK_IO_PROTOCOL.Reset().
|
||||||
@param ExtendedVerification Whether to execute extended verification.
|
It resets the block device hardware.
|
||||||
|
ExtendedVerification is ignored in this implementation.
|
||||||
|
|
||||||
@retval EFI_SUCCESS The device is successfully reseted.
|
@param This Indicates a pointer to the calling context.
|
||||||
@retval Others Failed to reset the device.
|
@param ExtendedVerification Indicates that the driver may perform a more exhaustive
|
||||||
|
verification operation of the device during reset.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The block device was reset.
|
||||||
|
@retval EFI_DEVICE_ERROR The block device is not functioning correctly and could not be reset.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
|
@ -45,9 +59,13 @@ UsbMassReset (
|
||||||
EFI_TPL OldTpl;
|
EFI_TPL OldTpl;
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
|
|
||||||
OldTpl = gBS->RaiseTPL (USB_MASS_TPL);
|
//
|
||||||
|
// Raise TPL to TPL_NOTIFY to serialize all its operations
|
||||||
|
// to protect shared data structures.
|
||||||
|
//
|
||||||
|
OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
|
||||||
|
|
||||||
UsbMass = USB_MASS_DEVICE_FROM_BLOCKIO (This);
|
UsbMass = USB_MASS_DEVICE_FROM_BLOCK_IO (This);
|
||||||
Status = UsbMass->Transport->Reset (UsbMass->Context, ExtendedVerification);
|
Status = UsbMass->Transport->Reset (UsbMass->Context, ExtendedVerification);
|
||||||
|
|
||||||
gBS->RestoreTPL (OldTpl);
|
gBS->RestoreTPL (OldTpl);
|
||||||
|
@ -56,22 +74,27 @@ UsbMassReset (
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Read some blocks of data from the block device.
|
Reads the requested number of blocks from the device.
|
||||||
|
|
||||||
@param This The Block IO protocol
|
This function implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks().
|
||||||
@param MediaId The media's ID of the device for current request
|
It reads the requested number of blocks from the device.
|
||||||
@param Lba The start block number
|
All the blocks are read, or an error is returned.
|
||||||
@param BufferSize The size of buffer to read data in
|
|
||||||
@param Buffer The buffer to read data to
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS The data is successfully read
|
@param This Indicates a pointer to the calling context.
|
||||||
@retval EFI_NO_MEDIA Media isn't present
|
@param MediaId The media ID that the read request is for.
|
||||||
@retval EFI_MEDIA_CHANGED The device media has been changed, that is,
|
@param Lba The starting logical block address to read from on the device.
|
||||||
MediaId changed
|
@param BufferSize The size of the Buffer in bytes.
|
||||||
@retval EFI_INVALID_PARAMETER Some parameters are invalid, such as Buffer is
|
This must be a multiple of the intrinsic block size of the device.
|
||||||
NULL.
|
@param Buffer A pointer to the destination buffer for the data. The caller is
|
||||||
@retval EFI_BAD_BUFFER_SIZE The buffer size isn't a multiple of media's block
|
responsible for either having implicit or explicit ownership of the buffer.
|
||||||
size, or overflow the last block number.
|
|
||||||
|
@retval EFI_SUCCESS The data was read correctly from the device.
|
||||||
|
@retval EFI_DEVICE_ERROR The device reported an error while attempting to perform the read operation.
|
||||||
|
@retval EFI_NO_MEDIA There is no media in the device.
|
||||||
|
@retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
|
||||||
|
@retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the intrinsic block size of the device.
|
||||||
|
@retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
|
||||||
|
or the buffer is not on proper alignment.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
|
@ -90,34 +113,35 @@ UsbMassReadBlocks (
|
||||||
EFI_TPL OldTpl;
|
EFI_TPL OldTpl;
|
||||||
UINTN TotalBlock;
|
UINTN TotalBlock;
|
||||||
|
|
||||||
OldTpl = gBS->RaiseTPL (USB_MASS_TPL);
|
|
||||||
UsbMass = USB_MASS_DEVICE_FROM_BLOCKIO (This);
|
|
||||||
Media = &UsbMass->BlockIoMedia;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// First, validate the parameters
|
// First, validate the parameters
|
||||||
//
|
//
|
||||||
if ((Buffer == NULL) || (BufferSize == 0)) {
|
if ((Buffer == NULL) || (BufferSize == 0)) {
|
||||||
Status = EFI_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
goto ON_EXIT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Raise TPL to TPL_NOTIFY to serialize all its operations
|
||||||
|
// to protect shared data structures.
|
||||||
|
//
|
||||||
|
OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
|
||||||
|
UsbMass = USB_MASS_DEVICE_FROM_BLOCK_IO (This);
|
||||||
|
Media = &UsbMass->BlockIoMedia;
|
||||||
|
|
||||||
//
|
//
|
||||||
// If it is a removable media, such as CD-Rom or Usb-Floppy,
|
// If it is a removable media, such as CD-Rom or Usb-Floppy,
|
||||||
// need to detect the media before each rw. While some of
|
// need to detect the media before each read/write. While some of
|
||||||
// Usb-Flash is marked as removable media.
|
// Usb-Flash is marked as removable media.
|
||||||
//
|
//
|
||||||
//
|
if (Media->RemovableMedia) {
|
||||||
if (Media->RemovableMedia == TRUE) {
|
|
||||||
Status = UsbBootDetectMedia (UsbMass);
|
Status = UsbBootDetectMedia (UsbMass);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
DEBUG ((EFI_D_ERROR, "UsbMassReadBlocks: UsbBootDetectMedia (%r)\n", Status));
|
|
||||||
goto ON_EXIT;
|
goto ON_EXIT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Make sure BlockSize and LBA is consistent with BufferSize
|
// BufferSize must be a multiple of the intrinsic block size of the device.
|
||||||
//
|
//
|
||||||
if ((BufferSize % Media->BlockSize) != 0) {
|
if ((BufferSize % Media->BlockSize) != 0) {
|
||||||
Status = EFI_BAD_BUFFER_SIZE;
|
Status = EFI_BAD_BUFFER_SIZE;
|
||||||
|
@ -126,6 +150,9 @@ UsbMassReadBlocks (
|
||||||
|
|
||||||
TotalBlock = BufferSize / Media->BlockSize;
|
TotalBlock = BufferSize / Media->BlockSize;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Make sure the range to read is valid.
|
||||||
|
//
|
||||||
if (Lba + TotalBlock - 1 > Media->LastBlock) {
|
if (Lba + TotalBlock - 1 > Media->LastBlock) {
|
||||||
Status = EFI_INVALID_PARAMETER;
|
Status = EFI_INVALID_PARAMETER;
|
||||||
goto ON_EXIT;
|
goto ON_EXIT;
|
||||||
|
@ -154,22 +181,28 @@ ON_EXIT:
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Write some blocks of data to the block device.
|
Writes a specified number of blocks to the device.
|
||||||
|
|
||||||
@param This The Block IO protocol
|
This function implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks().
|
||||||
@param MediaId The media's ID of the device for current request
|
It writes a specified number of blocks to the device.
|
||||||
@param Lba The start block number
|
All blocks are written, or an error is returned.
|
||||||
@param BufferSize The size of buffer to write data to
|
|
||||||
@param Buffer The buffer to write data to
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS The data is successfully written
|
@param This Indicates a pointer to the calling context.
|
||||||
@retval EFI_NO_MEDIA Media isn't present
|
@param MediaId The media ID that the write request is for.
|
||||||
@retval EFI_MEDIA_CHANGED The device media has been changed, that is,
|
@param Lba The starting logical block address to be written.
|
||||||
MediaId changed
|
@param BufferSize The size of the Buffer in bytes.
|
||||||
@retval EFI_INVALID_PARAMETER Some parameters are invalid, such as Buffer is
|
This must be a multiple of the intrinsic block size of the device.
|
||||||
NULL.
|
@param Buffer Pointer to the source buffer for the data.
|
||||||
@retval EFI_BAD_BUFFER_SIZE The buffer size isn't a multiple of media's block
|
|
||||||
size,
|
@retval EFI_SUCCESS The data were written correctly to the device.
|
||||||
|
@retval EFI_WRITE_PROTECTED The device cannot be written to.
|
||||||
|
@retval EFI_NO_MEDIA There is no media in the device.
|
||||||
|
@retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
|
||||||
|
@retval EFI_DEVICE_ERROR The device reported an error while attempting to perform the write operation.
|
||||||
|
@retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the intrinsic
|
||||||
|
block size of the device.
|
||||||
|
@retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
|
||||||
|
or the buffer is not on proper alignment.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
|
@ -188,34 +221,35 @@ UsbMassWriteBlocks (
|
||||||
EFI_TPL OldTpl;
|
EFI_TPL OldTpl;
|
||||||
UINTN TotalBlock;
|
UINTN TotalBlock;
|
||||||
|
|
||||||
OldTpl = gBS->RaiseTPL (USB_MASS_TPL);
|
|
||||||
UsbMass = USB_MASS_DEVICE_FROM_BLOCKIO (This);
|
|
||||||
Media = &UsbMass->BlockIoMedia;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// First, validate the parameters
|
// First, validate the parameters
|
||||||
//
|
//
|
||||||
if ((Buffer == NULL) || (BufferSize == 0)) {
|
if ((Buffer == NULL) || (BufferSize == 0)) {
|
||||||
Status = EFI_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
goto ON_EXIT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Raise TPL to TPL_NOTIFY to serialize all its operations
|
||||||
|
// to protect shared data structures.
|
||||||
|
//
|
||||||
|
OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
|
||||||
|
UsbMass = USB_MASS_DEVICE_FROM_BLOCK_IO (This);
|
||||||
|
Media = &UsbMass->BlockIoMedia;
|
||||||
|
|
||||||
//
|
//
|
||||||
// If it is a removable media, such as CD-Rom or Usb-Floppy,
|
// If it is a removable media, such as CD-Rom or Usb-Floppy,
|
||||||
// need to detect the media before each rw. While some of
|
// need to detect the media before each read/write. Some of
|
||||||
// Usb-Flash is marked as removable media.
|
// USB Flash is marked as removable media.
|
||||||
//
|
//
|
||||||
//
|
if (Media->RemovableMedia) {
|
||||||
if (Media->RemovableMedia == TRUE) {
|
|
||||||
Status = UsbBootDetectMedia (UsbMass);
|
Status = UsbBootDetectMedia (UsbMass);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
DEBUG ((EFI_D_ERROR, "UsbMassWriteBlocks: UsbBootDetectMedia (%r)\n", Status));
|
|
||||||
goto ON_EXIT;
|
goto ON_EXIT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Make sure BlockSize and LBA is consistent with BufferSize
|
// BufferSize must be a multiple of the intrinsic block size of the device.
|
||||||
//
|
//
|
||||||
if ((BufferSize % Media->BlockSize) != 0) {
|
if ((BufferSize % Media->BlockSize) != 0) {
|
||||||
Status = EFI_BAD_BUFFER_SIZE;
|
Status = EFI_BAD_BUFFER_SIZE;
|
||||||
|
@ -224,6 +258,9 @@ UsbMassWriteBlocks (
|
||||||
|
|
||||||
TotalBlock = BufferSize / Media->BlockSize;
|
TotalBlock = BufferSize / Media->BlockSize;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Make sure the range to write is valid.
|
||||||
|
//
|
||||||
if (Lba + TotalBlock - 1 > Media->LastBlock) {
|
if (Lba + TotalBlock - 1 > Media->LastBlock) {
|
||||||
Status = EFI_INVALID_PARAMETER;
|
Status = EFI_INVALID_PARAMETER;
|
||||||
goto ON_EXIT;
|
goto ON_EXIT;
|
||||||
|
@ -255,12 +292,17 @@ ON_EXIT:
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Flush the cached writes to disks. USB mass storage device doesn't
|
Flushes all modified data to a physical block device.
|
||||||
support write cache, so return EFI_SUCCESS directly.
|
|
||||||
|
|
||||||
@param This The BLOCK IO protocol
|
This function implements EFI_BLOCK_IO_PROTOCOL.FlushBlocks().
|
||||||
|
USB mass storage device doesn't support write cache,
|
||||||
|
so return EFI_SUCCESS directly.
|
||||||
|
|
||||||
@retval EFI_SUCCESS Always returns success
|
@param This Indicates a pointer to the calling context.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS All outstanding data were written correctly to the device.
|
||||||
|
@retval EFI_DEVICE_ERROR The device reported an error while attempting to write data.
|
||||||
|
@retval EFI_NO_MEDIA There is no media in the device.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
|
@ -273,12 +315,11 @@ UsbMassFlushBlocks (
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Retrieve the media parameters such as disk geometric for the
|
Initialize the media parameter data for EFI_BLOCK_IO_MEDIA of Block I/O Protocol.
|
||||||
device's BLOCK IO protocol.
|
|
||||||
|
|
||||||
@param UsbMass The USB mass storage device
|
@param UsbMass The USB mass storage device
|
||||||
|
|
||||||
@retval EFI_SUCCESS The media parameters is updated successfully.
|
@retval EFI_SUCCESS The media parameters are updated successfully.
|
||||||
@retval Others Failed to get the media parameters.
|
@retval Others Failed to get the media parameters.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
@ -294,18 +335,8 @@ UsbMassInitMedia (
|
||||||
Media = &UsbMass->BlockIoMedia;
|
Media = &UsbMass->BlockIoMedia;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Initialize the MediaPrsent/ReadOnly and others to the default.
|
// Fields of EFI_BLOCK_IO_MEDIA are defined in UEFI 2.0 spec,
|
||||||
// We are not forced to get it right at this time, check UEFI2.0
|
// section for Block I/O Protocol.
|
||||||
// spec for more information:
|
|
||||||
//
|
|
||||||
// MediaPresent: This field shows the media present status as
|
|
||||||
// of the most recent ReadBlocks or WriteBlocks call.
|
|
||||||
//
|
|
||||||
// ReadOnly : This field shows the read-only status as of the
|
|
||||||
// recent WriteBlocks call.
|
|
||||||
//
|
|
||||||
// but remember to update MediaId/MediaPresent/ReadOnly status
|
|
||||||
// after ReadBlocks and WriteBlocks
|
|
||||||
//
|
//
|
||||||
Media->MediaPresent = FALSE;
|
Media->MediaPresent = FALSE;
|
||||||
Media->LogicalPartition = FALSE;
|
Media->LogicalPartition = FALSE;
|
||||||
|
@ -323,9 +354,7 @@ UsbMassInitMedia (
|
||||||
for (Index = 0; Index < USB_BOOT_INIT_MEDIA_RETRY; Index++) {
|
for (Index = 0; Index < USB_BOOT_INIT_MEDIA_RETRY; Index++) {
|
||||||
|
|
||||||
Status = UsbBootGetParams (UsbMass);
|
Status = UsbBootGetParams (UsbMass);
|
||||||
if ((Status != EFI_MEDIA_CHANGED)
|
if ((Status != EFI_MEDIA_CHANGED) && (Status != EFI_NOT_READY) && (Status != EFI_TIMEOUT)) {
|
||||||
&& (Status != EFI_NOT_READY)
|
|
||||||
&& (Status != EFI_TIMEOUT)) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,14 +362,16 @@ UsbMassInitMedia (
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
gBS->Stall (USB_BOOT_RETRY_UNIT_READY_STALL * (Index + 1));
|
gBS->Stall (USB_BOOT_RETRY_UNIT_READY_STALL * (Index + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Initilize the transport.
|
Initilize the USB Mass Storage transport.
|
||||||
|
|
||||||
|
This function tries to find the matching USB Mass Storage transport
|
||||||
|
protocol for USB device. If found, initializes the matching transport.
|
||||||
|
|
||||||
@param This The USB mass driver's driver binding.
|
@param This The USB mass driver's driver binding.
|
||||||
@param Controller The device to test.
|
@param Controller The device to test.
|
||||||
|
@ -349,6 +380,7 @@ UsbMassInitMedia (
|
||||||
@param MaxLun Get the MaxLun if is BOT dev.
|
@param MaxLun Get the MaxLun if is BOT dev.
|
||||||
|
|
||||||
@retval EFI_SUCCESS The initialization is successful.
|
@retval EFI_SUCCESS The initialization is successful.
|
||||||
|
@retval EFI_UNSUPPORTED No matching transport protocol is found.
|
||||||
@retval Others Failed to initialize dev.
|
@retval Others Failed to initialize dev.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
@ -376,18 +408,22 @@ UsbMassInitTransport (
|
||||||
);
|
);
|
||||||
|
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
DEBUG ((EFI_D_ERROR, "UsbMassInitTransport: OpenUsbIoProtocol By Driver (%r)\n", Status));
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface);
|
Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
DEBUG ((EFI_D_ERROR, "UsbMassInitTransport: UsbIo->UsbGetInterfaceDescriptor (%r)\n", Status));
|
|
||||||
goto ON_EXIT;
|
goto ON_EXIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = EFI_UNSUPPORTED;
|
Status = EFI_UNSUPPORTED;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Traverse the USB_MASS_TRANSPORT arrary and try to find the
|
||||||
|
// matching transport protocol.
|
||||||
|
// If not found, return EFI_UNSUPPORTED.
|
||||||
|
// If found, execute USB_MASS_TRANSPORT.Init() to initialize the transport context.
|
||||||
|
//
|
||||||
for (Index = 0; mUsbMassTransport[Index] != NULL; Index++) {
|
for (Index = 0; mUsbMassTransport[Index] != NULL; Index++) {
|
||||||
*Transport = mUsbMassTransport[Index];
|
*Transport = mUsbMassTransport[Index];
|
||||||
|
|
||||||
|
@ -398,17 +434,16 @@ UsbMassInitTransport (
|
||||||
}
|
}
|
||||||
|
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
DEBUG ((EFI_D_ERROR, "UsbMassInitTransport: Transport->Init (%r)\n", Status));
|
|
||||||
goto ON_EXIT;
|
goto ON_EXIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// For bot device, try to get max lun.
|
// For BOT device, try to get its max LUN.
|
||||||
// If maxlun=0, then non-lun device, else multi-lun device.
|
// If max LUN is 0, then it is a non-lun device.
|
||||||
|
// Otherwise, it is a multi-lun device.
|
||||||
//
|
//
|
||||||
if ((*Transport)->Protocol == USB_MASS_STORE_BOT) {
|
if ((*Transport)->Protocol == USB_MASS_STORE_BOT) {
|
||||||
(*Transport)->GetMaxLun (*Context, MaxLun);
|
(*Transport)->GetMaxLun (*Context, MaxLun);
|
||||||
DEBUG ((EFI_D_INFO, "UsbMassInitTransport: GetMaxLun = %d\n", *MaxLun));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ON_EXIT:
|
ON_EXIT:
|
||||||
|
@ -687,13 +722,12 @@ ON_ERROR:
|
||||||
/**
|
/**
|
||||||
Check whether the controller is a supported USB mass storage.
|
Check whether the controller is a supported USB mass storage.
|
||||||
|
|
||||||
@param This The USB mass driver's driver binding.
|
@param This The USB mass storage driver binding protocol.
|
||||||
@param Controller The device to test against.
|
@param Controller The controller handle to check.
|
||||||
@param RemainingDevicePath The remaining device path
|
@param RemainingDevicePath The remaining device path.
|
||||||
|
|
||||||
@retval EFI_SUCCESS This device is a supported USB mass storage.
|
@retval EFI_SUCCESS The driver supports this controller.
|
||||||
@retval EFI_UNSUPPORTED The device isn't supported
|
@retval other This device isn't supported.
|
||||||
@retval Others Some error happened.
|
|
||||||
|
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
|
@ -708,11 +742,8 @@ USBMassDriverBindingSupported (
|
||||||
EFI_USB_INTERFACE_DESCRIPTOR Interface;
|
EFI_USB_INTERFACE_DESCRIPTOR Interface;
|
||||||
USB_MASS_TRANSPORT *Transport;
|
USB_MASS_TRANSPORT *Transport;
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
INTN Index;
|
UINTN Index;
|
||||||
|
|
||||||
//
|
|
||||||
// Check whether the controller support USB_IO
|
|
||||||
//
|
|
||||||
Status = gBS->OpenProtocol (
|
Status = gBS->OpenProtocol (
|
||||||
Controller,
|
Controller,
|
||||||
&gEfiUsbIoProtocolGuid,
|
&gEfiUsbIoProtocolGuid,
|
||||||
|
@ -726,7 +757,7 @@ USBMassDriverBindingSupported (
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the interface to check the USB class and find a transport
|
// Get the interface descriptor to check the USB class and find a transport
|
||||||
// protocol handler.
|
// protocol handler.
|
||||||
//
|
//
|
||||||
Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface);
|
Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface);
|
||||||
|
@ -740,6 +771,12 @@ USBMassDriverBindingSupported (
|
||||||
goto ON_EXIT;
|
goto ON_EXIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Traverse the USB_MASS_TRANSPORT arrary and try to find the
|
||||||
|
// matching transport method.
|
||||||
|
// If not found, return EFI_UNSUPPORTED.
|
||||||
|
// If found, execute USB_MASS_TRANSPORT.Init() to initialize the transport context.
|
||||||
|
//
|
||||||
for (Index = 0; mUsbMassTransport[Index] != NULL; Index++) {
|
for (Index = 0; mUsbMassTransport[Index] != NULL; Index++) {
|
||||||
Transport = mUsbMassTransport[Index];
|
Transport = mUsbMassTransport[Index];
|
||||||
if (Interface.InterfaceProtocol == Transport->Protocol) {
|
if (Interface.InterfaceProtocol == Transport->Protocol) {
|
||||||
|
@ -748,31 +785,34 @@ USBMassDriverBindingSupported (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG ((EFI_D_INFO, "Found a USB mass store device %r\n", Status));
|
|
||||||
|
|
||||||
ON_EXIT:
|
ON_EXIT:
|
||||||
gBS->CloseProtocol (
|
gBS->CloseProtocol (
|
||||||
Controller,
|
Controller,
|
||||||
&gEfiUsbIoProtocolGuid,
|
&gEfiUsbIoProtocolGuid,
|
||||||
This->DriverBindingHandle,
|
This->DriverBindingHandle,
|
||||||
Controller
|
Controller
|
||||||
);
|
);
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Start the USB mass storage device on the controller. It will
|
Starts the USB mass storage device with this driver.
|
||||||
install a BLOCK_IO protocol on the device if everything is OK.
|
|
||||||
|
|
||||||
@param This The USB mass storage driver binding.
|
This function consumes USB I/O Portocol, intializes USB mass storage device,
|
||||||
|
installs Block I/O Protocol, and submits Asynchronous Interrupt
|
||||||
|
Transfer to manage the USB mass storage device.
|
||||||
|
|
||||||
|
@param This The USB mass storage driver binding protocol.
|
||||||
@param Controller The USB mass storage device to start on
|
@param Controller The USB mass storage device to start on
|
||||||
@param RemainingDevicePath The remaining device path.
|
@param RemainingDevicePath The remaining device path.
|
||||||
|
|
||||||
@retval EFI_SUCCESS The driver has started on the device.
|
@retval EFI_SUCCESS This driver supports this device.
|
||||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory
|
@retval EFI_UNSUPPORTED This driver does not support this device.
|
||||||
@retval Others Failed to start the driver on the device.
|
@retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
|
||||||
|
@retval EFI_ALREADY_STARTED This driver has been started.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
|
@ -831,7 +871,7 @@ USBMassDriverBindingStart (
|
||||||
//
|
//
|
||||||
// Try best to initialize all LUNs, and return success only if one of LUNs successed to initialized.
|
// Try best to initialize all LUNs, and return success only if one of LUNs successed to initialized.
|
||||||
//
|
//
|
||||||
Status = UsbMassInitMultiLun(This, Controller, Transport, Context, DevicePath, MaxLun);
|
Status = UsbMassInitMultiLun (This, Controller, Transport, Context, DevicePath, MaxLun);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
gBS->CloseProtocol (
|
gBS->CloseProtocol (
|
||||||
Controller,
|
Controller,
|
||||||
|
@ -913,7 +953,7 @@ USBMassDriverBindingStop (
|
||||||
// This is a 1st type handle(non-multi-lun), which only needs uninstall
|
// This is a 1st type handle(non-multi-lun), which only needs uninstall
|
||||||
// blockio protocol, close usbio protocol and free mass device.
|
// blockio protocol, close usbio protocol and free mass device.
|
||||||
//
|
//
|
||||||
UsbMass = USB_MASS_DEVICE_FROM_BLOCKIO (BlockIo);
|
UsbMass = USB_MASS_DEVICE_FROM_BLOCK_IO (BlockIo);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Uninstall Block I/O protocol from the device handle,
|
// Uninstall Block I/O protocol from the device handle,
|
||||||
|
@ -935,7 +975,7 @@ USBMassDriverBindingStop (
|
||||||
Controller
|
Controller
|
||||||
);
|
);
|
||||||
|
|
||||||
UsbMass->Transport->Fini (UsbMass->Context);
|
UsbMass->Transport->CleanUp (UsbMass->Context);
|
||||||
gBS->FreePool (UsbMass);
|
gBS->FreePool (UsbMass);
|
||||||
|
|
||||||
DEBUG ((EFI_D_INFO, "Success to stop non-multi-lun root handle\n"));
|
DEBUG ((EFI_D_INFO, "Success to stop non-multi-lun root handle\n"));
|
||||||
|
@ -965,7 +1005,7 @@ USBMassDriverBindingStop (
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
UsbMass = USB_MASS_DEVICE_FROM_BLOCKIO (BlockIo);
|
UsbMass = USB_MASS_DEVICE_FROM_BLOCK_IO (BlockIo);
|
||||||
|
|
||||||
gBS->CloseProtocol (
|
gBS->CloseProtocol (
|
||||||
Controller,
|
Controller,
|
||||||
|
@ -1003,7 +1043,7 @@ USBMassDriverBindingStop (
|
||||||
// Success to stop this multi-lun handle, so go on next child.
|
// Success to stop this multi-lun handle, so go on next child.
|
||||||
//
|
//
|
||||||
if (((Index + 1) == NumberOfChildren) && AllChildrenStopped) {
|
if (((Index + 1) == NumberOfChildren) && AllChildrenStopped) {
|
||||||
UsbMass->Transport->Fini (UsbMass->Context);
|
UsbMass->Transport->CleanUp (UsbMass->Context);
|
||||||
}
|
}
|
||||||
gBS->FreePool (UsbMass);
|
gBS->FreePool (UsbMass);
|
||||||
}
|
}
|
||||||
|
@ -1017,15 +1057,6 @@ USBMassDriverBindingStop (
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
EFI_DRIVER_BINDING_PROTOCOL gUSBMassDriverBinding = {
|
|
||||||
USBMassDriverBindingSupported,
|
|
||||||
USBMassDriverBindingStart,
|
|
||||||
USBMassDriverBindingStop,
|
|
||||||
0x11,
|
|
||||||
NULL,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The entry point for the driver, which will install the driver binding and
|
The entry point for the driver, which will install the driver binding and
|
||||||
component name protocol.
|
component name protocol.
|
||||||
|
@ -1057,6 +1088,7 @@ USBMassStorageEntryPoint (
|
||||||
&gUsbMassStorageComponentName,
|
&gUsbMassStorageComponentName,
|
||||||
&gUsbMassStorageComponentName2
|
&gUsbMassStorageComponentName2
|
||||||
);
|
);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
return Status;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,16 +23,8 @@ typedef struct _USB_MASS_DEVICE USB_MASS_DEVICE;
|
||||||
#include "UsbMassCbi.h"
|
#include "UsbMassCbi.h"
|
||||||
#include "UsbMassBoot.h"
|
#include "UsbMassBoot.h"
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// MassStorage raises TPL to TPL_NOTIFY to serialize all its operations
|
|
||||||
// to protect shared data structures.
|
|
||||||
//
|
|
||||||
#define USB_MASS_TPL TPL_NOTIFY
|
|
||||||
|
|
||||||
#define USB_MASS_SIGNATURE SIGNATURE_32 ('U', 's', 'b', 'M')
|
#define USB_MASS_SIGNATURE SIGNATURE_32 ('U', 's', 'b', 'M')
|
||||||
|
|
||||||
|
|
||||||
struct _USB_MASS_DEVICE {
|
struct _USB_MASS_DEVICE {
|
||||||
UINT32 Signature;
|
UINT32 Signature;
|
||||||
EFI_HANDLE Controller;
|
EFI_HANDLE Controller;
|
||||||
|
@ -47,10 +39,196 @@ struct _USB_MASS_DEVICE {
|
||||||
VOID *Context; // Opaque storage for mass transport
|
VOID *Context; // Opaque storage for mass transport
|
||||||
};
|
};
|
||||||
|
|
||||||
#define USB_MASS_DEVICE_FROM_BLOCKIO(a) \
|
#define USB_MASS_DEVICE_FROM_BLOCK_IO(a) \
|
||||||
CR (a, USB_MASS_DEVICE, BlockIo, USB_MASS_SIGNATURE)
|
CR (a, USB_MASS_DEVICE, BlockIo, USB_MASS_SIGNATURE)
|
||||||
|
|
||||||
extern EFI_COMPONENT_NAME_PROTOCOL gUsbMassStorageComponentName;
|
extern EFI_COMPONENT_NAME_PROTOCOL gUsbMassStorageComponentName;
|
||||||
extern EFI_COMPONENT_NAME2_PROTOCOL gUsbMassStorageComponentName2;
|
extern EFI_COMPONENT_NAME2_PROTOCOL gUsbMassStorageComponentName2;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Functions for Driver Binding Protocol
|
||||||
|
//
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check whether the controller is a supported USB mass storage.
|
||||||
|
|
||||||
|
@param This The USB mass storage driver binding protocol.
|
||||||
|
@param Controller The controller handle to check.
|
||||||
|
@param RemainingDevicePath The remaining device path.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The driver supports this controller.
|
||||||
|
@retval other This device isn't supported.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
USBMassDriverBindingSupported (
|
||||||
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||||
|
IN EFI_HANDLE Controller,
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Starts the USB mass storage device with this driver.
|
||||||
|
|
||||||
|
This function consumes USB I/O Portocol, intializes USB mass storage device,
|
||||||
|
installs Block I/O Protocol, and submits Asynchronous Interrupt
|
||||||
|
Transfer to manage the USB mass storage device.
|
||||||
|
|
||||||
|
@param This The USB mass storage driver binding protocol.
|
||||||
|
@param Controller The USB mass storage device to start on
|
||||||
|
@param RemainingDevicePath The remaining device path.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS This driver supports this device.
|
||||||
|
@retval EFI_UNSUPPORTED This driver does not support this device.
|
||||||
|
@retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
|
||||||
|
@retval EFI_ALREADY_STARTED This driver has been started.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
USBMassDriverBindingStart (
|
||||||
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||||
|
IN EFI_HANDLE Controller,
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Stop controlling the device.
|
||||||
|
|
||||||
|
@param This The USB mass storage driver binding
|
||||||
|
@param Controller The device controller controlled by the driver.
|
||||||
|
@param NumberOfChildren The number of children of this device
|
||||||
|
@param ChildHandleBuffer The buffer of children handle.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The driver stopped from controlling the device.
|
||||||
|
@retval Others Failed to stop the driver
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
USBMassDriverBindingStop (
|
||||||
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||||
|
IN EFI_HANDLE Controller,
|
||||||
|
IN UINTN NumberOfChildren,
|
||||||
|
IN EFI_HANDLE *ChildHandleBuffer
|
||||||
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Functions for Block I/O Protocol
|
||||||
|
//
|
||||||
|
|
||||||
|
/**
|
||||||
|
Reset the block device.
|
||||||
|
|
||||||
|
This function implements EFI_BLOCK_IO_PROTOCOL.Reset().
|
||||||
|
It resets the block device hardware.
|
||||||
|
ExtendedVerification is ignored in this implementation.
|
||||||
|
|
||||||
|
@param This Indicates a pointer to the calling context.
|
||||||
|
@param ExtendedVerification Indicates that the driver may perform a more exhaustive
|
||||||
|
verification operation of the device during reset.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The block device was reset.
|
||||||
|
@retval EFI_DEVICE_ERROR The block device is not functioning correctly and could not be reset.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
UsbMassReset (
|
||||||
|
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||||
|
IN BOOLEAN ExtendedVerification
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Reads the requested number of blocks from the device.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
@param This Indicates a pointer to the calling context.
|
||||||
|
@param MediaId The media ID that the read request is for.
|
||||||
|
@param Lba The starting logical block address to read from on the device.
|
||||||
|
@param BufferSize The size of the Buffer in bytes.
|
||||||
|
This must be a multiple of the intrinsic block size of the device.
|
||||||
|
@param Buffer A pointer to the destination buffer for the data. The caller is
|
||||||
|
responsible for either having implicit or explicit ownership of the buffer.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The data was read correctly from the device.
|
||||||
|
@retval EFI_DEVICE_ERROR The device reported an error while attempting to perform the read operation.
|
||||||
|
@retval EFI_NO_MEDIA There is no media in the device.
|
||||||
|
@retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
|
||||||
|
@retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the intrinsic block size of the device.
|
||||||
|
@retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
|
||||||
|
or the buffer is not on proper alignment.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
UsbMassReadBlocks (
|
||||||
|
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||||
|
IN UINT32 MediaId,
|
||||||
|
IN EFI_LBA Lba,
|
||||||
|
IN UINTN BufferSize,
|
||||||
|
OUT VOID *Buffer
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Writes a specified number of blocks to the device.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
@param This Indicates a pointer to the calling context.
|
||||||
|
@param MediaId The media ID that the write request is for.
|
||||||
|
@param Lba The starting logical block address to be written.
|
||||||
|
@param BufferSize The size of the Buffer in bytes.
|
||||||
|
This must be a multiple of the intrinsic block size of the device.
|
||||||
|
@param Buffer Pointer to the source buffer for the data.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The data were written correctly to the device.
|
||||||
|
@retval EFI_WRITE_PROTECTED The device cannot be written to.
|
||||||
|
@retval EFI_NO_MEDIA There is no media in the device.
|
||||||
|
@retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
|
||||||
|
@retval EFI_DEVICE_ERROR The device reported an error while attempting to perform the write operation.
|
||||||
|
@retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the intrinsic
|
||||||
|
block size of the device.
|
||||||
|
@retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
|
||||||
|
or the buffer is not on proper alignment.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
UsbMassWriteBlocks (
|
||||||
|
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||||
|
IN UINT32 MediaId,
|
||||||
|
IN EFI_LBA Lba,
|
||||||
|
IN UINTN BufferSize,
|
||||||
|
IN VOID *Buffer
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Flushes all modified data to a physical block device.
|
||||||
|
|
||||||
|
This function implements EFI_BLOCK_IO_PROTOCOL.FlushBlocks().
|
||||||
|
USB mass storage device doesn't support write cache,
|
||||||
|
so return EFI_SUCCESS directly.
|
||||||
|
|
||||||
|
@param This Indicates a pointer to the calling context.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS All outstanding data were written correctly to the device.
|
||||||
|
@retval EFI_DEVICE_ERROR The device reported an error while attempting to write data.
|
||||||
|
@retval EFI_NO_MEDIA There is no media in the device.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
UsbMassFlushBlocks (
|
||||||
|
IN EFI_BLOCK_IO_PROTOCOL *This
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue