support for file based and sd partition based emusd

This commit is contained in:
Christoph Baumann
2025-05-20 00:40:48 +02:00
parent 865b9dc1a4
commit 9b95d026f3
25 changed files with 1691 additions and 294 deletions

View File

@@ -0,0 +1,190 @@
#include "file_based_storage.h"
#include <libs/fatfs/ff.h>
#include <stdlib.h>
#include <string.h>
#include "gfx_utils.h"
typedef struct{
FIL active_file;
s32 active_file_idx;
char base_path[0x80];
u32 part_sz_sct;
u32 base_path_len;
}file_based_storage_ctxt_t;
static file_based_storage_ctxt_t ctx;
int file_based_storage_init(const char *base_path) {
ctx.active_file_idx = -0xff;
ctx.base_path_len = strlen(base_path);
strcpy(ctx.base_path, base_path);
strcat(ctx.base_path, "00");
gfx_printf("file based init %d %s\n", ctx.base_path_len, ctx.base_path);
FILINFO fi;
if(f_stat(ctx.base_path, &fi) != FR_OK) {
return 0;
}
if(fi.fsize) {
ctx.part_sz_sct = fi.fsize >> 9;
gfx_printf("file based init sz 0x%x\n", ctx.part_sz_sct);
}else{
return 0;
}
ctx.part_sz_sct = fi.fsize;
return 1;
}
void file_based_storage_end() {
if(ctx.active_file_idx != -0xff) {
f_close(&ctx.active_file);
}
ctx.active_file_idx = -0xff;
ctx.part_sz_sct = 0;
}
static int file_based_storage_change_file(const char *name, s32 idx) {
int res;
if(ctx.active_file_idx == idx){
return FR_OK;
}
if(ctx.active_file_idx != -0xff){
f_close(&ctx.active_file);
ctx.active_file_idx = -0xff;
}
strcpy(ctx.base_path + ctx.base_path_len, name);
#if FF_FS_READONLY == 1
res = f_open(&ctx.active_file, ctx.base_path, FA_READ);
#else
res = f_open(&ctx.active_file, ctx.base_path, FA_READ | FA_WRITE);
#endif
if(res != FR_OK){
gfx_printf("file based open fail %s\n", ctx.base_path);
return res;
}
ctx.active_file_idx = idx;
return FR_OK;
}
static int file_based_storage_readwrite_single(u32 sector, u32 num_sectors, void *buf, bool is_write){
#if FF_FS_READONLY == 1
if(is_write){
return FR_WRITE_PROTECTED;
}
#endif
int res = f_lseek(&ctx.active_file, (u64)sector << 9);
if(res != FR_OK){
return res;
}
if(is_write){
res = f_write(&ctx.active_file, buf, (u64)num_sectors << 9, NULL);
}else{
res = f_read(&ctx.active_file, buf, (u64)num_sectors << 9, NULL);
}
if(res != FR_OK){
gfx_printf("file based rw fail %s 0x%x 0x%x \n", ctx.base_path, num_sectors, sector);
return res;
}
return FR_OK;
}
int file_based_storage_readwrite(u32 sector, u32 num_sectors, void *buf, bool is_write) {
#if FF_FS_READONLY == 1
if(is_write){
return 0;
}
#endif
if(ctx.part_sz_sct == 0){
return 0;
}
int res;
u32 scts_left = num_sectors;
u32 cur_sct = sector;
while(scts_left){
u32 offset = cur_sct % ctx.part_sz_sct;
u32 sct_cnt = ctx.part_sz_sct - offset;
sct_cnt = MIN(scts_left, sct_cnt);
u32 file_idx = cur_sct / ctx.part_sz_sct;
if((s32) file_idx != ctx.active_file_idx) {
char name[3];
if(file_idx < 10){
strcpy(name, "0");
}
itoa(file_idx, name + strlen(name), 10);
res = file_based_storage_change_file(name, file_idx);
if(res != FR_OK){
return 0;
}
}
res = file_based_storage_readwrite_single(offset, sct_cnt, buf + ((u64)(num_sectors - scts_left) << 9), is_write);
if(res != FR_OK){
return 0;
}
cur_sct += sct_cnt;
scts_left -= sct_cnt;
}
f_sync(&ctx.active_file);
return 1;
}
int file_based_storage_read(u32 sector, u32 num_sectors, void *buf) {
return file_based_storage_readwrite(sector, num_sectors, buf, false);
}
int file_based_storage_write(u32 sector, u32 num_sectors, void *buf) {
return file_based_storage_readwrite(sector, num_sectors, buf, true);
}
u32 file_based_storage_get_total_size() {
u32 total_size_sct = 0;
char file_path[0x80];
u32 cur_idx = 0;
int res;
strcpy(file_path, ctx.base_path);
strcpy(file_path + ctx.base_path_len, "00");
FILINFO fi;
res = f_stat(file_path, &fi);
while(res == FR_OK){
cur_idx++;
total_size_sct += fi.fsize >> 9;
char name[3] = "0";
if(cur_idx >= 10){
name[0] = '\0';
}
itoa(cur_idx, name + strlen(name), 10);
strcpy(file_path + ctx.base_path_len, name);
res = f_stat(file_path, &fi);
}
return total_size_sct;
}

