diff --git a/fusee/fusee-secondary/src/device_partition.c b/fusee/fusee-secondary/src/device_partition.c index e5c4251fe..afc1d3ba8 100644 --- a/fusee/fusee-secondary/src/device_partition.c +++ b/fusee/fusee-secondary/src/device_partition.c @@ -13,7 +13,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + +#include #include #include "device_partition.h" @@ -72,3 +73,29 @@ int device_partition_write_data(device_partition_t *devpart, const void *src, ui return devpart->writer(devpart, src, sector, num_sectors); } } + +int emu_device_partition_read_data(device_partition_t *devpart, void *dst, uint64_t sector, uint64_t num_sectors, const char *origin_path) +{ + int rc = 0; + + /* Read partition data using our backing file. */ + FILE *origin = fopen(origin_path, "rb"); + fseek(origin, sector * devpart->sector_size, SEEK_CUR); + rc = (fread(dst, devpart->sector_size, num_sectors, origin) > 0) ? 0 : -1; + fclose(origin); + + return rc; +} + +int emu_device_partition_write_data(device_partition_t *devpart, const void *src, uint64_t sector, uint64_t num_sectors, const char *origin_path) +{ + int rc = 0; + + /* Write partition data using our backing file. */ + FILE *origin = fopen(origin_path, "wb"); + fseek(origin, sector * devpart->sector_size, SEEK_CUR); + rc = (fwrite(src, devpart->sector_size, num_sectors, origin) > 0) ? 0 : -1; + fclose(origin); + + return rc; +} diff --git a/fusee/fusee-secondary/src/device_partition.h b/fusee/fusee-secondary/src/device_partition.h index 2bb059ffd..b2a58cef3 100644 --- a/fusee/fusee-secondary/src/device_partition.h +++ b/fusee/fusee-secondary/src/device_partition.h @@ -69,5 +69,7 @@ typedef struct device_partition_t { int device_partition_read_data(device_partition_t *devpart, void *dst, uint64_t sector, uint64_t num_sectors); int device_partition_write_data(device_partition_t *devpart, const void *src, uint64_t sector, uint64_t num_sectors); +int emu_device_partition_read_data(device_partition_t *devpart, void *dst, uint64_t sector, uint64_t num_sectors, const char *origin_path); +int emu_device_partition_write_data(device_partition_t *devpart, const void *src, uint64_t sector, uint64_t num_sectors, const char *origin_path); #endif diff --git a/fusee/fusee-secondary/src/emu_dev.c b/fusee/fusee-secondary/src/emu_dev.c index b7bbe7af9..0ae9b2b24 100644 --- a/fusee/fusee-secondary/src/emu_dev.c +++ b/fusee/fusee-secondary/src/emu_dev.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 Atmosphère-NX + * Copyright (c) 2018-2019 Atmosphère-NX * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -38,7 +38,7 @@ static int emudev_fsync(struct _reent *r, void *fd); typedef struct emudev_device_t { devoptab_t devoptab; - FILE *origin; + char origin_path[0x300+1]; uint8_t *tmp_sector; device_partition_t devpart; char name[32+1]; @@ -77,7 +77,7 @@ static emudev_device_t *emudev_find_device(const char *name) { return NULL; } -int emudev_mount_device(const char *name, const char *origin_path, const device_partition_t *devpart) { +int emudev_mount_device(const char *name, const device_partition_t *devpart, const char *origin_path) { emudev_device_t *device = NULL; if (name[0] == '\0' || devpart == NULL) { @@ -112,22 +112,11 @@ int emudev_mount_device(const char *name, const char *origin_path, const device_ strcpy(device->name, name); strcpy(device->root_path, name); strcat(device->root_path, ":/"); - + strcpy(device->origin_path, origin_path); + device->devoptab.name = device->name; device->devoptab.deviceData = device; - /* Try to open the backing file for this emulated device. */ - FILE *origin = fopen(origin_path, "rb"); - - /* Return invalid if we can't open the file. */ - if (origin == NULL) { - errno = EINVAL; - return -1; - } - - /* Bind the backing file to this device. */ - device->origin = origin; - /* Allocate memory for our intermediate sector. */ device->tmp_sector = (uint8_t *)malloc(devpart->sector_size); if (device->tmp_sector == NULL) { @@ -201,10 +190,6 @@ int emudev_unmount_device(const char *name) { if (rc == -1) { return -1; } - - /* Close the backing file, if there is one. */ - if (device->origin != NULL) - fclose(device->origin); free(device->tmp_sector); memset(device, 0, sizeof(emudev_device_t)); @@ -280,11 +265,7 @@ static ssize_t emudev_write(struct _reent *r, void *fd, const char *ptr, size_t /* Unaligned at the start, we need to read the sector and incorporate the data. */ if (f->offset % sector_size != 0) { size_t nb = (size_t)(len <= (sector_size - (f->offset % sector_size)) ? len : sector_size - (f->offset % sector_size)); - - /* Read partition data using our backing file. */ - fseek(device->origin, sector_begin, SEEK_CUR); - no = (fread(device->tmp_sector, sector_size, 1, device->origin) > 0) ? 0 : EIO; - + no = emu_device_partition_read_data(&device->devpart, device->tmp_sector, sector_begin, 1, device->origin_path); if (no != 0) { r->_errno = no; return -1; @@ -292,10 +273,7 @@ static ssize_t emudev_write(struct _reent *r, void *fd, const char *ptr, size_t memcpy(device->tmp_sector + (f->offset % sector_size), data, nb); - /* Write partition data using our backing file. */ - fseek(device->origin, sector_begin, SEEK_CUR); - no = (fwrite(device->tmp_sector, sector_size, 1, device->origin) > 0) ? 0 : EIO; - + no = emu_device_partition_write_data(&device->devpart, device->tmp_sector, sector_begin, 1, device->origin_path); if (no != 0) { r->_errno = no; return -1; @@ -314,10 +292,7 @@ static ssize_t emudev_write(struct _reent *r, void *fd, const char *ptr, size_t /* Write all of the sector-aligned data. */ if (current_sector != sector_end_aligned) { - /* Write partition data using our backing file. */ - fseek(device->origin, current_sector, SEEK_CUR); - no = (fwrite(device->tmp_sector, sector_size, sector_end_aligned - current_sector, device->origin) > 0) ? 0 : EIO; - + no = emu_device_partition_write_data(&device->devpart, data, current_sector, sector_end_aligned - current_sector, device->origin_path); if (no != 0) { r->_errno = no; return -1; @@ -329,10 +304,7 @@ static ssize_t emudev_write(struct _reent *r, void *fd, const char *ptr, size_t /* Unaligned at the end, we need to read the sector and incorporate the data. */ if (sector_end != sector_end_aligned) { - /* Read partition data using our backing file. */ - fseek(device->origin, sector_end_aligned, SEEK_CUR); - no = (fread(device->tmp_sector, sector_size, 1, device->origin) > 0) ? 0 : EIO; - + no = emu_device_partition_read_data(&device->devpart, device->tmp_sector, sector_end_aligned, 1, device->origin_path); if (no != 0) { r->_errno = no; return -1; @@ -340,10 +312,7 @@ static ssize_t emudev_write(struct _reent *r, void *fd, const char *ptr, size_t memcpy(device->tmp_sector, data, (size_t)((f->offset + len) % sector_size)); - /* Write partition data using our backing file. */ - fseek(device->origin, sector_end_aligned, SEEK_CUR); - no = (fwrite(device->tmp_sector, sector_size, 1, device->origin) > 0) ? 0 : EIO; - + no = emu_device_partition_write_data(&device->devpart, device->tmp_sector, sector_end_aligned, 1, device->origin_path); if (no != 0) { r->_errno = no; return -1; @@ -384,11 +353,7 @@ static ssize_t emudev_read(struct _reent *r, void *fd, char *ptr, size_t len) { /* Unaligned at the start, we need to read the sector and incorporate the data. */ if (f->offset % sector_size != 0) { size_t nb = (size_t)(len <= (sector_size - (f->offset % sector_size)) ? len : sector_size - (f->offset % sector_size)); - - /* Read partition data using our backing file. */ - fseek(device->origin, sector_begin, SEEK_CUR); - no = (fread(device->tmp_sector, sector_size, 1, device->origin) > 0) ? 0 : EIO; - + no = emu_device_partition_read_data(&device->devpart, device->tmp_sector, sector_begin, 1, device->origin_path); if (no != 0) { r->_errno = no; return -1; @@ -409,10 +374,7 @@ static ssize_t emudev_read(struct _reent *r, void *fd, char *ptr, size_t len) { /* Read all of the sector-aligned data. */ if (current_sector != sector_end_aligned) { - /* Read partition data using our backing file. */ - fseek(device->origin, current_sector, SEEK_CUR); - no = (fread(device->tmp_sector, sector_size, sector_end_aligned - current_sector, device->origin) > 0) ? 0 : EIO; - + no = emu_device_partition_read_data(&device->devpart, data, current_sector, sector_end_aligned - current_sector, device->origin_path); if (no != 0) { r->_errno = no; return -1; @@ -424,10 +386,7 @@ static ssize_t emudev_read(struct _reent *r, void *fd, char *ptr, size_t len) { /* Unaligned at the end, we need to read the sector and incorporate the data. */ if (sector_end != sector_end_aligned) { - /* Read partition data using our backing file. */ - fseek(device->origin, sector_end_aligned, SEEK_CUR); - no = (fread(device->tmp_sector, sector_size, 1, device->origin) > 0) ? 0 : EIO; - + no = emu_device_partition_read_data(&device->devpart, device->tmp_sector, sector_end_aligned, 1, device->origin_path); if (no != 0) { r->_errno = no; return -1; diff --git a/fusee/fusee-secondary/src/emu_dev.h b/fusee/fusee-secondary/src/emu_dev.h index a62079afd..08241731b 100644 --- a/fusee/fusee-secondary/src/emu_dev.h +++ b/fusee/fusee-secondary/src/emu_dev.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 Atmosphère-NX + * Copyright (c) 2018-2019 Atmosphère-NX * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -24,11 +24,11 @@ #define EMUDEV_MAX_DEVICES 16 -int emudev_mount_device(const char *name, const char *origin_path, const device_partition_t *devpart); +int emudev_mount_device(const char *name, const device_partition_t *devpart, const char *origin_path); int emudev_register_device(const char *name); - int emudev_unregister_device(const char *name); -int emudev_unmount_device(const char *name); /* also unregisters. */ +int emudev_unmount_device(const char *name); /* also unregisters. */ + int emudev_unmount_all(void); #endif diff --git a/fusee/fusee-secondary/src/fs_dev.c b/fusee/fusee-secondary/src/fs_dev.c index ac76e54c1..7e5a4df88 100644 --- a/fusee/fusee-secondary/src/fs_dev.c +++ b/fusee/fusee-secondary/src/fs_dev.c @@ -246,6 +246,19 @@ int fsdev_set_default_device(const char *name) { return ret; } +int fsdev_is_exfat(const char *name) { + fsdev_device_t *device = fsdev_find_device(name); + + if (device != NULL) { + if (device->registered) { + return ((device->fatfs.fs_type == FS_EXFAT) ? 1 : 0); + } + } + + errno = ENOENT; + return -1; +} + int fsdev_unmount_device(const char *name) { int ret; char drname[40]; diff --git a/fusee/fusee-secondary/src/fs_dev.h b/fusee/fusee-secondary/src/fs_dev.h index 7d348a032..459ad4ad0 100644 --- a/fusee/fusee-secondary/src/fs_dev.h +++ b/fusee/fusee-secondary/src/fs_dev.h @@ -24,10 +24,11 @@ int fsdev_mount_device(const char *name, const device_partition_t *devpart, bool initialize_immediately); 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_device(const char *name); /* also unregisters. */ + +int fsdev_set_default_device(const char *name); /* must be registered. */ +int fsdev_is_exfat(const char *name); /* must be registered. */ int fsdev_unmount_all(void); diff --git a/fusee/fusee-secondary/src/fs_utils.c b/fusee/fusee-secondary/src/fs_utils.c index f6224e373..5a8b2d11a 100644 --- a/fusee/fusee-secondary/src/fs_utils.c +++ b/fusee/fusee-secondary/src/fs_utils.c @@ -48,3 +48,21 @@ size_t dump_to_file(const void *src, size_t src_size, const char *filename) { return sz; } } + +bool is_valid_folder(const char *path) { + struct stat st; + if (stat(path, &st) == 0 && S_ISDIR(st.st_mode)) { + return true; + } + + return false; +} + +bool is_valid_file(const char *path) { + struct stat st; + if (stat(path, &st) == 0 && S_ISREG(st.st_mode)) { + return true; + } + + return false; +} diff --git a/fusee/fusee-secondary/src/fs_utils.h b/fusee/fusee-secondary/src/fs_utils.h index 271c79f06..3db96a6f2 100644 --- a/fusee/fusee-secondary/src/fs_utils.h +++ b/fusee/fusee-secondary/src/fs_utils.h @@ -23,5 +23,7 @@ size_t get_file_size(const char *filename); size_t read_from_file(void *dst, size_t dst_size, const char *filename); size_t dump_to_file(const void *src, size_t src_size, const char *filename); +bool is_valid_folder(const char *path); +bool is_valid_file(const char *path); #endif diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index 6b5be27f1..e18cd99e6 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -187,13 +187,13 @@ static uint32_t nxboot_get_target_firmware(const void *package1loader) { } else if (memcmp(package1loader_header->build_timestamp, "20181107", 8) == 0) { return ATMOSPHERE_TARGET_FIRMWARE_620; } else { - fatal_error("[NXBOOT]: Unable to identify package1!\n"); + fatal_error("[NXBOOT] Unable to identify package1!\n"); } } case 0x0F: return ATMOSPHERE_TARGET_FIRMWARE_700; default: - fatal_error("[NXBOOT]: Unable to identify package1!\n"); + fatal_error("[NXBOOT] Unable to identify package1!\n"); } } @@ -202,33 +202,45 @@ static bool nxboot_configure_emunand() { /* Load emunand settings from BCT.ini file. */ if (ini_parse_string(get_loader_ctx()->bct0, emunand_ini_handler, &emunand_cfg) < 0) { - fatal_error("[NXBOOT]: Failed to parse BCT.ini!\n"); + fatal_error("[NXBOOT] Failed to parse BCT.ini!\n"); } if (emunand_cfg.enabled) { bool do_nand_backup = false; + char emunand_boot0_path[0x300 + 1] = {0}; + char emunand_boot1_path[0x300 + 1] = {0}; + char emunand_rawnand_base_path[0x300 + 1] = {0}; + snprintf(emunand_boot0_path, sizeof(emunand_boot0_path) - 1, "sdmc:/%s/%s", emunand_cfg.path, "boot0"); + snprintf(emunand_boot1_path, sizeof(emunand_boot1_path) - 1, "sdmc:/%s/%s", emunand_cfg.path, "boot1"); + snprintf(emunand_rawnand_base_path, sizeof(emunand_rawnand_base_path) - 1, "sdmc:/%s/%s", emunand_cfg.path, "rawnand"); - /* TODO: Check if the supplied path is valid. */ + /* Check if the supplied path is valid. */ + if (!is_valid_folder(emunand_cfg.path)) { + fatal_error("[NXBOOT] Failed to find EmuNAND folder!\n"); + } - /* TODO: Check if all emunand image files are present. */ + /* Check if all emunand image files are present. */ + if (!is_valid_file(emunand_boot0_path) || !is_valid_file(emunand_boot1_path) || !is_valid_file(emunand_rawnand_base_path)) { + fatal_error("[NXBOOT] Failed to find EmuNAND image files!\n"); + } if (do_nand_backup) { /* Mount real NAND. */ if (nxfs_mount_emmc() < 0) { - fatal_error("[NXBOOT]: Failed to mount eMMC!\n"); + fatal_error("[NXBOOT] Failed to mount eMMC!\n"); } /* TODO: Read real NAND and create a backup image. */ /* Unmount real NAND. */ if (nxfs_unmount_emmc() < 0) { - fatal_error("[NXBOOT]: Failed to unmount eMMC!\n"); + fatal_error("[NXBOOT] Failed to unmount eMMC!\n"); } } /* Mount emulated NAND. */ - if (nxfs_mount_emu_emmc(emunand_cfg.path) < 0) { - fatal_error("[NXBOOT]: Failed to mount emulated eMMC!\n"); + if (nxfs_mount_emu_emmc(emunand_boot0_path, emunand_boot1_path, emunand_rawnand_base_path) < 0) { + fatal_error("[NXBOOT] Failed to mount emulated eMMC!\n"); } } @@ -247,11 +259,11 @@ static void nxboot_configure_exosphere(uint32_t target_firmware, unsigned int ke } if (ini_parse_string(get_loader_ctx()->bct0, exosphere_ini_handler, &exo_cfg) < 0) { - fatal_error("[NXBOOT]: Failed to parse BCT.ini!\n"); + fatal_error("[NXBOOT] Failed to parse BCT.ini!\n"); } if ((exo_cfg.target_firmware < ATMOSPHERE_TARGET_FIRMWARE_MIN) || (exo_cfg.target_firmware > ATMOSPHERE_TARGET_FIRMWARE_MAX)) { - fatal_error("[NXBOOT]: Invalid Exosphere target firmware!\n"); + fatal_error("[NXBOOT] Invalid Exosphere target firmware!\n"); } *(MAILBOX_EXOSPHERE_CONFIGURATION) = exo_cfg; @@ -260,7 +272,7 @@ static void nxboot_configure_exosphere(uint32_t target_firmware, unsigned int ke static void nxboot_configure_stratosphere(uint32_t target_firmware) { stratosphere_cfg_t strat_cfg = {0}; if (ini_parse_string(get_loader_ctx()->bct0, stratosphere_ini_handler, &strat_cfg) < 0) { - fatal_error("[NXBOOT]: Failed to parse BCT.ini!\n"); + fatal_error("[NXBOOT] Failed to parse BCT.ini!\n"); } /* Enable NOGC patches if the user requested it, or if the user is booting into 4.0.0+ with 3.0.2- fuses. */ @@ -285,18 +297,18 @@ static void nxboot_set_bootreason(void *bootreason_base) { /* Allocate memory for the BCT. */ bct = malloc(sizeof(nvboot_config_table)); if (bct == NULL) { - fatal_error("[NXBOOT]: Out of memory!\n"); + fatal_error("[NXBOOT] Out of memory!\n"); } /* Open boot0. */ boot0 = fopen("boot0:/", "rb"); if (boot0 == NULL) { - fatal_error("[NXBOOT]: Failed to open boot0!\n"); + fatal_error("[NXBOOT] Failed to open boot0!\n"); } /* Read the BCT. */ if (fread(bct, sizeof(nvboot_config_table), 1, boot0) == 0) { - fatal_error("[NXBOOT]: Failed to read the BCT!\n"); + fatal_error("[NXBOOT] Failed to read the BCT!\n"); } /* Close boot0. */ @@ -343,17 +355,17 @@ static void nxboot_move_bootconfig() { /* Allocate memory for reading BootConfig. */ bootconfig = memalign(0x1000, 0x4000); if (bootconfig == NULL) { - fatal_error("[NXBOOT]: Out of memory!\n"); + fatal_error("[NXBOOT] Out of memory!\n"); } /* Get BootConfig from the Package2 partition. */ bcfile = fopen("bcpkg21:/", "rb"); if (bcfile == NULL) { - fatal_error("[NXBOOT]: Failed to open BootConfig from eMMC!\n"); + fatal_error("[NXBOOT] Failed to open BootConfig from eMMC!\n"); } if (fread(bootconfig, 0x4000, 1, bcfile) < 1) { fclose(bcfile); - fatal_error("[NXBOOT]: Failed to read BootConfig!\n"); + fatal_error("[NXBOOT] Failed to read BootConfig!\n"); } fclose(bcfile); @@ -396,86 +408,86 @@ uint32_t nxboot_main(void) { /* Configure emunand or mount the real NAND. */ if (!nxboot_configure_emunand()) { if (nxfs_mount_emmc() < 0) { - fatal_error("[NXBOOT]: Failed to mount eMMC!\n"); + fatal_error("[NXBOOT] Failed to mount eMMC!\n"); } } /* Allocate memory for reading Package2. */ package2 = memalign(0x1000, PACKAGE2_SIZE_MAX); if (package2 == NULL) { - fatal_error("[NXBOOT]: Out of memory!\n"); + fatal_error("[NXBOOT] Out of memory!\n"); } /* Read Package2 from a file, otherwise from its partition(s). */ - print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Reading package2...\n"); + print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Reading package2...\n"); if (loader_ctx->package2_path[0] != '\0') { pk2file = fopen(loader_ctx->package2_path, "rb"); if (pk2file == NULL) { - fatal_error("[NXBOOT]: Failed to open Package2 from %s: %s!\n", loader_ctx->package2_path, strerror(errno)); + fatal_error("[NXBOOT] Failed to open Package2 from %s: %s!\n", loader_ctx->package2_path, strerror(errno)); } } else { pk2file = fopen("bcpkg21:/", "rb"); if (pk2file == NULL) { - fatal_error("[NXBOOT]: Failed to open Package2 from eMMC: %s!\n", strerror(errno)); + fatal_error("[NXBOOT] Failed to open Package2 from eMMC: %s!\n", strerror(errno)); } if (fseek(pk2file, 0x4000, SEEK_SET) != 0) { fclose(pk2file); - fatal_error("[NXBOOT]: Failed to seek Package2 in eMMC: %s!\n", strerror(errno)); + fatal_error("[NXBOOT] Failed to seek Package2 in eMMC: %s!\n", strerror(errno)); } } setvbuf(pk2file, NULL, _IONBF, 0); /* Workaround. */ if (fread(package2, sizeof(package2_header_t), 1, pk2file) < 1) { fclose(pk2file); - fatal_error("[NXBOOT]: Failed to read Package2!\n"); + fatal_error("[NXBOOT] Failed to read Package2!\n"); } package2_size = package2_meta_get_size(&package2->metadata); if ((package2_size > PACKAGE2_SIZE_MAX) || (package2_size <= sizeof(package2_header_t))) { fclose(pk2file); - fatal_error("[NXBOOT]: Package2 is too big or too small!\n"); + fatal_error("[NXBOOT] Package2 is too big or too small!\n"); } if (fread(package2->data, package2_size - sizeof(package2_header_t), 1, pk2file) < 1) { fclose(pk2file); - fatal_error("[NXBOOT]: Failed to read Package2!\n"); + fatal_error("[NXBOOT] Failed to read Package2!\n"); } fclose(pk2file); /* Read and parse boot0. */ - print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Reading boot0...\n"); + print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Reading boot0...\n"); boot0 = fopen("boot0:/", "rb"); if ((boot0 == NULL) || (package1_read_and_parse_boot0(&package1loader, &package1loader_size, g_keyblobs, &available_revision, boot0) == -1)) { - fatal_error("[NXBOOT]: Couldn't parse boot0: %s!\n", strerror(errno)); + fatal_error("[NXBOOT] Couldn't parse boot0: %s!\n", strerror(errno)); } fclose(boot0); /* Find the system's target firmware. */ uint32_t target_firmware = nxboot_get_target_firmware(package1loader); if (!target_firmware) - fatal_error("[NXBOOT]: Failed to detect target firmware!\n"); + fatal_error("[NXBOOT] Failed to detect target firmware!\n"); else - print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Detected target firmware %ld!\n", target_firmware); + print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Detected target firmware %ld!\n", target_firmware); /* Read the TSEC firmware from a file, otherwise from PK1L. */ if (loader_ctx->tsecfw_path[0] != '\0') { tsec_fw_size = get_file_size(loader_ctx->tsecfw_path); if ((tsec_fw_size != 0) && (tsec_fw_size != 0xF00 && tsec_fw_size != 0x2900 && tsec_fw_size != 0x3000)) { - fatal_error("[NXBOOT]: TSEC firmware from %s has a wrong size!\n", loader_ctx->tsecfw_path); + fatal_error("[NXBOOT] TSEC firmware from %s has a wrong size!\n", loader_ctx->tsecfw_path); } else if (tsec_fw_size == 0) { - fatal_error("[NXBOOT]: Could not read the TSEC firmware from %s!\n", loader_ctx->tsecfw_path); + fatal_error("[NXBOOT] Could not read the TSEC firmware from %s!\n", loader_ctx->tsecfw_path); } /* Allocate memory for the TSEC firmware. */ tsec_fw = memalign(0x100, tsec_fw_size); if (tsec_fw == NULL) { - fatal_error("[NXBOOT]: Out of memory!\n"); + fatal_error("[NXBOOT] Out of memory!\n"); } if (read_from_file(tsec_fw, tsec_fw_size, loader_ctx->tsecfw_path) != tsec_fw_size) { - fatal_error("[NXBOOT]: Could not read the TSEC firmware from %s!\n", loader_ctx->tsecfw_path); + fatal_error("[NXBOOT] Could not read the TSEC firmware from %s!\n", loader_ctx->tsecfw_path); } } else { if (!package1_get_tsec_fw(&tsec_fw, package1loader, package1loader_size)) { - fatal_error("[NXBOOT]: Failed to read the TSEC firmware from Package1loader!\n"); + fatal_error("[NXBOOT] Failed to read the TSEC firmware from Package1loader!\n"); } if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_700) { tsec_fw_size = 0x3000; @@ -486,7 +498,7 @@ uint32_t nxboot_main(void) { } } - print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Loaded firmware from eMMC...\n"); + print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Loaded firmware from eMMC...\n"); /* Get the TSEC keys. */ uint8_t tsec_key[0x10] = {0}; @@ -497,7 +509,7 @@ uint32_t nxboot_main(void) { reboot_to_sept(tsec_fw, tsec_fw_size, sept_secondary_enc, sept_secondary_enc_size); } else { if (mkey_detect_revision(fuse_get_retail_type() != 0) != 0) { - fatal_error("[NXBOOT]: Sept derived incorrect keys!\n"); + fatal_error("[NXBOOT] Sept derived incorrect keys!\n"); } } get_and_clear_has_run_sept(); @@ -513,7 +525,7 @@ uint32_t nxboot_main(void) { } else { /* Run the TSEC payload and get the key. */ if (tsec_get_key(tsec_key, 1, tsec_fw, tsec_fw_size) != 0) { - fatal_error("[NXBOOT]: Failed to get TSEC key!\n"); + fatal_error("[NXBOOT] Failed to get TSEC key!\n"); } } @@ -525,7 +537,7 @@ uint32_t nxboot_main(void) { unsigned int keygen_type = 0; if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_700) { if (derive_nx_keydata(target_firmware, g_keyblobs, available_revision, tsec_key, tsec_root_keys, &keygen_type) != 0) { - fatal_error("[NXBOOT]: Key derivation failed!\n"); + fatal_error("[NXBOOT] Key derivation failed!\n"); } } @@ -534,7 +546,7 @@ uint32_t nxboot_main(void) { /* Initialize Boot Reason on older firmware versions. */ if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) { - print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Initializing Boot Reason...\n"); + print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Initializing Boot Reason...\n"); nxboot_set_bootreason((void *)MAILBOX_NX_BOOTLOADER_BOOT_REASON_BASE(target_firmware)); } @@ -542,17 +554,17 @@ uint32_t nxboot_main(void) { if (loader_ctx->warmboot_path[0] != '\0') { warmboot_fw_size = get_file_size(loader_ctx->warmboot_path); if (warmboot_fw_size == 0) { - fatal_error("[NXBOOT]: Could not read the warmboot firmware from %s!\n", loader_ctx->warmboot_path); + fatal_error("[NXBOOT] Could not read the warmboot firmware from %s!\n", loader_ctx->warmboot_path); } /* Allocate memory for the warmboot firmware. */ warmboot_fw = malloc(warmboot_fw_size); if (warmboot_fw == NULL) { - fatal_error("[NXBOOT]: Out of memory!\n"); + fatal_error("[NXBOOT] Out of memory!\n"); } if (read_from_file(warmboot_fw, warmboot_fw_size, loader_ctx->warmboot_path) != warmboot_fw_size) { - fatal_error("[NXBOOT]: Could not read the warmboot firmware from %s!\n", loader_ctx->warmboot_path); + fatal_error("[NXBOOT] Could not read the warmboot firmware from %s!\n", loader_ctx->warmboot_path); } } else { /* Use Atmosphere's warmboot firmware implementation. */ @@ -560,13 +572,13 @@ uint32_t nxboot_main(void) { warmboot_fw = malloc(warmboot_fw_size); if (warmboot_fw == NULL) { - fatal_error("[NXBOOT]: Out of memory!\n"); + fatal_error("[NXBOOT] Out of memory!\n"); } memcpy(warmboot_fw, lp0fw_bin, warmboot_fw_size); if (warmboot_fw_size == 0) { - fatal_error("[NXBOOT]: Could not read the warmboot firmware from Package1!\n"); + fatal_error("[NXBOOT] Could not read the warmboot firmware from Package1!\n"); } } @@ -595,7 +607,7 @@ uint32_t nxboot_main(void) { warmboot_memaddr = (void *)0x4003E000; } - print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Copying warmboot firmware...\n"); + print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Copying warmboot firmware...\n"); /* Copy the warmboot firmware and set the address in PMC if necessary. */ if (warmboot_fw && (warmboot_fw_size > 0)) { @@ -604,17 +616,17 @@ uint32_t nxboot_main(void) { pmc->scratch1 = (uint32_t)warmboot_memaddr; } - print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Rebuilding package2...\n"); + print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Rebuilding package2...\n"); /* Parse stratosphere config. */ nxboot_configure_stratosphere(MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware); - print(SCREEN_LOG_LEVEL_INFO, u8"[NXBOOT]: Configured Stratosphere...\n"); + print(SCREEN_LOG_LEVEL_INFO, u8"[NXBOOT] Configured Stratosphere...\n"); /* Patch package2, adding Thermosphère + custom KIPs. */ package2_rebuild_and_copy(package2, MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware); - print(SCREEN_LOG_LEVEL_INFO, u8"[NXBOOT]: Reading Exosphère...\n"); + print(SCREEN_LOG_LEVEL_INFO, u8"[NXBOOT] Reading Exosphère...\n"); /* Select the right address for Exosphère. */ if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) { @@ -627,21 +639,21 @@ uint32_t nxboot_main(void) { if (loader_ctx->exosphere_path[0] != '\0') { size_t exosphere_size = get_file_size(loader_ctx->exosphere_path); if (exosphere_size == 0) { - fatal_error(u8"[NXBOOT]: Could not read Exosphère from %s!\n", loader_ctx->exosphere_path); + fatal_error(u8"[NXBOOT] Could not read Exosphère from %s!\n", loader_ctx->exosphere_path); } else if (exosphere_size > 0x10000) { /* The maximum is actually a bit less than that. */ - fatal_error(u8"[NXBOOT]: Exosphère from %s is too big!\n", loader_ctx->exosphere_path); + fatal_error(u8"[NXBOOT] Exosphère from %s is too big!\n", loader_ctx->exosphere_path); } if (read_from_file(exosphere_memaddr, exosphere_size, loader_ctx->exosphere_path) != exosphere_size) { - fatal_error(u8"[NXBOOT]: Could not read Exosphère from %s!\n", loader_ctx->exosphere_path); + fatal_error(u8"[NXBOOT] Could not read Exosphère from %s!\n", loader_ctx->exosphere_path); } } else { memcpy(exosphere_memaddr, exosphere_bin, exosphere_bin_size); } /* Move BootConfig. */ - print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Moving BootConfig...\n"); + print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Moving BootConfig...\n"); nxboot_move_bootconfig(); /* Set 3.0.0/3.0.1/3.0.2 warmboot security check. */ @@ -663,7 +675,7 @@ uint32_t nxboot_main(void) { } free(package2); - print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Powering on the CCPLEX...\n"); + print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Powering on the CCPLEX...\n"); /* Unmount everything. */ nxfs_end(); diff --git a/fusee/fusee-secondary/src/nxfs.c b/fusee/fusee-secondary/src/nxfs.c index 0aea6068f..a45b8580b 100644 --- a/fusee/fusee-secondary/src/nxfs.c +++ b/fusee/fusee-secondary/src/nxfs.c @@ -380,29 +380,30 @@ int nxfs_mount_emmc() { return rc; } -int nxfs_mount_emu_emmc(const char *emunand_path) { +int nxfs_mount_emu_emmc(const char *emunand_boot0_path, const char *emunand_boot1_path, const char *emunand_rawnand_base_path) { device_partition_t model; int rc; FILE *rawnand; + bool is_exfat; + + /* Check if the SD card is EXFAT formatted. */ + rc = fsdev_is_exfat("sdmc"); + + /* Failed to detect file system type. */ + if (rc == -1) { + return -1; + } + + /* Set EXFAT status. */ + is_exfat = (rc == 1); - /* Setup emunand paths. */ - char emu_boot0_path[0x100]; - char emu_boot1_path[0x100]; - char emu_rawnand_path[0x100]; - memset(emu_boot0_path, 0, sizeof(emu_boot0_path)); - memset(emu_boot1_path, 0, sizeof(emu_boot1_path)); - memset(emu_rawnand_path, 0, sizeof(emu_rawnand_path)); - snprintf(emu_boot0_path, sizeof(emu_boot0_path), "sdmc:/%s/%s", emunand_path, "boot0"); - snprintf(emu_boot1_path, sizeof(emu_boot1_path), "sdmc:/%s/%s", emunand_path, "boot1"); - snprintf(emu_rawnand_path, sizeof(emu_rawnand_path), "sdmc:/%s/%s", emunand_path, "rawnand"); - /* Setup an emulation template for boot0. */ model = g_emummc_devpart_template; model.start_sector = 0; model.num_sectors = 0x184000 / model.sector_size; /* Mount emulated boot0 device. */ - rc = emudev_mount_device("boot0", emu_boot0_path, &model); + rc = emudev_mount_device("boot0", &model, emunand_boot0_path); if (rc == -1) { return -1; @@ -421,7 +422,7 @@ int nxfs_mount_emu_emmc(const char *emunand_path) { model.num_sectors = 0x80000 / model.sector_size; /* Mount emulated boot1 device. */ - rc = emudev_mount_device("boot1", emu_boot1_path, &model); + rc = emudev_mount_device("boot1", &model, emunand_boot1_path); if (rc == -1) { return -1; @@ -434,32 +435,36 @@ int nxfs_mount_emu_emmc(const char *emunand_path) { model.start_sector = 0; model.num_sectors = (256ull << 30) / model.sector_size; - /* Mount emulated raw NAND device. */ - rc = emudev_mount_device("rawnand", emu_rawnand_path, &model); - - if (rc == -1) { - return -1; + if (!is_exfat) { + /* TODO: Use file concatenation for FAT32. */ + } else { + /* Mount emulated raw NAND device. */ + rc = emudev_mount_device("rawnand", &model, emunand_rawnand_base_path); + + if (rc == -1) { + return -1; + } + + /* Register emulated raw NAND device. */ + rc = emudev_register_device("rawnand"); + if (rc == -1) { + return -1; + } + + /* Open emulated raw NAND device. */ + rawnand = fopen("rawnand:/", "rb"); + + if (rawnand == NULL) { + return -1; + } + + /* Iterate the GPT and mount each emulated raw NAND partition. */ + rc = gpt_iterate_through_entries(rawnand, model.sector_size, nxfs_mount_partition_gpt_callback, &model); + + /* Close emulated raw NAND device. */ + fclose(rawnand); } - /* Register emulated raw NAND device. */ - rc = emudev_register_device("rawnand"); - if (rc == -1) { - return -1; - } - - /* Open emulated raw NAND device. */ - rawnand = fopen("rawnand:/", "rb"); - - if (rawnand == NULL) { - return -1; - } - - /* Iterate the GPT and mount each emulated raw NAND partition. */ - rc = gpt_iterate_through_entries(rawnand, model.sector_size, nxfs_mount_partition_gpt_callback, &model); - - /* Close emulated raw NAND device. */ - fclose(rawnand); - /* All emulated devices are ready. */ if (rc == 0) { g_emudev_ready = true; diff --git a/fusee/fusee-secondary/src/nxfs.h b/fusee/fusee-secondary/src/nxfs.h index 7a9d6a455..e26d47497 100644 --- a/fusee/fusee-secondary/src/nxfs.h +++ b/fusee/fusee-secondary/src/nxfs.h @@ -26,7 +26,7 @@ int nxfs_end(); int nxfs_mount_sd(); int nxfs_mount_emmc(); -int nxfs_mount_emu_emmc(const char *emunand_path); +int nxfs_mount_emu_emmc(const char *emunand_boot0_path, const char *emunand_boot1_path, const char *emunand_rawnand_base_path); int nxfs_unmount_sd(); int nxfs_unmount_emmc(); int nxfs_unmount_emu_emmc(); diff --git a/fusee/fusee-secondary/src/raw_dev.h b/fusee/fusee-secondary/src/raw_dev.h index 5cc0ad55e..4c5910d7b 100644 --- a/fusee/fusee-secondary/src/raw_dev.h +++ b/fusee/fusee-secondary/src/raw_dev.h @@ -24,11 +24,11 @@ #define RAWDEV_MAX_DEVICES 16 -int rawdev_mount_device(const char *name, const device_partition_t *device, bool mount_immediately); +int rawdev_mount_device(const char *name, const device_partition_t *devpart, bool initialize_immediately); int rawdev_register_device(const char *name); - int rawdev_unregister_device(const char *name); -int rawdev_unmount_device(const char *name); /* also unregisters. */ +int rawdev_unmount_device(const char *name); /* also unregisters. */ + int rawdev_unmount_all(void); #endif