diff --git a/CMakeLists.txt b/CMakeLists.txt index b811f44..7a41915 100644 --- a/CMakeLists.txt +++ b/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 diff --git a/README.md b/README.md index 86715d9..43b641e 100644 --- a/README.md +++ b/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 ``` diff --git a/msc_content/Makefile b/msc_content/Makefile index 058f708..a3b7499 100644 --- a/msc_content/Makefile +++ b/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: + diff --git a/pico-sdk/src/rp2_common/pico_standard_link/memmap_default.ld b/pico-sdk/src/rp2_common/pico_standard_link/memmap_default.ld index 07d5812..07fc84b 100644 --- a/pico-sdk/src/rp2_common/pico_standard_link/memmap_default.ld +++ b/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); diff --git a/src/msc_disk.c b/src/msc_disk.c index a20ee41..2888fe4 100644 --- a/src/msc_disk.c +++ b/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; -#define README_CONTENTS \ -"This is the password vault utilities directory.\r\n\r\nWork in progress\r\n" - -enum -{ - DISK_BLOCK_NUM = 16, // 8KB is the smallest size that windows allow to mount - DISK_BLOCK_SIZE = 512 +struct drive { + const uint8_t lun; + const char vid[8]; + const char pid[16]; + const char rev[4]; + const uint32_t n_lba; }; -#ifdef CFG_EXAMPLE_MSC_READONLY -const -#endif -uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = -{ - //------------- 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, +#define N_DRIVES 2 - // 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, +static uint8_t drv_active[N_DRIVES] = {1, 0}; - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +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"; - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 +static const struct drive Drives[N_DRIVES] = { + { 0, "DLX", "MEP Tools", "0.1", 1024}, + { 1, "DLX", "MEP Vault", "0.1", 1024} }; + +uint8_t tud_msc_get_maxlun_cb(void) +{ + 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; + const struct drive *drv; + (void) power_condition; - if ( load_eject ) - { - if (start) - { - // load disk storage - }else - { - // unload disk storage - ejected = true; + 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; + const struct drive *drv; + uint8_t const *addr; + if (lun >= N_DRIVES) + return -1; + drv = &Drives[lun]; - uint8_t const* addr = msc_disk[lba] + offset; - memcpy(buffer, addr, bufsize); + if ( lba >= drv->n_lba ) + return -1; - return bufsize; + + + + 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; - } - - // return resplen must not larger than bufsize - if ( resplen > bufsize ) resplen = bufsize; - - if ( response && (resplen > 0) ) - { - if(in_xfer) + switch (scsi_cmd[0]) { - memcpy(buffer, response, resplen); - }else - { - // SCSI output + 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; + // return resplen must not larger than bufsize + if ( resplen > bufsize ) resplen = bufsize; + + if ( response && (resplen > 0) ) + { + if(in_xfer) + { + memcpy(buffer, response, resplen); + }else + { + // SCSI output + } + } + + return resplen; } #endif