mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-23 13:44:33 +02:00
[Description]:
UsbMassStorage driver need support multi-lun feature. [Impaction]: UsbMassStorageDxe. [Reference Info]: EDK tracker 1143 - UsbMassStorage driver need support multi-lun feature. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@5375 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
bd1d34eecf
commit
c7e39923c0
@ -1,6 +1,6 @@
|
|||||||
/** @file
|
/** @file
|
||||||
|
|
||||||
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
|
||||||
@ -36,6 +36,7 @@ Revision History
|
|||||||
|
|
||||||
#include <Protocol/BlockIo.h>
|
#include <Protocol/BlockIo.h>
|
||||||
#include <Protocol/UsbIo.h>
|
#include <Protocol/UsbIo.h>
|
||||||
|
#include <Protocol/DevicePath.h>
|
||||||
|
|
||||||
#include <Library/DebugLib.h>
|
#include <Library/DebugLib.h>
|
||||||
#include <Library/BaseMemoryLib.h>
|
#include <Library/BaseMemoryLib.h>
|
||||||
@ -43,6 +44,7 @@ Revision History
|
|||||||
#include <Library/UefiBootServicesTableLib.h>
|
#include <Library/UefiBootServicesTableLib.h>
|
||||||
#include <Library/UefiLib.h>
|
#include <Library/UefiLib.h>
|
||||||
#include <Library/MemoryAllocationLib.h>
|
#include <Library/MemoryAllocationLib.h>
|
||||||
|
#include <Library/DevicePathLib.h>
|
||||||
|
|
||||||
#define USB_IS_IN_ENDPOINT(EndPointAddr) (((EndPointAddr) & 0x80) == 0x80)
|
#define USB_IS_IN_ENDPOINT(EndPointAddr) (((EndPointAddr) & 0x80) == 0x80)
|
||||||
#define USB_IS_OUT_ENDPOINT(EndPointAddr) (((EndPointAddr) & 0x80) == 0)
|
#define USB_IS_OUT_ENDPOINT(EndPointAddr) (((EndPointAddr) & 0x80) == 0)
|
||||||
@ -85,7 +87,6 @@ typedef
|
|||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
(*USB_MASS_INIT_TRANSPORT) (
|
(*USB_MASS_INIT_TRANSPORT) (
|
||||||
IN EFI_USB_IO_PROTOCOL *Usb,
|
IN EFI_USB_IO_PROTOCOL *Usb,
|
||||||
IN EFI_HANDLE Controller,
|
|
||||||
OUT VOID **Context OPTIONAL
|
OUT VOID **Context OPTIONAL
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -98,6 +99,7 @@ EFI_STATUS
|
|||||||
IN EFI_USB_DATA_DIRECTION DataDir,
|
IN EFI_USB_DATA_DIRECTION DataDir,
|
||||||
IN VOID *Data,
|
IN VOID *Data,
|
||||||
IN UINT32 DataLen,
|
IN UINT32 DataLen,
|
||||||
|
IN UINT8 Lun,
|
||||||
IN UINT32 Timeout,
|
IN UINT32 Timeout,
|
||||||
OUT UINT32 *CmdStatus
|
OUT UINT32 *CmdStatus
|
||||||
);
|
);
|
||||||
@ -109,6 +111,13 @@ EFI_STATUS
|
|||||||
IN BOOLEAN ExtendedVerification
|
IN BOOLEAN ExtendedVerification
|
||||||
);
|
);
|
||||||
|
|
||||||
|
typedef
|
||||||
|
EFI_STATUS
|
||||||
|
(*USB_MASS_GET_MAX_LUN) (
|
||||||
|
IN VOID *Context,
|
||||||
|
IN UINT8 *MaxLun
|
||||||
|
);
|
||||||
|
|
||||||
typedef
|
typedef
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
(*USB_MASS_FINI) (
|
(*USB_MASS_FINI) (
|
||||||
@ -128,6 +137,7 @@ typedef struct {
|
|||||||
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_FINI Fini; // Clean up the resources.
|
USB_MASS_FINI Fini; // Clean up the resources.
|
||||||
} USB_MASS_TRANSPORT;
|
} USB_MASS_TRANSPORT;
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/** @file
|
/** @file
|
||||||
|
|
||||||
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
|
||||||
@ -163,6 +163,7 @@ UsbBootRequestSense (
|
|||||||
EfiUsbDataIn,
|
EfiUsbDataIn,
|
||||||
&SenseData,
|
&SenseData,
|
||||||
sizeof (USB_BOOT_REQUEST_SENSE_DATA),
|
sizeof (USB_BOOT_REQUEST_SENSE_DATA),
|
||||||
|
UsbMass->Lun,
|
||||||
USB_BOOT_GENERAL_CMD_TIMEOUT,
|
USB_BOOT_GENERAL_CMD_TIMEOUT,
|
||||||
&CmdResult
|
&CmdResult
|
||||||
);
|
);
|
||||||
@ -280,6 +281,7 @@ UsbBootExecCmd (
|
|||||||
DataDir,
|
DataDir,
|
||||||
Data,
|
Data,
|
||||||
DataLen,
|
DataLen,
|
||||||
|
UsbMass->Lun,
|
||||||
Timeout,
|
Timeout,
|
||||||
&CmdResult
|
&CmdResult
|
||||||
);
|
);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/** @file
|
/** @file
|
||||||
|
|
||||||
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
|
||||||
@ -39,7 +39,6 @@ UsbBotResetDevice (
|
|||||||
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 IO protocol to use
|
||||||
@param Controller The controller to init
|
|
||||||
@param Context The variable to save the context to
|
@param Context The variable to save the context to
|
||||||
|
|
||||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory
|
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory
|
||||||
@ -51,7 +50,6 @@ STATIC
|
|||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
UsbBotInit (
|
UsbBotInit (
|
||||||
IN EFI_USB_IO_PROTOCOL * UsbIo,
|
IN EFI_USB_IO_PROTOCOL * UsbIo,
|
||||||
IN EFI_HANDLE Controller,
|
|
||||||
OUT VOID **Context OPTIONAL
|
OUT VOID **Context OPTIONAL
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@ -149,6 +147,7 @@ ON_ERROR:
|
|||||||
@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
|
||||||
|
|
||||||
@retval EFI_NOT_READY The device return NAK to the transfer
|
@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.
|
||||||
@ -162,7 +161,8 @@ UsbBotSendCommand (
|
|||||||
IN UINT8 *Cmd,
|
IN UINT8 *Cmd,
|
||||||
IN UINT8 CmdLen,
|
IN UINT8 CmdLen,
|
||||||
IN EFI_USB_DATA_DIRECTION DataDir,
|
IN EFI_USB_DATA_DIRECTION DataDir,
|
||||||
IN UINT32 TransLen
|
IN UINT32 TransLen,
|
||||||
|
IN UINT8 Lun
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
USB_BOT_CBW Cbw;
|
USB_BOT_CBW Cbw;
|
||||||
@ -180,7 +180,7 @@ UsbBotSendCommand (
|
|||||||
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) ? 0x80 : 0);
|
||||||
Cbw.Lun = 0;
|
Cbw.Lun = Lun;
|
||||||
Cbw.CmdLen = CmdLen;
|
Cbw.CmdLen = CmdLen;
|
||||||
|
|
||||||
ZeroMem (Cbw.CmdBlock, USB_BOT_MAX_CMDLEN);
|
ZeroMem (Cbw.CmdBlock, USB_BOT_MAX_CMDLEN);
|
||||||
@ -389,6 +389,7 @@ UsbBotGetStatus (
|
|||||||
@param DataDir The direction of the data transfer
|
@param DataDir The direction of the data transfer
|
||||||
@param Data The buffer to hold data
|
@param Data The buffer to hold data
|
||||||
@param DataLen The length of the data
|
@param DataLen The length of the data
|
||||||
|
@param Lun The number of logic unit
|
||||||
@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
|
||||||
|
|
||||||
@ -405,6 +406,7 @@ UsbBotExecCommand (
|
|||||||
IN EFI_USB_DATA_DIRECTION DataDir,
|
IN EFI_USB_DATA_DIRECTION DataDir,
|
||||||
IN VOID *Data,
|
IN VOID *Data,
|
||||||
IN UINT32 DataLen,
|
IN UINT32 DataLen,
|
||||||
|
IN UINT8 Lun,
|
||||||
IN UINT32 Timeout,
|
IN UINT32 Timeout,
|
||||||
OUT UINT32 *CmdStatus
|
OUT UINT32 *CmdStatus
|
||||||
)
|
)
|
||||||
@ -421,7 +423,7 @@ UsbBotExecCommand (
|
|||||||
// Send the command to the device. Return immediately if device
|
// Send the command to the device. Return immediately if device
|
||||||
// rejects the command.
|
// rejects the command.
|
||||||
//
|
//
|
||||||
Status = UsbBotSendCommand (UsbBot, Cmd, CmdLen, DataDir, DataLen);
|
Status = UsbBotSendCommand (UsbBot, Cmd, CmdLen, DataDir, DataLen, Lun);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
DEBUG ((EFI_D_ERROR, "UsbBotExecCommand: UsbBotSendCommand (%r)\n", Status));
|
DEBUG ((EFI_D_ERROR, "UsbBotExecCommand: UsbBotSendCommand (%r)\n", Status));
|
||||||
return Status;
|
return Status;
|
||||||
@ -488,10 +490,10 @@ UsbBotResetDevice (
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Issue a class specific "Bulk-Only Mass Storage Reset reqest.
|
// Issue a class specific Bulk-Only Mass Storage Reset reqest.
|
||||||
// See the spec section 3.1
|
// See the spec section 3.1
|
||||||
//
|
//
|
||||||
Request.RequestType = 0x21;
|
Request.RequestType = 0x21; // Class, Interface, Host to Device
|
||||||
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;
|
||||||
@ -528,6 +530,86 @@ UsbBotResetDevice (
|
|||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Reset the mass storage device by BOT protocol
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Context - The context of the BOT protocol, that is, USB_BOT_PROTOCOL
|
||||||
|
MaxLun - Return pointer to the max number of lun. Maxlun=1 means lun0 and
|
||||||
|
lun1 in all.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - The device is reset
|
||||||
|
Others - Failed to reset the device.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
STATIC
|
||||||
|
EFI_STATUS
|
||||||
|
UsbBotGetMaxLun (
|
||||||
|
IN VOID *Context,
|
||||||
|
IN UINT8 *MaxLun
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Reset the mass storage device by BOT protocol
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Context - The context of the BOT protocol, that is, USB_BOT_PROTOCOL
|
||||||
|
MaxLun - Return pointer to the max number of lun. Maxlun=1 means lun0 and
|
||||||
|
lun1 in all.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - The device is reset
|
||||||
|
Others - Failed to reset the device.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
USB_BOT_PROTOCOL *UsbBot;
|
||||||
|
EFI_USB_DEVICE_REQUEST Request;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINT32 Result;
|
||||||
|
UINT32 Timeout;
|
||||||
|
|
||||||
|
ASSERT (Context);
|
||||||
|
|
||||||
|
UsbBot = (USB_BOT_PROTOCOL *) Context;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Issue a class specific Bulk-Only Mass Storage get max lun reqest.
|
||||||
|
// See the spec section 3.2
|
||||||
|
//
|
||||||
|
Request.RequestType = 0xA1; // Class, Interface, Device to Host
|
||||||
|
Request.Request = USB_BOT_GETLUN_REQUEST;
|
||||||
|
Request.Value = 0;
|
||||||
|
Request.Index = UsbBot->Interface.InterfaceNumber;
|
||||||
|
Request.Length = 1;
|
||||||
|
Timeout = USB_BOT_RESET_DEVICE_TIMEOUT / USB_MASS_1_MILLISECOND;
|
||||||
|
|
||||||
|
Status = UsbBot->UsbIo->UsbControlTransfer (
|
||||||
|
UsbBot->UsbIo,
|
||||||
|
&Request,
|
||||||
|
EfiUsbDataIn,
|
||||||
|
Timeout,
|
||||||
|
(VOID *)MaxLun,
|
||||||
|
1,
|
||||||
|
&Result
|
||||||
|
);
|
||||||
|
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "UsbBotGetMaxLun: (%r)\n", Status));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Clean up the resource used by this BOT protocol
|
Clean up the resource used by this BOT protocol
|
||||||
@ -554,5 +636,7 @@ mUsbBotTransport = {
|
|||||||
UsbBotInit,
|
UsbBotInit,
|
||||||
UsbBotExecCommand,
|
UsbBotExecCommand,
|
||||||
UsbBotResetDevice,
|
UsbBotResetDevice,
|
||||||
|
UsbBotGetMaxLun,
|
||||||
UsbBotFini
|
UsbBotFini
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/** @file
|
/** @file
|
||||||
|
|
||||||
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
|
||||||
@ -40,7 +40,6 @@ UsbCbiResetDevice (
|
|||||||
If Context isn't NULL, it will save its context in it.
|
If Context isn't NULL, it will save its context in it.
|
||||||
|
|
||||||
@param UsbIo The USB IO to use
|
@param UsbIo The USB IO to use
|
||||||
@param Controller The device controller
|
|
||||||
@param Context The variable to save context in
|
@param Context The variable to save context in
|
||||||
|
|
||||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory
|
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory
|
||||||
@ -52,7 +51,6 @@ STATIC
|
|||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
UsbCbiInit (
|
UsbCbiInit (
|
||||||
IN EFI_USB_IO_PROTOCOL *UsbIo,
|
IN EFI_USB_IO_PROTOCOL *UsbIo,
|
||||||
IN EFI_HANDLE Controller,
|
|
||||||
OUT VOID **Context OPTIONAL
|
OUT VOID **Context OPTIONAL
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@ -413,6 +411,7 @@ UsbCbiGetStatus (
|
|||||||
@param DataDir The direction of data transfer
|
@param DataDir The direction of data transfer
|
||||||
@param Data The buffer to hold the data
|
@param Data The buffer to hold the data
|
||||||
@param DataLen The length of the buffer
|
@param DataLen The length of the buffer
|
||||||
|
@param Lun Should be 0, this field for bot only
|
||||||
@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
|
||||||
|
|
||||||
@ -429,6 +428,7 @@ UsbCbiExecCommand (
|
|||||||
IN EFI_USB_DATA_DIRECTION DataDir,
|
IN EFI_USB_DATA_DIRECTION DataDir,
|
||||||
IN VOID *Data,
|
IN VOID *Data,
|
||||||
IN UINT32 DataLen,
|
IN UINT32 DataLen,
|
||||||
|
IN UINT8 Lun,
|
||||||
IN UINT32 Timeout,
|
IN UINT32 Timeout,
|
||||||
OUT UINT32 *CmdStatus
|
OUT UINT32 *CmdStatus
|
||||||
)
|
)
|
||||||
@ -603,6 +603,7 @@ mUsbCbi0Transport = {
|
|||||||
UsbCbiInit,
|
UsbCbiInit,
|
||||||
UsbCbiExecCommand,
|
UsbCbiExecCommand,
|
||||||
UsbCbiResetDevice,
|
UsbCbiResetDevice,
|
||||||
|
NULL,
|
||||||
UsbCbiFini
|
UsbCbiFini
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -612,5 +613,6 @@ mUsbCbi1Transport = {
|
|||||||
UsbCbiInit,
|
UsbCbiInit,
|
||||||
UsbCbiExecCommand,
|
UsbCbiExecCommand,
|
||||||
UsbCbiResetDevice,
|
UsbCbiResetDevice,
|
||||||
|
NULL,
|
||||||
UsbCbiFini
|
UsbCbiFini
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/** @file
|
/** @file
|
||||||
|
|
||||||
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
|
||||||
@ -40,74 +40,6 @@ USB_MASS_TRANSPORT *mUsbMassTransport[] = {
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
Retrieve the media parameters such as disk gemotric for the
|
|
||||||
device's BLOCK IO protocol.
|
|
||||||
|
|
||||||
@param UsbMass The USB mass storage device
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS The media parameters is updated successfully.
|
|
||||||
@retval Others Failed to get the media parameters.
|
|
||||||
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
UsbMassInitMedia (
|
|
||||||
IN USB_MASS_DEVICE *UsbMass
|
|
||||||
)
|
|
||||||
{
|
|
||||||
EFI_BLOCK_IO_MEDIA *Media;
|
|
||||||
EFI_STATUS Status;
|
|
||||||
UINTN Index;
|
|
||||||
|
|
||||||
Media = &UsbMass->BlockIoMedia;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Initialize the MediaPrsent/ReadOnly and others to the default.
|
|
||||||
// We are not forced to get it right at this time, check UEFI2.0
|
|
||||||
// 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->LogicalPartition = FALSE;
|
|
||||||
Media->ReadOnly = FALSE;
|
|
||||||
Media->WriteCaching = FALSE;
|
|
||||||
Media->IoAlign = 0;
|
|
||||||
Media->MediaId = 1;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Some device may spend several seconds before it is ready.
|
|
||||||
// Try several times before giving up. Wait 5s at most.
|
|
||||||
//
|
|
||||||
Status = EFI_SUCCESS;
|
|
||||||
|
|
||||||
for (Index = 0; Index < USB_BOOT_INIT_MEDIA_RETRY; Index++) {
|
|
||||||
|
|
||||||
Status = UsbBootGetParams (UsbMass);
|
|
||||||
if ((Status != EFI_MEDIA_CHANGED)
|
|
||||||
&& (Status != EFI_NOT_READY)
|
|
||||||
&& (Status != EFI_TIMEOUT)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = UsbBootIsUnitReady (UsbMass);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
gBS->Stall (USB_BOOT_RETRY_UNIT_READY_STALL * (Index + 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Reset the block device. ExtendedVerification is ignored for this.
|
Reset the block device. ExtendedVerification is ignored for this.
|
||||||
|
|
||||||
@ -139,7 +71,6 @@ UsbMassReset (
|
|||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Read some blocks of data from the block device.
|
Read some blocks of data from the block device.
|
||||||
|
|
||||||
@ -339,7 +270,6 @@ ON_EXIT:
|
|||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Flush the cached writes to disks. USB mass storage device doesn't
|
Flush the cached writes to disks. USB mass storage device doesn't
|
||||||
support write cache, so return EFI_SUCCESS directly.
|
support write cache, so return EFI_SUCCESS directly.
|
||||||
@ -358,6 +288,381 @@ UsbMassFlushBlocks (
|
|||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Retrieve the media parameters such as disk gemotric for the
|
||||||
|
device's BLOCK IO protocol.
|
||||||
|
|
||||||
|
@param UsbMass The USB mass storage device
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The media parameters is updated successfully.
|
||||||
|
@retval Others Failed to get the media parameters.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
UsbMassInitMedia (
|
||||||
|
IN USB_MASS_DEVICE *UsbMass
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_BLOCK_IO_MEDIA *Media;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINTN Index;
|
||||||
|
|
||||||
|
Media = &UsbMass->BlockIoMedia;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Initialize the MediaPrsent/ReadOnly and others to the default.
|
||||||
|
// We are not forced to get it right at this time, check UEFI2.0
|
||||||
|
// 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->LogicalPartition = FALSE;
|
||||||
|
Media->ReadOnly = FALSE;
|
||||||
|
Media->WriteCaching = FALSE;
|
||||||
|
Media->IoAlign = 0;
|
||||||
|
Media->MediaId = 1;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Some device may spend several seconds before it is ready.
|
||||||
|
// Try several times before giving up. Wait 5s at most.
|
||||||
|
//
|
||||||
|
Status = EFI_SUCCESS;
|
||||||
|
|
||||||
|
for (Index = 0; Index < USB_BOOT_INIT_MEDIA_RETRY; Index++) {
|
||||||
|
|
||||||
|
Status = UsbBootGetParams (UsbMass);
|
||||||
|
if ((Status != EFI_MEDIA_CHANGED)
|
||||||
|
&& (Status != EFI_NOT_READY)
|
||||||
|
&& (Status != EFI_TIMEOUT)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = UsbBootIsUnitReady (UsbMass);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
gBS->Stall (USB_BOOT_RETRY_UNIT_READY_STALL * (Index + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC
|
||||||
|
EFI_STATUS
|
||||||
|
UsbMassInitTransport (
|
||||||
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||||
|
IN EFI_HANDLE Controller,
|
||||||
|
OUT USB_MASS_TRANSPORT **Transport,
|
||||||
|
OUT VOID **Context,
|
||||||
|
OUT UINT8 *MaxLun
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_USB_IO_PROTOCOL *UsbIo;
|
||||||
|
EFI_USB_INTERFACE_DESCRIPTOR Interface;
|
||||||
|
UINT8 Index;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
Status = gBS->OpenProtocol (
|
||||||
|
Controller,
|
||||||
|
&gEfiUsbIoProtocolGuid,
|
||||||
|
&UsbIo,
|
||||||
|
This->DriverBindingHandle,
|
||||||
|
Controller,
|
||||||
|
EFI_OPEN_PROTOCOL_BY_DRIVER
|
||||||
|
);
|
||||||
|
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "UsbMassInitTransport: OpenUsbIoProtocol By Driver (%r)\n", Status));
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "UsbMassInitTransport: UsbIo->UsbGetInterfaceDescriptor (%r)\n", Status));
|
||||||
|
goto ON_EXIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = EFI_UNSUPPORTED;
|
||||||
|
|
||||||
|
for (Index = 0; mUsbMassTransport[Index] != NULL; Index++) {
|
||||||
|
*Transport = mUsbMassTransport[Index];
|
||||||
|
|
||||||
|
if (Interface.InterfaceProtocol == (*Transport)->Protocol) {
|
||||||
|
Status = (*Transport)->Init (UsbIo, Context);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "UsbMassInitTransport: Transport->Init (%r)\n", Status));
|
||||||
|
goto ON_EXIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// For bot device, try to get max lun.
|
||||||
|
// If maxlun=0, then non-lun device, else multi-lun device.
|
||||||
|
//
|
||||||
|
if ((*Transport)->Protocol == USB_MASS_STORE_BOT) {
|
||||||
|
(*Transport)->GetMaxLun (*Context, MaxLun);
|
||||||
|
DEBUG ((EFI_D_INFO, "UsbMassInitTransport: GetMaxLun = %d\n", *MaxLun));
|
||||||
|
}
|
||||||
|
|
||||||
|
ON_EXIT:
|
||||||
|
gBS->CloseProtocol (
|
||||||
|
Controller,
|
||||||
|
&gEfiUsbIoProtocolGuid,
|
||||||
|
This->DriverBindingHandle,
|
||||||
|
Controller
|
||||||
|
);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC
|
||||||
|
EFI_STATUS
|
||||||
|
UsbMassInitMultiLun (
|
||||||
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||||
|
IN EFI_HANDLE Controller,
|
||||||
|
IN USB_MASS_TRANSPORT *Transport,
|
||||||
|
IN VOID *Context,
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
|
||||||
|
IN UINT8 MaxLun
|
||||||
|
)
|
||||||
|
{
|
||||||
|
USB_MASS_DEVICE *UsbMass;
|
||||||
|
EFI_USB_IO_PROTOCOL *UsbIo;
|
||||||
|
DEVICE_LOGICAL_UNIT_DEVICE_PATH LunNode;
|
||||||
|
UINT8 Index;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
ASSERT (MaxLun > 0);
|
||||||
|
|
||||||
|
for (Index = 0; Index <= MaxLun; Index++) {
|
||||||
|
|
||||||
|
DEBUG ((EFI_D_INFO, "UsbMassInitMultiLun: Start to initialize No.%d logic unit\n", Index));
|
||||||
|
|
||||||
|
UsbIo = NULL;
|
||||||
|
UsbMass = AllocateZeroPool (sizeof (USB_MASS_DEVICE));
|
||||||
|
if (UsbMass == NULL) {
|
||||||
|
Status = EFI_OUT_OF_RESOURCES;
|
||||||
|
goto ON_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
UsbMass->Signature = USB_MASS_SIGNATURE;
|
||||||
|
UsbMass->UsbIo = UsbIo;
|
||||||
|
UsbMass->BlockIo.Media = &UsbMass->BlockIoMedia;
|
||||||
|
UsbMass->BlockIo.Reset = UsbMassReset;
|
||||||
|
UsbMass->BlockIo.ReadBlocks = UsbMassReadBlocks;
|
||||||
|
UsbMass->BlockIo.WriteBlocks = UsbMassWriteBlocks;
|
||||||
|
UsbMass->BlockIo.FlushBlocks = UsbMassFlushBlocks;
|
||||||
|
UsbMass->OpticalStorage = FALSE;
|
||||||
|
UsbMass->Transport = Transport;
|
||||||
|
UsbMass->Context = Context;
|
||||||
|
UsbMass->Lun = Index;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get the storage's parameters, such as last block number.
|
||||||
|
// then install the BLOCK_IO
|
||||||
|
//
|
||||||
|
Status = UsbMassInitMedia (UsbMass);
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
if ((UsbMass->Pdt != USB_PDT_DIRECT_ACCESS) &&
|
||||||
|
(UsbMass->Pdt != USB_PDT_CDROM) &&
|
||||||
|
(UsbMass->Pdt != USB_PDT_OPTICAL) &&
|
||||||
|
(UsbMass->Pdt != USB_PDT_SIMPLE_DIRECT)) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: Found an unsupported peripheral type[%d]\n", UsbMass->Pdt));
|
||||||
|
goto ON_ERROR;
|
||||||
|
}
|
||||||
|
} else if (Status != EFI_NO_MEDIA){
|
||||||
|
DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: UsbMassInitMedia (%r)\n", Status));
|
||||||
|
goto ON_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Create a device path node of device logic unit, and append it
|
||||||
|
//
|
||||||
|
LunNode.Header.Type = MESSAGING_DEVICE_PATH;
|
||||||
|
LunNode.Header.SubType = MSG_DEVICE_LOGICAL_UNIT_DP;
|
||||||
|
LunNode.Lun = UsbMass->Lun;
|
||||||
|
|
||||||
|
SetDevicePathNodeLength (&LunNode.Header, sizeof (LunNode));
|
||||||
|
|
||||||
|
UsbMass->DevicePath = AppendDevicePathNode (DevicePath, &LunNode.Header);
|
||||||
|
|
||||||
|
if (UsbMass->DevicePath == NULL) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: failed to create device logic unit device path\n"));
|
||||||
|
|
||||||
|
Status = EFI_OUT_OF_RESOURCES;
|
||||||
|
goto ON_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Create a UsbMass handle for each lun, and install blockio and devicepath protocols.
|
||||||
|
//
|
||||||
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||||
|
&UsbMass->Controller,
|
||||||
|
&gEfiDevicePathProtocolGuid,
|
||||||
|
UsbMass->DevicePath,
|
||||||
|
&gEfiBlockIoProtocolGuid,
|
||||||
|
&UsbMass->BlockIo,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: InstallMultipleProtocolInterfaces (%r)\n", Status));
|
||||||
|
goto ON_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Open UsbIo protocol by child to setup a parent-child relationship.
|
||||||
|
//
|
||||||
|
Status = gBS->OpenProtocol (
|
||||||
|
Controller,
|
||||||
|
&gEfiUsbIoProtocolGuid,
|
||||||
|
&UsbIo,
|
||||||
|
This->DriverBindingHandle,
|
||||||
|
UsbMass->Controller,
|
||||||
|
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
|
||||||
|
);
|
||||||
|
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: OpenUsbIoProtocol By Child (%r)\n", Status));
|
||||||
|
gBS->UninstallMultipleProtocolInterfaces (
|
||||||
|
&UsbMass->Controller,
|
||||||
|
&gEfiDevicePathProtocolGuid,
|
||||||
|
UsbMass->DevicePath,
|
||||||
|
&gEfiBlockIoProtocolGuid,
|
||||||
|
&UsbMass->BlockIo,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
goto ON_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG ((EFI_D_INFO, "UsbMassInitMultiLun: Success to initialize No.%d logic unit\n", Index));
|
||||||
|
}
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
|
||||||
|
ON_ERROR:
|
||||||
|
if (UsbMass->DevicePath != NULL) {
|
||||||
|
gBS->FreePool (UsbMass->DevicePath);
|
||||||
|
}
|
||||||
|
if (UsbMass != NULL) {
|
||||||
|
gBS->FreePool (UsbMass);
|
||||||
|
}
|
||||||
|
if (UsbIo != NULL) {
|
||||||
|
gBS->CloseProtocol (
|
||||||
|
Controller,
|
||||||
|
&gEfiUsbIoProtocolGuid,
|
||||||
|
This->DriverBindingHandle,
|
||||||
|
UsbMass->Controller
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// If only success to initialize one lun, return success, or else return error
|
||||||
|
//
|
||||||
|
if (Index > 0) {
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
} else {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC
|
||||||
|
EFI_STATUS
|
||||||
|
UsbMassInitNonLun (
|
||||||
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||||
|
IN EFI_HANDLE Controller,
|
||||||
|
IN USB_MASS_TRANSPORT *Transport,
|
||||||
|
IN VOID *Context
|
||||||
|
)
|
||||||
|
{
|
||||||
|
USB_MASS_DEVICE *UsbMass;
|
||||||
|
EFI_USB_IO_PROTOCOL *UsbIo;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
UsbIo = NULL;
|
||||||
|
UsbMass = AllocateZeroPool (sizeof (USB_MASS_DEVICE));
|
||||||
|
if (UsbMass == NULL) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
Status = gBS->OpenProtocol (
|
||||||
|
Controller,
|
||||||
|
&gEfiUsbIoProtocolGuid,
|
||||||
|
&UsbIo,
|
||||||
|
This->DriverBindingHandle,
|
||||||
|
Controller,
|
||||||
|
EFI_OPEN_PROTOCOL_BY_DRIVER
|
||||||
|
);
|
||||||
|
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "UsbMassInitNonLun: OpenUsbIoProtocol By Driver (%r)\n", Status));
|
||||||
|
goto ON_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
UsbMass->Signature = USB_MASS_SIGNATURE;
|
||||||
|
UsbMass->Controller = Controller;
|
||||||
|
UsbMass->UsbIo = UsbIo;
|
||||||
|
UsbMass->BlockIo.Media = &UsbMass->BlockIoMedia;
|
||||||
|
UsbMass->BlockIo.Reset = UsbMassReset;
|
||||||
|
UsbMass->BlockIo.ReadBlocks = UsbMassReadBlocks;
|
||||||
|
UsbMass->BlockIo.WriteBlocks = UsbMassWriteBlocks;
|
||||||
|
UsbMass->BlockIo.FlushBlocks = UsbMassFlushBlocks;
|
||||||
|
UsbMass->OpticalStorage = FALSE;
|
||||||
|
UsbMass->Transport = Transport;
|
||||||
|
UsbMass->Context = Context;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get the storage's parameters, such as last block number.
|
||||||
|
// then install the BLOCK_IO
|
||||||
|
//
|
||||||
|
Status = UsbMassInitMedia (UsbMass);
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
if ((UsbMass->Pdt != USB_PDT_DIRECT_ACCESS) &&
|
||||||
|
(UsbMass->Pdt != USB_PDT_CDROM) &&
|
||||||
|
(UsbMass->Pdt != USB_PDT_OPTICAL) &&
|
||||||
|
(UsbMass->Pdt != USB_PDT_SIMPLE_DIRECT)) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "UsbMassInitNonLun: Found an unsupported peripheral type[%d]\n", UsbMass->Pdt));
|
||||||
|
goto ON_ERROR;
|
||||||
|
}
|
||||||
|
} else if (Status != EFI_NO_MEDIA){
|
||||||
|
DEBUG ((EFI_D_ERROR, "UsbMassInitNonLun: UsbMassInitMedia (%r)\n", Status));
|
||||||
|
goto ON_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = gBS->InstallProtocolInterface (
|
||||||
|
&Controller,
|
||||||
|
&gEfiBlockIoProtocolGuid,
|
||||||
|
EFI_NATIVE_INTERFACE,
|
||||||
|
&UsbMass->BlockIo
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
goto ON_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
|
||||||
|
ON_ERROR:
|
||||||
|
if (UsbMass != NULL) {
|
||||||
|
gBS->FreePool (UsbMass);
|
||||||
|
}
|
||||||
|
gBS->CloseProtocol (
|
||||||
|
Controller,
|
||||||
|
&gEfiUsbIoProtocolGuid,
|
||||||
|
This->DriverBindingHandle,
|
||||||
|
Controller
|
||||||
|
);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Check whether the controller is a supported USB mass storage.
|
Check whether the controller is a supported USB mass storage.
|
||||||
@ -418,7 +723,7 @@ USBMassDriverBindingSupported (
|
|||||||
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) {
|
||||||
Status = Transport->Init (UsbIo, Controller, NULL);
|
Status = Transport->Init (UsbIo, NULL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -458,107 +763,65 @@ USBMassDriverBindingStart (
|
|||||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
EFI_USB_IO_PROTOCOL *UsbIo;
|
|
||||||
EFI_USB_INTERFACE_DESCRIPTOR Interface;
|
|
||||||
USB_MASS_DEVICE *UsbMass;
|
|
||||||
USB_MASS_TRANSPORT *Transport;
|
USB_MASS_TRANSPORT *Transport;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
||||||
|
VOID *Context;
|
||||||
|
UINT8 MaxLun;
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
UINTN Index;
|
|
||||||
|
Transport = NULL;
|
||||||
|
Context = NULL;
|
||||||
|
MaxLun = 0;
|
||||||
|
|
||||||
Status = gBS->OpenProtocol (
|
//
|
||||||
Controller,
|
// Get interface and protocols, initialize transport
|
||||||
&gEfiUsbIoProtocolGuid,
|
//
|
||||||
(VOID **) &UsbIo,
|
Status = UsbMassInitTransport (This, Controller, &Transport, &Context, &MaxLun);
|
||||||
This->DriverBindingHandle,
|
|
||||||
Controller,
|
|
||||||
EFI_OPEN_PROTOCOL_BY_DRIVER
|
|
||||||
);
|
|
||||||
|
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: UsbMassInitTransport (%r)\n", Status));
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
if (MaxLun == 0) {
|
||||||
|
//
|
||||||
|
// Initialize No/Unsupported LUN device
|
||||||
|
//
|
||||||
|
Status = UsbMassInitNonLun(This, Controller, Transport, Context);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: UsbMassInitNonLun (%r)\n", Status));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// Open device path to perpare append Device Logic Unit node.
|
||||||
|
//
|
||||||
|
Status = gBS->OpenProtocol (
|
||||||
|
Controller,
|
||||||
|
&gEfiDevicePathProtocolGuid,
|
||||||
|
(VOID **) &DevicePath,
|
||||||
|
This->DriverBindingHandle,
|
||||||
|
Controller,
|
||||||
|
EFI_OPEN_PROTOCOL_BY_DRIVER
|
||||||
|
);
|
||||||
|
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: OpenDevicePathProtocol By Driver (%r)\n", Status));
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
UsbMass = AllocateZeroPool (sizeof (USB_MASS_DEVICE));
|
//
|
||||||
if (UsbMass == NULL) {
|
// Try best to initialize all LUNs, and return success only if one of LUNs successed to initialized.
|
||||||
return EFI_OUT_OF_RESOURCES;
|
//
|
||||||
}
|
Status = UsbMassInitMultiLun(This, Controller, Transport, Context, DevicePath, MaxLun);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
//
|
gBS->CloseProtocol (
|
||||||
// Initialize the transport protocols
|
Controller,
|
||||||
//
|
&gEfiDevicePathProtocolGuid,
|
||||||
Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface);
|
This->DriverBindingHandle,
|
||||||
if (EFI_ERROR (Status)) {
|
Controller
|
||||||
DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: UsbIo->UsbGetInterfaceDescriptor (%r)\n", Status));
|
);
|
||||||
goto ON_ERROR;
|
DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: UsbMassInitMultiLun (%r) with Maxlun=%d\n", Status, MaxLun));
|
||||||
}
|
|
||||||
|
|
||||||
Status = EFI_UNSUPPORTED;
|
|
||||||
|
|
||||||
for (Index = 0; mUsbMassTransport[Index] != NULL; Index++) {
|
|
||||||
Transport = mUsbMassTransport[Index];
|
|
||||||
|
|
||||||
if (Interface.InterfaceProtocol == Transport->Protocol) {
|
|
||||||
UsbMass->Transport = Transport;
|
|
||||||
Status = Transport->Init (UsbIo, Controller, &UsbMass->Context);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: Transport->Init (%r)\n", Status));
|
|
||||||
goto ON_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
UsbMass->Signature = USB_MASS_SIGNATURE;
|
|
||||||
UsbMass->Controller = Controller;
|
|
||||||
UsbMass->UsbIo = UsbIo;
|
|
||||||
UsbMass->BlockIo.Media = &UsbMass->BlockIoMedia;
|
|
||||||
UsbMass->BlockIo.Reset = UsbMassReset;
|
|
||||||
UsbMass->BlockIo.ReadBlocks = UsbMassReadBlocks;
|
|
||||||
UsbMass->BlockIo.WriteBlocks = UsbMassWriteBlocks;
|
|
||||||
UsbMass->BlockIo.FlushBlocks = UsbMassFlushBlocks;
|
|
||||||
UsbMass->OpticalStorage = FALSE;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Get the storage's parameters, such as last block number.
|
|
||||||
// then install the BLOCK_IO
|
|
||||||
//
|
|
||||||
Status = UsbMassInitMedia (UsbMass);
|
|
||||||
if (!EFI_ERROR (Status)) {
|
|
||||||
if ((UsbMass->Pdt != USB_PDT_DIRECT_ACCESS) &&
|
|
||||||
(UsbMass->Pdt != USB_PDT_CDROM) &&
|
|
||||||
(UsbMass->Pdt != USB_PDT_OPTICAL) &&
|
|
||||||
(UsbMass->Pdt != USB_PDT_SIMPLE_DIRECT)) {
|
|
||||||
DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: Found an unsupported peripheral type[%d]\n", UsbMass->Pdt));
|
|
||||||
goto ON_ERROR;
|
|
||||||
}
|
|
||||||
} else if (Status != EFI_NO_MEDIA){
|
|
||||||
DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: UsbMassInitMedia (%r)\n", Status));
|
|
||||||
goto ON_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = gBS->InstallProtocolInterface (
|
|
||||||
&Controller,
|
|
||||||
&gEfiBlockIoProtocolGuid,
|
|
||||||
EFI_NATIVE_INTERFACE,
|
|
||||||
&UsbMass->BlockIo
|
|
||||||
);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
goto ON_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
|
||||||
|
|
||||||
ON_ERROR:
|
|
||||||
gBS->FreePool (UsbMass);
|
|
||||||
|
|
||||||
gBS->CloseProtocol (
|
|
||||||
Controller,
|
|
||||||
&gEfiUsbIoProtocolGuid,
|
|
||||||
This->DriverBindingHandle,
|
|
||||||
Controller
|
|
||||||
);
|
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -586,49 +849,151 @@ USBMassDriverBindingStop (
|
|||||||
{
|
{
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
USB_MASS_DEVICE *UsbMass;
|
USB_MASS_DEVICE *UsbMass;
|
||||||
|
EFI_USB_IO_PROTOCOL *UsbIo;
|
||||||
EFI_BLOCK_IO_PROTOCOL *BlockIo;
|
EFI_BLOCK_IO_PROTOCOL *BlockIo;
|
||||||
|
UINTN Index;
|
||||||
|
BOOLEAN AllChildrenStopped;
|
||||||
|
|
||||||
//
|
//
|
||||||
// First, get our context back from the BLOCK_IO
|
// This a bus driver stop function since multi-lun supported. There are three
|
||||||
|
// kinds of device handle might be passed, 1st is a handle with devicepath/
|
||||||
|
// usbio/blockio installed(non-multi-lun), 2nd is a handle with devicepath/
|
||||||
|
// usbio installed(multi-lun root), 3rd is a handle with devicepath/blockio
|
||||||
|
// installed(multi-lun).
|
||||||
//
|
//
|
||||||
Status = gBS->OpenProtocol (
|
if (NumberOfChildren == 0) {
|
||||||
Controller,
|
//
|
||||||
&gEfiBlockIoProtocolGuid,
|
// A handle without any children, might be 1st and 2nd type.
|
||||||
(VOID **) &BlockIo,
|
//
|
||||||
This->DriverBindingHandle,
|
Status = gBS->OpenProtocol (
|
||||||
Controller,
|
Controller,
|
||||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
&gEfiBlockIoProtocolGuid,
|
||||||
);
|
&BlockIo,
|
||||||
|
This->DriverBindingHandle,
|
||||||
|
Controller,
|
||||||
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||||
|
);
|
||||||
|
|
||||||
|
if (EFI_ERROR(Status)) {
|
||||||
|
//
|
||||||
|
// This is a 2nd type handle(multi-lun root), which only needs close
|
||||||
|
// devicepath protocol.
|
||||||
|
//
|
||||||
|
gBS->CloseProtocol (
|
||||||
|
Controller,
|
||||||
|
&gEfiDevicePathProtocolGuid,
|
||||||
|
This->DriverBindingHandle,
|
||||||
|
Controller
|
||||||
|
);
|
||||||
|
DEBUG ((EFI_D_INFO, "Success to stop multi-lun root handle\n"));
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// This is a 1st type handle(non-multi-lun), which only needs uninstall
|
||||||
|
// blockio protocol, close usbio protocol and free mass device.
|
||||||
|
//
|
||||||
|
UsbMass = USB_MASS_DEVICE_FROM_BLOCKIO (BlockIo);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Uninstall Block I/O protocol from the device handle,
|
||||||
|
// then call the transport protocol to stop itself.
|
||||||
|
//
|
||||||
|
Status = gBS->UninstallProtocolInterface (
|
||||||
|
Controller,
|
||||||
|
&gEfiBlockIoProtocolGuid,
|
||||||
|
&UsbMass->BlockIo
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
gBS->CloseProtocol (
|
||||||
|
Controller,
|
||||||
|
&gEfiUsbIoProtocolGuid,
|
||||||
|
This->DriverBindingHandle,
|
||||||
|
Controller
|
||||||
|
);
|
||||||
|
|
||||||
|
UsbMass->Transport->Fini (UsbMass->Context);
|
||||||
|
gBS->FreePool (UsbMass);
|
||||||
|
|
||||||
|
DEBUG ((EFI_D_INFO, "Success to stop non-multi-lun root handle\n"));
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
if (EFI_ERROR (Status)) {
|
//
|
||||||
return Status;
|
// This is a 3rd type handle(multi-lun), which needs uninstall
|
||||||
|
// blockio and devicepath protocol, close usbio protocol and
|
||||||
|
// free mass device.
|
||||||
|
//
|
||||||
|
AllChildrenStopped = TRUE;
|
||||||
|
|
||||||
|
for (Index = 0; Index < NumberOfChildren; Index++) {
|
||||||
|
|
||||||
|
Status = gBS->OpenProtocol (
|
||||||
|
ChildHandleBuffer[Index],
|
||||||
|
&gEfiBlockIoProtocolGuid,
|
||||||
|
(VOID **) &BlockIo,
|
||||||
|
This->DriverBindingHandle,
|
||||||
|
Controller,
|
||||||
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
AllChildrenStopped = FALSE;
|
||||||
|
DEBUG ((EFI_D_ERROR, "Fail to stop No.%d multi-lun child handle when opening blockio\n", Index));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
UsbMass = USB_MASS_DEVICE_FROM_BLOCKIO (BlockIo);
|
||||||
|
|
||||||
|
gBS->CloseProtocol (
|
||||||
|
Controller,
|
||||||
|
&gEfiUsbIoProtocolGuid,
|
||||||
|
This->DriverBindingHandle,
|
||||||
|
ChildHandleBuffer[Index]
|
||||||
|
);
|
||||||
|
|
||||||
|
Status = gBS->UninstallMultipleProtocolInterfaces (
|
||||||
|
ChildHandleBuffer[Index],
|
||||||
|
&gEfiDevicePathProtocolGuid,
|
||||||
|
UsbMass->DevicePath,
|
||||||
|
&gEfiBlockIoProtocolGuid,
|
||||||
|
&UsbMass->BlockIo,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
//
|
||||||
|
// Fail to uninstall blockio and devicepath protocol, so re-open usbio by child.
|
||||||
|
//
|
||||||
|
AllChildrenStopped = FALSE;
|
||||||
|
DEBUG ((EFI_D_ERROR, "Fail to stop No.%d multi-lun child handle when uninstalling blockio and devicepath\n", Index));
|
||||||
|
|
||||||
|
gBS->OpenProtocol (
|
||||||
|
Controller,
|
||||||
|
&gEfiUsbIoProtocolGuid,
|
||||||
|
&UsbIo,
|
||||||
|
This->DriverBindingHandle,
|
||||||
|
ChildHandleBuffer[Index],
|
||||||
|
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// Success to stop this multi-lun handle, so go on next child.
|
||||||
|
//
|
||||||
|
if (((Index + 1) == NumberOfChildren) && AllChildrenStopped) {
|
||||||
|
UsbMass->Transport->Fini (UsbMass->Context);
|
||||||
|
}
|
||||||
|
gBS->FreePool (UsbMass);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UsbMass = USB_MASS_DEVICE_FROM_BLOCKIO (BlockIo);
|
if (!AllChildrenStopped) {
|
||||||
|
return EFI_DEVICE_ERROR;
|
||||||
//
|
|
||||||
// Uninstall Block I/O protocol from the device handle,
|
|
||||||
// then call the transport protocol to stop itself.
|
|
||||||
//
|
|
||||||
Status = gBS->UninstallProtocolInterface (
|
|
||||||
Controller,
|
|
||||||
&gEfiBlockIoProtocolGuid,
|
|
||||||
&UsbMass->BlockIo
|
|
||||||
);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
return Status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gBS->CloseProtocol (
|
DEBUG ((EFI_D_INFO, "Success to stop all %d multi-lun children handles\n", NumberOfChildren));
|
||||||
Controller,
|
|
||||||
&gEfiUsbIoProtocolGuid,
|
|
||||||
This->DriverBindingHandle,
|
|
||||||
Controller
|
|
||||||
);
|
|
||||||
|
|
||||||
UsbMass->Transport->Fini (UsbMass->Context);
|
|
||||||
gBS->FreePool (UsbMass);
|
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/** @file
|
/** @file
|
||||||
|
|
||||||
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
|
||||||
@ -43,16 +43,17 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct _USB_MASS_DEVICE {
|
struct _USB_MASS_DEVICE {
|
||||||
UINT32 Signature;
|
UINT32 Signature;
|
||||||
EFI_HANDLE Controller;
|
EFI_HANDLE Controller;
|
||||||
EFI_USB_IO_PROTOCOL *UsbIo;
|
EFI_USB_IO_PROTOCOL *UsbIo;
|
||||||
EFI_BLOCK_IO_PROTOCOL BlockIo;
|
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
||||||
EFI_BLOCK_IO_MEDIA BlockIoMedia;
|
EFI_BLOCK_IO_PROTOCOL BlockIo;
|
||||||
BOOLEAN OpticalStorage;
|
EFI_BLOCK_IO_MEDIA BlockIoMedia;
|
||||||
UINT8 Lun; // Logical Unit Number
|
BOOLEAN OpticalStorage;
|
||||||
UINT8 Pdt; // Peripheral Device Type
|
UINT8 Lun; // Logical Unit Number
|
||||||
USB_MASS_TRANSPORT *Transport; // USB mass storage transport protocol
|
UINT8 Pdt; // Peripheral Device Type
|
||||||
VOID *Context; // Opaque storage for mass transport
|
USB_MASS_TRANSPORT *Transport; // USB mass storage transport protocol
|
||||||
|
VOID *Context; // Opaque storage for mass transport
|
||||||
};
|
};
|
||||||
|
|
||||||
#define USB_MASS_DEVICE_FROM_BLOCKIO(a) \
|
#define USB_MASS_DEVICE_FROM_BLOCKIO(a) \
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#/** @file
|
#/** @file
|
||||||
# Component name for module UsbMassStorage
|
# Component name for module UsbMassStorage
|
||||||
#
|
#
|
||||||
# Copyright (c) 2006, Intel Corporation.
|
# Copyright (c) 2006 - 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
|
||||||
@ -53,9 +53,11 @@
|
|||||||
UefiDriverEntryPoint
|
UefiDriverEntryPoint
|
||||||
BaseMemoryLib
|
BaseMemoryLib
|
||||||
DebugLib
|
DebugLib
|
||||||
|
DevicePathLib
|
||||||
|
|
||||||
|
|
||||||
[Protocols]
|
[Protocols]
|
||||||
gEfiUsbIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
gEfiUsbIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||||
gEfiBlockIoProtocolGuid # PROTOCOL ALWAYS_PRODUCED
|
gEfiBlockIoProtocolGuid # PROTOCOL ALWAYS_PRODUCED
|
||||||
|
gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user