diff --git a/Makefile b/Makefile index d1db70423..75cc6e781 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,9 @@ +ifeq ($(strip $(DEVKITPRO)),) +$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=devkitPro) +endif + +include $(DEVKITPRO)/devkitA64/base_tools + TOPTARGETS := all clean dist-no-debug dist AMSBRANCH := $(shell git symbolic-ref --short HEAD) AMSHASH := $(shell git rev-parse --short HEAD) @@ -56,15 +62,6 @@ dist-no-debug: all mkdir atmosphere-$(AMSVER)/atmosphere mkdir atmosphere-$(AMSVER)/sept mkdir atmosphere-$(AMSVER)/switch - mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/0100000000000008 - mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/010000000000000D - mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/010000000000002B - mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/0100000000000032 - mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/0100000000000034 - mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/0100000000000036 - mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/0100000000000037 - mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/010000000000003C - mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/0100000000000042 mkdir -p atmosphere-$(AMSVER)/atmosphere/fatal_errors mkdir -p atmosphere-$(AMSVER)/atmosphere/config_templates mkdir -p atmosphere-$(AMSVER)/atmosphere/config @@ -84,19 +81,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 - cp stratosphere/boot2/boot2.nsp atmosphere-$(AMSVER)/atmosphere/contents/0100000000000008/exefs.nsp - cp stratosphere/dmnt/dmnt.nsp atmosphere-$(AMSVER)/atmosphere/contents/010000000000000D/exefs.nsp - cp stratosphere/erpt/erpt.nsp atmosphere-$(AMSVER)/atmosphere/contents/010000000000002B/exefs.nsp - cp stratosphere/eclct.stub/eclct.stub.nsp atmosphere-$(AMSVER)/atmosphere/contents/0100000000000032/exefs.nsp - cp stratosphere/fatal/fatal.nsp atmosphere-$(AMSVER)/atmosphere/contents/0100000000000034/exefs.nsp - cp stratosphere/creport/creport.nsp atmosphere-$(AMSVER)/atmosphere/contents/0100000000000036/exefs.nsp - cp stratosphere/ro/ro.nsp atmosphere-$(AMSVER)/atmosphere/contents/0100000000000037/exefs.nsp - cp stratosphere/jpegdec/jpegdec.nsp atmosphere-$(AMSVER)/atmosphere/contents/010000000000003C/exefs.nsp - cp stratosphere/pgl/pgl.nsp atmosphere-$(AMSVER)/atmosphere/contents/0100000000000042/exefs.nsp - mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/0100000000000032/flags - touch atmosphere-$(AMSVER)/atmosphere/contents/0100000000000032/flags/boot2.flag - mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/0100000000000037/flags - touch atmosphere-$(AMSVER)/atmosphere/contents/0100000000000037/flags/boot2.flag + 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 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/source/fs/fs_code.cpp b/libraries/libstratosphere/source/fs/fs_code.cpp index 3e706728d..248a6b082 100644 --- a/libraries/libstratosphere/source/fs/fs_code.cpp +++ b/libraries/libstratosphere/source/fs/fs_code.cpp @@ -20,6 +20,55 @@ namespace ams::fs { namespace { + constinit os::SdkMutex g_mount_stratosphere_romfs_lock; + constinit bool g_mounted_stratosphere_romfs = false; + + constinit TYPED_STORAGE(FileHandleStorage) g_stratosphere_romfs_storage = {}; + constinit TYPED_STORAGE(RomFsFileSystem) g_stratosphere_romfs_fs = {}; + + Result EnsureStratosphereRomfsMounted() { + std::scoped_lock lk(g_mount_stratosphere_romfs_lock); + + if (AMS_UNLIKELY(!g_mounted_stratosphere_romfs)) { + /* Mount the SD card. */ + R_TRY(fs::MountSdCard("#strat-romfs-sd")); + auto sd_guard = SCOPE_GUARD { fs::Unmount("#strat-romfs-sd"); }; + + /* Open sd:/atmosphere/stratosphere.romfs. */ + fs::FileHandle stratosphere_romfs_file; + R_TRY(fs::OpenFile(std::addressof(stratosphere_romfs_file), "#strat-romfs-sd:/atmosphere/stratosphere.romfs", fs::OpenMode_Read)); + + /* Setup the storage. */ + /* NOTE: This owns the file, and so on failure it will be closed appropriately. */ + std::construct_at(GetPointer(g_stratosphere_romfs_storage), stratosphere_romfs_file, true); + auto storage_guard = SCOPE_GUARD { std::destroy_at(GetPointer(g_stratosphere_romfs_storage)); }; + + /* Create the filesystem. */ + std::construct_at(GetPointer(g_stratosphere_romfs_fs)); + auto fs_guard = SCOPE_GUARD { std::destroy_at(GetPointer(g_stratosphere_romfs_fs)); }; + + /* Initialize the filesystem. */ + R_TRY(GetReference(g_stratosphere_romfs_fs).Initialize(GetPointer(g_stratosphere_romfs_storage), nullptr, 0, false)); + + /* We succeeded, and so stratosphere.romfs is mounted. */ + fs_guard.Cancel(); + storage_guard.Cancel(); + sd_guard.Cancel(); + + g_mounted_stratosphere_romfs = true; + } + + return ResultSuccess(); + } + + fsa::IFileSystem &GetStratosphereRomFsFileSystem() { + /* Ensure that stratosphere.romfs is mounted. */ + /* NOTE: Abort is used here to ensure that atmosphere's filesystem is structurally valid. */ + R_ABORT_UNLESS(EnsureStratosphereRomfsMounted()); + + return GetReference(g_stratosphere_romfs_fs); + } + Result OpenCodeFileSystemImpl(CodeVerificationData *out_verification_data, std::unique_ptr *out, const char *path, ncm::ProgramId program_id) { /* Print a path suitable for the remote service. */ fssrv::sf::Path sf_path; @@ -62,10 +111,46 @@ namespace ams::fs { return OpenPackageFileSystemImpl(out, sf_path.str); } - Result OpenSdCardCodeOrCodeFileSystemImpl(CodeVerificationData *out_verification_data, std::unique_ptr *out, const char *path, ncm::ProgramId program_id) { + Result OpenStratosphereCodeFileSystemImpl(std::unique_ptr *out, ncm::ProgramId program_id) { + /* Ensure we don't access the SD card too early. */ + R_UNLESS(cfg::IsSdCardInitialized(), fs::ResultSdCardNotPresent()); + + /* Open the program's package. */ + std::unique_ptr package_file; + { + /* Get the stratosphere.romfs filesystem. */ + auto &romfs_fs = GetStratosphereRomFsFileSystem(); + + /* 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)); + + /* Open the package within stratosphere.romfs. */ + R_TRY(romfs_fs.OpenFile(std::addressof(package_file), sf_path.str, fs::OpenMode_Read)); + } + + /* Create a file storage for the program's package. */ + auto package_storage = std::make_shared(std::move(package_file)); + R_UNLESS(package_storage != nullptr, fs::ResultAllocationFailureInCodeA()); + + /* Create a partition filesystem. */ + auto package_fs = std::make_unique(); + R_UNLESS(package_fs != nullptr, fs::ResultAllocationFailureInCodeA()); + + /* Initialize the partition filesystem. */ + R_TRY(package_fs->Initialize(package_storage)); + + *out = std::move(package_fs); + return ResultSuccess(); + } + + Result OpenSdCardCodeOrStratosphereCodeOrCodeFileSystemImpl(CodeVerificationData *out_verification_data, std::unique_ptr *out, const char *path, ncm::ProgramId program_id) { /* If we can open an sd card code fs, use it. */ R_SUCCEED_IF(R_SUCCEEDED(OpenSdCardCodeFileSystemImpl(out, program_id))); + /* If we can open a stratosphere code fs, use it. */ + R_SUCCEED_IF(R_SUCCEEDED(OpenStratosphereCodeFileSystemImpl(out, program_id))); + /* Otherwise, fall back to a normal code fs. */ return OpenCodeFileSystemImpl(out_verification_data, out, path, program_id); } @@ -239,7 +324,7 @@ namespace ams::fs { /* Open the code filesystem. */ std::unique_ptr fsa; - R_TRY(OpenSdCardCodeOrCodeFileSystemImpl(out_verification_data, std::addressof(fsa), path, program_id)); + R_TRY(OpenSdCardCodeOrStratosphereCodeOrCodeFileSystemImpl(out_verification_data, std::addressof(fsa), path, program_id)); this->code_fs.emplace(std::move(fsa), program_id, is_specific); this->program_id = program_id; @@ -326,7 +411,7 @@ namespace ams::fs { /* Open the code file system. */ std::unique_ptr fsa; - R_TRY(OpenSdCardCodeOrCodeFileSystemImpl(out, std::addressof(fsa), path, program_id)); + R_TRY(OpenSdCardCodeOrStratosphereCodeOrCodeFileSystemImpl(out, std::addressof(fsa), path, program_id)); /* Create a wrapper fs. */ auto wrap_fsa = std::make_unique(std::move(fsa), program_id, false); diff --git a/libraries/libstratosphere/source/ncm/ncm_submission_package_install_task.cpp b/libraries/libstratosphere/source/ncm/ncm_submission_package_install_task.cpp index 37f702277..2c3a6cd8d 100644 --- a/libraries/libstratosphere/source/ncm/ncm_submission_package_install_task.cpp +++ b/libraries/libstratosphere/source/ncm/ncm_submission_package_install_task.cpp @@ -38,6 +38,9 @@ namespace ams::ncm { auto partition_file_system = std::make_unique(); R_UNLESS(partition_file_system != nullptr, ncm::ResultAllocationFailed()); + /* Initialize the partition file system. */ + R_TRY(partition_file_system->Initialize(std::addressof(this->storage))); + /* Create a mount name and register the file system. */ auto mount_name = impl::CreateUniqueMountName(); R_TRY(fs::fsa::Register(mount_name.str, std::move(partition_file_system)));