Browse Source

Added read-only USB drive with host utils for linux

Daniele Lacamera 10 months ago
parent
commit
f49e1a5eb7
5 changed files with 184 additions and 163 deletions
  1. 1 0
      CMakeLists.txt
  2. 1 0
      README.md
  3. 21 2
      msc_content/Makefile
  4. 12 1
      pico-sdk/src/rp2_common/pico_standard_link/memmap_default.ld
  5. 149 160
      src/msc_disk.c

+ 1 - 0
CMakeLists.txt

@@ -25,6 +25,7 @@ target_sources(${PROJECT} PUBLIC
         ${CMAKE_CURRENT_SOURCE_DIR}/src/fsm.c
         ${CMAKE_CURRENT_SOURCE_DIR}/src/flash.c
         ${CMAKE_CURRENT_SOURCE_DIR}/src/hid.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/src/disk0.c
         ${CMAKE_CURRENT_SOURCE_DIR}/lib/wolfssl/wolfcrypt/src/wc_port.c
         ${CMAKE_CURRENT_SOURCE_DIR}/lib/wolfssl/wolfcrypt/src/wolfmath.c
         ${CMAKE_CURRENT_SOURCE_DIR}/lib/wolfssl/wolfcrypt/src/hash.c

+ 1 - 0
README.md

@@ -164,6 +164,7 @@ To compile the firmware run the following from the source directory:
 ```
 mkdir build
 cd build
+make -C ../msc_content
 cmake .. -DFAMILY=rp2040 -DPICO_SDK_PATH=/path/to/motenpoche/pico-sdk
 ```
 

+ 21 - 2
msc_content/Makefile

@@ -1,7 +1,26 @@
-all: mep 
+all: ../src/disk0.c
 	
 mep: mep.c
 	gcc -g -ggdb -o mep mep.c -lwolfssl
 
+../src/disk0.c: mep FORCE
+	dd if=/dev/zero of=disk0.img bs=1K count=128
+	sudo mkfs.vfat disk0.img
+	sudo mkdir -p tmpfs
+	sudo mount -o loop disk0.img tmpfs
+	sudo mkdir -p tmpfs/mep
+	sudo cp mep.c mep tmpfs/mep
+	sudo cp Makefile.flash tmpfs/mep/Makefile
+	sudo cp ../README.md tmpfs
+	sudo umount tmpfs
+	xxd -i disk0.img | sed -e "s/unsigned/const unsigned/g" \
+	   | sed -e "s/char/char __attribute__((section(\".disk0\")))/g" > ../src/disk0.c 
+	
+
 clean:
-	rm -f mep
+	rm -f mep fatfs ../fatfs.ld
+	sudo umount tmpfs || true
+	sudo rm -rf tmpfs
+
+FORCE: 
+

+ 12 - 1
pico-sdk/src/rp2_common/pico_standard_link/memmap_default.ld

@@ -21,6 +21,7 @@
     __stack (== StackTop)
 */
 
+
 MEMORY
 {
     FLASH(rx) : ORIGIN = 0x10000000, LENGTH = 2048k
@@ -93,6 +94,13 @@ SECTIONS
         *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*)))
         . = ALIGN(4);
     } > FLASH
+    
+    .fatfs_rodata : {
+        . = ALIGN(512);
+        __fatfs_start = .;
+        KEEP(*(.disk0*));
+        __fatfs_end = .;
+    } > FLASH
 
     .ARM.extab :
     {
@@ -115,7 +123,8 @@ SECTIONS
         *(.binary_info.*)
     } > FLASH
     __binary_info_end = .;
-    . = ALIGN(4);
+
+
 
     /* End of .text-like segments */
     __etext = .;
@@ -178,6 +187,7 @@ SECTIONS
         . = ALIGN(4);
         *(.uninitialized_data*)
     } > RAM
