ams: distribute sysmodules in single file as stratosphere.romfs

This commit is contained in:
Michael Scire 2021-03-21 02:51:59 -07:00 committed by SciresM
parent 3afd9a737c
commit 79e4c82d7e
3 changed files with 118 additions and 25 deletions

View file

@ -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<fsa::IFileSystem> *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<fsa::IFileSystem> *out, const char *path, ncm::ProgramId program_id) {
Result OpenStratosphereCodeFileSystemImpl(std::unique_ptr<fsa::IFileSystem> *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<fsa::IFile> 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<FileStorage>(std::move(package_file));
R_UNLESS(package_storage != nullptr, fs::ResultAllocationFailureInCodeA());
/* Create a partition filesystem. */
auto package_fs = std::make_unique<fssystem::PartitionFileSystem>();
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<fsa::IFileSystem> *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::IFileSystem> 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::IFileSystem> 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<SdCardRedirectionCodeFileSystem>(std::move(fsa), program_id, false);