View File

@@ -0,0 +1,15 @@
#ifndef _FILE_BASED_STORAGE_H
#define _FILE_BASED_STORAGE_H
#include <bdk.h>
int file_based_storage_init(const char *base_path);
void file_based_storage_end();
int file_based_storage_read(u32 sector, u32 num_sectors, void *buf);
int file_based_storage_write(u32 sector, u32 num_sectors, void *buf);
u32 file_based_storage_get_total_size();
#endif

View File

@@ -35,6 +35,7 @@ typedef enum _sdmmc_type
MMC_EMUMMC_RAW_SD = 3,
MMC_EMUMMC_RAW_EMMC = 4,
MMC_EMUMMC_FILE_EMMC = 5,
MMC_FILE_BASED = 6,
EMMC_GPP = 0,
EMMC_BOOT0 = 1,

View File

@@ -21,6 +21,7 @@
#include <storage/emmc.h>
#include <storage/emummc_file_based.h>
#include <storage/file_based_storage.h>
#include <string.h>
#include <usb/usbd.h>
@@ -500,6 +501,10 @@ static int _scsi_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
if(ums->lun.storage){
if (!sdmmc_storage_read(ums->lun.storage, ums->lun.offset + lba_offset, amount, sdmmc_buf))
amount = 0;
}else if (ums->lun.type == MMC_FILE_BASED) {
if(!file_based_storage_read(ums->lun.offset + lba_offset, amount, sdmmc_buf)){
amount = 0;
}
}else{
if(!emummc_storage_file_based_read(ums->lun.offset + lba_offset, amount, sdmmc_buf)){
amount = 0;
@@ -662,6 +667,10 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
if (!sdmmc_storage_write(ums->lun.storage, ums->lun.offset + lba_offset,
amount >> UMS_DISK_LBA_SHIFT, (u8 *)bulk_ctxt->bulk_out_buf))
amount = 0;
}else if(ums->lun.type == MMC_FILE_BASED){
if(!file_based_storage_write(ums->lun.offset + lba_offset, amount >> UMS_DISK_LBA_SHIFT, (u8*)bulk_ctxt->bulk_out_buf)){
amount = 0;
}
}else{
if(!emummc_storage_file_based_write(ums->lun.offset + lba_offset, amount >> UMS_DISK_LBA_SHIFT, (u8*)bulk_ctxt->bulk_out_buf)){
amount = 0;
@@ -739,6 +748,10 @@ static int _scsi_verify(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
if(ums->lun.storage){
if (!sdmmc_storage_read(ums->lun.storage, ums->lun.offset + lba_offset, amount, bulk_ctxt->bulk_in_buf))
amount = 0;
}else if(ums->lun.type == MMC_FILE_BASED){
if(!file_based_storage_read(ums->lun.offset + lba_offset, amount, bulk_ctxt->bulk_in_buf)){
amount = 0;
}
}else{
if(!emummc_storage_file_based_read(ums->lun.offset + lba_offset, amount, bulk_ctxt->bulk_in_buf)){
amount = 0;
@@ -1934,6 +1947,10 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
}
ums.lun.storage = NULL;
ums.lun.sdmmc = NULL;
}else if(usbs->type == MMC_FILE_BASED){
// file based must be initialized at this point
ums.lun.storage = NULL;
ums.lun.sdmmc = NULL;
} else{
if (!emmc_initialize(false))
{
@@ -1980,6 +1997,9 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
case MMC_EMUMMC_RAW_EMMC:
ums.set_text(ums.label, "#FFDD00 No sector count set for emuMMC!#");
break;
case MMC_FILE_BASED:
ums.set_text(ums.label, "#FFDD00 No sector count set for emuSD!#");
break;
}
}