stm32/usbdev: Fix calculation of SCSI LUN size with multiple LUNs.

The SCSI driver calls GetCapacity to get the block size and number of
blocks of the underlying block-device/LUN.  It caches these values and uses
them later on to verify that reads/writes are within the bounds of the LUN.
But, prior to this commit, there was only one set of cached values for all
LUNs, so the bounds checking for a LUN could use incorrect values, values
from one of the other LUNs that most recently updated the cached values.
This would lead to failed SCSI requests.

This commit fixes this issue by having separate cached values for each LUN.

Signed-off-by: Damien George <damien@micropython.org>
This commit is contained in:
Damien George 2020-07-22 23:45:08 +10:00
parent 37e1b5c891
commit fd2ff867a0
3 changed files with 23 additions and 20 deletions

View File

@ -26,8 +26,6 @@
#ifndef MICROPY_INCLUDED_STM32_USBD_MSC_INTERFACE_H #ifndef MICROPY_INCLUDED_STM32_USBD_MSC_INTERFACE_H
#define MICROPY_INCLUDED_STM32_USBD_MSC_INTERFACE_H #define MICROPY_INCLUDED_STM32_USBD_MSC_INTERFACE_H
#define USBD_MSC_MAX_LUN (2)
extern const USBD_StorageTypeDef usbd_msc_fops; extern const USBD_StorageTypeDef usbd_msc_fops;
void usbd_msc_init_lu(size_t lu_n, const void *lu_data); void usbd_msc_init_lu(size_t lu_n, const void *lu_data);

View File

