diff --git a/stratosphere/fs_mitm/source/fsmitm_layeredrom.cpp b/stratosphere/fs_mitm/source/fsmitm_layeredrom.cpp index 819029f53..6d2797268 100644 --- a/stratosphere/fs_mitm/source/fsmitm_layeredrom.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_layeredrom.cpp @@ -9,7 +9,12 @@ LayeredRomFS::LayeredRomFS(std::shared_ptr s_r, std::shared_ptr f_r, u64 tid) : storage_romfs(s_r), file_romfs(f_r), title_id(tid) { /* Start building the new virtual romfs. */ RomFSBuildContext build_ctx(this->title_id); - this->p_source_infos = std::make_shared>(); + this->p_source_infos = std::shared_ptr>(new std::vector(), [](std::vector *to_delete) { + for (unsigned int i = 0; i < to_delete->size(); i++) { + (*to_delete)[i].Cleanup(); + } + delete to_delete; + }); if (Utils::IsSdInitialized()) { build_ctx.MergeSdFiles(); } @@ -51,6 +56,7 @@ Result LayeredRomFS::Read(void *buffer, size_t size, u64 offset) { } } + Result rc; size_t read_so_far = 0; while (read_so_far < size) { RomFSSourceInfo *cur_source = &((*this->p_source_infos)[cur_source_ind]); @@ -59,38 +65,47 @@ Result LayeredRomFS::Read(void *buffer, size_t size, u64 offset) { if (cur_read_size > cur_source->size - (offset - cur_source->virtual_offset)) { cur_read_size = cur_source->size - (offset - cur_source->virtual_offset); } - auto source_info_visitor = [&](auto& info) -> Result { - Result rc = 0; - if constexpr (std::is_same_v) { - FsFile file; - if (R_FAILED((rc = Utils::OpenRomFSSdFile(this->title_id, info.path, FS_OPEN_READ, &file)))) { - fatalSimple(rc); + switch (cur_source->type) { + case RomFSDataSource::LooseFile: + { + FsFile file; + if (R_FAILED((rc = Utils::OpenRomFSSdFile(this->title_id, cur_source->loose_source_info.path, FS_OPEN_READ, &file)))) { + fatalSimple(rc); + } + size_t out_read; + if (R_FAILED((rc = fsFileRead(&file, (offset - cur_source->virtual_offset), (void *)((uintptr_t)buffer + read_so_far), cur_read_size, &out_read)))) { + fatalSimple(rc); + } + if (out_read != cur_read_size) { + Reboot(); + } + fsFileClose(&file); } - size_t out_read; - if (R_FAILED((rc = fsFileRead(&file, (offset - cur_source->virtual_offset), (void *)((uintptr_t)buffer + read_so_far), cur_read_size, &out_read)))) { - fatalSimple(rc); + break; + case RomFSDataSource::Memory: + { + memcpy((void *)((uintptr_t)buffer + read_so_far), cur_source->memory_source_info.data + (offset - cur_source->virtual_offset), cur_read_size); } - if (out_read != cur_read_size) { - Reboot(); + break; + case RomFSDataSource::BaseRomFS: + { + if (R_FAILED((rc = this->storage_romfs->Read((void *)((uintptr_t)buffer + read_so_far), cur_read_size, cur_source->base_source_info.offset + (offset - cur_source->virtual_offset))))) { + /* TODO: Can this ever happen? */ + /* fatalSimple(rc); */ + return rc; + } } - fsFileClose(&file); - } else if constexpr (std::is_same_v) { - memcpy((void *)((uintptr_t)buffer + read_so_far), info.data + (offset - cur_source->virtual_offset), cur_read_size); - } else if constexpr (std::is_same_v) { - if (R_FAILED((rc = this->storage_romfs->Read((void *)((uintptr_t)buffer + read_so_far), cur_read_size, info.offset + (offset - cur_source->virtual_offset))))) { - /* TODO: Can this ever happen? */ - /* fatalSimple(rc); */ - return rc; + break; + case RomFSDataSource::FileRomFS: + { + if (R_FAILED((rc = this->file_romfs->Read((void *)((uintptr_t)buffer + read_so_far), cur_read_size, cur_source->base_source_info.offset + (offset - cur_source->virtual_offset))))) { + fatalSimple(rc); + } } - } else if constexpr (std::is_same_v) { - if (R_FAILED((rc = this->file_romfs->Read((void *)((uintptr_t)buffer + read_so_far), cur_read_size, info.offset + (offset - cur_source->virtual_offset))))) { - fatalSimple(rc); - } - } - return rc; - }; - Result rc = std::visit(source_info_visitor, cur_source->info); - + break; + default: + fatalSimple(0xF601); + } read_so_far += cur_read_size; } else { /* Handle padding explicitly. */ @@ -100,7 +115,7 @@ Result LayeredRomFS::Read(void *buffer, size_t size, u64 offset) { read_so_far += ((*this->p_source_infos)[cur_source_ind]).virtual_offset - (cur_source->virtual_offset + cur_source->size); } } - + return 0; } Result LayeredRomFS::GetSize(u64 *out_size) { diff --git a/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp b/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp index b8c954796..e9406e123 100644 --- a/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp @@ -357,7 +357,7 @@ void RomFSBuildContext::Build(std::vector *out_infos) { case RomFSDataSource::BaseRomFS: case RomFSDataSource::FileRomFS: /* Try to compact, if possible. */ - if (out_infos->back().GetType() == cur_file->source) { + if (out_infos->back().type == cur_file->source) { out_infos->back().size = cur_file->offset + ROMFS_FILEPARTITION_OFS + cur_file->size - out_infos->back().virtual_offset; } else { out_infos->emplace_back(cur_file->offset + ROMFS_FILEPARTITION_OFS, cur_file->size, cur_file->orig_offset + ROMFS_FILEPARTITION_OFS, cur_file->source); diff --git a/stratosphere/fs_mitm/source/fsmitm_romfsbuild.hpp b/stratosphere/fs_mitm/source/fsmitm_romfsbuild.hpp index 473880306..892c2066a 100644 --- a/stratosphere/fs_mitm/source/fsmitm_romfsbuild.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_romfsbuild.hpp @@ -4,6 +4,8 @@ #include "fsmitm_romstorage.hpp" +#include "debug.hpp" + #define ROMFS_ENTRY_EMPTY 0xFFFFFFFF #define ROMFS_FILEPARTITION_OFS 0x200 @@ -31,92 +33,66 @@ struct RomFSMemorySourceInfo { const u8 *data; }; -class RomFSSourceInfo { - using InfoVariant = std::variant; - - static InfoVariant MakeInfoVariantFromOffset(u64 offset, RomFSDataSource t) { - switch(t) { - case RomFSDataSource::BaseRomFS: - return RomFSBaseSourceInfo { offset }; - - case RomFSDataSource::FileRomFS: - return RomFSFileSourceInfo { offset }; - - default: - fatalSimple(0xF601); - } - } - - static InfoVariant MakeInfoVariantFromPointer(const void *arg, RomFSDataSource t) { - switch(t) { - case RomFSDataSource::LooseFile: - return RomFSLooseSourceInfo { (decltype(RomFSLooseSourceInfo::path))arg }; - - case RomFSDataSource::Memory: - return RomFSMemorySourceInfo { (decltype(RomFSMemorySourceInfo::data))arg }; - - default: - fatalSimple(0xF601); - } - } - - struct InfoCleanupHelper { - void operator()(RomFSBaseSourceInfo& info) { - } - - void operator()(RomFSFileSourceInfo& info) { - } - - void operator()(RomFSLooseSourceInfo& info) { - delete info.path; - } - - void operator()(RomFSMemorySourceInfo& info) { - delete info.data; - } - }; - - struct GetTypeHelper { - RomFSDataSource operator()(const RomFSBaseSourceInfo& info) const { - return RomFSDataSource::BaseRomFS; - } - - RomFSDataSource operator()(const RomFSFileSourceInfo& info) const { - return RomFSDataSource::FileRomFS; - } - - RomFSDataSource operator()(const RomFSLooseSourceInfo& info) const { - return RomFSDataSource::LooseFile; - } - - RomFSDataSource operator()(const RomFSMemorySourceInfo& info) const { - return RomFSDataSource::Memory; - } - }; - -public: +struct RomFSSourceInfo { u64 virtual_offset; u64 size; - - InfoVariant info; - - RomFSSourceInfo(u64 v_o, u64 s, u64 offset, RomFSDataSource t) : virtual_offset(v_o), size(s), info(MakeInfoVariantFromOffset(offset, t)) { + union { + RomFSBaseSourceInfo base_source_info; + RomFSFileSourceInfo file_source_info; + RomFSLooseSourceInfo loose_source_info; + RomFSMemorySourceInfo memory_source_info; + }; + RomFSDataSource type; + + RomFSSourceInfo(u64 v_o, u64 s, u64 offset, RomFSDataSource t) : virtual_offset(v_o), size(s), type(t) { + switch (this->type) { + case RomFSDataSource::BaseRomFS: + this->base_source_info.offset = offset; + break; + case RomFSDataSource::FileRomFS: + this->file_source_info.offset = offset; + break; + case RomFSDataSource::LooseFile: + case RomFSDataSource::Memory: + default: + fatalSimple(0xF601); + } } - - RomFSSourceInfo(u64 v_o, u64 s, const void *arg, RomFSDataSource t) : virtual_offset(v_o), size(s), info(MakeInfoVariantFromPointer(arg, t)) { + + RomFSSourceInfo(u64 v_o, u64 s, const void *arg, RomFSDataSource t) : virtual_offset(v_o), size(s), type(t) { + switch (this->type) { + case RomFSDataSource::LooseFile: + this->loose_source_info.path = (decltype(this->loose_source_info.path))arg; + break; + case RomFSDataSource::Memory: + this->memory_source_info.data = (decltype(this->memory_source_info.data))arg; + break; + case RomFSDataSource::BaseRomFS: + case RomFSDataSource::FileRomFS: + default: + fatalSimple(0xF601); + } } - - ~RomFSSourceInfo() { - std::visit(InfoCleanupHelper{}, info); + + void Cleanup() { + switch (this->type) { + case RomFSDataSource::BaseRomFS: + case RomFSDataSource::FileRomFS: + break; + case RomFSDataSource::LooseFile: + delete this->loose_source_info.path; + break; + case RomFSDataSource::Memory: + delete this->memory_source_info.data; + break; + default: + fatalSimple(0xF601); + } } - + static bool Compare(RomFSSourceInfo *a, RomFSSourceInfo *b) { return (a->virtual_offset < b->virtual_offset); } - - RomFSDataSource GetType() const { - return std::visit(GetTypeHelper{}, info); - } }; /* Types for building a RomFS. */ @@ -165,26 +141,26 @@ struct RomFSBuildDirectoryContext { char path[FS_MAX_PATH]; u32 cur_path_ofs; u32 path_len; - u32 entry_offset; - RomFSBuildDirectoryContext *parent; - RomFSBuildDirectoryContext *child; - RomFSBuildDirectoryContext *sibling; - RomFSBuildFileContext *file; - RomFSBuildDirectoryContext *next; + u32 entry_offset = 0; + RomFSBuildDirectoryContext *parent = NULL; + RomFSBuildDirectoryContext *child = NULL; + RomFSBuildDirectoryContext *sibling = NULL; + RomFSBuildFileContext *file = NULL; + RomFSBuildDirectoryContext *next = NULL; }; struct RomFSBuildFileContext { char path[FS_MAX_PATH]; u32 cur_path_ofs; u32 path_len; - u32 entry_offset; - u64 offset; - u64 size; - RomFSBuildDirectoryContext *parent; - RomFSBuildFileContext *sibling; - RomFSBuildFileContext *next; - RomFSDataSource source; - u64 orig_offset; + u32 entry_offset = 0; + u64 offset = 0; + u64 size = 0; + RomFSBuildDirectoryContext *parent = NULL; + RomFSBuildFileContext *sibling = NULL; + RomFSBuildFileContext *next = NULL; + RomFSDataSource source{0}; + u64 orig_offset = 0; }; class RomFSBuildContext { @@ -210,7 +186,7 @@ class RomFSBuildContext { bool AddFile(RomFSBuildDirectoryContext *parent_dir_ctx, RomFSBuildFileContext *file_ctx); public: RomFSBuildContext(u64 tid) : title_id(tid), root(NULL), files(NULL), num_dirs(0), num_files(0), dir_table_size(0), file_table_size(0), dir_hash_table_size(0), file_hash_table_size(0), file_partition_size(0) { - this->root = new RomFSBuildDirectoryContext({0}); + this->root = new RomFSBuildDirectoryContext({0}); this->num_dirs = 1; this->dir_table_size = 0x18; } diff --git a/stratosphere/fs_mitm/source/fsmitm_service.cpp b/stratosphere/fs_mitm/source/fsmitm_service.cpp index 41d6ae8b9..f23794039 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.cpp @@ -70,28 +70,44 @@ Result FsMitMService::handle_deferred() { /* Add redirection for RomFS to the SD card. */ std::tuple> FsMitMService::open_data_storage_by_current_process() { IPCSession *out_session = NULL; - FsStorage data_storage; - FsFile data_file; + std::shared_ptr out_storage = nullptr; u32 out_domain_id = 0; Result rc; - if (this->get_owner() == NULL) { - rc = fsOpenDataStorageByCurrentProcessFwd(this->forward_service, &data_storage); - } else { - rc = fsOpenDataStorageByCurrentProcessFromDomainFwd(this->forward_service, &out_domain_id); - if (R_SUCCEEDED(rc)) { - rc = ipcCopyFromDomain(this->forward_service->handle, out_domain_id, &data_storage.s); - } - } - Log(armGetTls(), 0x100); - if (R_SUCCEEDED(rc)) { - /* TODO: Is there a sensible path that ends in ".romfs" we can use?" */ - if (R_SUCCEEDED(Utils::OpenSdFileForAtmosphere(this->title_id, "romfs.bin", FS_OPEN_READ, &data_file))) { - out_session = new IPCSession(std::make_shared(new LayeredRomFS(std::make_shared(data_storage), std::make_shared(data_file), this->title_id))); + if (this->romfs_storage != nullptr) { + if (this->get_owner() != NULL) { + rc = fsOpenDataStorageByCurrentProcessFromDomainFwd(this->forward_service, &out_domain_id); } else { - out_session = new IPCSession(std::make_shared(new LayeredRomFS(std::make_shared(data_storage), nullptr, this->title_id))); + rc = 0; } + if (R_SUCCEEDED(rc)) { + out_storage = this->romfs_storage; + out_session = new IPCSession(out_storage); + } + } else { + FsStorage data_storage; + FsFile data_file; + if (this->get_owner() == NULL) { - FsMitMWorker::AddWaitable(out_session); + rc = fsOpenDataStorageByCurrentProcessFwd(this->forward_service, &data_storage); + } else { + rc = fsOpenDataStorageByCurrentProcessFromDomainFwd(this->forward_service, &out_domain_id); + if (R_SUCCEEDED(rc)) { + rc = ipcCopyFromDomain(this->forward_service->handle, out_domain_id, &data_storage.s); + } + } + Log(armGetTls(), 0x100); + if (R_SUCCEEDED(rc)) { + /* TODO: Is there a sensible path that ends in ".romfs" we can use?" */ + if (R_SUCCEEDED(Utils::OpenSdFileForAtmosphere(this->title_id, "romfs.bin", FS_OPEN_READ, &data_file))) { + out_storage = std::make_shared(new LayeredRomFS(std::make_shared(data_storage), std::make_shared(data_file), this->title_id)); + } else { + out_storage = std::make_shared(new LayeredRomFS(std::make_shared(data_storage), nullptr, this->title_id)); + } + this->romfs_storage = out_storage; + out_session = new IPCSession(out_storage); + if (this->get_owner() == NULL) { + FsMitMWorker::AddWaitable(out_session); + } } } diff --git a/stratosphere/fs_mitm/source/fsmitm_service.hpp b/stratosphere/fs_mitm/source/fsmitm_service.hpp index f34709fd3..6fcf5b6b3 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.hpp @@ -14,6 +14,7 @@ class FsMitMService : public IMitMServiceObject { private: bool has_initialized; u64 init_pid; + std::shared_ptr romfs_storage; public: FsMitMService(Service *s) : IMitMServiceObject(s), has_initialized(false), init_pid(0) { /* ... */ diff --git a/stratosphere/fs_mitm/source/mitm_session.hpp b/stratosphere/fs_mitm/source/mitm_session.hpp index e1afef72e..1dd801c93 100644 --- a/stratosphere/fs_mitm/source/mitm_session.hpp +++ b/stratosphere/fs_mitm/source/mitm_session.hpp @@ -130,6 +130,8 @@ class MitMSession final : public ISession { MitMSession *new_sess = new MitMSession((MitMServer *)this->server, s_h, c_h, cur_out_r.Handles[0]); new_sess->service_object = this->service_object; + IServiceObject *obj = this->service_object.get(); + if (this->is_domain) { new_sess->is_domain = true; new_sess->domain = this->domain; @@ -185,11 +187,7 @@ class MitMSession final : public ISession { u64 retval_for_log = retval; Log(&retval_for_log, sizeof(u64)); if (R_FAILED(retval)) { - // Reboot(); - } - - if (retval == 0xA08) { - Reboot(); + //Reboot(); } return retval; diff --git a/stratosphere/libstratosphere/include/stratosphere/domainowner.hpp b/stratosphere/libstratosphere/include/stratosphere/domainowner.hpp index adb64b9c3..882db5c39 100644 --- a/stratosphere/libstratosphere/include/stratosphere/domainowner.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/domainowner.hpp @@ -14,7 +14,11 @@ class DomainOwner { private: std::array, DOMAIN_ID_MAX> domain_objects; public: - DomainOwner() = default; + DomainOwner() { + for (unsigned int i = 0; i < DOMAIN_ID_MAX; i++) { + this->domain_objects[i].reset(); + } + } /* Shared ptrs should auto delete here. */ virtual ~DomainOwner() = default; @@ -33,14 +37,14 @@ class DomainOwner { } *out_i = std::distance(domain_objects.begin(), object_it); - *object_it = std::move(object); - (*object_it)->set_owner(this); + *object_it = object; + object->set_owner(this); return 0; } Result set_object(std::shared_ptr object, unsigned int i) { - if (domain_objects[i] == NULL) { - domain_objects[i] = std::move(object); + if (domain_objects[i] == nullptr) { + domain_objects[i] = object; object->set_owner(this); return 0; }