From 9309b0bed5ad18376096d4f6afc2a266a849c5dc Mon Sep 17 00:00:00 2001 From: TuxSH Date: Thu, 17 May 2018 01:53:32 +0200 Subject: [PATCH] Don't overflow devoptabs, etc. --- fusee/fusee-secondary/src/fs_dev.c | 113 ++++++++++++++++++++------ fusee/fusee-secondary/src/fs_dev.h | 7 +- fusee/fusee-secondary/src/raw_dev.c | 85 +++++++++++++++---- fusee/fusee-secondary/src/raw_dev.h | 4 +- fusee/fusee-secondary/src/switch_fs.c | 54 ++++++++---- 5 files changed, 203 insertions(+), 60 deletions(-) diff --git a/fusee/fusee-secondary/src/fs_dev.c b/fusee/fusee-secondary/src/fs_dev.c index 8d185fff1..39af77c98 100644 --- a/fusee/fusee-secondary/src/fs_dev.c +++ b/fusee/fusee-secondary/src/fs_dev.c @@ -10,6 +10,10 @@ #include "lib/fatfs/ff.h" +#if FF_VOLUMES != 10 +#error "FatFs misconfigured, expected FF_VOLUMES == 10" +#endif + #include "fs_dev.h" /* Quite a bit of code comes from https://github.com/switchbrew/libnx/blob/master/nx/source/runtime/devices/fs_dev.c */ @@ -67,15 +71,15 @@ static devoptab_t g_fsdev_devoptab = { .rmdir_r = fsdev_rmdir, }; -typedef struct fsdev_fsdevice_t { +typedef struct fsdev_device_t { devoptab_t devoptab; device_partition_t devpart; FATFS fatfs; char name[32+1]; - bool setup; -} fsdev_fsdevice_t; + bool setup, registered; +} fsdev_device_t; -static fsdev_fsdevice_t g_fsdev_devices[FF_VOLUMES] = { 0 }; +static fsdev_device_t g_fsdev_devices[FF_VOLUMES] = { 0 }; /* Required by ff.c */ /* FF_VOLUMES = 10 */ @@ -86,10 +90,26 @@ const char *VolumeStr[FF_VOLUMES] = { FKNAM, FKNAM, FKNAM, FKNAM, FKNAM, FKNAM, /* For diskio.c code */ device_partition_t *g_volume_to_devparts[FF_VOLUMES] = { NULL }; +static fsdev_device_t *fsdev_find_device(const char *name) { + for (size_t i = 0; i < FF_VOLUMES; i++) { + if (g_fsdev_devices[i].setup && strcmp(g_fsdev_devices[i].name, name) == 0) { + return &g_fsdev_devices[i]; + } + } + + return NULL; +} + int fsdev_mount_device(const char *name, const device_partition_t *devpart, bool initialize_immediately) { - fsdev_fsdevice_t *device = NULL; + fsdev_device_t *device = fsdev_find_device(name); FRESULT rc; char drname[40]; + + if (device != NULL) { + errno = EEXIST; /* Device already exists */ + return -1; + } + strcpy(drname, name); strcat(drname, ":"); @@ -102,10 +122,6 @@ int fsdev_mount_device(const char *name, const device_partition_t *devpart, bool return -1; } - if (FindDevice(drname) != -1) { - errno = EEXIST; /* Device already exists */ - return -1; - } /* Find an unused slot. */ for(size_t i = 0; i < FF_VOLUMES; i++) { if (!g_fsdev_devices[i].setup) { @@ -118,6 +134,7 @@ int fsdev_mount_device(const char *name, const device_partition_t *devpart, bool return -1; } + memset(device, 0, sizeof(fsdev_device_t)); strcpy(device->name, name); device->devoptab = g_fsdev_devoptab; @@ -132,17 +149,60 @@ int fsdev_mount_device(const char *name, const device_partition_t *devpart, bool rc = f_mount(&device->fatfs, drname, initialize_immediately ? 1 : 0); if (rc != FR_OK) { + g_volume_to_devparts[device - g_fsdev_devices] = NULL; + VolumeStr[device - g_fsdev_devices] = FKNAM; return fsdev_convert_rc(NULL, rc); } + device->setup = true; + device->registered = false; + + return 0; +} + +int fsdev_register_device(const char *name) { + fsdev_device_t *device = fsdev_find_device(name); + if (device == NULL) { + errno = ENOENT; + return -1; + } + + if (device->registered) { + /* Do nothing if the device is already registered. */ + return 0; + } + if (AddDevice(&device->devoptab) == -1) { - f_unmount(drname); - g_volume_to_devparts[device - g_fsdev_devices] = NULL; - VolumeStr[device - g_fsdev_devices] = FKNAM; errno = ENOMEM; return -1; } else { - device->setup = true; + device->registered = true; + return 0; + } +} + +int fsdev_unregister_device(const char *name) { + fsdev_device_t *device = fsdev_find_device(name); + char drname[40]; + + if (device == NULL) { + errno = ENOENT; + return -1; + } + + if (!device->registered) { + /* Do nothing if the device is not registered. */ + return 0; + } + + strcpy(drname, name); + strcat(drname, ":"); + + if (RemoveDevice(drname) == -1) { + errno = ENOENT; + return -1; + } else { + device->registered = false; return 0; } } @@ -156,14 +216,12 @@ int fsdev_set_default_device(const char *name) { strcat(drname, ":"); devid = FindDevice(drname); - if (devid == -1) { + if (devid == -1 || fsdev_find_device(name) == NULL) { errno = ENOENT; return -1; } -#if FF_VOLUMES >= 2 ret = fsdev_convert_rc(NULL, f_chdrive(drname)); -#endif if (ret == 0) { setDefaultDevice(devid); } @@ -174,27 +232,28 @@ int fsdev_set_default_device(const char *name) { int fsdev_unmount_device(const char *name) { int ret; char drname[40]; - int devid; + fsdev_device_t *device = fsdev_find_device(name); - strcpy(drname, name); - strcat(drname, ":"); - - devid = FindDevice(drname); - - if (devid == -1) { + if (device == NULL) { errno = ENOENT; return -1; } + ret = fsdev_unregister_device(name); + if (ret == -1) { + return -1; + } + + strcpy(drname, name); + strcat(drname, ":"); + ret = fsdev_convert_rc(NULL, f_unmount(drname)); if (ret == 0) { - fsdev_fsdevice_t *device = (fsdev_fsdevice_t *)(GetDeviceOpTab(name)->deviceData); - RemoveDevice(drname); VolumeStr[device - g_fsdev_devices] = FKNAM; g_volume_to_devparts[device - g_fsdev_devices] = NULL; device->devpart.finalizer(&device->devpart); - memset(device, 0, sizeof(fsdev_fsdevice_t)); + memset(device, 0, sizeof(fsdev_device_t)); } return ret; @@ -202,7 +261,7 @@ int fsdev_unmount_device(const char *name) { int fsdev_unmount_all(void) { for (size_t i = 0; i < FF_VOLUMES; i++) { - int ret = fsdev_unmount_device(VolumeStr[i]); + int ret = fsdev_unmount_device(g_fsdev_devices[i].name); if (ret != 0) { return ret; } diff --git a/fusee/fusee-secondary/src/fs_dev.h b/fusee/fusee-secondary/src/fs_dev.h index f5b1bd58b..93a1b8deb 100644 --- a/fusee/fusee-secondary/src/fs_dev.h +++ b/fusee/fusee-secondary/src/fs_dev.h @@ -7,8 +7,11 @@ #include "device_partition.h" int fsdev_mount_device(const char *name, const device_partition_t *devpart, bool initialize_immediately); -int fsdev_set_default_device(const char *name); -int fsdev_unmount_device(const char *name); +int fsdev_register_device(const char *name); +int fsdev_set_default_device(const char *name); /* must be registered. */ + +int fsdev_unregister_device(const char *name); +int fsdev_unmount_device(const char *name); /* also unregisters. */ int fsdev_unmount_all(void); diff --git a/fusee/fusee-secondary/src/raw_dev.c b/fusee/fusee-secondary/src/raw_dev.c index 01150669c..3938900a5 100644 --- a/fusee/fusee-secondary/src/raw_dev.c +++ b/fusee/fusee-secondary/src/raw_dev.c @@ -25,7 +25,7 @@ typedef struct rawdev_device_t { device_partition_t devpart; char name[32+1]; char root_path[34+1]; - bool setup; + bool setup, registered; } rawdev_device_t; typedef struct rawdev_file_t { @@ -49,6 +49,16 @@ static devoptab_t g_rawdev_devoptab = { .deviceData = NULL, }; +static rawdev_device_t *rawdev_find_device(const char *name) { + for (size_t i = 0; i < RAWDEV_MAX_DEVICES; i++) { + if (g_rawdev_devices[i].setup && strcmp(g_rawdev_devices[i].name, name) == 0) { + return &g_rawdev_devices[i]; + } + } + + return NULL; +} + int rawdev_mount_device(const char *name, const device_partition_t *devpart, bool initialize_immediately) { rawdev_device_t *device = NULL; char drname[40]; @@ -64,7 +74,7 @@ int rawdev_mount_device(const char *name, const device_partition_t *devpart, boo errno = ENAMETOOLONG; return -1; } - if (FindDevice(drname) != -1) { + if (rawdev_find_device(name) != NULL) { errno = EEXIST; /* Device already exists */ return -1; } @@ -105,32 +115,73 @@ int rawdev_mount_device(const char *name, const device_partition_t *devpart, boo return -1; } + device->setup = true; + device->registered = false; + + return 0; +} + +int rawdev_register_device(const char *name) { + rawdev_device_t *device = rawdev_find_device(name); + if (device == NULL) { + errno = ENOENT; + return -1; + } + + if (device->registered) { + /* Do nothing if the device is already registered. */ + return 0; + } + if (AddDevice(&device->devoptab) == -1) { errno = ENOMEM; return -1; } else { - device->setup = true; + device->registered = true; + return 0; + } +} + +int rawdev_unregister_device(const char *name) { + rawdev_device_t *device = rawdev_find_device(name); + char drname[40]; + + if (device == NULL) { + errno = ENOENT; + return -1; + } + + if (!device->registered) { + /* Do nothing if the device is not registered. */ + return 0; + } + + strcpy(drname, name); + strcat(drname, ":"); + + if (RemoveDevice(drname) == -1) { + errno = ENOENT; + return -1; + } else { + device->registered = false; return 0; } } int rawdev_unmount_device(const char *name) { - char drname[40]; - int devid; - rawdev_device_t *device; + int rc; + rawdev_device_t *device = rawdev_find_device(name); - strcpy(drname, name); - strcat(drname, ":"); - - devid = FindDevice(drname); - - if (devid == -1) { + if (device == NULL) { errno = ENOENT; return -1; } - device = (rawdev_device_t *)(GetDeviceOpTab(name)->deviceData); - RemoveDevice(drname); + rc = rawdev_unregister_device(name); + if (rc == -1) { + return -1; + } + free(device->tmp_sector); device->devpart.finalizer(&device->devpart); memset(device, 0, sizeof(rawdev_device_t)); @@ -140,8 +191,10 @@ int rawdev_unmount_device(const char *name) { int rawdev_unmount_all(void) { for (size_t i = 0; i < RAWDEV_MAX_DEVICES; i++) { - RemoveDevice(g_rawdev_devices[i].root_path); - memset(&g_rawdev_devices[i], 0, sizeof(rawdev_device_t)); + int rc = rawdev_unmount_device(g_rawdev_devices[i].name); + if (rc != 0) { + return rc; + } } return 0; diff --git a/fusee/fusee-secondary/src/raw_dev.h b/fusee/fusee-secondary/src/raw_dev.h index 134016267..17cee846a 100644 --- a/fusee/fusee-secondary/src/raw_dev.h +++ b/fusee/fusee-secondary/src/raw_dev.h @@ -9,8 +9,10 @@ #define RAWDEV_MAX_DEVICES 16 int rawdev_mount_device(const char *name, const device_partition_t *device, bool mount_immediately); +int rawdev_register_device(const char *name); -int rawdev_unmount_device(const char *name); +int rawdev_unregister_device(const char *name); +int rawdev_unmount_device(const char *name); /* also unregisters. */ int rawdev_unmount_all(void); #endif diff --git a/fusee/fusee-secondary/src/switch_fs.c b/fusee/fusee-secondary/src/switch_fs.c index 59bcf5ea0..8e60664bb 100644 --- a/fusee/fusee-secondary/src/switch_fs.c +++ b/fusee/fusee-secondary/src/switch_fs.c @@ -138,18 +138,19 @@ static int switchfs_mount_partition_gpt_callback(const efi_entry_t *entry, void const char *mount_point; bool is_fat; bool is_encrypted; + bool register_immediately; } known_partitions[] = { - {"PRODINFO", "prodinfo", false, true}, - {"PRODINFOF", "prodinfof", true, true}, - {"BCPKG2-1-Normal-Main", "bcpkg21", false, false}, - {"BCPKG2-2-Normal-Sub", "bcpkg22", false, false}, - {"BCPKG2-3-SafeMode-Main", "bcpkg23", false, false}, - {"BCPKG2-4-SafeMode-Sub", "bcpkg24", false, false}, - {"BCPKG2-5-Repair-Main", "bcpkg25", false, false}, - {"BCPKG2-6-Repair-Sub", "bcpkg26", false, false}, - {"SAFE", "safe", true, true}, - {"SYSTEM", "system", true, true}, - {"USER", "user", true, true}, + {"PRODINFO", "prodinfo", false, true, false}, + {"PRODINFOF", "prodinfof", true, true, false}, + {"BCPKG2-1-Normal-Main", "bcpkg21", false, false, true}, + {"BCPKG2-2-Normal-Sub", "bcpkg22", false, false, false}, + {"BCPKG2-3-SafeMode-Main", "bcpkg23", false, false, false}, + {"BCPKG2-4-SafeMode-Sub", "bcpkg24", false, false, false}, + {"BCPKG2-5-Repair-Main", "bcpkg25", false, false, false}, + {"BCPKG2-6-Repair-Sub", "bcpkg26", false, false, false}, + {"SAFE", "safe", true, true, false}, + {"SYSTEM", "system", true, true, false}, + {"USER", "user", true, true, false}, }; /* Convert the partition name to ASCII, for comparison. */ @@ -174,15 +175,27 @@ static int switchfs_mount_partition_gpt_callback(const efi_entry_t *entry, void } if (known_partitions[i].is_fat) { - rc = fsdev_mount_device(known_partitions[i].partition_name, &devpart, false); + rc = fsdev_mount_device(known_partitions[i].mount_point, &devpart, false); if (rc == -1) { return -1; } + if (known_partitions[i].register_immediately) { + rc = fsdev_register_device(known_partitions[i].mount_point); + if (rc == -1) { + return -1; + } + } } else { - rc = rawdev_mount_device(known_partitions[i].partition_name, &devpart, false); + rc = rawdev_mount_device(known_partitions[i].mount_point, &devpart, false); if (rc == -1) { return -1; } + if (known_partitions[i].register_immediately) { + rc = rawdev_register_device(known_partitions[i].mount_point); + if (rc == -1) { + return -1; + } + } } } } @@ -204,6 +217,10 @@ int switchfs_mount_all(void) { if (rc == -1) { return -1; } + rc = fsdev_register_device("sdmc"); + if (rc == -1) { + return -1; + } /* Boot0. */ model = g_mmc_devpart_template; @@ -214,6 +231,10 @@ int switchfs_mount_all(void) { if (rc == -1) { return -1; } + rc = rawdev_register_device("boot0"); + if (rc == -1) { + return -1; + } /* Boot1. */ model = g_mmc_devpart_template; @@ -224,6 +245,7 @@ int switchfs_mount_all(void) { if (rc == -1) { return -1; } + /* Don't register boot1 for now. */ /* Raw NAND (excluding boot partitions), and its partitions. */ model = g_mmc_devpart_template; @@ -235,10 +257,14 @@ int switchfs_mount_all(void) { if (rc == -1) { return -1; } + rc = rawdev_register_device("rawnand"); + if (rc == -1) { + return -1; + } rawnand = fopen("rawnand:/", "rb"); rc = gpt_iterate_through_entries(rawnand, model.sector_size, switchfs_mount_partition_gpt_callback, &model); fclose(rawnand); - if (rc != 0) { + if (rc == 0) { rc = fsdev_set_default_device("sdmc"); } return rc;