diff --git a/Makefile b/Makefile index 75cc6e781..2d248175a 100644 --- a/Makefile +++ b/Makefile @@ -65,6 +65,8 @@ dist-no-debug: all mkdir -p atmosphere-$(AMSVER)/atmosphere/fatal_errors mkdir -p atmosphere-$(AMSVER)/atmosphere/config_templates mkdir -p atmosphere-$(AMSVER)/atmosphere/config + mkdir -p atmosphere-$(AMSVER)/atmosphere/flags + touch atmosphere-$(AMSVER)/atmosphere/flags/clean_stratosphere_for_0.19.0.flag 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-experimental.bin atmosphere-$(AMSVER)/atmosphere/fusee-secondary.bin @@ -81,27 +83,27 @@ dist-no-debug: all cp config_templates/exosphere.ini atmosphere-$(AMSVER)/atmosphere/config_templates/exosphere.ini cp -r config_templates/kip_patches atmosphere-$(AMSVER)/atmosphere/kip_patches cp -r config_templates/hbl_html atmosphere-$(AMSVER)/atmosphere/hbl_html - mkdir -p atmosphere-$(AMSVER)/atmosphere/stratosphere_romfs/contents/0100000000000008 - mkdir -p atmosphere-$(AMSVER)/atmosphere/stratosphere_romfs/contents/0100000000000008 - mkdir -p atmosphere-$(AMSVER)/atmosphere/stratosphere_romfs/contents/010000000000000D - mkdir -p atmosphere-$(AMSVER)/atmosphere/stratosphere_romfs/contents/010000000000002B - mkdir -p atmosphere-$(AMSVER)/atmosphere/stratosphere_romfs/contents/0100000000000032 - mkdir -p atmosphere-$(AMSVER)/atmosphere/stratosphere_romfs/contents/0100000000000034 - mkdir -p atmosphere-$(AMSVER)/atmosphere/stratosphere_romfs/contents/0100000000000036 - mkdir -p atmosphere-$(AMSVER)/atmosphere/stratosphere_romfs/contents/0100000000000037 - mkdir -p atmosphere-$(AMSVER)/atmosphere/stratosphere_romfs/contents/010000000000003C - mkdir -p atmosphere-$(AMSVER)/atmosphere/stratosphere_romfs/contents/0100000000000042 - cp stratosphere/boot2/boot2.nsp atmosphere-$(AMSVER)/atmosphere/stratosphere_romfs/contents/0100000000000008/exefs.nsp - cp stratosphere/dmnt/dmnt.nsp atmosphere-$(AMSVER)/atmosphere/stratosphere_romfs/contents/010000000000000D/exefs.nsp - cp stratosphere/erpt/erpt.nsp atmosphere-$(AMSVER)/atmosphere/stratosphere_romfs/contents/010000000000002B/exefs.nsp - cp stratosphere/eclct.stub/eclct.stub.nsp atmosphere-$(AMSVER)/atmosphere/stratosphere_romfs/contents/0100000000000032/exefs.nsp - cp stratosphere/fatal/fatal.nsp atmosphere-$(AMSVER)/atmosphere/stratosphere_romfs/contents/0100000000000034/exefs.nsp - cp stratosphere/creport/creport.nsp atmosphere-$(AMSVER)/atmosphere/stratosphere_romfs/contents/0100000000000036/exefs.nsp - cp stratosphere/ro/ro.nsp atmosphere-$(AMSVER)/atmosphere/stratosphere_romfs/contents/0100000000000037/exefs.nsp - cp stratosphere/jpegdec/jpegdec.nsp atmosphere-$(AMSVER)/atmosphere/stratosphere_romfs/contents/010000000000003C/exefs.nsp - cp stratosphere/pgl/pgl.nsp atmosphere-$(AMSVER)/atmosphere/stratosphere_romfs/contents/0100000000000042/exefs.nsp - @build_romfs atmosphere-$(AMSVER)/atmosphere/stratosphere_romfs atmosphere-$(AMSVER)/atmosphere/stratosphere.romfs - rm -r atmosphere-$(AMSVER)/atmosphere/stratosphere_romfs + mkdir -p atmosphere-$(AMSVER)/stratosphere_romfs/atmosphere/contents/0100000000000008 + mkdir -p atmosphere-$(AMSVER)/stratosphere_romfs/atmosphere/contents/0100000000000008 + mkdir -p atmosphere-$(AMSVER)/stratosphere_romfs/atmosphere/contents/010000000000000D + mkdir -p atmosphere-$(AMSVER)/stratosphere_romfs/atmosphere/contents/010000000000002B + mkdir -p atmosphere-$(AMSVER)/stratosphere_romfs/atmosphere/contents/0100000000000032 + mkdir -p atmosphere-$(AMSVER)/stratosphere_romfs/atmosphere/contents/0100000000000034 + mkdir -p atmosphere-$(AMSVER)/stratosphere_romfs/atmosphere/contents/0100000000000036 + mkdir -p atmosphere-$(AMSVER)/stratosphere_romfs/atmosphere/contents/0100000000000037 + mkdir -p atmosphere-$(AMSVER)/stratosphere_romfs/atmosphere/contents/010000000000003C + mkdir -p atmosphere-$(AMSVER)/stratosphere_romfs/atmosphere/contents/0100000000000042 + cp stratosphere/boot2/boot2.nsp atmosphere-$(AMSVER)/stratosphere_romfs/atmosphere/contents/0100000000000008/exefs.nsp + cp stratosphere/dmnt/dmnt.nsp atmosphere-$(AMSVER)/stratosphere_romfs/atmosphere/contents/010000000000000D/exefs.nsp + cp stratosphere/erpt/erpt.nsp atmosphere-$(AMSVER)/stratosphere_romfs/atmosphere/contents/010000000000002B/exefs.nsp + cp stratosphere/eclct.stub/eclct.stub.nsp atmosphere-$(AMSVER)/stratosphere_romfs/atmosphere/contents/0100000000000032/exefs.nsp + cp stratosphere/fatal/fatal.nsp atmosphere-$(AMSVER)/stratosphere_romfs/atmosphere/contents/0100000000000034/exefs.nsp + cp stratosphere/creport/creport.nsp atmosphere-$(AMSVER)/stratosphere_romfs/atmosphere/contents/0100000000000036/exefs.nsp + cp stratosphere/ro/ro.nsp atmosphere-$(AMSVER)/stratosphere_romfs/atmosphere/contents/0100000000000037/exefs.nsp + cp stratosphere/jpegdec/jpegdec.nsp atmosphere-$(AMSVER)/stratosphere_romfs/atmosphere/contents/010000000000003C/exefs.nsp + cp stratosphere/pgl/pgl.nsp atmosphere-$(AMSVER)/stratosphere_romfs/atmosphere/contents/0100000000000042/exefs.nsp + @build_romfs atmosphere-$(AMSVER)/stratosphere_romfs atmosphere-$(AMSVER)/atmosphere/stratosphere.romfs + rm -r atmosphere-$(AMSVER)/stratosphere_romfs cp troposphere/reboot_to_payload/reboot_to_payload.nro atmosphere-$(AMSVER)/switch/reboot_to_payload.nro cp troposphere/daybreak/daybreak.nro atmosphere-$(AMSVER)/switch/daybreak.nro cd atmosphere-$(AMSVER); zip -r ../atmosphere-$(AMSVER).zip ./*; cd ../; diff --git a/libraries/libstratosphere/include/stratosphere/cfg/cfg_api.hpp b/libraries/libstratosphere/include/stratosphere/cfg/cfg_api.hpp index 5cb515619..3d7b13b27 100644 --- a/libraries/libstratosphere/include/stratosphere/cfg/cfg_api.hpp +++ b/libraries/libstratosphere/include/stratosphere/cfg/cfg_api.hpp @@ -40,6 +40,7 @@ namespace ams::cfg { bool HasFlag(const sm::MitmProcessInfo &process_info, const char *flag); bool HasContentSpecificFlag(ncm::ProgramId program_id, const char *flag); bool HasGlobalFlag(const char *flag); + Result DeleteGlobalFlag(const char *flag); /* HBL Configuration utilities. */ bool HasHblFlag(const char *flag); diff --git a/libraries/libstratosphere/source/boot2/boot2_api.cpp b/libraries/libstratosphere/source/boot2/boot2_api.cpp index 5c5c16ed7..d660ac5e0 100644 --- a/libraries/libstratosphere/source/boot2/boot2_api.cpp +++ b/libraries/libstratosphere/source/boot2/boot2_api.cpp @@ -23,7 +23,7 @@ namespace ams::boot2 { /* psc, bus, pcv is the minimal set of required programs to get SD card. */ /* bus depends on pcie, and pcv depends on settings. */ - constexpr ncm::SystemProgramId PreSdCardLaunchPrograms[] = { + constexpr const ncm::SystemProgramId PreSdCardLaunchPrograms[] = { ncm::SystemProgramId::Psc, /* psc */ ncm::SystemProgramId::Pcie, /* pcie */ ncm::SystemProgramId::Bus, /* bus */ @@ -33,7 +33,7 @@ namespace ams::boot2 { }; constexpr size_t NumPreSdCardLaunchPrograms = util::size(PreSdCardLaunchPrograms); - constexpr ncm::SystemProgramId AdditionalLaunchPrograms[] = { + constexpr const ncm::SystemProgramId AdditionalLaunchPrograms[] = { ncm::SystemProgramId::Am, /* am */ ncm::SystemProgramId::NvServices, /* nvservices */ ncm::SystemProgramId::NvnFlinger, /* nvnflinger */ @@ -78,7 +78,7 @@ namespace ams::boot2 { }; constexpr size_t NumAdditionalLaunchPrograms = util::size(AdditionalLaunchPrograms); - constexpr ncm::SystemProgramId AdditionalMaintenanceLaunchPrograms[] = { + constexpr const ncm::SystemProgramId AdditionalMaintenanceLaunchPrograms[] = { ncm::SystemProgramId::Am, /* am */ ncm::SystemProgramId::NvServices, /* nvservices */ ncm::SystemProgramId::NvnFlinger, /* nvnflinger */ @@ -311,6 +311,57 @@ namespace ams::boot2 { return hos::GetVersion() >= hos::Version_9_0_0; } + /* Prior to 0.19.0, we distributed system modules inside /atmosphere/contents/. */ + /* We need to clean these up, so that we don't break horribly on first upgrade. */ + constexpr const ncm::SystemProgramId StratosphereSystemModulesForPostZeroPointNineteenPointZeroCleanup[] = { + ncm::SystemProgramId::Boot2, + ncm::SystemProgramId::Creport, + ncm::SystemProgramId::Dmnt, + ncm::SystemProgramId::Eclct, + ncm::SystemProgramId::Erpt, + ncm::SystemProgramId::Fatal, + ncm::SystemProgramId::JpegDec, + ncm::SystemProgramId::Pgl, + ncm::SystemProgramId::Ro, + }; + + alignas(0x40) constinit u8 g_fs_cleanup_buffer[4_KB]; + lmem::HeapHandle g_fs_cleanup_heap_handle; + + void *AllocateForFsForCleanup(size_t size) { + return lmem::AllocateFromExpHeap(g_fs_cleanup_heap_handle, size); + } + + void DeallocateForFsForCleanup(void *p, size_t size) { + return lmem::FreeToExpHeap(g_fs_cleanup_heap_handle, p); + } + + void InitializeFsHeapForCleanup() { + g_fs_cleanup_heap_handle = lmem::CreateExpHeap(g_fs_cleanup_buffer, sizeof(g_fs_cleanup_buffer), lmem::CreateOption_None); + fs::SetAllocator(AllocateForFsForCleanup, DeallocateForFsForCleanup); + } + + void CleanupSdCardSystemProgramsForUpgradeToZeroPointNineteenPointZero() { + /* Temporarily mount the SD card. */ + R_ABORT_UNLESS(fs::MountSdCard("sdmc")); + ON_SCOPE_EXIT { fs::Unmount("sdmc"); }; + + for (const auto program_id : StratosphereSystemModulesForPostZeroPointNineteenPointZeroCleanup) { + /* Get the program's contents path. */ + char path[fs::EntryNameLengthMax]; + util::SNPrintf(path, sizeof(path), "sdmc:/atmosphere/contents/%016lx/", program_id.value); + + /* Check if we have old contents. */ + bool has_dir; + R_ABORT_UNLESS(fs::HasDirectory(std::addressof(has_dir), path)); + + /* Cleanup the old contents, if we have them. */ + if (has_dir) { + R_ABORT_UNLESS(fs::DeleteDirectoryRecursively(path)); + } + } + } + } /* Boot2 API. */ @@ -370,6 +421,28 @@ namespace ams::boot2 { } } + /* Perform cleanup to faciliate upgrade to 0.19.0. */ + /* NOTE: This will be removed in a future atmosphere revision. */ + { + /* Setup FS heap for cleanup. */ + InitializeFsHeapForCleanup(); + + /* Temporarily initialize fs. */ + sm::DoWithSession([&] { + R_ABORT_UNLESS(fsInitialize()); + }); + ON_SCOPE_EXIT { fsExit(); }; + + /* Wait for the sd card to be available. */ + cfg::WaitSdCardInitialized(); + + /* Cleanup. */ + if (cfg::HasGlobalFlag("clean_stratosphere_for_0.19.0")) { + CleanupSdCardSystemProgramsForUpgradeToZeroPointNineteenPointZero(); + R_ABORT_UNLESS(cfg::DeleteGlobalFlag("clean_stratosphere_for_0.19.0")); + } + } + /* Launch Atmosphere boot2, using NcmStorageId_None to force SD card boot. */ LaunchProgram(nullptr, ncm::ProgramLocation::Make(ncm::SystemProgramId::Boot2, ncm::StorageId::None), 0); } diff --git a/libraries/libstratosphere/source/cfg/cfg_flags.cpp b/libraries/libstratosphere/source/cfg/cfg_flags.cpp index be0b1bb03..3ef313f10 100644 --- a/libraries/libstratosphere/source/cfg/cfg_flags.cpp +++ b/libraries/libstratosphere/source/cfg/cfg_flags.cpp @@ -52,6 +52,26 @@ namespace ams::cfg { return has_file; } + Result DeleteFlagFile(const char *flag_path) { + /* We need the SD card to be available to delete anything. */ + AMS_ABORT_UNLESS(IsSdCardInitialized()); + + /* Mount the sd card. */ + char mount_name[fs::MountNameLengthMax + 1]; + GetFlagMountName(mount_name); + R_TRY(fs::MountSdCard(mount_name)); + ON_SCOPE_EXIT { fs::Unmount(mount_name); }; + + /* Get the flag path. */ + char full_path[fs::EntryNameLengthMax + 1]; + util::SNPrintf(full_path, sizeof(full_path), "%s:/%s", mount_name, flag_path[0] == '/' ? flag_path + 1 : flag_path); + + /* Delete the file. */ + R_TRY(fs::DeleteFile(full_path)); + + return ResultSuccess(); + } + } /* Flag utilities. */ @@ -77,4 +97,10 @@ namespace ams::cfg { return HasGlobalFlag(hbl_flag); } + Result DeleteGlobalFlag(const char *flag) { + char global_flag[fs::EntryNameLengthMax + 1]; + util::SNPrintf(global_flag, sizeof(global_flag) - 1, "/atmosphere/flags/%s.flag", flag); + return DeleteFlagFile(global_flag); + } + } diff --git a/libraries/libstratosphere/source/fs/fs_code.cpp b/libraries/libstratosphere/source/fs/fs_code.cpp index 248a6b082..0fe32294d 100644 --- a/libraries/libstratosphere/source/fs/fs_code.cpp +++ b/libraries/libstratosphere/source/fs/fs_code.cpp @@ -123,7 +123,7 @@ namespace ams::fs { /* Print a path to the program's package. */ fssrv::sf::Path sf_path; - R_TRY(FspPathPrintf(std::addressof(sf_path), "/contents/%016lX/exefs.nsp", program_id.value)); + R_TRY(FspPathPrintf(std::addressof(sf_path), "/atmosphere/contents/%016lX/exefs.nsp", program_id.value)); /* Open the package within stratosphere.romfs. */ R_TRY(romfs_fs.OpenFile(std::addressof(package_file), sf_path.str, fs::OpenMode_Read));