Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stop invalid LUNs from reading unallocated structs #141

Merged
merged 1 commit into from
Jul 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 69 additions & 48 deletions src/BlueSCSI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ byte m_msg; // Message bytes
byte m_buf[MAX_BLOCKSIZE]; // General purpose buffer
byte m_scsi_buf[SCSI_BUF_SIZE]; // Buffer for SCSI READ/WRITE Buffer
byte m_msb[256]; // Command storage bytes
SCSI_DEVICE scsi_device_list[NUM_SCSIID][MAX_SCSILUN]; // Maximum number
SCSI_DEVICE scsi_device_list[NUM_SCSIID][NUM_SCSILUN]; // Maximum number
SCSI_INQUIRY_DATA default_hdd, default_optical;

static byte onUnimplemented(SCSI_DEVICE *dev, const byte *cdb)
{
Expand Down Expand Up @@ -150,7 +151,7 @@ void readSCSIDeviceConfig(SCSI_DEVICE *dev) {
if (!config_file.isOpen()) {
return;
}
SCSI_INQUIRY_DATA *iq = &dev->inquiry_block;
SCSI_INQUIRY_DATA *iq = dev->inquiry_block;

char vendor[9];
memset(vendor, 0, sizeof(vendor));
Expand Down Expand Up @@ -295,6 +296,30 @@ void setup()
scsi_command_table[SCSI_SEND_DIAG] = onSendDiagnostic;
scsi_command_table[SCSI_READ_DEFECT_DATA] = onReadDefectData;

// clear and initialize default inquiry blocks
// default SCSI HDD
memset(&default_hdd, 0, sizeof(default_hdd));
default_hdd.ansi_version = 1;
default_hdd.response_format = 1;
default_hdd.additional_length = 31;
memcpy(&default_hdd.vendor, "QUANTUM", 7);
memcpy(&default_hdd.product, "FIREBALL1", 9);
erichelgeson marked this conversation as resolved.
Show resolved Hide resolved
memcpy(&default_hdd.revision, "1.0", 3);

// default SCSI CDROM
memset(&default_optical, 0, sizeof(default_optical));
default_optical.peripheral_device_type = 5;
default_optical.rmb = 1;
default_optical.ansi_version = 1;
default_optical.response_format = 1;
default_optical.additional_length = 42;
default_optical.sync = 1;
memcpy(&default_optical.vendor, "BLUESCSI", 8);
memcpy(&default_optical.product, "CD-ROM CDU-55S", 14);
memcpy(&default_optical.revision, "1.9a", 4);
default_optical.release = 0x20;
memcpy(&default_optical.revision_date, "1995", 4);

// Serial initialization
#if DEBUG > 0
Serial.begin(9600);
Expand Down Expand Up @@ -521,27 +546,12 @@ void findDriveImages(FsFile root) {
{
case SCSI_DEVICE_HDD:
// default SCSI HDD
dev->inquiry_block.ansi_version = 1;
dev->inquiry_block.response_format = 1;
dev->inquiry_block.additional_length = 31;
memcpy(dev->inquiry_block.vendor, "QUANTUM", 7);
memcpy(dev->inquiry_block.product, "BLUESCSI F1", 11);
memcpy(dev->inquiry_block.revision, "1.1", 3);
dev->inquiry_block = &default_hdd;
break;

case SCSI_DEVICE_OPTICAL:
// default SCSI CDROM
dev->inquiry_block.peripheral_device_type = 5;
dev->inquiry_block.rmb = 1;
dev->inquiry_block.ansi_version = 1;
dev->inquiry_block.response_format = 1;
dev->inquiry_block.additional_length = 42;
dev->inquiry_block.sync = 1;
memcpy(dev->inquiry_block.vendor, "BLUESCSI", 8);
memcpy(dev->inquiry_block.product, "CD-ROM CDU-55S", 14);
memcpy(dev->inquiry_block.revision, "1.9a", 4);
dev->inquiry_block.release = 0x20;
memcpy(dev->inquiry_block.revision_date, "1995", 4);
dev->inquiry_block = &default_optical;
break;
}

Expand Down Expand Up @@ -968,7 +978,7 @@ void verifyDataPhaseSD(SCSI_DEVICE *dev, uint32_t adds, uint32_t len)
*/
byte onInquiry(SCSI_DEVICE *dev, const byte *cdb)
{
writeDataPhase(cdb[4] < 36 ? cdb[4] : 36, dev->inquiry_block.raw);
writeDataPhase(cdb[4] < 36 ? cdb[4] : 36, dev->inquiry_block->raw);
return SCSI_STATUS_GOOD;
}

Expand Down Expand Up @@ -1547,14 +1557,6 @@ void loop()
// IDENTIFY
if (m_msb[i] >= 0x80) {
m_lun = m_msb[i] & 0x1f;
if(m_lun >= NUM_SCSILUN)
{
SCSI_DEVICE *d = &scsi_device_list[m_id][m_lun];
d->m_senseKey = SCSI_SENSE_ILLEGAL_REQUEST;
d->m_additional_sense_code = SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED;
m_sts |= SCSI_STATUS_CHECK_CONDITION;
goto Status;
}
}
// Extended message
if (m_msb[i] == 0x01) {
Expand Down Expand Up @@ -1607,11 +1609,10 @@ void loop()
LOGHEX(cmd[i]);
}
// LUN confirmation
m_sts = cmd[1]&0xe0; // Preset LUN in status byte
// if it wasn't set in the IDENTIFY then grab it from the CDB
if(m_lun > NUM_SCSILUN)
if(m_lun > MAX_SCSILUN)
{
m_lun = m_sts>>5;
m_lun = (cmd[1] & 0xe0) >> 5;
}

LOG(":ID ");
Expand All @@ -1620,39 +1621,59 @@ void loop()
LOG(m_lun);
LOGN("");

dev = &(scsi_device_list[m_id][m_lun]);
// HDD Image selection
if(m_lun >= NUM_SCSILUN || !dev->m_file)
if(m_lun >= NUM_SCSILUN)
{
// REQUEST SENSE and INQUIRY are handled different with invalid LUNs
if(cmd[0] != SCSI_REQUEST_SENSE || cmd[0] != SCSI_INQUIRY)
{
dev->m_senseKey = SCSI_SENSE_ILLEGAL_REQUEST;
dev->m_additional_sense_code = SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED;
m_sts = SCSI_STATUS_CHECK_CONDITION;
goto Status;
}
m_sts = SCSI_STATUS_GOOD;

// REQUEST SENSE and INQUIRY are handled different with invalid LUNs
if(cmd[0] == SCSI_INQUIRY)
{
// Special INQUIRY handling for invalid LUNs
LOGN("onInquiry - InvalidLUN");
dev = &(scsi_device_list[m_id][0]);

byte temp = dev->inquiry_block.raw[0];
byte temp = dev->inquiry_block->raw[0];

// If the LUN is invalid byte 0 of inquiry block needs to be 7fh
dev->inquiry_block.raw[0] = 0x7f;
dev->inquiry_block->raw[0] = 0x7f;

// only write back what was asked for
writeDataPhase(cmd[4], dev->inquiry_block.raw);
writeDataPhase(cmd[4], dev->inquiry_block->raw);

// return it back to normal if it was altered
dev->inquiry_block.raw[0] = temp;

m_sts = SCSI_STATUS_GOOD;
goto Status;
dev->inquiry_block->raw[0] = temp;
}
else if(cmd[0] == SCSI_REQUEST_SENSE)
{
byte buf[18] = {
0x70, //CheckCondition
0, //Segment number
SCSI_SENSE_ILLEGAL_REQUEST, //Sense key
0, 0, 0, 0, //information
10, //Additional data length
0, 0, 0, 0, // command specific information bytes
(byte)(SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED >> 8),
(byte)SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED,
0, 0, 0, 0,
};
writeDataPhase(cmd[4] < 18 ? cmd[4] : 18, buf);
}
else
{
m_sts = SCSI_STATUS_CHECK_CONDITION;
}

goto Status;
}

dev = &(scsi_device_list[m_id][m_lun]);
if(!dev->m_file)
{
dev->m_senseKey = SCSI_SENSE_ILLEGAL_REQUEST;
dev->m_additional_sense_code = SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED;
m_sts = SCSI_STATUS_CHECK_CONDITION;
goto Status;
}

LED_ON();
Expand Down
4 changes: 2 additions & 2 deletions src/BlueSCSI.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

// SCSI config
#define MAX_SCSIID 7 // Maximum number of supported SCSI-IDs (The minimum is 0)
#define MAX_SCSILUN 1 // Maximum number of LUNs supported (The minimum is 0)
#define MAX_SCSILUN 8 // Maximum number of LUNs supported (The minimum is 0)
#define NUM_SCSIID MAX_SCSIID // Number of enabled SCSI IDs
#define NUM_SCSILUN 1 // Number of enabled LUNs
#define READ_PARITY_CHECK 0 // Perform read parity check (unverified)
Expand Down Expand Up @@ -313,7 +313,7 @@ typedef __attribute__((aligned(4))) struct _SCSI_DEVICE
uint8_t m_type; // SCSI device type
uint32_t m_blockcount; // blockcount
bool m_raw; // Raw disk
SCSI_INQUIRY_DATA inquiry_block; // SCSI information
SCSI_INQUIRY_DATA *inquiry_block; // SCSI information
uint8_t m_senseKey; // Sense key
uint16_t m_additional_sense_code; // ASC/ASCQ
bool m_mode2; // MODE2 CDROM
Expand Down