mirror of https://github.com/acidanthera/audk.git
MdeModulePkg/UsbMassStorage: Add 16 byte SCSI cmds support if the last LBA can not be presented by 4bytes width
Signed-off-by: Feng Tian <feng.tian@intel.com> Reviewed-by: Li Elvin <elvin.li@intel.com> git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13311 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
8c1babfd28
commit
99c1725ee6
|
@ -2,7 +2,7 @@
|
||||||
Definition of USB Mass Storage Class and its value, USB Mass Transport Protocol,
|
Definition of USB Mass Storage Class and its value, USB Mass Transport Protocol,
|
||||||
and other common definitions.
|
and other common definitions.
|
||||||
|
|
||||||
Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2007 - 2012, Intel Corporation. All rights reserved.<BR>
|
||||||
This program and the accompanying materials
|
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
|
||||||
|
@ -18,7 +18,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
|
||||||
#include <Uefi.h>
|
#include <Uefi.h>
|
||||||
|
#include <IndustryStandard/Scsi.h>
|
||||||
#include <Protocol/BlockIo.h>
|
#include <Protocol/BlockIo.h>
|
||||||
#include <Protocol/UsbIo.h>
|
#include <Protocol/UsbIo.h>
|
||||||
#include <Protocol/DevicePath.h>
|
#include <Protocol/DevicePath.h>
|
||||||
|
@ -209,6 +209,7 @@ struct _USB_MASS_DEVICE {
|
||||||
VOID *Context;
|
VOID *Context;
|
||||||
EFI_DISK_INFO_PROTOCOL DiskInfo;
|
EFI_DISK_INFO_PROTOCOL DiskInfo;
|
||||||
USB_BOOT_INQUIRY_DATA InquiryData;
|
USB_BOOT_INQUIRY_DATA InquiryData;
|
||||||
|
BOOLEAN Cdb16Byte;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -386,6 +386,87 @@ UsbBootInquiry (
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Execute READ CAPACITY 16 bytes command to request information regarding
|
||||||
|
the capacity of the installed medium of the device.
|
||||||
|
|
||||||
|
This function executes READ CAPACITY 16 bytes command to get the capacity
|
||||||
|
of the USB mass storage media, including the presence, block size,
|
||||||
|
and last block number.
|
||||||
|
|
||||||
|
@param UsbMass The device to retireve disk gemotric.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The disk geometry is successfully retrieved.
|
||||||
|
@retval EFI_NOT_READY The returned block size is zero.
|
||||||
|
@retval Other READ CAPACITY 16 bytes command execution failed.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
UsbBootReadCapacity16 (
|
||||||
|
IN USB_MASS_DEVICE *UsbMass
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINT8 CapacityCmd[16];
|
||||||
|
EFI_SCSI_DISK_CAPACITY_DATA16 CapacityData;
|
||||||
|
EFI_BLOCK_IO_MEDIA *Media;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINT32 BlockSize;
|
||||||
|
|
||||||
|
Media = &UsbMass->BlockIoMedia;
|
||||||
|
|
||||||
|
Media->MediaPresent = FALSE;
|
||||||
|
Media->LastBlock = 0;
|
||||||
|
Media->BlockSize = 0;
|
||||||
|
|
||||||
|
ZeroMem (CapacityCmd, sizeof (CapacityCmd));
|
||||||
|
ZeroMem (&CapacityData, sizeof (CapacityData));
|
||||||
|
|
||||||
|
CapacityCmd[0] = EFI_SCSI_OP_READ_CAPACITY16;
|
||||||
|
CapacityCmd[1] = 0x10;
|
||||||
|
//
|
||||||
|
// Partial medium indicator, set the bytes 2 ~ 9 of the Cdb as ZERO.
|
||||||
|
//
|
||||||
|
ZeroMem ((CapacityCmd + 2), 8);
|
||||||
|
|
||||||
|
CapacityCmd[13] = sizeof (CapacityData);
|
||||||
|
|
||||||
|
Status = UsbBootExecCmdWithRetry (
|
||||||
|
UsbMass,
|
||||||
|
CapacityCmd,
|
||||||
|
(UINT8) sizeof (CapacityCmd),
|
||||||
|
EfiUsbDataIn,
|
||||||
|
&CapacityData,
|
||||||
|
sizeof (CapacityData),
|
||||||
|
USB_BOOT_GENERAL_CMD_TIMEOUT
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get the information on media presence, block size, and last block number
|
||||||
|
// from READ CAPACITY data.
|
||||||
|
//
|
||||||
|
Media->MediaPresent = TRUE;
|
||||||
|
Media->LastBlock = SwapBytes64 (ReadUnaligned64 ((CONST UINT64 *) &(CapacityData.LastLba7)));
|
||||||
|
|
||||||
|
BlockSize = SwapBytes32 (ReadUnaligned32 ((CONST UINT32 *) &(CapacityData.BlockSize3)));
|
||||||
|
|
||||||
|
Media->LowestAlignedLba = (CapacityData.LowestAlignLogic2 << 8) |
|
||||||
|
CapacityData.LowestAlignLogic1;
|
||||||
|
Media->LogicalBlocksPerPhysicalBlock = (1 << CapacityData.LogicPerPhysical);
|
||||||
|
if (BlockSize == 0) {
|
||||||
|
//
|
||||||
|
// Get sense data
|
||||||
|
//
|
||||||
|
return UsbBootRequestSense (UsbMass);
|
||||||
|
} else {
|
||||||
|
Media->BlockSize = BlockSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Execute READ CAPACITY command to request information regarding
|
Execute READ CAPACITY command to request information regarding
|
||||||
|
@ -451,6 +532,13 @@ UsbBootReadCapacity (
|
||||||
Media->BlockSize = BlockSize;
|
Media->BlockSize = BlockSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Media->LastBlock == 0xFFFFFFFF) {
|
||||||
|
Status = UsbBootReadCapacity16 (UsbMass);
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
UsbMass->Cdb16Byte = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -731,7 +819,7 @@ UsbBootReadBlocks (
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
DEBUG ((EFI_D_BLKIO, "UsbBootReadBlocks: LBA (0x%x), Blk (0x%x)\n", Lba, TotalBlock));
|
DEBUG ((EFI_D_BLKIO, "UsbBootReadBlocks: LBA (0x%x), Blk (0x%x)\n", Lba, Count));
|
||||||
Lba += Count;
|
Lba += Count;
|
||||||
Buffer += Count * BlockSize;
|
Buffer += Count * BlockSize;
|
||||||
TotalBlock -= Count;
|
TotalBlock -= Count;
|
||||||
|
@ -807,7 +895,155 @@ UsbBootWriteBlocks (
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
DEBUG ((EFI_D_BLKIO, "UsbBootWriteBlocks: LBA (0x%x), Blk (0x%x)\n", Lba, TotalBlock));
|
DEBUG ((EFI_D_BLKIO, "UsbBootWriteBlocks: LBA (0x%x), Blk (0x%x)\n", Lba, Count));
|
||||||
|
|
||||||
|
Lba += Count;
|
||||||
|
Buffer += Count * BlockSize;
|
||||||
|
TotalBlock -= Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Read some blocks from the device by SCSI 16 byte cmd.
|
||||||
|
|
||||||
|
@param UsbMass The USB mass storage device to read from
|
||||||
|
@param Lba The start block number
|
||||||
|
@param TotalBlock Total block number to read
|
||||||
|
@param Buffer The buffer to read to
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Data are read into the buffer
|
||||||
|
@retval Others Failed to read all the data
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
UsbBootReadBlocks16 (
|
||||||
|
IN USB_MASS_DEVICE *UsbMass,
|
||||||
|
IN UINT64 Lba,
|
||||||
|
IN UINTN TotalBlock,
|
||||||
|
OUT UINT8 *Buffer
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINT8 ReadCmd[16];
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINT16 Count;
|
||||||
|
UINT32 BlockSize;
|
||||||
|
UINT32 ByteSize;
|
||||||
|
UINT32 Timeout;
|
||||||
|
|
||||||
|
BlockSize = UsbMass->BlockIoMedia.BlockSize;
|
||||||
|
Status = EFI_SUCCESS;
|
||||||
|
|
||||||
|
while (TotalBlock > 0) {
|
||||||
|
//
|
||||||
|
// Split the total blocks into smaller pieces.
|
||||||
|
//
|
||||||
|
Count = (UINT16)((TotalBlock < USB_BOOT_IO_BLOCKS) ? TotalBlock : USB_BOOT_IO_BLOCKS);
|
||||||
|
ByteSize = (UINT32)Count * BlockSize;
|
||||||
|
|
||||||
|
//
|
||||||
|
// USB command's upper limit timeout is 5s. [USB2.0-9.2.6.1]
|
||||||
|
//
|
||||||
|
Timeout = (UINT32) USB_BOOT_GENERAL_CMD_TIMEOUT;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Fill in the command then execute
|
||||||
|
//
|
||||||
|
ZeroMem (ReadCmd, sizeof (ReadCmd));
|
||||||
|
|
||||||
|
ReadCmd[0] = EFI_SCSI_OP_READ16;
|
||||||
|
ReadCmd[1] = (UINT8) ((USB_BOOT_LUN (UsbMass->Lun) & 0xE0));
|
||||||
|
WriteUnaligned64 ((UINT64 *) &ReadCmd[2], SwapBytes64 (Lba));
|
||||||
|
WriteUnaligned32 ((UINT32 *) &ReadCmd[10], SwapBytes32 (Count));
|
||||||
|
|
||||||
|
Status = UsbBootExecCmdWithRetry (
|
||||||
|
UsbMass,
|
||||||
|
ReadCmd,
|
||||||
|
(UINT8) sizeof (ReadCmd),
|
||||||
|
EfiUsbDataIn,
|
||||||
|
Buffer,
|
||||||
|
ByteSize,
|
||||||
|
Timeout
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
DEBUG ((EFI_D_BLKIO, "UsbBootReadBlocks16: LBA (0x%lx), Blk (0x%x)\n", Lba, Count));
|
||||||
|
Lba += Count;
|
||||||
|
Buffer += Count * BlockSize;
|
||||||
|
TotalBlock -= Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Write some blocks to the device by SCSI 16 byte cmd.
|
||||||
|
|
||||||
|
@param UsbMass The USB mass storage device to write to
|
||||||
|
@param Lba The start block number
|
||||||
|
@param TotalBlock Total block number to write
|
||||||
|
@param Buffer Pointer to the source buffer for the data.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Data are written into the buffer
|
||||||
|
@retval Others Failed to write all the data
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
UsbBootWriteBlocks16 (
|
||||||
|
IN USB_MASS_DEVICE *UsbMass,
|
||||||
|
IN UINT64 Lba,
|
||||||
|
IN UINTN TotalBlock,
|
||||||
|
IN UINT8 *Buffer
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINT8 WriteCmd[16];
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINT16 Count;
|
||||||
|
UINT32 BlockSize;
|
||||||
|
UINT32 ByteSize;
|
||||||
|
UINT32 Timeout;
|
||||||
|
|
||||||
|
BlockSize = UsbMass->BlockIoMedia.BlockSize;
|
||||||
|
Status = EFI_SUCCESS;
|
||||||
|
|
||||||
|
while (TotalBlock > 0) {
|
||||||
|
//
|
||||||
|
// Split the total blocks into smaller pieces.
|
||||||
|
//
|
||||||
|
Count = (UINT16)((TotalBlock < USB_BOOT_IO_BLOCKS) ? TotalBlock : USB_BOOT_IO_BLOCKS);
|
||||||
|
ByteSize = (UINT32)Count * BlockSize;
|
||||||
|
|
||||||
|
//
|
||||||
|
// USB command's upper limit timeout is 5s. [USB2.0-9.2.6.1]
|
||||||
|
//
|
||||||
|
Timeout = (UINT32) USB_BOOT_GENERAL_CMD_TIMEOUT;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Fill in the write16 command block
|
||||||
|
//
|
||||||
|
ZeroMem (WriteCmd, sizeof (WriteCmd));
|
||||||
|
|
||||||
|
WriteCmd[0] = EFI_SCSI_OP_WRITE16;
|
||||||
|
WriteCmd[1] = (UINT8) ((USB_BOOT_LUN (UsbMass->Lun) & 0xE0));
|
||||||
|
WriteUnaligned64 ((UINT64 *) &WriteCmd[2], SwapBytes64 (Lba));
|
||||||
|
WriteUnaligned32 ((UINT32 *) &WriteCmd[10], SwapBytes32 (Count));
|
||||||
|
|
||||||
|
Status = UsbBootExecCmdWithRetry (
|
||||||
|
UsbMass,
|
||||||
|
WriteCmd,
|
||||||
|
(UINT8) sizeof (WriteCmd),
|
||||||
|
EfiUsbDataOut,
|
||||||
|
Buffer,
|
||||||
|
ByteSize,
|
||||||
|
Timeout
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
DEBUG ((EFI_D_BLKIO, "UsbBootWriteBlocks: LBA (0x%lx), Blk (0x%x)\n", Lba, Count));
|
||||||
Lba += Count;
|
Lba += Count;
|
||||||
Buffer += Count * BlockSize;
|
Buffer += Count * BlockSize;
|
||||||
TotalBlock -= Count;
|
TotalBlock -= Count;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
Definition of the command set of USB Mass Storage Specification
|
Definition of the command set of USB Mass Storage Specification
|
||||||
for Bootability, Revision 1.0.
|
for Bootability, Revision 1.0.
|
||||||
|
|
||||||
Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2007 - 2012, Intel Corporation. All rights reserved.<BR>
|
||||||
This program and the accompanying materials
|
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
|
||||||
|
@ -310,6 +310,47 @@ UsbBootWriteBlocks (
|
||||||
IN UINT8 *Buffer
|
IN UINT8 *Buffer
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Read some blocks from the device by SCSI 16 byte cmd.
|
||||||
|
|
||||||
|
@param UsbMass The USB mass storage device to read from
|
||||||
|
@param Lba The start block number
|
||||||
|
@param TotalBlock Total block number to read
|
||||||
|
@param Buffer The buffer to read to
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Data are read into the buffer
|
||||||
|
@retval Others Failed to read all the data
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
UsbBootReadBlocks16 (
|
||||||
|
IN USB_MASS_DEVICE *UsbMass,
|
||||||
|
IN UINT64 Lba,
|
||||||
|
IN UINTN TotalBlock,
|
||||||
|
OUT UINT8 *Buffer
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Write some blocks to the device by SCSI 16 byte cmd.
|
||||||
|
|
||||||
|
@param UsbMass The USB mass storage device to write to
|
||||||
|
@param Lba The start block number
|
||||||
|
@param TotalBlock Total block number to write
|
||||||
|
@param Buffer Pointer to the source buffer for the data.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Data are written into the buffer
|
||||||
|
@retval Others Failed to write all the data
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
UsbBootWriteBlocks16 (
|
||||||
|
IN USB_MASS_DEVICE *UsbMass,
|
||||||
|
IN UINT64 Lba,
|
||||||
|
IN UINTN TotalBlock,
|
||||||
|
IN UINT8 *Buffer
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Use the USB clear feature control transfer to clear the endpoint stall condition.
|
Use the USB clear feature control transfer to clear the endpoint stall condition.
|
||||||
|
|
||||||
|
|
|
@ -171,7 +171,12 @@ UsbMassReadBlocks (
|
||||||
goto ON_EXIT;
|
goto ON_EXIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = UsbBootReadBlocks (UsbMass, (UINT32) Lba, TotalBlock, Buffer);
|
if (UsbMass->Cdb16Byte) {
|
||||||
|
Status = UsbBootReadBlocks16 (UsbMass, Lba, TotalBlock, Buffer);
|
||||||
|
} else {
|
||||||
|
Status = UsbBootReadBlocks (UsbMass, (UINT32) Lba, TotalBlock, Buffer);
|
||||||
|
}
|
||||||
|
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
DEBUG ((EFI_D_ERROR, "UsbMassReadBlocks: UsbBootReadBlocks (%r) -> Reset\n", Status));
|
DEBUG ((EFI_D_ERROR, "UsbMassReadBlocks: UsbBootReadBlocks (%r) -> Reset\n", Status));
|
||||||
UsbMassReset (This, TRUE);
|
UsbMassReset (This, TRUE);
|
||||||
|
@ -286,7 +291,12 @@ UsbMassWriteBlocks (
|
||||||
// Try to write the data even the device is marked as ReadOnly,
|
// Try to write the data even the device is marked as ReadOnly,
|
||||||
// and clear the status should the write succeed.
|
// and clear the status should the write succeed.
|
||||||
//
|
//
|
||||||
Status = UsbBootWriteBlocks (UsbMass, (UINT32) Lba, TotalBlock, Buffer);
|
if (UsbMass->Cdb16Byte) {
|
||||||
|
Status = UsbBootWriteBlocks16 (UsbMass, Lba, TotalBlock, Buffer);
|
||||||
|
} else {
|
||||||
|
Status = UsbBootWriteBlocks (UsbMass, (UINT32) Lba, TotalBlock, Buffer);
|
||||||
|
}
|
||||||
|
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
DEBUG ((EFI_D_ERROR, "UsbMassWriteBlocks: UsbBootWriteBlocks (%r) -> Reset\n", Status));
|
DEBUG ((EFI_D_ERROR, "UsbMassWriteBlocks: UsbBootWriteBlocks (%r) -> Reset\n", Status));
|
||||||
UsbMassReset (This, TRUE);
|
UsbMassReset (This, TRUE);
|
||||||
|
|
Loading…
Reference in New Issue