msc_fuzz.cc 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. #include "fuzz/fuzz_private.h"
  2. #include "tusb.h"
  3. #include <cassert>
  4. #include <array>
  5. #include <limits>
  6. #if CFG_TUD_MSC==1
  7. // Whether host does safe eject.
  8. // tud_msc_get_maxlun_cb returns a uint8_t so the max logical units that are
  9. // allowed is 255, so we need to keep track of 255 fuzzed logical units.
  10. static std::array<bool, std::numeric_limits<uint8_t>::max()> ejected = {false};
  11. extern "C" {
  12. // Invoked when received SCSI_CMD_INQUIRY
  13. // Application fill vendor id, product id and revision with string up to 8, 16,
  14. // 4 characters respectively
  15. void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8],
  16. uint8_t product_id[16], uint8_t product_rev[4]) {
  17. (void)lun;
  18. assert(_fuzz_data_provider.has_value());
  19. std::string vid = _fuzz_data_provider->ConsumeBytesAsString(8);
  20. std::string pid = _fuzz_data_provider->ConsumeBytesAsString(16);
  21. std::string rev = _fuzz_data_provider->ConsumeBytesAsString(4);
  22. memcpy(vendor_id, vid.c_str(), strlen(vid.c_str()));
  23. memcpy(product_id, pid.c_str(), strlen(pid.c_str()));
  24. memcpy(product_rev, rev.c_str(), strlen(rev.c_str()));
  25. }
  26. // Invoked when received Test Unit Ready command.
  27. // return true allowing host to read/write this LUN e.g SD card inserted
  28. bool tud_msc_test_unit_ready_cb(uint8_t lun) {
  29. // RAM disk is ready until ejected
  30. if (ejected[lun]) {
  31. // Additional Sense 3A-00 is NOT_FOUND
  32. tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3a, 0x00);
  33. return false;
  34. }
  35. return _fuzz_data_provider->ConsumeBool();
  36. }
  37. // Invoked when received SCSI_CMD_READ_CAPACITY_10 and
  38. // SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size Application update
  39. // block count and block size
  40. void tud_msc_capacity_cb(uint8_t lun, uint32_t *block_count,
  41. uint16_t *block_size) {
  42. (void)lun;
  43. *block_count = _fuzz_data_provider->ConsumeIntegral<uint32_t>();
  44. *block_size = _fuzz_data_provider->ConsumeIntegral<uint16_t>();
  45. }
  46. // Invoked when received Start Stop Unit command
  47. // - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage
  48. // - Start = 1 : active mode, if load_eject = 1 : load disk storage
  49. bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start,
  50. bool load_eject) {
  51. (void)power_condition;
  52. assert(_fuzz_data_provider.has_value());
  53. if (load_eject) {
  54. if (start) {
  55. // load disk storage
  56. } else {
  57. // unload disk storage
  58. ejected[lun] = true;
  59. }
  60. }
  61. return _fuzz_data_provider->ConsumeBool();
  62. }
  63. // Callback invoked when received READ10 command.
  64. // Copy disk's data to buffer (up to bufsize) and return number of copied bytes.
  65. int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset,
  66. void *buffer, uint32_t bufsize) {
  67. assert(_fuzz_data_provider.has_value());
  68. (void)lun;
  69. (void)lba;
  70. (void)offset;
  71. std::vector<uint8_t> consumed_buffer = _fuzz_data_provider->ConsumeBytes<uint8_t>(
  72. _fuzz_data_provider->ConsumeIntegralInRange<uint32_t>(0, bufsize));
  73. memcpy(buffer, consumed_buffer.data(), consumed_buffer.size());
  74. // Sometimes return an error code;
  75. if (_fuzz_data_provider->ConsumeBool()) {
  76. return _fuzz_data_provider->ConsumeIntegralInRange(
  77. std::numeric_limits<int32_t>::min(), -1);
  78. }
  79. return consumed_buffer.size();
  80. }
  81. bool tud_msc_is_writable_cb(uint8_t lun) {
  82. assert(_fuzz_data_provider.has_value());
  83. (void)lun;
  84. return _fuzz_data_provider->ConsumeBool();
  85. }
  86. // Callback invoked when received WRITE10 command.
  87. // Process data in buffer to disk's storage and return number of written bytes
  88. int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset,
  89. uint8_t *buffer, uint32_t bufsize) {
  90. // Ignore these as they are outputs and don't affect the return value.
  91. (void)lun;
  92. (void)lba;
  93. (void)offset;
  94. (void)buffer;
  95. assert(_fuzz_data_provider.has_value());
  96. // -ve error codes -> bufsize.
  97. return _fuzz_data_provider->ConsumeIntegralInRange<int32_t>(
  98. std::numeric_limits<int32_t>::min(), bufsize);
  99. }
  100. // Callback invoked when received an SCSI command not in built-in list below
  101. // - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE
  102. // - READ10 and WRITE10 has their own callbacks
  103. int32_t tud_msc_scsi_cb(uint8_t lun, uint8_t const scsi_cmd[16], void *buffer,
  104. uint16_t bufsize) {
  105. (void)buffer;
  106. (void)bufsize;
  107. assert(_fuzz_data_provider.has_value());
  108. switch (scsi_cmd[0]) {
  109. case SCSI_CMD_TEST_UNIT_READY:
  110. break;
  111. case SCSI_CMD_INQUIRY:
  112. break;
  113. case SCSI_CMD_MODE_SELECT_6:
  114. break;
  115. case SCSI_CMD_MODE_SENSE_6:
  116. break;
  117. case SCSI_CMD_START_STOP_UNIT:
  118. break;
  119. case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
  120. break;
  121. case SCSI_CMD_READ_CAPACITY_10:
  122. break;
  123. case SCSI_CMD_REQUEST_SENSE:
  124. break;
  125. case SCSI_CMD_READ_FORMAT_CAPACITY:
  126. break;
  127. case SCSI_CMD_READ_10:
  128. break;
  129. case SCSI_CMD_WRITE_10:
  130. break;
  131. default:
  132. // Set Sense = Invalid Command Operation
  133. tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00);
  134. return _fuzz_data_provider->ConsumeIntegralInRange<int32_t>(
  135. std::numeric_limits<int32_t>::min(), -1);
  136. }
  137. return 0;
  138. }
  139. }
  140. #endif