msc_disk.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. /*
  2. * The MIT License (MIT)
  3. *
  4. * Copyright (c) 2019 Ha Thach (tinyusb.org)
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. * THE SOFTWARE.
  23. *
  24. */
  25. #include "bsp/board.h"
  26. #include "tusb.h"
  27. #include "flash.h"
  28. #include "fsm.h"
  29. #if CFG_TUD_MSC
  30. #define MSC_RO_ORIGIN (0x10180000)
  31. #define DISK_BLOCK_NUM 1024
  32. #define DISK_BLOCK_SIZE 512
  33. #define BLOCKS_PER_SECTOR (SPI_FLASH_SECTOR_SIZE / DISK_BLOCK_SIZE)
  34. extern const unsigned char disk0_img[];
  35. struct disk_lba {
  36. uint8_t data[DISK_BLOCK_SIZE];
  37. };
  38. static const uint8_t last_cluster_init_info[4] = { 0xF8, 0xFF, 0xFF, 0xFF };
  39. const uint8_t disk1_mbr[DISK_BLOCK_SIZE] = {
  40. 0xeb, 0x3c, 0x90, 0x6d, 0x6b, 0x66, 0x73, 0x2e, 0x66, 0x61, 0x74, 0x00,
  41. 0x02, 0x04, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x04, 0xf8, 0x01, 0x00,
  42. 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  43. 0x80, 0x00, 0x29, 0x9d, 0x0b, 0x6e, 0xd0, 'M', 'E', 'P', ' ', 'V',
  44. 'a', 'u', 'l', 't', 0x20, 0x20, 0x46, 0x41, 0x54, 0x31, 0x32, 0x20,
  45. 0x20, 0x20, 0x0e, 0x1f, 0xbe, 0x5b, 0x7c, 0xac, 0x22, 0xc0, 0x74, 0x0b,
  46. 0x56, 0xb4, 0x0e, 0xbb, 0x07, 0x00, 0xcd, 0x10, 0x5e, 0xeb, 0xf0, 0x32,
  47. 0xe4, 0xcd, 0x16, 0xcd, 0x19, 0xeb, 0xfe, 0x54, 0x68, 0x69, 0x73, 0x20,
  48. 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x20, 0x62, 0x6f, 0x6f,
  49. 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x64, 0x69, 0x73, 0x6b, 0x2e, 0x20,
  50. 0x20, 0x50, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x69, 0x6e, 0x73, 0x65,
  51. 0x72, 0x74, 0x20, 0x61, 0x20, 0x62, 0x6f, 0x6f, 0x74, 0x61, 0x62, 0x6c,
  52. 0x65, 0x20, 0x66, 0x6c, 0x6f, 0x70, 0x70, 0x79, 0x20, 0x61, 0x6e, 0x64,
  53. 0x0d, 0x0a, 0x70, 0x72, 0x65, 0x73, 0x73, 0x20, 0x61, 0x6e, 0x79, 0x20,
  54. 0x6b, 0x65, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x72, 0x79, 0x20, 0x61,
  55. 0x67, 0x61, 0x69, 0x6e, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x0d, 0x0a, 0x00,
  56. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  57. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  58. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  59. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  60. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  61. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  62. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  63. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  64. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  65. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  66. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  67. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  68. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  69. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  70. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  71. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  72. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  73. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  74. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  75. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  76. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  78. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  79. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  80. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  81. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  82. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa
  83. };
  84. // whether host does safe-eject
  85. static bool ejected = false;
  86. static struct disk_lba sector_cache[BLOCKS_PER_SECTOR];
  87. static int sector_cached = -1;
  88. static volatile int cache_busy = 1;
  89. static int sector_cache_load(uint32_t sector)
  90. {
  91. int ret;
  92. if (sector * SPI_FLASH_SECTOR_SIZE > DRIVE_FLASH_SIZE) {
  93. sector_cached = -1;
  94. return -1;
  95. }
  96. ret = flash_decrypt_read_sector(sector, sector_cache[0].data);
  97. if (ret < 0) {
  98. sector_cached = -1;
  99. return ret;
  100. }
  101. sector_cached = sector;
  102. return sector;
  103. }
  104. static inline void sector_cache_sched_commit(void)
  105. {
  106. cache_busy = 1;
  107. }
  108. static void sector_cache_commit(void)
  109. {
  110. int ret;
  111. uint32_t sector = sector_cached;
  112. if (sector * SPI_FLASH_SECTOR_SIZE > DRIVE_FLASH_SIZE) {
  113. cache_busy = 0;
  114. return;
  115. }
  116. flash_sector_erase(sector * SPI_FLASH_SECTOR_SIZE + DRIVE_FLASH_OFFSET);
  117. flash_encrypt_write_sector(sector, sector_cache[0].data);
  118. cache_busy = 0;
  119. }
  120. struct drive {
  121. const uint8_t lun;
  122. const char vid[8];
  123. const char pid[16];
  124. const char rev[4];
  125. const uint32_t n_lba;
  126. };
  127. #define N_DRIVES 2
  128. static uint8_t drv_active[N_DRIVES] = {1, 1};
  129. const char global_vid[8] = "DLX";
  130. const char host_pid[16] = "MEP Tools";
  131. const char vault_pid[16] = "MEP Vault";
  132. const char global_rev[4] = "0.1";
  133. static const struct drive Drives[N_DRIVES] = {
  134. { 0, "DLX", "MEP Tools", "0.1", 256},
  135. { 1, "DLX", "MEP Vault", "0.1", 1024}
  136. };
  137. uint8_t tud_msc_get_maxlun_cb(void)
  138. {
  139. #ifdef HAVE_VAULT
  140. return 2;
  141. #else
  142. return 1;
  143. #endif
  144. }
  145. // Invoked when received SCSI_CMD_INQUIRY
  146. // Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively
  147. void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4])
  148. {
  149. const struct drive *drv;
  150. if (lun >= N_DRIVES) {
  151. return;
  152. }
  153. drv = &Drives[lun];
  154. memcpy(vendor_id , drv->vid, strlen(drv->vid));
  155. memcpy(product_id , drv->pid, strlen(drv->pid));
  156. memcpy(product_rev, drv->rev, strlen(drv->rev));
  157. }
  158. // Invoked when received Test Unit Ready command.
  159. // return true allowing host to read/write this LUN e.g SD card inserted
  160. bool tud_msc_test_unit_ready_cb(uint8_t lun)
  161. {
  162. if (lun >= N_DRIVES) {
  163. tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3a, 0x00);
  164. return false;
  165. }
  166. if (drv_active[lun]) {
  167. return true;
  168. } else {
  169. tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3a, 0x00);
  170. return false;
  171. }
  172. }
  173. // Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size
  174. // Application update block count and block size
  175. void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size)
  176. {
  177. if (lun >= N_DRIVES) {
  178. *block_count = 0;
  179. *block_size = DISK_BLOCK_SIZE;
  180. } else {
  181. *block_count = Drives[lun].n_lba;
  182. *block_size = DISK_BLOCK_SIZE;
  183. }
  184. }
  185. // Invoked when received Start Stop Unit command
  186. // - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage
  187. // - Start = 1 : active mode, if load_eject = 1 : load disk storage
  188. bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject)
  189. {
  190. const struct drive *drv;
  191. (void) power_condition;
  192. if (lun < N_DRIVES) {
  193. drv = &Drives[lun];
  194. if ( load_eject )
  195. {
  196. if (start)
  197. {
  198. drv_active[lun] = 1;
  199. }else
  200. {
  201. drv_active[lun] = 0;
  202. }
  203. }
  204. }
  205. return true;
  206. }
  207. // Callback invoked when received READ10 command.
  208. // Copy disk's data to buffer (up to bufsize) and return number of copied bytes.
  209. int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize)
  210. {
  211. const struct drive *drv;
  212. uint32_t sector, sec_off;
  213. uint32_t remaining_bufsize = 0, total_bufsize = bufsize;
  214. if (lun >= N_DRIVES)
  215. return -1;
  216. drv = &Drives[lun];
  217. if ( lba >= drv->n_lba )
  218. return -1;
  219. if (lun == 0) {
  220. struct disk_lba *msc_ro = (struct disk_lba *)disk0_img;
  221. memcpy(buffer, msc_ro[lba].data + offset, bufsize);
  222. asm volatile("DMB");
  223. return bufsize;
  224. } else {
  225. if (fsm_get() < VAULT_MAIN_MENU) {
  226. memset(buffer, 0, bufsize);
  227. return bufsize;
  228. }
  229. sector = lba / BLOCKS_PER_SECTOR;
  230. sec_off = lba - (sector * BLOCKS_PER_SECTOR);
  231. do {
  232. if ( sector != sector_cached) {
  233. if (!cache_busy) {
  234. if (sector_cache_load(sector) != sector)
  235. return -1;
  236. } else {
  237. if (total_bufsize == bufsize)
  238. return -1;
  239. return total_bufsize - bufsize;
  240. }
  241. }
  242. if (sec_off * DISK_BLOCK_SIZE + offset + bufsize > SPI_FLASH_SECTOR_SIZE) {
  243. remaining_bufsize = bufsize;
  244. bufsize = SPI_FLASH_SECTOR_SIZE - (sec_off * DISK_BLOCK_SIZE + offset);
  245. remaining_bufsize -= bufsize;
  246. }
  247. memcpy(buffer, sector_cache[sec_off].data + offset, bufsize);
  248. asm volatile("DMB");
  249. if (remaining_bufsize > 0) {
  250. sector++;
  251. sec_off = 0;
  252. bufsize = remaining_bufsize;
  253. remaining_bufsize = 0;
  254. } else {
  255. break;
  256. }
  257. } while (bufsize > 0);
  258. return total_bufsize;
  259. }
  260. }
  261. bool tud_msc_is_writable_cb (uint8_t lun)
  262. {
  263. if (lun != 1) {
  264. /* Read only. */
  265. return false;
  266. } else {
  267. return true;
  268. }
  269. }
  270. // Callback invoked when received WRITE10 command.
  271. // Process data in buffer to disk's storage and return number of written bytes
  272. int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize)
  273. {
  274. uint32_t sector, sec_off;
  275. uint32_t remaining_bufsize = 0;
  276. uint32_t total_bufsize = bufsize;
  277. if (lun == 0)
  278. return bufsize;
  279. if ( lba >= Drives[lun].n_lba)
  280. return -1;
  281. if (fsm_get() < VAULT_MAIN_MENU)
  282. return -1;
  283. sector = lba / BLOCKS_PER_SECTOR;
  284. sec_off = lba - (sector * BLOCKS_PER_SECTOR);
  285. do {
  286. if ( sector != sector_cached) {
  287. while(cache_busy)
  288. sleep_ms(1);
  289. if (sector_cache_load(sector) < 0)
  290. return total_bufsize;
  291. }
  292. if (bufsize + sec_off * DISK_BLOCK_SIZE + offset > SPI_FLASH_SECTOR_SIZE) {
  293. remaining_bufsize = bufsize;
  294. bufsize = SPI_FLASH_SECTOR_SIZE - (sec_off * DISK_BLOCK_SIZE + offset);
  295. remaining_bufsize -= bufsize;
  296. } else {
  297. remaining_bufsize = 0;
  298. }
  299. if (bufsize == 0)
  300. return total_bufsize;
  301. memcpy(sector_cache[sec_off].data + offset, buffer, bufsize);
  302. sector_cache_sched_commit();
  303. if (remaining_bufsize > 0) {
  304. return total_bufsize;
  305. /*
  306. sector++;
  307. sec_off = 0;
  308. bufsize = remaining_bufsize;
  309. remaining_bufsize = 0;
  310. */
  311. } else {
  312. bufsize = 0;
  313. break;
  314. }
  315. } while (bufsize > 0);
  316. asm volatile("DMB");
  317. return total_bufsize;
  318. }
  319. // Callback invoked when received an SCSI command not in built-in list below
  320. // - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE
  321. // - READ10 and WRITE10 has their own callbacks
  322. int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize)
  323. {
  324. // read10 & write10 has their own callback and MUST not be handled here
  325. void const* response = NULL;
  326. int32_t resplen = 0;
  327. // most scsi handled is input
  328. bool in_xfer = true;
  329. switch (scsi_cmd[0])
  330. {
  331. case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
  332. // Host is about to read/write etc ... better not to disconnect disk
  333. resplen = 0;
  334. break;
  335. default:
  336. // Set Sense = Invalid Command Operation
  337. tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00);
  338. // negative means error -> tinyusb could stall and/or response with failed status
  339. resplen = -1;
  340. break;
  341. }
  342. // return resplen must not larger than bufsize
  343. if ( resplen > bufsize ) resplen = bufsize;
  344. if ( response && (resplen > 0) )
  345. {
  346. if(in_xfer)
  347. {
  348. memcpy(buffer, response, resplen);
  349. }else
  350. {
  351. // SCSI output
  352. }
  353. }
  354. return resplen;
  355. }
  356. void disk1_format(void)
  357. {
  358. uint8_t block[DISK_BLOCK_SIZE];
  359. int i, j;
  360. if (cryptoengine_check_vault() < 0)
  361. return;
  362. memset(block, 0, DISK_BLOCK_SIZE);
  363. for (i = 1; i < 5; i++) {
  364. if (sector_cached != i) {
  365. if (sector_cache_load(i) < 0)
  366. break;
  367. }
  368. for (j = 0; j < BLOCKS_PER_SECTOR; j++)
  369. memcpy(sector_cache[j].data, block, DISK_BLOCK_SIZE);
  370. sector_cache_commit();
  371. }
  372. /* Fill "last cluster" info */
  373. sector_cache_load(0);
  374. for (j = 0; j < BLOCKS_PER_SECTOR; j++)
  375. memcpy(sector_cache[j].data, block, DISK_BLOCK_SIZE);
  376. memcpy(sector_cache[0].data, disk1_mbr, DISK_BLOCK_SIZE);
  377. memcpy(sector_cache[1].data, last_cluster_init_info, 4);
  378. memcpy(sector_cache[2].data, last_cluster_init_info, 4);
  379. sector_cache_commit();
  380. }
  381. void disk_crypto_activate(int status)
  382. {
  383. drv_active[1] = status;
  384. if (status) {
  385. }
  386. }
  387. void msc_task(void) {
  388. if (cache_busy)
  389. sector_cache_commit();
  390. }
  391. #endif