diff --git a/Makefile b/Makefile index d13a8baec..5c4d7d446 100644 --- a/Makefile +++ b/Makefile @@ -58,6 +58,7 @@ dist: all mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/0100000000000037 mkdir -p atmosphere-$(AMSVER)/atmosphere/fatal_errors mkdir -p atmosphere-$(AMSVER)/atmosphere/config_templates + mkdir -p atmosphere-$(AMSVER)/atmosphere/config cp fusee/fusee-primary/fusee-primary.bin atmosphere-$(AMSVER)/atmosphere/reboot_payload.bin cp fusee/fusee-mtc/fusee-mtc.bin atmosphere-$(AMSVER)/atmosphere/fusee-mtc.bin cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/atmosphere/fusee-secondary.bin @@ -66,7 +67,7 @@ dist: all cp sept/sept-secondary/sept-secondary.bin atmosphere-$(AMSVER)/sept/sept-secondary.bin cp sept/sept-secondary/sept-secondary_00.enc atmosphere-$(AMSVER)/sept/sept-secondary_00.enc cp sept/sept-secondary/sept-secondary_01.enc atmosphere-$(AMSVER)/sept/sept-secondary_01.enc - cp common/defaults/BCT.ini atmosphere-$(AMSVER)/atmosphere/BCT.ini + cp common/defaults/BCT.ini atmosphere-$(AMSVER)/atmosphere/config/BCT.ini cp common/defaults/override_config.ini atmosphere-$(AMSVER)/atmosphere/config_templates/override_config.ini cp common/defaults/system_settings.ini atmosphere-$(AMSVER)/atmosphere/config_templates/system_settings.ini cp -r common/defaults/kip_patches atmosphere-$(AMSVER)/atmosphere/kip_patches diff --git a/fusee/fusee-primary/src/main.c b/fusee/fusee-primary/src/main.c index aa8050b73..10ca0ee19 100644 --- a/fusee/fusee-primary/src/main.c +++ b/fusee/fusee-primary/src/main.c @@ -51,7 +51,7 @@ static char g_bct0_buffer[BCTO_MAX_SIZE]; "[stratosphere]\n" static const char *load_config(void) { - if (!read_from_file(g_bct0_buffer, BCTO_MAX_SIZE, "atmosphere/BCT.ini")) { + if (!read_from_file(g_bct0_buffer, BCTO_MAX_SIZE, "atmosphere/config/BCT.ini")) { print(SCREEN_LOG_LEVEL_DEBUG, "Failed to read BCT0 from SD!\n"); print(SCREEN_LOG_LEVEL_DEBUG, "Using default BCT0!\n"); memcpy(g_bct0_buffer, DEFAULT_BCT0, sizeof(DEFAULT_BCT0)); diff --git a/fusee/fusee-secondary/src/main.c b/fusee/fusee-secondary/src/main.c index b4e5f32dd..8baa6a5fd 100644 --- a/fusee/fusee-secondary/src/main.c +++ b/fusee/fusee-secondary/src/main.c @@ -13,7 +13,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + #include #include #include @@ -46,7 +46,7 @@ static void setup_env(void) { if (console_init() < 0) { generic_panic(); } - + /* Set up exception handlers. */ setup_exception_handlers(); @@ -80,7 +80,7 @@ int main(int argc, void **argv) { if (argc != STAGE2_ARGC) { generic_panic(); } - + g_stage2_args = &g_stage2_args_store; memcpy(g_stage2_args, (stage2_args_t *)argv[STAGE2_ARGV_ARGUMENT_STRUCT], sizeof(*g_stage2_args)); @@ -88,20 +88,20 @@ int main(int argc, void **argv) { if (g_stage2_args->version != 0) { generic_panic(); } - + /* Override the global logging level. */ log_set_log_level(g_stage2_args->log_level); - + /* Initialize the boot environment. */ setup_env(); - + print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, u8"Welcome to Atmosphère Fusée Stage 2!\n"); print(SCREEN_LOG_LEVEL_DEBUG, "Stage 2 executing from: %s\n", (const char *)argv[STAGE2_ARGV_PROGRAM_PATH]); - + /* Load BCT0 from SD if needed. */ if (strcmp(g_stage2_args->bct0, "") == 0) { uint32_t bct_tmp_buf[sizeof(g_stage2_args->bct0) / sizeof(uint32_t)] = {0}; - if (!read_from_file(bct_tmp_buf, sizeof(bct_tmp_buf) - 1, "atmosphere/BCT.ini")) { + if (!read_from_file(bct_tmp_buf, sizeof(bct_tmp_buf) - 1, "atmosphere/config/BCT.ini")) { fatal_error("Failed to read BCT0 from SD!\n"); } memcpy(g_stage2_args->bct0, bct_tmp_buf, sizeof(bct_tmp_buf)); @@ -110,17 +110,17 @@ int main(int argc, void **argv) { /* This will load all remaining binaries off of the SD. */ load_payload(g_stage2_args->bct0); print(SCREEN_LOG_LEVEL_INFO, "Loaded payloads!\n"); - + g_do_nxboot = (loader_ctx->chainload_entrypoint == 0); if (g_do_nxboot) { print(SCREEN_LOG_LEVEL_INFO, "Now performing nxboot.\n"); /* Start boot. */ uint32_t boot_memaddr = nxboot_main(); - + /* Terminate the boot environment. */ cleanup_env(); - + /* Finish boot. */ nxboot_finish(boot_memaddr); } else { @@ -129,7 +129,7 @@ int main(int argc, void **argv) { print(SCREEN_LOG_LEVEL_INFO, "Now chainloading.\n"); g_chainloader_argc = 1; strcpy(g_chainloader_arg_data, path); - + /* Terminate the boot environment. */ cleanup_env(); } diff --git a/stratosphere/ams_mitm/source/amsmitm_fs_utils.cpp b/stratosphere/ams_mitm/source/amsmitm_fs_utils.cpp index 73ce9d665..7d0c8592e 100644 --- a/stratosphere/ams_mitm/source/amsmitm_fs_utils.cpp +++ b/stratosphere/ams_mitm/source/amsmitm_fs_utils.cpp @@ -40,6 +40,14 @@ namespace ams::mitm::fs { } } + void FormatAtmosphereSdPath(char *dst_path, size_t dst_path_size, const char *subdir, const char *src_path) { + if (src_path[0] == '/') { + std::snprintf(dst_path, dst_path_size, "/atmosphere/%s%s", subdir, src_path); + } else { + std::snprintf(dst_path, dst_path_size, "/atmosphere/%s/%s", subdir, src_path); + } + } + void FormatAtmosphereSdPath(char *dst_path, size_t dst_path_size, ncm::ProgramId program_id, const char *src_path) { if (src_path[0] == '/') { std::snprintf(dst_path, dst_path_size, "/atmosphere/contents/%016lx%s", static_cast(program_id), src_path); @@ -146,6 +154,15 @@ namespace ams::mitm::fs { return fsFsOpenDirectory(fs, fixed_path, mode, out); } + /* TODO: Remove this in Atmosphere 0.10.1. */ + Result RenameProgramDirectoryForCompatibility(const char *dir_name) { + R_TRY(EnsureSdInitialized()); + char titles_fixed_path[ams::fs::EntryNameLengthMax + 1]; + char contents_fixed_path[ams::fs::EntryNameLengthMax + 1]; + FormatAtmosphereSdPath(titles_fixed_path, sizeof(titles_fixed_path), "titles", dir_name); + FormatAtmosphereSdPath(contents_fixed_path, sizeof(contents_fixed_path), "contents", dir_name); + return fsFsRenameDirectory(&g_sd_filesystem, titles_fixed_path, contents_fixed_path); + } bool HasSdRomfsContent(ncm::ProgramId program_id) { /* Check if romfs.bin is present. */ diff --git a/stratosphere/ams_mitm/source/amsmitm_fs_utils.hpp b/stratosphere/ams_mitm/source/amsmitm_fs_utils.hpp index dcbd0b90c..6adbcaac8 100644 --- a/stratosphere/ams_mitm/source/amsmitm_fs_utils.hpp +++ b/stratosphere/ams_mitm/source/amsmitm_fs_utils.hpp @@ -38,6 +38,9 @@ namespace ams::mitm::fs { Result OpenAtmosphereSdRomfsDirectory(FsDir *out, ncm::ProgramId program_id, const char *path, u32 mode); Result OpenAtmosphereRomfsDirectory(FsDir *out, ncm::ProgramId program_id, const char *path, u32 mode, FsFileSystem *fs); + /* TODO: Remove this in Atmosphere 0.10.1. */ + Result RenameProgramDirectoryForCompatibility(const char *dir_name); + bool HasSdRomfsContent(ncm::ProgramId program_id); Result SaveAtmosphereSdFile(FsFile *out, ncm::ProgramId program_id, const char *path, void *data, size_t size); diff --git a/stratosphere/ams_mitm/source/amsmitm_initialization.cpp b/stratosphere/ams_mitm/source/amsmitm_initialization.cpp index 0ee9aaeb6..87ffee4bc 100644 --- a/stratosphere/ams_mitm/source/amsmitm_initialization.cpp +++ b/stratosphere/ams_mitm/source/amsmitm_initialization.cpp @@ -65,6 +65,17 @@ namespace ams::mitm { /* Emummc file protection. */ FsFile g_emummc_file; + constexpr inline bool IsHexadecimal(const char *str) { + while (*str) { + if (std::isxdigit(static_cast(*str))) { + str++; + } else { + return false; + } + } + return true; + } + void GetBackupFileName(char *dst, size_t dst_size, const char *serial_number, const char *fn) { if (strlen(serial_number) > 0) { std::snprintf(dst, dst_size, "automatic_backups/%s_%s", serial_number, fn); @@ -167,6 +178,23 @@ namespace ams::mitm { } } + void RenameTitlesDirectoryProgramFoldersForCompatibility() { + FsDir titles_dir; + if (R_FAILED(mitm::fs::OpenAtmosphereSdDirectory(&titles_dir, "/titles", ams::fs::OpenDirectoryMode_Directory))) { + return; + } + ON_SCOPE_EXIT { fsDirClose(&titles_dir); }; + + ams::fs::DirectoryEntry dir_entry; + s64 read_entries; + while (R_SUCCEEDED(fsDirRead(&titles_dir, &read_entries, 1, &dir_entry)) && read_entries == 1) { + if (strlen(dir_entry.name) == 2 * sizeof(ncm::ProgramId) && IsHexadecimal(dir_entry.name)) { + /* We found a program directory, try to rename it. Failure is allowed. */ + mitm::fs::RenameProgramDirectoryForCompatibility(dir_entry.name); + } + } + } + /* Initialization implementation */ void InitializeThreadFunc(void *arg) { /* Wait for the SD card to be ready. */ @@ -182,6 +210,10 @@ namespace ams::mitm { /* Backup Calibration Binary and BIS keys. */ CreateAutomaticBackups(); + /* Rename program folders in the titles directory. */ + /* TODO: Remove this in Atmosphere 0.10.1. */ + RenameTitlesDirectoryProgramFoldersForCompatibility(); + /* If we're emummc, persist a write-handle to prevent other processes from touching the image. */ if (emummc::IsActive()) { if (const char *emummc_file_path = emummc::GetFilePath(); emummc_file_path != nullptr) { diff --git a/stratosphere/ams_mitm/source/set_mitm/settings_sd_kvs.cpp b/stratosphere/ams_mitm/source/set_mitm/settings_sd_kvs.cpp index b99e68d87..733dcd443 100644 --- a/stratosphere/ams_mitm/source/set_mitm/settings_sd_kvs.cpp +++ b/stratosphere/ams_mitm/source/set_mitm/settings_sd_kvs.cpp @@ -291,7 +291,7 @@ namespace ams::settings::fwdbg { Result LoadSdCardKeyValueStore() { /* Open file. */ FsFile config_file; - if (R_FAILED(ams::mitm::fs::OpenAtmosphereSdFile(&config_file, "/system_settings.ini", fs::OpenMode_Read))) { + if (R_FAILED(ams::mitm::fs::OpenAtmosphereSdFile(&config_file, "/config/system_settings.ini", fs::OpenMode_Read))) { /* It's okay if the file isn't readable/present, because we already loaded defaults. */ return ResultSuccess(); } diff --git a/stratosphere/libstratosphere/source/cfg/cfg_override.cpp b/stratosphere/libstratosphere/source/cfg/cfg_override.cpp index fd26b2565..1b0a06b1d 100644 --- a/stratosphere/libstratosphere/source/cfg/cfg_override.cpp +++ b/stratosphere/libstratosphere/source/cfg/cfg_override.cpp @@ -230,7 +230,7 @@ namespace ams::cfg { } void RefreshOverrideConfiguration() { - ParseIniFile(OverrideConfigIniHandler, "/atmosphere/override_config.ini", nullptr); + ParseIniFile(OverrideConfigIniHandler, "/atmosphere/config/override_config.ini", nullptr); } ContentSpecificOverrideConfig GetContentOverrideConfig(ncm::ProgramId program_id) {