mirror of
https://github.com/genodelabs/genode.git
synced 2025-05-30 14:14:31 +00:00
usb_block: enable WARN_STRICT_CONVERSION switch
Implicitely fixes problems with USB devices having more than 4G blocks. Formerly the 16-Cmd LBA requests were silently casted to 32-bit. Fix genodelabs/genode#4771
This commit is contained in:
parent
57fcc7a25f
commit
caef7d642a
@ -23,6 +23,7 @@ namespace Usb {
|
|||||||
|
|
||||||
|
|
||||||
using Genode::uint8_t;
|
using Genode::uint8_t;
|
||||||
|
using Genode::uint16_t;
|
||||||
using Genode::uint32_t;
|
using Genode::uint32_t;
|
||||||
using Genode::uint64_t;
|
using Genode::uint64_t;
|
||||||
using Genode::size_t;
|
using Genode::size_t;
|
||||||
@ -161,7 +162,7 @@ struct Read_capacity_10 : Usb::Cbw, Scsi::Read_capacity_10
|
|||||||
struct Read_10 : Usb::Cbw, Scsi::Read_10
|
struct Read_10 : Usb::Cbw, Scsi::Read_10
|
||||||
{
|
{
|
||||||
Read_10(addr_t addr, uint32_t tag, uint8_t lun,
|
Read_10(addr_t addr, uint32_t tag, uint8_t lun,
|
||||||
uint32_t lba, uint32_t len, uint32_t block_size)
|
uint32_t lba, uint16_t len, uint32_t block_size)
|
||||||
:
|
:
|
||||||
Cbw(addr, tag, len * block_size,
|
Cbw(addr, tag, len * block_size,
|
||||||
Usb::ENDPOINT_IN, lun, Scsi::Read_10::LENGTH),
|
Usb::ENDPOINT_IN, lun, Scsi::Read_10::LENGTH),
|
||||||
@ -180,7 +181,7 @@ struct Read_10 : Usb::Cbw, Scsi::Read_10
|
|||||||
struct Write_10 : Usb::Cbw, Scsi::Write_10
|
struct Write_10 : Usb::Cbw, Scsi::Write_10
|
||||||
{
|
{
|
||||||
Write_10(addr_t addr, uint32_t tag, uint8_t lun,
|
Write_10(addr_t addr, uint32_t tag, uint8_t lun,
|
||||||
uint32_t lba, uint32_t len, uint32_t block_size)
|
uint32_t lba, uint16_t len, uint32_t block_size)
|
||||||
:
|
:
|
||||||
Cbw(addr, tag, len * block_size,
|
Cbw(addr, tag, len * block_size,
|
||||||
Usb::ENDPOINT_OUT, lun, Scsi::Write_10::LENGTH),
|
Usb::ENDPOINT_OUT, lun, Scsi::Write_10::LENGTH),
|
||||||
@ -217,7 +218,7 @@ struct Read_capacity_16 : Usb::Cbw, Scsi::Read_capacity_16
|
|||||||
struct Read_16 : Usb::Cbw, Scsi::Read_16
|
struct Read_16 : Usb::Cbw, Scsi::Read_16
|
||||||
{
|
{
|
||||||
Read_16(addr_t addr, uint32_t tag, uint8_t lun,
|
Read_16(addr_t addr, uint32_t tag, uint8_t lun,
|
||||||
uint32_t lba, uint32_t len, uint32_t block_size)
|
uint64_t lba, uint32_t len, uint32_t block_size)
|
||||||
:
|
:
|
||||||
Cbw(addr, tag, len * block_size,
|
Cbw(addr, tag, len * block_size,
|
||||||
Usb::ENDPOINT_IN, lun, Scsi::Read_16::LENGTH),
|
Usb::ENDPOINT_IN, lun, Scsi::Read_16::LENGTH),
|
||||||
@ -236,7 +237,7 @@ struct Read_16 : Usb::Cbw, Scsi::Read_16
|
|||||||
struct Write_16 : Usb::Cbw, Scsi::Write_16
|
struct Write_16 : Usb::Cbw, Scsi::Write_16
|
||||||
{
|
{
|
||||||
Write_16(addr_t addr, uint32_t tag, uint8_t lun,
|
Write_16(addr_t addr, uint32_t tag, uint8_t lun,
|
||||||
uint32_t lba, uint32_t len, uint32_t block_size)
|
uint64_t lba, uint32_t len, uint32_t block_size)
|
||||||
:
|
:
|
||||||
Cbw(addr, tag, len * block_size,
|
Cbw(addr, tag, len * block_size,
|
||||||
Usb::ENDPOINT_OUT, lun, Scsi::Write_16::LENGTH),
|
Usb::ENDPOINT_OUT, lun, Scsi::Write_16::LENGTH),
|
||||||
|
@ -142,12 +142,15 @@ struct Usb::Block_driver : Usb::Completion
|
|||||||
return usb_label;
|
return usb_label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum Sizes : size_t { PACKET_STREAM_BUF_SIZE = 2 * (1UL << 20) };
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* USB session
|
* USB session
|
||||||
*/
|
*/
|
||||||
Allocator_avl alloc;
|
Allocator_avl alloc;
|
||||||
Usb::Connection usb { env, &alloc,
|
Usb::Connection usb { env, &alloc,
|
||||||
get_label<128>(config.xml()).string(), 2 * (1<<20), state_change_dispatcher };
|
get_label<128>(config.xml()).string(), PACKET_STREAM_BUF_SIZE,
|
||||||
|
state_change_dispatcher };
|
||||||
Usb::Device device;
|
Usb::Device device;
|
||||||
Signal_handler<Main> &block_request_handler;
|
Signal_handler<Main> &block_request_handler;
|
||||||
|
|
||||||
@ -161,7 +164,7 @@ struct Usb::Block_driver : Usb::Completion
|
|||||||
* Block session
|
* Block session
|
||||||
*/
|
*/
|
||||||
Block::sector_t _block_count { 0 };
|
Block::sector_t _block_count { 0 };
|
||||||
size_t _block_size { 0 };
|
uint32_t _block_size { 0 };
|
||||||
|
|
||||||
bool _writeable = false;
|
bool _writeable = false;
|
||||||
|
|
||||||
@ -204,7 +207,7 @@ struct Usb::Block_driver : Usb::Completion
|
|||||||
uint8_t interface;
|
uint8_t interface;
|
||||||
|
|
||||||
Block::sector_t block_count = 0;
|
Block::sector_t block_count = 0;
|
||||||
size_t block_size = 0;
|
uint32_t block_size = 0;
|
||||||
|
|
||||||
char vendor[Scsi::Inquiry_response::Vid::ITEMS+1];
|
char vendor[Scsi::Inquiry_response::Vid::ITEMS+1];
|
||||||
char product[Scsi::Inquiry_response::Pid::ITEMS+1];
|
char product[Scsi::Inquiry_response::Pid::ITEMS+1];
|
||||||
@ -328,8 +331,8 @@ struct Usb::Block_driver : Usb::Completion
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t const tag = csw.tag();
|
uint32_t const tag = csw.tag();
|
||||||
uint8_t const status = csw.sts();
|
uint32_t const status = csw.sts();
|
||||||
if (status != Csw::PASSED) {
|
if (status != Csw::PASSED) {
|
||||||
error("CSW failed: ", Hex(status, Hex::PREFIX, Hex::PAD),
|
error("CSW failed: ", Hex(status, Hex::PREFIX, Hex::PAD),
|
||||||
" tag: ", tag);
|
" tag: ", tag);
|
||||||
@ -451,7 +454,7 @@ struct Usb::Block_driver : Usb::Completion
|
|||||||
/* cap value in case there is no bulk-only */
|
/* cap value in case there is no bulk-only */
|
||||||
active_alt_setting = 0;
|
active_alt_setting = 0;
|
||||||
|
|
||||||
for (unsigned i = 0; i < iface.alternate_count(); i++) {
|
for (uint16_t i = 0; i < iface.alternate_count(); i++) {
|
||||||
Alternate_interface &aif = iface.alternate_interface(i);
|
Alternate_interface &aif = iface.alternate_interface(i);
|
||||||
if (aif.iclass == ICLASS_MASS_STORAGE
|
if (aif.iclass == ICLASS_MASS_STORAGE
|
||||||
&& aif.isubclass == ISUBCLASS_SCSI
|
&& aif.isubclass == ISUBCLASS_SCSI
|
||||||
@ -480,7 +483,7 @@ struct Usb::Block_driver : Usb::Completion
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < alt_iface.num_endpoints; i++) {
|
for (uint8_t i = 0; i < alt_iface.num_endpoints; i++) {
|
||||||
Endpoint ep = alt_iface.endpoint(i);
|
Endpoint ep = alt_iface.endpoint(i);
|
||||||
if (!ep.bulk())
|
if (!ep.bulk())
|
||||||
continue;
|
continue;
|
||||||
@ -617,9 +620,12 @@ struct Usb::Block_driver : Usb::Completion
|
|||||||
throw -1;
|
throw -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (init.block_count == 0x100000000) {
|
/**
|
||||||
|
* The READ_CAPACITY_10 count is 32-bit last() block + 1.
|
||||||
|
* If the maximum value is reached READ_CAPACITY_16 has to be used.
|
||||||
|
*/
|
||||||
|
if (init.block_count > ~(uint32_t)0U) {
|
||||||
|
|
||||||
/* capacity too large, try Scsi::Opcode::READ_CAPACITY_16 next */
|
|
||||||
Read_capacity_16 read_cap((addr_t)cbw_buffer, CAP_TAG, active_lun);
|
Read_capacity_16 read_cap((addr_t)cbw_buffer, CAP_TAG, active_lun);
|
||||||
|
|
||||||
init.read_capacity = false;
|
init.read_capacity = false;
|
||||||
@ -789,7 +795,7 @@ struct Usb::Block_driver : Usb::Completion
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t const status = csw.sts();
|
uint32_t const status = csw.sts();
|
||||||
if (status != Csw::PASSED) {
|
if (status != Csw::PASSED) {
|
||||||
error("CSW failed: ", Hex(status, Hex::PREFIX, Hex::PAD),
|
error("CSW failed: ", Hex(status, Hex::PREFIX, Hex::PAD),
|
||||||
" read: ", request->read(), " buffer: ", (void *)request->address,
|
" read: ", request->read(), " buffer: ", (void *)request->address,
|
||||||
@ -818,14 +824,13 @@ struct Usb::Block_driver : Usb::Completion
|
|||||||
{
|
{
|
||||||
_writeable = node.attribute_value("writeable", false);
|
_writeable = node.attribute_value("writeable", false);
|
||||||
_report_device = node.attribute_value("report", false);
|
_report_device = node.attribute_value("report", false);
|
||||||
active_interface = node.attribute_value("interface", 0UL);
|
active_interface = node.attribute_value<uint8_t>("interface", 0);
|
||||||
active_lun = node.attribute_value("lun", 0UL);
|
active_lun = node.attribute_value<uint8_t>("lun", 0);
|
||||||
reset_device = node.attribute_value("reset_device", false);
|
reset_device = node.attribute_value("reset_device", false);
|
||||||
verbose_scsi = node.attribute_value("verbose_scsi", false);
|
verbose_scsi = node.attribute_value("verbose_scsi", false);
|
||||||
|
|
||||||
active_alt_setting =
|
active_alt_setting =
|
||||||
node.attribute_value("alt_setting",
|
node.attribute_value<uint16_t>("alt_setting", INVALID_ALT_SETTING);
|
||||||
(unsigned long)INVALID_ALT_SETTING);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -862,13 +867,24 @@ struct Usb::Block_driver : Usb::Completion
|
|||||||
{
|
{
|
||||||
uint32_t const t = new_tag();
|
uint32_t const t = new_tag();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assuming a minimal packet size of 512. Total packet stream buffer
|
||||||
|
* should not exceed 16-bit block count value.
|
||||||
|
*/
|
||||||
|
static_assert((PACKET_STREAM_BUF_SIZE / 512UL) < (uint16_t)~0UL);
|
||||||
|
uint16_t c = (uint16_t) count;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We check for lba fitting 32-bit value for 10-Cmd mode
|
||||||
|
* before entering this function
|
||||||
|
*/
|
||||||
char cb[Cbw::LENGTH];
|
char cb[Cbw::LENGTH];
|
||||||
if (read) {
|
if (read) {
|
||||||
if (force_cmd_16) Read_16 r((addr_t)cb, t, active_lun, lba, count, _block_size);
|
if (force_cmd_16) Read_16 r((addr_t)cb, t, active_lun, lba, c, _block_size);
|
||||||
else Read_10 r((addr_t)cb, t, active_lun, lba, count, _block_size);
|
else Read_10 r((addr_t)cb, t, active_lun, (uint32_t)lba, c, _block_size);
|
||||||
} else {
|
} else {
|
||||||
if (force_cmd_16) Write_16 w((addr_t)cb, t, active_lun, lba, count, _block_size);
|
if (force_cmd_16) Write_16 w((addr_t)cb, t, active_lun, lba, c, _block_size);
|
||||||
else Write_10 w((addr_t)cb, t, active_lun, lba, count, _block_size);
|
else Write_10 w((addr_t)cb, t, active_lun, (uint32_t)lba, c, _block_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
cbw(cb, *this);
|
cbw(cb, *this);
|
||||||
@ -904,6 +920,10 @@ struct Usb::Block_driver : Usb::Completion
|
|||||||
if (last > info().block_count)
|
if (last > info().block_count)
|
||||||
return Response::REJECTED;
|
return Response::REJECTED;
|
||||||
|
|
||||||
|
/* we only support 32-bit block numbers in 10-Cmd mode */
|
||||||
|
if (!force_cmd_16 && last >= ~0U)
|
||||||
|
return Response::REJECTED;
|
||||||
|
|
||||||
/* check if request is pending */
|
/* check if request is pending */
|
||||||
if (request_pending())
|
if (request_pending())
|
||||||
return Response::RETRY;
|
return Response::RETRY;
|
||||||
|
@ -22,9 +22,20 @@ namespace Scsi {
|
|||||||
|
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
uint16_t be16(uint16_t val);
|
/*******************
|
||||||
uint32_t be32(uint32_t val);
|
** Endian helper **
|
||||||
uint64_t be64(uint64_t val);
|
*******************/
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T be(T val)
|
||||||
|
{
|
||||||
|
uint8_t * p = reinterpret_cast<uint8_t *>(&val);
|
||||||
|
T ret = 0;
|
||||||
|
for (size_t i = 0; i < sizeof(T); i++)
|
||||||
|
ret |= (T) (p[i] << ((sizeof(T)-i-1)*8));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/******************
|
/******************
|
||||||
* SCSI commands **
|
* SCSI commands **
|
||||||
@ -69,30 +80,6 @@ namespace Scsi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*******************
|
|
||||||
** Endian helper **
|
|
||||||
*******************/
|
|
||||||
|
|
||||||
Genode::uint16_t Scsi::be16(Genode::uint16_t val)
|
|
||||||
{
|
|
||||||
Genode::uint8_t *p = reinterpret_cast<Genode::uint8_t*>(&val);
|
|
||||||
return (p[1]<<0)|(p[0]<<8);
|
|
||||||
}
|
|
||||||
|
|
||||||
Genode::uint32_t Scsi::be32(Genode::uint32_t val)
|
|
||||||
{
|
|
||||||
Genode::uint8_t *p = reinterpret_cast<Genode::uint8_t*>(&val);
|
|
||||||
return (p[3]<<0)|(p[2]<<8)|(p[1]<<16)|(p[0]<<24);
|
|
||||||
}
|
|
||||||
|
|
||||||
Genode::uint64_t Scsi::be64(Genode::uint64_t val)
|
|
||||||
{
|
|
||||||
Genode::uint8_t *p = reinterpret_cast<Genode::uint8_t*>(&val);
|
|
||||||
return ((((Genode::uint64_t)(p[3]<<0)|(p[2]<<8)|(p[1]<<16)|(p[0]<<24))<<32)|
|
|
||||||
(((Genode::uint32_t)(p[7]<<0)|(p[6]<<8)|(p[5]<<16)|(p[4]<<24))));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***************************
|
/***************************
|
||||||
* SCSI command responses **
|
* SCSI command responses **
|
||||||
***************************/
|
***************************/
|
||||||
@ -189,8 +176,8 @@ struct Scsi::Capacity_response_10 : Genode::Mmio
|
|||||||
|
|
||||||
Capacity_response_10(addr_t addr) : Mmio(addr) { }
|
Capacity_response_10(addr_t addr) : Mmio(addr) { }
|
||||||
|
|
||||||
uint32_t last_block() const { return be32(read<Lba>()); }
|
uint32_t last_block() const { return be(read<Lba>()); }
|
||||||
uint32_t block_size() const { return be32(read<Bs>()); }
|
uint32_t block_size() const { return be(read<Bs>()); }
|
||||||
|
|
||||||
void dump()
|
void dump()
|
||||||
{
|
{
|
||||||
@ -210,8 +197,8 @@ struct Scsi::Capacity_response_16 : Genode::Mmio
|
|||||||
|
|
||||||
Capacity_response_16(addr_t addr) : Mmio(addr) { }
|
Capacity_response_16(addr_t addr) : Mmio(addr) { }
|
||||||
|
|
||||||
uint64_t last_block() const { return be64(read<Lba>()); }
|
uint64_t last_block() const { return be(read<Lba>()); }
|
||||||
uint32_t block_size() const { return be32(read<Bs>()); }
|
uint32_t block_size() const { return be(read<Bs>()); }
|
||||||
|
|
||||||
void dump()
|
void dump()
|
||||||
{
|
{
|
||||||
@ -239,7 +226,7 @@ struct Scsi::Cmd_6 : Genode::Mmio
|
|||||||
void dump()
|
void dump()
|
||||||
{
|
{
|
||||||
Genode::log("Op: ", Genode::Hex(read<Op>()));
|
Genode::log("Op: ", Genode::Hex(read<Op>()));
|
||||||
Genode::log("Lba: ", Genode::Hex(be16(read<Lba>())));
|
Genode::log("Lba: ", Genode::Hex(be(read<Lba>())));
|
||||||
Genode::log("Len: ", read<Len>());
|
Genode::log("Len: ", read<Len>());
|
||||||
Genode::log("Ctl: ", Genode::Hex(read<Ctl>()));
|
Genode::log("Ctl: ", Genode::Hex(read<Ctl>()));
|
||||||
}
|
}
|
||||||
@ -327,8 +314,8 @@ struct Scsi::Cmd_10 : Genode::Mmio
|
|||||||
void dump()
|
void dump()
|
||||||
{
|
{
|
||||||
Genode::log("Op: ", Genode::Hex(read<Op>()));
|
Genode::log("Op: ", Genode::Hex(read<Op>()));
|
||||||
Genode::log("Lba: ", Genode::Hex(be32(read<Lba>())));
|
Genode::log("Lba: ", Genode::Hex(be(read<Lba>())));
|
||||||
Genode::log("Len: ", be16(read<Len>()));
|
Genode::log("Len: ", be(read<Len>()));
|
||||||
Genode::log("Ctl: ", Genode::Hex(read<Ctl>()));
|
Genode::log("Ctl: ", Genode::Hex(read<Ctl>()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -347,8 +334,8 @@ struct Scsi::Io_10 : Cmd_10
|
|||||||
{
|
{
|
||||||
Io_10(addr_t addr, uint32_t lba, uint16_t len) : Cmd_10(addr)
|
Io_10(addr_t addr, uint32_t lba, uint16_t len) : Cmd_10(addr)
|
||||||
{
|
{
|
||||||
write<Cmd_10::Lba>(be32(lba));
|
write<Cmd_10::Lba>(be(lba));
|
||||||
write<Cmd_10::Len>(be16(len));
|
write<Cmd_10::Len>(be(len));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -388,8 +375,8 @@ struct Scsi::Cmd_16 : Genode::Mmio
|
|||||||
void dump()
|
void dump()
|
||||||
{
|
{
|
||||||
Genode::log("Op: ", Genode::Hex(read<Op>()));
|
Genode::log("Op: ", Genode::Hex(read<Op>()));
|
||||||
Genode::log("Lba: ", Genode::Hex(be64(read<Lba>())));
|
Genode::log("Lba: ", Genode::Hex(be(read<Lba>())));
|
||||||
Genode::log("Len: ", be32(read<Len>()));
|
Genode::log("Len: ", be(read<Len>()));
|
||||||
Genode::log("Ctl: ", Genode::Hex(read<Ctl>()));
|
Genode::log("Ctl: ", Genode::Hex(read<Ctl>()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -408,8 +395,8 @@ struct Scsi::Io_16 : Cmd_16
|
|||||||
{
|
{
|
||||||
Io_16(addr_t addr, uint64_t lba, uint32_t len) : Cmd_16(addr)
|
Io_16(addr_t addr, uint64_t lba, uint32_t len) : Cmd_16(addr)
|
||||||
{
|
{
|
||||||
write<Cmd_16::Lba>(be64(lba));
|
write<Cmd_16::Lba>(be(lba));
|
||||||
write<Cmd_16::Len>(be32(len));
|
write<Cmd_16::Len>(be(len));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2,5 +2,3 @@ TARGET = usb_block_drv
|
|||||||
SRC_CC = main.cc
|
SRC_CC = main.cc
|
||||||
INC_DIR = $(PRG_DIR)
|
INC_DIR = $(PRG_DIR)
|
||||||
LIBS = base
|
LIBS = base
|
||||||
|
|
||||||
CC_CXX_WARN_STRICT_CONVERSION =
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user