+    
 
     /* Start and end symbols must be word-aligned */
     .scratch_x : {
@@ -234,6 +244,7 @@ SECTIONS
     .flash_end : {
         __flash_binary_end = .;
     } > FLASH
+    
 
     /* stack limit is poorly named, but historically is maximum heap ptr */
     __StackLimit = ORIGIN(RAM) + LENGTH(RAM);

+ 149 - 160
src/msc_disk.c

@@ -28,133 +28,93 @@
 
 #if CFG_TUD_MSC
 
+#define MSC_RO_ORIGIN (0x10180000)
+#define DISK_BLOCK_NUM 1024
+#define DISK_BLOCK_SIZE 512
+
+extern const unsigned char disk0_img[];
+
+struct disk_lba {
+    uint8_t data[DISK_BLOCK_SIZE];
+};
+
+
 // whether host does safe-eject
 static bool ejected = false;
 
-// Some MCU doesn't have enough 8KB SRAM to store the whole disk
-// We will use Flash as read-only disk with board that has
-// CFG_EXAMPLE_MSC_READONLY defined
+static struct disk_lba lba_cache;
+static int lba_cached = -1;
+
+struct drive {
+    const uint8_t lun;
+    const char vid[8];
+    const char pid[16];
+    const char rev[4];
+    const uint32_t n_lba;
+};
 
-#define README_CONTENTS \
-"This is the password vault utilities directory.\r\n\r\nWork in progress\r\n"
+#define N_DRIVES 2
 
-enum
-{
-  DISK_BLOCK_NUM  = 16, // 8KB is the smallest size that windows allow to mount
-  DISK_BLOCK_SIZE = 512
+static uint8_t drv_active[N_DRIVES] = {1, 0};
+
+
+const char global_vid[8] = "DLX";
+const char host_pid[16] = "MEP Tools";
+const char vault_pid[16] = "MEP Vault";
+const char global_rev[4] = "0.1";
+
+static const struct drive Drives[N_DRIVES] = { 
+    { 0, "DLX", "MEP Tools", "0.1", 1024},
+    { 1, "DLX", "MEP Vault", "0.1", 1024}
 };
 
-#ifdef CFG_EXAMPLE_MSC_READONLY
-const
-#endif
-uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] =
+
+uint8_t tud_msc_get_maxlun_cb(void)
 {
-  //------------- Block0: Boot Sector -------------//
-  // byte_per_sector    = DISK_BLOCK_SIZE; fat12_sector_num_16  = DISK_BLOCK_NUM;
-  // sector_per_cluster = 1; reserved_sectors = 1;
-  // fat_num            = 1; fat12_root_entry_num = 16;
-  // sector_per_fat     = 1; sector_per_track = 1; head_num = 1; hidden_sectors = 0;
-  // drive_number       = 0x80; media_type = 0xf8; extended_boot_signature = 0x29;
-  // filesystem_type    = "FAT12   "; volume_serial_number = 0x1234; volume_label = "TinyUSB MSC";
-  // FAT magic code at offset 510-511
-  {
-      0xEB, 0x3C, 0x90, 0x4D, 0x53, 0x44, 0x4F, 0x53, 0x35, 0x2E, 0x30, 0x00, 0x02, 0x01, 0x01, 0x00,
-      0x01, 0x10, 0x00, 0x10, 0x00, 0xF8, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x29, 0x34, 0x12, 0x00, 0x00, 'V' , 'a' , 'u' , 'l' , 't' ,
-      ' ' , 'T' , 'o' , 'o' , 'l' , 's' , 0x46, 0x41, 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, 0x00, 0x00,
-
-      // Zero up to 2 last bytes of FAT magic code
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA
-  },
-
-  //------------- Block1: FAT12 Table -------------//
-  {
-      0xF8, 0xFF, 0xFF, 0xFF, 0x0F // // first 2 entries must be F8FF, third entry is cluster end of readme file
-  },
-
-  //------------- Block2: Root Directory -------------//
-  {
-      // first entry is volume label
-      'V' , 'a' , 'u' , 'l' , 't' , ' ' , 'T' , 'o' , 'o' , 'l' , 's' , 0x08, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4F, 0x6D, 0x65, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      // second entry is readme file
-      'R' , 'E' , 'A' , 'D' , 'M' , 'E' , ' ' , ' ' , 'T' , 'X' , 'T' , 0x20, 0x00, 0xC6, 0x52, 0x6D,
-      0x65, 0x43, 0x65, 0x43, 0x00, 0x00, 0x88, 0x6D, 0x65, 0x43, 0x02, 0x00,
-      sizeof(README_CONTENTS)-1, 0x00, 0x00, 0x00 // readme's files size (4 Bytes)
-  },
-
-  //------------- Block3: Readme Content -------------//
-  README_CONTENTS
-};
+  return 1;
+}
 
 // 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;
-
-  const char vid[] = "DLX";
-  const char pid[] = "Vault tools";
-  const char rev[] = "0.1a";
-
-  memcpy(vendor_id  , vid, strlen(vid));
-  memcpy(product_id , pid, strlen(pid));
-  memcpy(product_rev, rev, strlen(rev));
+    const struct drive *drv;
+    if (lun >= N_DRIVES) {
+        return;
+    }
+    drv = &Drives[lun];
+    memcpy(vendor_id  , drv->vid, strlen(drv->vid));
+    memcpy(product_id , drv->pid, strlen(drv->pid));
+    memcpy(product_rev, drv->rev, strlen(drv->rev));
 }
 
 // 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)
 {
-  (void) lun;
-
-  // RAM disk is ready until ejected
-  if (ejected) {
-    tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3a, 0x00);
-    return false;
-  }
-
-  return true;
+    if (lun >= N_DRIVES) {
+        tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3a, 0x00);
+        return false;
+    }
+    if (drv_active[lun]) {
+        return true;
+    } else {
+        tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3a, 0x00);
+        return false;
+    }
 }
 
 // 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 = DISK_BLOCK_NUM;
