| 
									
										
										
										
											2022-11-10 02:09:58 +00:00
										 |  |  | #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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-17 16:12:49 +07:00
										 |  |  | #endif
 |