| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- #include "fuzz/fuzz_private.h"
- #include "tusb.h"
- #include <cassert>
- #include <array>
- #include <limits>
- #if CFG_TUD_MSC==1
- // Whether host does safe eject.
- // tud_msc_get_maxlun_cb returns a uint8_t so the max logical units that are
- // allowed is 255, so we need to keep track of 255 fuzzed logical units.
- static std::array<bool, std::numeric_limits<uint8_t>::max()> ejected = {false};
- extern "C" {
- // Invoked when received SCSI_CMD_INQUIRY
- // Application fill vendor id, product id and revision with string up to 8, 16,
- // 4 characters respectively
- void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8],
- uint8_t product_id[16], uint8_t product_rev[4]) {
- (void)lun;
- assert(_fuzz_data_provider.has_value());
- std::string vid = _fuzz_data_provider->ConsumeBytesAsString(8);
- std::string pid = _fuzz_data_provider->ConsumeBytesAsString(16);
- std::string rev = _fuzz_data_provider->ConsumeBytesAsString(4);
- memcpy(vendor_id, vid.c_str(), strlen(vid.c_str()));
- memcpy(product_id, pid.c_str(), strlen(pid.c_str()));
- memcpy(product_rev, rev.c_str(), strlen(rev.c_str()));
- }
- // Invoked when received Test Unit Ready command.
- // return true allowing host to read/write this LUN e.g SD card inserted
- bool tud_msc_test_unit_ready_cb(uint8_t lun) {
- // RAM disk is ready until ejected
- if (ejected[lun]) {
- // Additional Sense 3A-00 is NOT_FOUND
- tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3a, 0x00);
- return false;
- }
- return _fuzz_data_provider->ConsumeBool();
- }
- // Invoked when received SCSI_CMD_READ_CAPACITY_10 and
- // SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size Application update
- // block count and block size
- void tud_msc_capacity_cb(uint8_t lun, uint32_t *block_count,
- uint16_t *block_size) {
- (void)lun;
- *block_count = _fuzz_data_provider->ConsumeIntegral<uint32_t>();
- *block_size = _fuzz_data_provider->ConsumeIntegral<uint16_t>();
- }
- // Invoked when received Start Stop Unit command
- // - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage
- // - Start = 1 : active mode, if load_eject = 1 : load disk storage
- bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start,
- bool load_eject) {
- (void)power_condition;
- assert(_fuzz_data_provider.has_value());
- if (load_eject) {
- if (start) {
- // load disk storage
- } else {
- // unload disk storage
- ejected[lun] = true;
- }
- }
- return _fuzz_data_provider->ConsumeBool();
- }
- // Callback invoked when received READ10 command.
- // Copy disk's data to buffer (up to bufsize) and return number of copied bytes.
- int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset,
- void *buffer, uint32_t bufsize) {
- assert(_fuzz_data_provider.has_value());
- (void)lun;
- (void)lba;
- (void)offset;
- std::vector<uint8_t> consumed_buffer = _fuzz_data_provider->ConsumeBytes<uint8_t>(
- _fuzz_data_provider->ConsumeIntegralInRange<uint32_t>(0, bufsize));
- memcpy(buffer, consumed_buffer.data(), consumed_buffer.size());
- // Sometimes return an error code;
- if (_fuzz_data_provider->ConsumeBool()) {
- return _fuzz_data_provider->ConsumeIntegralInRange(
- std::numeric_limits<int32_t>::min(), -1);
- }
- return consumed_buffer.size();
- }
- bool tud_msc_is_writable_cb(uint8_t lun) {
- assert(_fuzz_data_provider.has_value());
- (void)lun;
- return _fuzz_data_provider->ConsumeBool();
- }
- // Callback invoked when received WRITE10 command.
- // Process data in buffer to disk's storage and return number of written bytes
- int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset,
- uint8_t *buffer, uint32_t bufsize) {
- // Ignore these as they are outputs and don't affect the return value.
- (void)lun;
- (void)lba;
- (void)offset;
- (void)buffer;
- assert(_fuzz_data_provider.has_value());
- // -ve error codes -> bufsize.
- return _fuzz_data_provider->ConsumeIntegralInRange<int32_t>(
- std::numeric_limits<int32_t>::min(), bufsize);
- }
- // Callback invoked when received an SCSI command not in built-in list below
- // - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE
- // - READ10 and WRITE10 has their own callbacks
- int32_t tud_msc_scsi_cb(uint8_t lun, uint8_t const scsi_cmd[16], void *buffer,
- uint16_t bufsize) {
- (void)buffer;
- (void)bufsize;
- assert(_fuzz_data_provider.has_value());
- switch (scsi_cmd[0]) {
- case SCSI_CMD_TEST_UNIT_READY:
- break;
- case SCSI_CMD_INQUIRY:
- break;
- case SCSI_CMD_MODE_SELECT_6:
- break;
- case SCSI_CMD_MODE_SENSE_6:
- break;
- case SCSI_CMD_START_STOP_UNIT:
- break;
- case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
- break;
- case SCSI_CMD_READ_CAPACITY_10:
- break;
- case SCSI_CMD_REQUEST_SENSE:
- break;
- case SCSI_CMD_READ_FORMAT_CAPACITY:
- break;
- case SCSI_CMD_READ_10:
- break;
- case SCSI_CMD_WRITE_10:
- break;
- default:
- // Set Sense = Invalid Command Operation
- tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00);
- return _fuzz_data_provider->ConsumeIntegralInRange<int32_t>(
- std::numeric_limits<int32_t>::min(), -1);
- }
- return 0;
- }
- }
- #endif
|