-  *block_size  = DISK_BLOCK_SIZE;
+    if (lun >= N_DRIVES) {
+        *block_count = DISK_BLOCK_NUM;
+        *block_size  = DISK_BLOCK_SIZE;
+    } else {
+        *block_count = Drives[lun].n_lba;
+        *block_size  = DISK_BLOCK_SIZE;
+    }
 }
 
 // Invoked when received Start Stop Unit command
@@ -162,45 +122,74 @@ void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_siz
 // - 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) lun;
-  (void) power_condition;
-
-  if ( load_eject )
-  {
-    if (start)
-    {
-      // load disk storage
-    }else
-    {
-      // unload disk storage
-      ejected = true;
+    const struct drive *drv;
+    (void) power_condition;
+
+    if (lun < N_DRIVES) {
+        drv = &Drives[lun];
+        if ( load_eject )
+        {
+            if (start)
+            {
+                drv_active[lun] = 1;
+            }else
+            {
+                drv_active[lun] = 0;
+            }
+        }
     }
-  }
-
-  return true;
+    return true;
 }
 
 // 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)
 {
-  (void) lun;
-
-  // out of ramdisk
-  if ( lba >= DISK_BLOCK_NUM ) return -1;
-
-  uint8_t const* addr = msc_disk[lba] + offset;
-  memcpy(buffer, addr, bufsize);
 
-  return bufsize;
+    const struct drive *drv;
+    uint8_t const *addr;
+    if (lun >= N_DRIVES)
+        return -1;
+    drv = &Drives[lun];
+
+    if ( lba >= drv->n_lba )
+        return -1;
+
+
+
+
+    if (lun == 0) {
+        struct disk_lba *msc_ro = (struct disk_lba *)disk0_img;
+        memcpy(buffer, msc_ro[lba].data + offset, bufsize);
+        asm volatile("DMB");
+        return bufsize;
+    } else {
+#if 0
+        if ( lba != lba_cached) {
+            if (lba == 0) {
+                memcpy(lba_cache.data, mbr.data, sizeof(struct disk_lba)); 
+                lba_cached = lba;
+                return 0;
+            }
+            memcpy(lba_cache.data, msc_ro[lba].data, sizeof(struct disk_lba)); 
+            lba_cached = lba;
+            return 0;
+        }
+        memcpy(buffer, lba_cache.data + offset, bufsize);
+#endif
+        memset(buffer, 0xA5, bufsize);
+        return bufsize;
+    }
 }
 
 bool tud_msc_is_writable_cb (uint8_t lun)
 {
-  (void) lun;
-
-  /* Read only. */
-  return false;
+    if (lun != 1) {
+      /* Read only. */
+      return false;
+    } else {
+        return true;
+    }
 }
 
 // Callback invoked when received WRITE10 command.
@@ -221,45 +210,45 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t*
 // - 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)
 {
-  // read10 & write10 has their own callback and MUST not be handled here
+    // read10 & write10 has their own callback and MUST not be handled here
 
-  void const* response = NULL;
-  int32_t resplen = 0;
+    void const* response = NULL;
+    int32_t resplen = 0;
 
-  // most scsi handled is input
-  bool in_xfer = true;
+    // most scsi handled is input
+    bool in_xfer = true;
 
-  switch (scsi_cmd[0])
-  {
-    case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
-      // Host is about to read/write etc ... better not to disconnect disk
-      resplen = 0;
-    break;
-
-    default:
-      // Set Sense = Invalid Command Operation
-      tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00);
-
-      // negative means error -> tinyusb could stall and/or response with failed status
-      resplen = -1;
-    break;
-  }
+    switch (scsi_cmd[0])
+    {
+        case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
+            // Host is about to read/write etc ... better not to disconnect disk
+            resplen = 0;
+            break;
+
+        default:
+            // Set Sense = Invalid Command Operation
+            tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00);
+
+            // negative means error -> tinyusb could stall and/or response with failed status
+            resplen = -1;
+            break;
+    }
 
-  // return resplen must not larger than bufsize
-  if ( resplen > bufsize ) resplen = bufsize;
+    // return resplen must not larger than bufsize
+    if ( resplen > bufsize ) resplen = bufsize;
 
-  if ( response && (resplen > 0) )
-  {
-    if(in_xfer)
-    {
-      memcpy(buffer, response, resplen);
-    }else
+    if ( response && (resplen > 0) )
     {
-      // SCSI output
+        if(in_xfer)
+        {
+            memcpy(buffer, response, resplen);
+        }else
+        {
+            // SCSI output
+        }
     }
-  }
 
-  return resplen;
+    return resplen;
 }
 
 #endif