@ -34,6 +34,9 @@
#define MSC_MEDIA_PACKET (2048) // was 8192; how low can it go whilst still working? #define MSC_MEDIA_PACKET (2048) // was 8192; how low can it go whilst still working?
#define HID_DATA_FS_MAX_PACKET_SIZE (64) // endpoint IN & OUT packet size #define HID_DATA_FS_MAX_PACKET_SIZE (64) // endpoint IN & OUT packet size
// Maximum number of LUN that can be exposed on the MSC interface
#define USBD_MSC_MAX_LUN (2)
// Need to define here for BOT and SCSI layers // Need to define here for BOT and SCSI layers
#define MSC_IN_EP (0x81) #define MSC_IN_EP (0x81)
#define MSC_OUT_EP (0x01) #define MSC_OUT_EP (0x01)
@ -78,8 +81,8 @@ typedef struct {
uint8_t scsi_sense_head; uint8_t scsi_sense_head;
uint8_t scsi_sense_tail; uint8_t scsi_sense_tail;
uint16_t scsi_blk_size; uint16_t scsi_blk_size[USBD_MSC_MAX_LUN];
uint32_t scsi_blk_nbr; uint32_t scsi_blk_nbr[USBD_MSC_MAX_LUN];
uint32_t scsi_blk_addr_in_blks; uint32_t scsi_blk_addr_in_blks;
uint32_t scsi_blk_len; uint32_t scsi_blk_len;

View File

@ -247,7 +247,7 @@ static int8_t SCSI_ReadCapacity10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_
{ {
USBD_MSC_BOT_HandleTypeDef *hmsc = &((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->MSC_BOT_ClassData; USBD_MSC_BOT_HandleTypeDef *hmsc = &((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->MSC_BOT_ClassData;
if(hmsc->bdev_ops->GetCapacity(lun, &hmsc->scsi_blk_nbr, &hmsc->scsi_blk_size) != 0) if(hmsc->bdev_ops->GetCapacity(lun, &hmsc->scsi_blk_nbr[lun], &hmsc->scsi_blk_size[lun]) != 0)
{ {
SCSI_SenseCode(pdev, SCSI_SenseCode(pdev,
lun, lun,
@ -258,15 +258,17 @@ static int8_t SCSI_ReadCapacity10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_
else else
{ {
hmsc->bot_data[0] = (uint8_t)((hmsc->scsi_blk_nbr - 1) >> 24); uint32_t blk_nbr = hmsc->scsi_blk_nbr[lun];
hmsc->bot_data[1] = (uint8_t)((hmsc->scsi_blk_nbr - 1) >> 16); hmsc->bot_data[0] = (uint8_t)((blk_nbr - 1) >> 24);
hmsc->bot_data[2] = (uint8_t)((hmsc->scsi_blk_nbr - 1) >> 8); hmsc->bot_data[1] = (uint8_t)((blk_nbr - 1) >> 16);
hmsc->bot_data[3] = (uint8_t)(hmsc->scsi_blk_nbr - 1); hmsc->bot_data[2] = (uint8_t)((blk_nbr - 1) >> 8);
hmsc->bot_data[3] = (uint8_t)(blk_nbr - 1);
hmsc->bot_data[4] = (uint8_t)(hmsc->scsi_blk_size >> 24); uint32_t blk_size = hmsc->scsi_blk_size[lun];
hmsc->bot_data[5] = (uint8_t)(hmsc->scsi_blk_size >> 16); hmsc->bot_data[4] = (uint8_t)(blk_size >> 24);
hmsc->bot_data[6] = (uint8_t)(hmsc->scsi_blk_size >> 8); hmsc->bot_data[5] = (uint8_t)(blk_size >> 16);
hmsc->bot_data[7] = (uint8_t)(hmsc->scsi_blk_size); hmsc->bot_data[6] = (uint8_t)(blk_size >> 8);
hmsc->bot_data[7] = (uint8_t)(blk_size);
hmsc->bot_data_length = 8; hmsc->bot_data_length = 8;
return 0; return 0;
@ -516,7 +518,7 @@ static int8_t SCSI_Read10(USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *para
} }
hmsc->bot_state = USBD_BOT_DATA_IN; hmsc->bot_state = USBD_BOT_DATA_IN;
hmsc->scsi_blk_len *= hmsc->scsi_blk_size; hmsc->scsi_blk_len *= hmsc->scsi_blk_size[lun];
/* cases 4,5 : Hi <> Dn */ /* cases 4,5 : Hi <> Dn */
if (hmsc->cbw.dDataLength != hmsc->scsi_blk_len) if (hmsc->cbw.dDataLength != hmsc->scsi_blk_len)
@ -596,7 +598,7 @@ static int8_t SCSI_Write10 (USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *pa
return -1; /* error */ return -1; /* error */
} }
hmsc->scsi_blk_len *= hmsc->scsi_blk_size; hmsc->scsi_blk_len *= hmsc->scsi_blk_size[lun];
/* cases 3,11,13 : Hn,Ho <> D0 */ /* cases 3,11,13 : Hn,Ho <> D0 */
if (hmsc->cbw.dDataLength != hmsc->scsi_blk_len) if (hmsc->cbw.dDataLength != hmsc->scsi_blk_len)
@ -670,7 +672,7 @@ static int8_t SCSI_CheckAddressRange (USBD_HandleTypeDef *pdev, uint8_t lun , u
{ {
USBD_MSC_BOT_HandleTypeDef *hmsc = &((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->MSC_BOT_ClassData; USBD_MSC_BOT_HandleTypeDef *hmsc = &((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->MSC_BOT_ClassData;
if ((blk_offset + blk_nbr) > hmsc->scsi_blk_nbr ) if ((blk_offset + blk_nbr) > hmsc->scsi_blk_nbr[lun])
{ {
SCSI_SenseCode(pdev, SCSI_SenseCode(pdev,
lun, lun,
@ -697,7 +699,7 @@ static int8_t SCSI_ProcessRead (USBD_HandleTypeDef *pdev, uint8_t lun)
if( hmsc->bdev_ops->Read(lun , if( hmsc->bdev_ops->Read(lun ,
hmsc->bot_data, hmsc->bot_data,
hmsc->scsi_blk_addr_in_blks, hmsc->scsi_blk_addr_in_blks,
len / hmsc->scsi_blk_size) < 0) len / hmsc->scsi_blk_size[lun]) < 0)
{ {
SCSI_SenseCode(pdev, SCSI_SenseCode(pdev,
@ -714,7 +716,7 @@ static int8_t SCSI_ProcessRead (USBD_HandleTypeDef *pdev, uint8_t lun)
len); len);
hmsc->scsi_blk_addr_in_blks += len / hmsc->scsi_blk_size; hmsc->scsi_blk_addr_in_blks += len / hmsc->scsi_blk_size[lun];
hmsc->scsi_blk_len -= len; hmsc->scsi_blk_len -= len;
/* case 6 : Hi = Di */ /* case 6 : Hi = Di */
@ -744,7 +746,7 @@ static int8_t SCSI_ProcessWrite (USBD_HandleTypeDef *pdev, uint8_t lun)
if(hmsc->bdev_ops->Write(lun , if(hmsc->bdev_ops->Write(lun ,
hmsc->bot_data, hmsc->bot_data,
hmsc->scsi_blk_addr_in_blks, hmsc->scsi_blk_addr_in_blks,
len / hmsc->scsi_blk_size) < 0) len / hmsc->scsi_blk_size[lun]) < 0)
{ {
SCSI_SenseCode(pdev, SCSI_SenseCode(pdev,
lun, lun,
@ -754,7 +756,7 @@ static int8_t SCSI_ProcessWrite (USBD_HandleTypeDef *pdev, uint8_t lun)
} }
hmsc->scsi_blk_addr_in_blks += len / hmsc->scsi_blk_size; hmsc->scsi_blk_addr_in_blks += len / hmsc->scsi_blk_size[lun];
hmsc->scsi_blk_len -= len; hmsc->scsi_blk_len -= len;
/* case 12 : Ho = Do */ /* case 12 : Ho = Do */