msc_disk.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  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. static 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, 0x4e, 0x4f, 0x20, 0x4e, 0x41,
  44. 0x4d, 0x45, 0x20, 0x20, 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 int sector_cache_load(uint32_t sector)
  89. {
  90. int ret;
  91. if (sector * SPI_FLASH_SECTOR_SIZE > DRIVE_FLASH_SIZE) {
  92. sector_cached = -1;
  93. return -1;
  94. }
  95. //ret = flash_decrypt_read_sector(sector, sector_cache[0].data);
  96. ret = flash_read(sector * SPI_FLASH_SECTOR_SIZE + DRIVE_FLASH_OFFSET,
  97. sector_cache[0].data, SPI_FLASH_SECTOR_SIZE);
  98. if (ret < 0) {
  99. sector_cached = -1;
  100. return ret;
  101. }
  102. sector_cached = sector;
  103. }
  104. static void sector_cache_commit(void)
  105. {
  106. int ret;
  107. uint32_t sector = sector_cached;
  108. if (sector * SPI_FLASH_SECTOR_SIZE > DRIVE_FLASH_SIZE)
  109. return;
  110. //flash_encrypt_write_sector(sector, sector_cache[0].data);
  111. flash_write(sector * SPI_FLASH_SECTOR_SIZE + DRIVE_FLASH_OFFSET,
  112. sector_cache[0].data, SPI_FLASH_SECTOR_SIZE);
  113. }
  114. struct drive {
  115. const uint8_t lun;
  116. const char vid[8];
  117. const char pid[16];
  118. const char rev[4];
  119. const uint32_t n_lba;
  120. };
  121. #define N_DRIVES 2
  122. static uint8_t drv_active[N_DRIVES] = {1, 1};
  123. const char global_vid[8] = "DLX";
  124. const char host_pid[16] = "MEP Tools";
  125. const char vault_pid[16] = "MEP Vault";
  126. const char global_rev[4] = "0.1";
  127. static const struct drive Drives[N_DRIVES] = {
  128. { 0, "DLX", "MEP Tools", "0.1", 256},
  129. { 1, "DLX", "MEP Vault", "0.1", 1024}
  130. };
  131. uint8_t tud_msc_get_maxlun_cb(void)
  132. {
  133. return 2;
  134. }
  135. // Invoked when received SCSI_CMD_INQUIRY
  136. // Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively
  137. void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4])
  138. {
  139. const struct drive *drv;
  140. if (lun >= N_DRIVES) {
  141. return;
  142. }
  143. drv = &Drives[lun];
  144. memcpy(vendor_id , drv->vid, strlen(drv->vid));
  145. memcpy(product_id , drv->pid, strlen(drv->pid));
  146. memcpy(product_rev, drv->rev, strlen(drv->rev));
  147. }
  148. // Invoked when received Test Unit Ready command.
  149. // return true allowing host to read/write this LUN e.g SD card inserted
  150. bool tud_msc_test_unit_ready_cb(uint8_t lun)
  151. {
  152. if (lun >= N_DRIVES) {
  153. tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3a, 0x00);
  154. return false;
  155. }
  156. if (drv_active[lun]) {
  157. return true;
  158. } else {
  159. tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3a, 0x00);
  160. return false;
  161. }
  162. }
  163. // Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size
  164. // Application update block count and block size
  165. void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size)
  166. {
  167. if (lun >= N_DRIVES) {
  168. *block_count = 0;
  169. *block_size = DISK_BLOCK_SIZE;
  170. } else {
  171. *block_count = Drives[lun].n_lba;
  172. *block_size = DISK_BLOCK_SIZE;
  173. }
  174. }
  175. // Invoked when received Start Stop Unit command
  176. // - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage
  177. // - Start = 1 : active mode, if load_eject = 1 : load disk storage
  178. bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject)
  179. {
  180. const struct drive *drv;
  181. (void) power_condition;
  182. if (lun < N_DRIVES) {
  183. drv = &Drives[lun];
  184. if ( load_eject )
  185. {
  186. if (start)
  187. {
  188. drv_active[lun] = 1;
  189. }else
  190. {
  191. drv_active[lun] = 0;
  192. }
  193. }
  194. }
  195. return true;
  196. }
  197. // Callback invoked when received READ10 command.
  198. // Copy disk's data to buffer (up to bufsize) and return number of copied bytes.
  199. int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize)
  200. {
  201. const struct drive *drv;
  202. uint32_t sector, sec_off;
  203. if (lun >= N_DRIVES)
  204. return -1;
  205. drv = &Drives[lun];
  206. if ( lba >= drv->n_lba )
  207. return -1;
  208. if (lun == 0) {
  209. struct disk_lba *msc_ro = (struct disk_lba *)disk0_img;
  210. memcpy(buffer, msc_ro[lba].data + offset, bufsize);
  211. asm volatile("DMB");
  212. return bufsize;
  213. } else {
  214. if (fsm_get() < VAULT_MAIN_MENU) {
  215. memset(buffer, 0, bufsize);
  216. return bufsize;
  217. }
  218. if (lba == 0) {
  219. memcpy(buffer, disk1_mbr + offset, bufsize);
  220. return bufsize;
  221. }
  222. sector = lba / BLOCKS_PER_SECTOR;
  223. sec_off = lba - (sector * BLOCKS_PER_SECTOR);
  224. if ( sector != sector_cached) {
  225. sector_cache_load(sector);
  226. return 0;
  227. }
  228. memcpy(buffer, sector_cache[sec_off].data + offset, bufsize);
  229. asm volatile("DMB");
  230. return bufsize;
  231. }
  232. }
  233. bool tud_msc_is_writable_cb (uint8_t lun)
  234. {
  235. if (lun != 1) {
  236. /* Read only. */
  237. return false;
  238. } else {
  239. return true;
  240. }
  241. }
  242. // Callback invoked when received WRITE10 command.
  243. // Process data in buffer to disk's storage and return number of written bytes
  244. int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize)
  245. {
  246. uint32_t sector, sec_off;
  247. if (lun == 0)
  248. return bufsize;
  249. /*
  250. if (lba == 0)
  251. return bufsize;
  252. */
  253. if ( lba >= Drives[lun].n_lba)
  254. return -1;
  255. if (fsm_get() < VAULT_MAIN_MENU)
  256. return -1;
  257. sector = lba / BLOCKS_PER_SECTOR;
  258. sec_off = lba - (sector * BLOCKS_PER_SECTOR);
  259. if ( sector != sector_cached) {
  260. sector_cache_load(sector);
  261. }
  262. memcpy(sector_cache[sec_off].data + offset, buffer, bufsize);
  263. sector_cache_commit();
  264. asm volatile("DMB");
  265. return bufsize;
  266. }
  267. // Callback invoked when received an SCSI command not in built-in list below
  268. // - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE
  269. // - READ10 and WRITE10 has their own callbacks
  270. int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize)
  271. {
  272. // read10 & write10 has their own callback and MUST not be handled here
  273. void const* response = NULL;
  274. int32_t resplen = 0;
  275. // most scsi handled is input
  276. bool in_xfer = true;
  277. switch (scsi_cmd[0])
  278. {
  279. case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
  280. // Host is about to read/write etc ... better not to disconnect disk
  281. resplen = 0;
  282. break;
  283. default:
  284. // Set Sense = Invalid Command Operation
  285. tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00);
  286. // negative means error -> tinyusb could stall and/or response with failed status
  287. resplen = -1;
  288. break;
  289. }
  290. // return resplen must not larger than bufsize
  291. if ( resplen > bufsize ) resplen = bufsize;
  292. if ( response && (resplen > 0) )
  293. {
  294. if(in_xfer)
  295. {
  296. memcpy(buffer, response, resplen);
  297. }else
  298. {
  299. // SCSI output
  300. }
  301. }
  302. return resplen;
  303. }
  304. void disk1_format(void)
  305. {
  306. uint8_t block[DISK_BLOCK_SIZE];
  307. int i, j;
  308. if (cryptoengine_check_vault() < 0)
  309. return;
  310. memset(block, 0, DISK_BLOCK_SIZE);
  311. for (i = 1; i < 5; i++) {
  312. if (sector_cached != i) {
  313. sector_cache_load(i);
  314. }
  315. for (j = 0; j < BLOCKS_PER_SECTOR; j++)
  316. memcpy(sector_cache[j].data, block, DISK_BLOCK_SIZE);
  317. sector_cache_commit();
  318. }
  319. /* Fill "last cluster" info */
  320. sector_cache_load(0);
  321. for (j = 0; j < BLOCKS_PER_SECTOR; j++)
  322. memcpy(sector_cache[j].data, block, DISK_BLOCK_SIZE);
  323. memcpy(sector_cache[0].data, disk1_mbr, DISK_BLOCK_SIZE);
  324. memcpy(sector_cache[1].data, last_cluster_init_info, 4);
  325. memcpy(sector_cache[2].data, last_cluster_init_info, 4);
  326. sector_cache_commit();
  327. }
  328. void disk_crypto_activate(int status)
  329. {
  330. drv_active[1] = status;
  331. if (status) {
  332. }
  333. }
  334. #endif