From 3d767edd8a508b9860c79d51b0e2a0f0694ed611 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sat, 13 May 2023 17:30:45 +0200 Subject: [PATCH] IOS/FS: Split FSDevice into FSCore and FSDevice. FSCore implements the core functionality that can also be used outside of emulation. FSDevice implements the IOS device and is only available during emulation. --- Source/Core/Core/IOS/ES/ES.cpp | 10 +- Source/Core/Core/IOS/ES/Formats.cpp | 15 ++- Source/Core/Core/IOS/ES/Formats.h | 8 +- Source/Core/Core/IOS/ES/NandUtils.cpp | 14 +-- Source/Core/Core/IOS/ES/TitleContents.cpp | 10 +- Source/Core/Core/IOS/ES/TitleManagement.cpp | 6 +- Source/Core/Core/IOS/FS/FileSystemProxy.cpp | 121 +++++++++++--------- Source/Core/Core/IOS/FS/FileSystemProxy.h | 75 +++++++----- Source/Core/Core/IOS/IOS.cpp | 24 ++-- Source/Core/Core/IOS/IOS.h | 5 +- 10 files changed, 164 insertions(+), 124 deletions(-) diff --git a/Source/Core/Core/IOS/ES/ES.cpp b/Source/Core/Core/IOS/ES/ES.cpp index e53e1a3b4e..20906ed5bf 100644 --- a/Source/Core/Core/IOS/ES/ES.cpp +++ b/Source/Core/Core/IOS/ES/ES.cpp @@ -254,7 +254,7 @@ IPCReply ESDevice::GetTitleId(const IOCtlVRequest& request) static bool UpdateUIDAndGID(Kernel& kernel, const ES::TMDReader& tmd) { - ES::UIDSys uid_sys{kernel.GetFSDevice()}; + ES::UIDSys uid_sys{kernel.GetFSCore()}; const u64 title_id = tmd.GetTitleId(); const u32 uid = uid_sys.GetOrInsertUIDForTitle(title_id); if (uid == 0) @@ -270,7 +270,7 @@ static bool UpdateUIDAndGID(Kernel& kernel, const ES::TMDReader& tmd) static ReturnCode CheckIsAllowedToSetUID(Kernel& kernel, const u32 caller_uid, const ES::TMDReader& active_tmd) { - ES::UIDSys uid_map{kernel.GetFSDevice()}; + ES::UIDSys uid_map{kernel.GetFSCore()}; const u32 system_menu_uid = uid_map.GetOrInsertUIDForTitle(Titles::SYSTEM_MENU); if (!system_menu_uid) return ES_SHORT_READ; @@ -388,7 +388,7 @@ bool ESDevice::LaunchIOS(u64 ios_title_id, HangPPC hang_ppc) s32 ESDevice::WriteLaunchFile(const ES::TMDReader& tmd, Ticks ticks) { - GetEmulationKernel().GetFSDevice()->DeleteFile(PID_KERNEL, PID_KERNEL, SPACE_FILE_PATH, ticks); + GetEmulationKernel().GetFSCore().DeleteFile(PID_KERNEL, PID_KERNEL, SPACE_FILE_PATH, ticks); std::vector launch_data(sizeof(u64) + sizeof(ES::TicketView)); const u64 title_id = tmd.GetTitleId(); @@ -432,7 +432,7 @@ bool ESDevice::LaunchPPCTitle(u64 title_id) // To keep track of the PPC title launch, a temporary launch file (LAUNCH_FILE_PATH) is used // to store the title ID of the title to launch and its TMD. // The launch file not existing means an IOS reload is required. - if (const auto launch_file_fd = GetEmulationKernel().GetFSDevice()->Open( + if (const auto launch_file_fd = GetEmulationKernel().GetFSCore().Open( PID_KERNEL, PID_KERNEL, LAUNCH_FILE_PATH, FS::Mode::Read, {}, &ticks); launch_file_fd.Get() < 0) { @@ -452,7 +452,7 @@ bool ESDevice::LaunchPPCTitle(u64 title_id) // Otherwise, assume that the PPC title can now be launched directly. // Unlike IOS, we won't bother checking the title ID in the launch file. (It's not useful.) - GetEmulationKernel().GetFSDevice()->DeleteFile(PID_KERNEL, PID_KERNEL, LAUNCH_FILE_PATH, &ticks); + GetEmulationKernel().GetFSCore().DeleteFile(PID_KERNEL, PID_KERNEL, LAUNCH_FILE_PATH, &ticks); WriteSystemFile(SPACE_FILE_PATH, std::vector(SPACE_FILE_SIZE), &ticks); m_core.m_title_context.Update(tmd, ticket, DiscIO::Platform::WiiWAD); diff --git a/Source/Core/Core/IOS/ES/Formats.cpp b/Source/Core/Core/IOS/ES/Formats.cpp index cccf5086b8..60749b70c9 100644 --- a/Source/Core/Core/IOS/ES/Formats.cpp +++ b/Source/Core/Core/IOS/ES/Formats.cpp @@ -554,17 +554,16 @@ struct SharedContentMap::Entry }; constexpr char CONTENT_MAP_PATH[] = "/shared1/content.map"; -SharedContentMap::SharedContentMap(std::shared_ptr fs) - : m_fs_device{fs}, m_fs{fs->GetFS()} +SharedContentMap::SharedContentMap(HLE::FSCore& fs_core) : m_fs_core{fs_core}, m_fs{fs_core.GetFS()} { static_assert(sizeof(Entry) == 28, "SharedContentMap::Entry has the wrong size"); Entry entry; const auto fd = - fs->Open(PID_KERNEL, PID_KERNEL, CONTENT_MAP_PATH, HLE::FS::Mode::Read, {}, &m_ticks); + fs_core.Open(PID_KERNEL, PID_KERNEL, CONTENT_MAP_PATH, HLE::FS::Mode::Read, {}, &m_ticks); if (fd.Get() < 0) return; - while (fs->Read(fd.Get(), &entry, 1, &m_ticks) == sizeof(entry)) + while (fs_core.Read(fd.Get(), &entry, 1, &m_ticks) == sizeof(entry)) { m_entries.push_back(entry); m_last_id++; @@ -637,7 +636,7 @@ bool SharedContentMap::WriteEntries() const HLE::FS::ResultCode::Success; } -static std::pair ReadUidSysEntry(HLE::FSDevice& fs, u64 fd, u64* ticks) +static std::pair ReadUidSysEntry(HLE::FSCore& fs, u64 fd, u64* ticks) { u64 title_id = 0; if (fs.Read(fd, &title_id, 1, ticks) != sizeof(title_id)) @@ -651,15 +650,15 @@ static std::pair ReadUidSysEntry(HLE::FSDevice& fs, u64 fd, u64* ticks } constexpr char UID_MAP_PATH[] = "/sys/uid.sys"; -UIDSys::UIDSys(std::shared_ptr fs) : m_fs_device{fs}, m_fs{fs->GetFS()} +UIDSys::UIDSys(HLE::FSCore& fs_core) : m_fs_core{fs_core}, m_fs{fs_core.GetFS()} { if (const auto fd = - fs->Open(PID_KERNEL, PID_KERNEL, UID_MAP_PATH, HLE::FS::Mode::Read, {}, &m_ticks); + fs_core.Open(PID_KERNEL, PID_KERNEL, UID_MAP_PATH, HLE::FS::Mode::Read, {}, &m_ticks); fd.Get() >= 0) { while (true) { - std::pair entry = ReadUidSysEntry(*fs, fd.Get(), &m_ticks); + std::pair entry = ReadUidSysEntry(fs_core, fd.Get(), &m_ticks); if (!entry.first && !entry.second) break; diff --git a/Source/Core/Core/IOS/ES/Formats.h b/Source/Core/Core/IOS/ES/Formats.h index 72f36beded..56704e9caa 100644 --- a/Source/Core/Core/IOS/ES/Formats.h +++ b/Source/Core/Core/IOS/ES/Formats.h @@ -280,7 +280,7 @@ public: class SharedContentMap final { public: - explicit SharedContentMap(std::shared_ptr fs); + explicit SharedContentMap(HLE::FSCore& fs_core); ~SharedContentMap(); std::optional GetFilenameFromSHA1(const std::array& sha1) const; @@ -296,7 +296,7 @@ private: struct Entry; u32 m_last_id = 0; std::vector m_entries; - std::shared_ptr m_fs_device; + HLE::FSCore& m_fs_core; std::shared_ptr m_fs; u64 m_ticks = 0; }; @@ -304,7 +304,7 @@ private: class UIDSys final { public: - explicit UIDSys(std::shared_ptr fs); + explicit UIDSys(HLE::FSCore& fs_core); u32 GetUIDFromTitle(u64 title_id) const; u32 GetOrInsertUIDForTitle(u64 title_id); @@ -313,7 +313,7 @@ public: u64 GetTicks() const { return m_ticks; } private: - std::shared_ptr m_fs_device; + HLE::FSCore& m_fs_core; std::shared_ptr m_fs; std::map m_entries; u64 m_ticks = 0; diff --git a/Source/Core/Core/IOS/ES/NandUtils.cpp b/Source/Core/Core/IOS/ES/NandUtils.cpp index 9e1892f00c..89af3f140f 100644 --- a/Source/Core/Core/IOS/ES/NandUtils.cpp +++ b/Source/Core/Core/IOS/ES/NandUtils.cpp @@ -25,7 +25,7 @@ namespace IOS::HLE { -static ES::TMDReader FindTMD(FSDevice& fs, const std::string& tmd_path, Ticks ticks) +static ES::TMDReader FindTMD(FSCore& fs, const std::string& tmd_path, Ticks ticks) { const auto fd = fs.Open(PID_KERNEL, PID_KERNEL, tmd_path, FS::Mode::Read, {}, ticks); if (fd.Get() < 0) @@ -40,13 +40,13 @@ static ES::TMDReader FindTMD(FSDevice& fs, const std::string& tmd_path, Ticks ti ES::TMDReader ESCore::FindImportTMD(u64 title_id, Ticks ticks) const { - return FindTMD(*m_ios.GetFSDevice(), Common::GetImportTitlePath(title_id) + "/content/title.tmd", + return FindTMD(m_ios.GetFSCore(), Common::GetImportTitlePath(title_id) + "/content/title.tmd", ticks); } ES::TMDReader ESCore::FindInstalledTMD(u64 title_id, Ticks ticks) const { - return FindTMD(*m_ios.GetFSDevice(), Common::GetTMDFileName(title_id), ticks); + return FindTMD(m_ios.GetFSCore(), Common::GetTMDFileName(title_id), ticks); } ES::TicketReader ESCore::FindSignedTicket(u64 title_id, std::optional desired_version) const @@ -228,7 +228,7 @@ u32 ESCore::GetSharedContentsCount() const std::vector> ESCore::GetSharedContents() const { - const ES::SharedContentMap map{m_ios.GetFSDevice()}; + const ES::SharedContentMap map{m_ios.GetFSCore()}; return map.GetHashes(); } @@ -278,7 +278,7 @@ bool ESCore::CreateTitleDirectories(u64 title_id, u16 group_id) const return false; } - ES::UIDSys uid_sys{m_ios.GetFSDevice()}; + ES::UIDSys uid_sys{m_ios.GetFSCore()}; const u32 uid = uid_sys.GetOrInsertUIDForTitle(title_id); if (fs->SetMetadata(0, data_dir, uid, group_id, 0, data_dir_modes) != FS::ResultCode::Success) { @@ -397,7 +397,7 @@ std::string ESCore::GetContentPath(const u64 title_id, const ES::Content& conten { if (content.IsShared()) { - ES::SharedContentMap content_map{m_ios.GetFSDevice()}; + ES::SharedContentMap content_map{m_ios.GetFSCore()}; ticks.Add(content_map.GetTicks()); return content_map.GetFilenameFromSHA1(content.sha1).value_or(""); } @@ -406,7 +406,7 @@ std::string ESCore::GetContentPath(const u64 title_id, const ES::Content& conten s32 ESDevice::WriteSystemFile(const std::string& path, const std::vector& data, Ticks ticks) { - auto& fs = *GetEmulationKernel().GetFSDevice(); + auto& fs = GetEmulationKernel().GetFSCore(); const std::string tmp_path = "/tmp/" + PathToFileName(path); auto result = fs.CreateFile(PID_KERNEL, PID_KERNEL, tmp_path, {}, diff --git a/Source/Core/Core/IOS/ES/TitleContents.cpp b/Source/Core/Core/IOS/ES/TitleContents.cpp index 1a10c0fca1..5d9d84f235 100644 --- a/Source/Core/Core/IOS/ES/TitleContents.cpp +++ b/Source/Core/Core/IOS/ES/TitleContents.cpp @@ -29,7 +29,7 @@ s32 ESCore::OpenContent(const ES::TMDReader& tmd, u16 content_index, u32 uid, Ti continue; const std::string path = GetContentPath(title_id, content, ticks); - auto fd = m_ios.GetFSDevice()->Open(PID_KERNEL, PID_KERNEL, path, FS::Mode::Read, {}, ticks); + auto fd = m_ios.GetFSCore().Open(PID_KERNEL, PID_KERNEL, path, FS::Mode::Read, {}, ticks); if (fd.Get() < 0) return fd.Get(); @@ -84,7 +84,7 @@ IPCReply ESDevice::OpenActiveTitleContent(u32 caller_uid, const IOCtlVRequest& r if (!m_core.m_title_context.active) return ES_EINVAL; - ES::UIDSys uid_map{GetEmulationKernel().GetFSDevice()}; + ES::UIDSys uid_map{GetEmulationKernel().GetFSCore()}; const u32 uid = uid_map.GetOrInsertUIDForTitle(m_core.m_title_context.tmd.GetTitleId()); ticks.Add(uid_map.GetTicks()); if (caller_uid != 0 && caller_uid != uid) @@ -105,7 +105,7 @@ s32 ESCore::ReadContent(u32 cfd, u8* buffer, u32 size, u32 uid, Ticks ticks) if (!entry.m_opened) return IPC_EINVAL; - return m_ios.GetFSDevice()->Read(entry.m_fd, buffer, size, {}, ticks); + return m_ios.GetFSCore().Read(entry.m_fd, buffer, size, {}, ticks); } IPCReply ESDevice::ReadContent(u32 uid, const IOCtlVRequest& request) @@ -137,7 +137,7 @@ s32 ESCore::CloseContent(u32 cfd, u32 uid, Ticks ticks) if (!entry.m_opened) return IPC_EINVAL; - m_ios.GetFSDevice()->Close(entry.m_fd, ticks); + m_ios.GetFSCore().Close(entry.m_fd, ticks); entry = {}; INFO_LOG_FMT(IOS_ES, "CloseContent: CFD {}", cfd); return IPC_SUCCESS; @@ -167,7 +167,7 @@ s32 ESCore::SeekContent(u32 cfd, u32 offset, SeekMode mode, u32 uid, Ticks ticks if (!entry.m_opened) return IPC_EINVAL; - return m_ios.GetFSDevice()->Seek(entry.m_fd, offset, static_cast(mode), ticks); + return m_ios.GetFSCore().Seek(entry.m_fd, offset, static_cast(mode), ticks); } IPCReply ESDevice::SeekContent(u32 uid, const IOCtlVRequest& request) diff --git a/Source/Core/Core/IOS/ES/TitleManagement.cpp b/Source/Core/Core/IOS/ES/TitleManagement.cpp index 35f831256b..0a48ab9c47 100644 --- a/Source/Core/Core/IOS/ES/TitleManagement.cpp +++ b/Source/Core/Core/IOS/ES/TitleManagement.cpp @@ -408,7 +408,7 @@ ReturnCode ESCore::ImportContentEnd(Context& context, u32 content_fd) std::string content_path; if (content_info.IsShared()) { - ES::SharedContentMap shared_content{m_ios.GetFSDevice()}; + ES::SharedContentMap shared_content{m_ios.GetFSCore()}; content_path = shared_content.AddSharedContent(content_info.sha1); } else @@ -458,7 +458,7 @@ static bool HasAllRequiredContents(Kernel& ios, const ES::TMDReader& tmd) { const u64 title_id = tmd.GetTitleId(); const std::vector contents = tmd.GetContents(); - const ES::SharedContentMap shared_content_map{ios.GetFSDevice()}; + const ES::SharedContentMap shared_content_map{ios.GetFSCore()}; return std::all_of(contents.cbegin(), contents.cend(), [&](const ES::Content& content) { if (content.IsOptional()) return true; @@ -865,7 +865,7 @@ IPCReply ESDevice::ExportTitleDone(Context& context, const IOCtlVRequest& reques ReturnCode ESCore::DeleteSharedContent(const std::array& sha1) const { - ES::SharedContentMap map{m_ios.GetFSDevice()}; + ES::SharedContentMap map{m_ios.GetFSCore()}; const auto content_path = map.GetFilenameFromSHA1(sha1); if (!content_path) return ES_EINVAL; diff --git a/Source/Core/Core/IOS/FS/FileSystemProxy.cpp b/Source/Core/Core/IOS/FS/FileSystemProxy.cpp index 81820ef79b..0dd3284b51 100644 --- a/Source/Core/Core/IOS/FS/FileSystemProxy.cpp +++ b/Source/Core/Core/IOS/FS/FileSystemProxy.cpp @@ -83,7 +83,7 @@ constexpr SystemTimers::TimeBaseTick GetFreeClusterCheckTbTicks() constexpr size_t CLUSTER_DATA_SIZE = 0x4000; -FSDevice::FSDevice(Kernel& ios, const std::string& device_name) : Device(ios, device_name) +FSCore::FSCore(Kernel& ios) : m_ios(ios) { if (ios.GetFS()->Delete(PID_KERNEL, PID_KERNEL, "/tmp") == ResultCode::Success) { @@ -92,14 +92,23 @@ FSDevice::FSDevice(Kernel& ios, const std::string& device_name) : Device(ios, de } } +FSCore::~FSCore() = default; + +FSDevice::FSDevice(EmulationKernel& ios, FSCore& core, const std::string& device_name) + : EmulationDevice(ios, device_name), m_core(core) +{ +} + +FSDevice::~FSDevice() = default; + void FSDevice::DoState(PointerWrap& p) { Device::DoState(p); - p.Do(m_dirty_cache); - p.Do(m_cache_chain_index); - p.Do(m_cache_fd); - p.Do(m_next_fd); - p.Do(m_fd_map); + p.Do(m_core.m_dirty_cache); + p.Do(m_core.m_cache_chain_index); + p.Do(m_core.m_cache_fd); + p.Do(m_core.m_next_fd); + p.Do(m_core.m_fd_map); } template @@ -161,14 +170,15 @@ static IPCReply GetReplyForSuperblockOperation(int ios_version, ResultCode resul std::optional FSDevice::Open(const OpenRequest& request) { return MakeIPCReply([&](Ticks t) { - return Open(request.uid, request.gid, request.path, static_cast(request.flags & 3), - request.fd, t) + return m_core + .Open(request.uid, request.gid, request.path, static_cast(request.flags & 3), + request.fd, t) .Release(); }); } -FSDevice::ScopedFd FSDevice::Open(FS::Uid uid, FS::Gid gid, const std::string& path, FS::Mode mode, - std::optional ipc_fd, Ticks ticks) +FSCore::ScopedFd FSCore::Open(FS::Uid uid, FS::Gid gid, const std::string& path, FS::Mode mode, + std::optional ipc_fd, Ticks ticks) { ticks.Add(IPC_OVERHEAD_TICKS); @@ -200,10 +210,10 @@ FSDevice::ScopedFd FSDevice::Open(FS::Uid uid, FS::Gid gid, const std::string& p std::optional FSDevice::Close(u32 fd) { - return MakeIPCReply([&](Ticks t) { return Close(static_cast(fd), t); }); + return MakeIPCReply([&](Ticks t) { return m_core.Close(static_cast(fd), t); }); } -s32 FSDevice::Close(u64 fd, Ticks ticks) +s32 FSCore::Close(u64 fd, Ticks ticks) { ticks.Add(IPC_OVERHEAD_TICKS); @@ -232,7 +242,7 @@ s32 FSDevice::Close(u64 fd, Ticks ticks) return IPC_SUCCESS; } -u64 FSDevice::SimulatePopulateFileCache(u64 fd, u32 offset, u32 file_size) +u64 FSCore::SimulatePopulateFileCache(u64 fd, u32 offset, u32 file_size) { if (HasCacheForFile(fd, offset)) return 0; @@ -246,7 +256,7 @@ u64 FSDevice::SimulatePopulateFileCache(u64 fd, u32 offset, u32 file_size) return ticks; } -u64 FSDevice::SimulateFlushFileCache() +u64 FSCore::SimulateFlushFileCache() { if (!m_cache_fd.has_value() || !m_dirty_cache) return 0; @@ -256,8 +266,8 @@ u64 FSDevice::SimulateFlushFileCache() } // Simulate parts of the FS read/write logic to estimate ticks for file operations correctly. -u64 FSDevice::EstimateTicksForReadWrite(const Handle& handle, u64 fd, IPCCommandType command, - u32 size) +u64 FSCore::EstimateTicksForReadWrite(const Handle& handle, u64 fd, IPCCommandType command, + u32 size) { u64 ticks = 0; @@ -304,7 +314,7 @@ u64 FSDevice::EstimateTicksForReadWrite(const Handle& handle, u64 fd, IPCCommand return ticks; } -bool FSDevice::HasCacheForFile(u64 fd, u32 offset) const +bool FSCore::HasCacheForFile(u64 fd, u32 offset) const { const u16 chain_index = static_cast(offset / CLUSTER_DATA_SIZE); return m_cache_fd == fd && m_cache_chain_index == chain_index; @@ -313,13 +323,14 @@ bool FSDevice::HasCacheForFile(u64 fd, u32 offset) const std::optional FSDevice::Read(const ReadWriteRequest& request) { return MakeIPCReply([&](Ticks t) { - auto& system = Core::System::GetInstance(); + auto& system = GetSystem(); auto& memory = system.GetMemory(); - return Read(request.fd, memory.GetPointer(request.buffer), request.size, request.buffer, t); + return m_core.Read(request.fd, memory.GetPointer(request.buffer), request.size, request.buffer, + t); }); } -s32 FSDevice::Read(u64 fd, u8* data, u32 size, std::optional ipc_buffer_addr, Ticks ticks) +s32 FSCore::Read(u64 fd, u8* data, u32 size, std::optional ipc_buffer_addr, Ticks ticks) { ticks.Add(IPC_OVERHEAD_TICKS); @@ -343,14 +354,14 @@ s32 FSDevice::Read(u64 fd, u8* data, u32 size, std::optional ipc_buffer_add std::optional FSDevice::Write(const ReadWriteRequest& request) { return MakeIPCReply([&](Ticks t) { - auto& system = Core::System::GetInstance(); + auto& system = GetSystem(); auto& memory = system.GetMemory(); - return Write(request.fd, memory.GetPointer(request.buffer), request.size, request.buffer, t); + return m_core.Write(request.fd, memory.GetPointer(request.buffer), request.size, request.buffer, + t); }); } -s32 FSDevice::Write(u64 fd, const u8* data, u32 size, std::optional ipc_buffer_addr, - Ticks ticks) +s32 FSCore::Write(u64 fd, const u8* data, u32 size, std::optional ipc_buffer_addr, Ticks ticks) { ticks.Add(IPC_OVERHEAD_TICKS); @@ -374,11 +385,11 @@ s32 FSDevice::Write(u64 fd, const u8* data, u32 size, std::optional ipc_buf std::optional FSDevice::Seek(const SeekRequest& request) { return MakeIPCReply([&](Ticks t) { - return Seek(request.fd, request.offset, HLE::FS::SeekMode(request.mode), t); + return m_core.Seek(request.fd, request.offset, HLE::FS::SeekMode(request.mode), t); }); } -s32 FSDevice::Seek(u64 fd, u32 offset, FS::SeekMode mode, Ticks ticks) +s32 FSCore::Seek(u64 fd, u32 offset, FS::SeekMode mode, Ticks ticks) { ticks.Add(IPC_OVERHEAD_TICKS); @@ -422,14 +433,11 @@ struct ISFSFileStats #pragma pack(pop) template -static Result GetParams(const IOCtlRequest& request) +static Result GetParams(Memory::MemoryManager& memory, const IOCtlRequest& request) { if (request.buffer_in_size < sizeof(T)) return ResultCode::Invalid; - auto& system = Core::System::GetInstance(); - auto& memory = system.GetMemory(); - T params; memory.CopyFromEmu(¶ms, request.buffer_in, sizeof(params)); return params; @@ -437,8 +445,8 @@ static Result GetParams(const IOCtlRequest& request) std::optional FSDevice::IOCtl(const IOCtlRequest& request) { - const auto it = m_fd_map.find(request.fd); - if (it == m_fd_map.end()) + const auto it = m_core.m_fd_map.find(request.fd); + if (it == m_core.m_fd_map.end()) return IPCReply(ConvertResult(ResultCode::Invalid)); switch (request.request) @@ -472,8 +480,8 @@ std::optional FSDevice::IOCtl(const IOCtlRequest& request) std::optional FSDevice::IOCtlV(const IOCtlVRequest& request) { - const auto it = m_fd_map.find(request.fd); - if (it == m_fd_map.end()) + const auto it = m_core.m_fd_map.find(request.fd); + if (it == m_core.m_fd_map.end()) return IPCReply(ConvertResult(ResultCode::Invalid)); switch (request.request) @@ -506,7 +514,7 @@ IPCReply FSDevice::GetStats(const Handle& handle, const IOCtlRequest& request) if (!stats) return IPCReply(ConvertResult(stats.Error())); - auto& system = Core::System::GetInstance(); + auto& system = GetSystem(); auto& memory = system.GetMemory(); ISFSNandStats out; @@ -523,7 +531,7 @@ IPCReply FSDevice::GetStats(const Handle& handle, const IOCtlRequest& request) IPCReply FSDevice::CreateDirectory(const Handle& handle, const IOCtlRequest& request) { - const auto params = GetParams(request); + const auto params = GetParams(GetSystem().GetMemory(), request); if (!params) return GetFSReply(ConvertResult(params.Error())); @@ -541,7 +549,7 @@ IPCReply FSDevice::ReadDirectory(const Handle& handle, const IOCtlVRequest& requ return GetFSReply(ConvertResult(ResultCode::Invalid)); } - auto& system = Core::System::GetInstance(); + auto& system = GetSystem(); auto& memory = system.GetMemory(); u32 file_list_address, file_count_address, max_count; @@ -592,7 +600,7 @@ IPCReply FSDevice::ReadDirectory(const Handle& handle, const IOCtlVRequest& requ IPCReply FSDevice::SetAttribute(const Handle& handle, const IOCtlRequest& request) { - const auto params = GetParams(request); + const auto params = GetParams(GetSystem().GetMemory(), request); if (!params) return GetFSReply(ConvertResult(params.Error())); @@ -607,7 +615,7 @@ IPCReply FSDevice::GetAttribute(const Handle& handle, const IOCtlRequest& reques if (request.buffer_in_size < 64 || request.buffer_out_size < sizeof(ISFSParams)) return GetFSReply(ConvertResult(ResultCode::Invalid)); - auto& system = Core::System::GetInstance(); + auto& system = GetSystem(); auto& memory = system.GetMemory(); const std::string path = memory.GetString(request.buffer_in, 64); @@ -629,7 +637,7 @@ IPCReply FSDevice::GetAttribute(const Handle& handle, const IOCtlRequest& reques return GetFSReply(IPC_SUCCESS, ticks); } -FS::ResultCode FSDevice::DeleteFile(FS::Uid uid, FS::Gid gid, const std::string& path, Ticks ticks) +FS::ResultCode FSCore::DeleteFile(FS::Uid uid, FS::Gid gid, const std::string& path, Ticks ticks) { ticks.Add(IPC_OVERHEAD_TICKS); @@ -644,16 +652,17 @@ IPCReply FSDevice::DeleteFile(const Handle& handle, const IOCtlRequest& request) if (request.buffer_in_size < 64) return GetFSReply(ConvertResult(ResultCode::Invalid)); - auto& system = Core::System::GetInstance(); + auto& system = GetSystem(); auto& memory = system.GetMemory(); const std::string path = memory.GetString(request.buffer_in, 64); - return MakeIPCReply( - [&](Ticks ticks) { return ConvertResult(DeleteFile(handle.uid, handle.gid, path, ticks)); }); + return MakeIPCReply([&](Ticks ticks) { + return ConvertResult(m_core.DeleteFile(handle.uid, handle.gid, path, ticks)); + }); } -FS::ResultCode FSDevice::RenameFile(FS::Uid uid, FS::Gid gid, const std::string& old_path, - const std::string& new_path, Ticks ticks) +FS::ResultCode FSCore::RenameFile(FS::Uid uid, FS::Gid gid, const std::string& old_path, + const std::string& new_path, Ticks ticks) { ticks.Add(IPC_OVERHEAD_TICKS); @@ -668,18 +677,18 @@ IPCReply FSDevice::RenameFile(const Handle& handle, const IOCtlRequest& request) if (request.buffer_in_size < 64 * 2) return GetFSReply(ConvertResult(ResultCode::Invalid)); - auto& system = Core::System::GetInstance(); + auto& system = GetSystem(); auto& memory = system.GetMemory(); const std::string old_path = memory.GetString(request.buffer_in, 64); const std::string new_path = memory.GetString(request.buffer_in + 64, 64); return MakeIPCReply([&](Ticks ticks) { - return ConvertResult(RenameFile(handle.uid, handle.gid, old_path, new_path, ticks)); + return ConvertResult(m_core.RenameFile(handle.uid, handle.gid, old_path, new_path, ticks)); }); } -FS::ResultCode FSDevice::CreateFile(FS::Uid uid, FS::Gid gid, const std::string& path, - FS::FileAttribute attribute, FS::Modes modes, Ticks ticks) +FS::ResultCode FSCore::CreateFile(FS::Uid uid, FS::Gid gid, const std::string& path, + FS::FileAttribute attribute, FS::Modes modes, Ticks ticks) { ticks.Add(IPC_OVERHEAD_TICKS); @@ -691,18 +700,18 @@ FS::ResultCode FSDevice::CreateFile(FS::Uid uid, FS::Gid gid, const std::string& IPCReply FSDevice::CreateFile(const Handle& handle, const IOCtlRequest& request) { - const auto params = GetParams(request); + const auto params = GetParams(GetSystem().GetMemory(), request); if (!params) return GetFSReply(ConvertResult(params.Error())); return MakeIPCReply([&](Ticks ticks) { return ConvertResult( - CreateFile(handle.uid, handle.gid, params->path, params->attribute, params->modes)); + m_core.CreateFile(handle.uid, handle.gid, params->path, params->attribute, params->modes)); }); } IPCReply FSDevice::SetFileVersionControl(const Handle& handle, const IOCtlRequest& request) { - const auto params = GetParams(request); + const auto params = GetParams(GetSystem().GetMemory(), request); if (!params) return GetFSReply(ConvertResult(params.Error())); @@ -718,11 +727,11 @@ IPCReply FSDevice::GetFileStats(const Handle& handle, const IOCtlRequest& reques return GetFSReply(ConvertResult(ResultCode::Invalid)); return MakeIPCReply([&](Ticks ticks) { - const Result status = GetFileStatus(request.fd, ticks); + const Result status = m_core.GetFileStatus(request.fd, ticks); if (!status) return ConvertResult(status.Error()); - auto& system = Core::System::GetInstance(); + auto& system = GetSystem(); auto& memory = system.GetMemory(); ISFSFileStats out; @@ -733,7 +742,7 @@ IPCReply FSDevice::GetFileStats(const Handle& handle, const IOCtlRequest& reques }); } -FS::Result FSDevice::GetFileStatus(u64 fd, Ticks ticks) +FS::Result FSCore::GetFileStatus(u64 fd, Ticks ticks) { ticks.Add(IPC_OVERHEAD_TICKS); const auto& handle = m_fd_map[fd]; @@ -753,7 +762,7 @@ IPCReply FSDevice::GetUsage(const Handle& handle, const IOCtlVRequest& request) return GetFSReply(ConvertResult(ResultCode::Invalid)); } - auto& system = Core::System::GetInstance(); + auto& system = GetSystem(); auto& memory = system.GetMemory(); const std::string directory = memory.GetString(request.in_vectors[0].address, 64); diff --git a/Source/Core/Core/IOS/FS/FileSystemProxy.h b/Source/Core/Core/IOS/FS/FileSystemProxy.h index 49779ef6e5..8f3bb1e8b4 100644 --- a/Source/Core/Core/IOS/FS/FileSystemProxy.h +++ b/Source/Core/Core/IOS/FS/FileSystemProxy.h @@ -20,13 +20,22 @@ namespace IOS::HLE { constexpr FS::Fd INVALID_FD = 0xffffffff; -class FSDevice : public Device +class FSDevice; + +class FSCore final { public: + explicit FSCore(Kernel& ios); + FSCore(const FSCore& other) = delete; + FSCore(FSCore&& other) = delete; + FSCore& operator=(const FSCore& other) = delete; + FSCore& operator=(FSCore&& other) = delete; + ~FSCore(); + class ScopedFd { public: - ScopedFd(FSDevice* fs, s64 fd, Ticks tick_tracker = {}) + ScopedFd(FSCore* fs, s64 fd, Ticks tick_tracker = {}) : m_fs{fs}, m_fd{fd}, m_tick_tracker{tick_tracker} { } @@ -46,13 +55,11 @@ public: s64 Release() { return std::exchange(m_fd, -1); } private: - FSDevice* m_fs{}; + FSCore* m_fs{}; s64 m_fd = -1; Ticks m_tick_tracker{}; }; - FSDevice(Kernel& ios, const std::string& device_name); - // These are the equivalent of the IPC command handlers so IPC overhead is included // in timing calculations. ScopedFd Open(FS::Uid uid, FS::Gid gid, const std::string& path, FS::Mode mode, @@ -78,16 +85,6 @@ public: std::shared_ptr GetFS() const { return m_ios.GetFS(); } - void DoState(PointerWrap& p) override; - - std::optional Open(const OpenRequest& request) override; - std::optional Close(u32 fd) override; - std::optional Read(const ReadWriteRequest& request) override; - std::optional Write(const ReadWriteRequest& request) override; - std::optional Seek(const SeekRequest& request) override; - std::optional IOCtl(const IOCtlRequest& request) override; - std::optional IOCtlV(const IOCtlVRequest& request) override; - private: struct Handle { @@ -99,6 +96,40 @@ private: bool superblock_flush_needed = false; }; + u64 EstimateTicksForReadWrite(const Handle& handle, u64 fd, IPCCommandType command, u32 size); + u64 SimulatePopulateFileCache(u64 fd, u32 offset, u32 file_size); + u64 SimulateFlushFileCache(); + bool HasCacheForFile(u64 fd, u32 offset) const; + + Kernel& m_ios; + + bool m_dirty_cache = false; + u16 m_cache_chain_index = 0; + std::optional m_cache_fd; + // The first 0x18 IDs are reserved for the PPC. + u64 m_next_fd = 0x18; + std::map m_fd_map; + + friend class FSDevice; +}; + +class FSDevice final : public EmulationDevice +{ +public: + FSDevice(EmulationKernel& ios, FSCore& core, const std::string& device_name); + ~FSDevice(); + + void DoState(PointerWrap& p) override; + + std::optional Open(const OpenRequest& request) override; + std::optional Close(u32 fd) override; + std::optional Read(const ReadWriteRequest& request) override; + std::optional Write(const ReadWriteRequest& request) override; + std::optional Seek(const SeekRequest& request) override; + std::optional IOCtl(const IOCtlRequest& request) override; + std::optional IOCtlV(const IOCtlVRequest& request) override; + +private: enum { ISFS_IOCTL_FORMAT = 1, @@ -116,6 +147,8 @@ private: ISFS_IOCTL_SHUTDOWN = 13, }; + using Handle = FSCore::Handle; + IPCReply Format(const Handle& handle, const IOCtlRequest& request); IPCReply GetStats(const Handle& handle, const IOCtlRequest& request); IPCReply CreateDirectory(const Handle& handle, const IOCtlRequest& request); @@ -130,16 +163,6 @@ private: IPCReply GetUsage(const Handle& handle, const IOCtlVRequest& request); IPCReply Shutdown(const Handle& handle, const IOCtlRequest& request); - u64 EstimateTicksForReadWrite(const Handle& handle, u64 fd, IPCCommandType command, u32 size); - u64 SimulatePopulateFileCache(u64 fd, u32 offset, u32 file_size); - u64 SimulateFlushFileCache(); - bool HasCacheForFile(u64 fd, u32 offset) const; - - bool m_dirty_cache = false; - u16 m_cache_chain_index = 0; - std::optional m_cache_fd; - // The first 0x18 IDs are reserved for the PPC. - u64 m_next_fd = 0x18; - std::map m_fd_map; + FSCore& m_core; }; } // namespace IOS::HLE diff --git a/Source/Core/Core/IOS/IOS.cpp b/Source/Core/Core/IOS/IOS.cpp index 88b9a6c8ec..0a91b6ff6a 100644 --- a/Source/Core/Core/IOS/IOS.cpp +++ b/Source/Core/Core/IOS/IOS.cpp @@ -303,7 +303,7 @@ Kernel::Kernel(IOSC::ConsoleType console_type) : m_iosc(console_type) m_fs = FS::MakeFileSystem(IOS::HLE::FS::Location::Session, Core::GetActiveNandRedirects()); ASSERT(m_fs); - AddDevice(std::make_unique(*this, "/dev/fs")); + m_fs_core = std::make_unique(*this); m_es_core = std::make_unique(*this); } @@ -340,7 +340,8 @@ EmulationKernel::EmulationKernel(Core::System& system, u64 title_id) m_fs = FS::MakeFileSystem(IOS::HLE::FS::Location::Session, Core::GetActiveNandRedirects()); ASSERT(m_fs); - AddDevice(std::make_unique(*this, "/dev/fs")); + m_fs_core = std::make_unique(*this); + AddDevice(std::make_unique(*this, *m_fs_core, "/dev/fs")); m_es_core = std::make_unique(*this); AddDevice(std::make_unique(*this, *m_es_core, "/dev/es")); @@ -365,7 +366,12 @@ std::shared_ptr Kernel::GetFS() return m_fs; } -std::shared_ptr Kernel::GetFSDevice() +FSCore& Kernel::GetFSCore() +{ + return *m_fs_core; +} + +std::shared_ptr EmulationKernel::GetFSDevice() { return std::static_pointer_cast(m_device_map.at("/dev/fs")); } @@ -407,19 +413,19 @@ u16 Kernel::GetGidForPPC() const return m_ppc_gid; } -static std::vector ReadBootContent(FSDevice* fs, const std::string& path, size_t max_size, +static std::vector ReadBootContent(FSCore& fs, const std::string& path, size_t max_size, Ticks ticks = {}) { - const auto fd = fs->Open(0, 0, path, FS::Mode::Read, {}, ticks); + const auto fd = fs.Open(0, 0, path, FS::Mode::Read, {}, ticks); if (fd.Get() < 0) return {}; - const size_t file_size = fs->GetFileStatus(fd.Get(), ticks)->size; + const size_t file_size = fs.GetFileStatus(fd.Get(), ticks)->size; if (max_size != 0 && file_size > max_size) return {}; std::vector buffer(file_size); - if (!fs->Read(fd.Get(), buffer.data(), buffer.size(), ticks)) + if (!fs.Read(fd.Get(), buffer.data(), buffer.size(), ticks)) return {}; return buffer; } @@ -431,7 +437,7 @@ bool Kernel::BootstrapPPC(Core::System& system, const std::string& boot_content_ // Seeking and processing overhead is ignored as most time is spent reading from the NAND. u64 ticks = 0; - const DolReader dol{ReadBootContent(GetFSDevice().get(), boot_content_path, 0, &ticks)}; + const DolReader dol{ReadBootContent(GetFSCore(), boot_content_path, 0, &ticks)}; if (!dol.IsValid()) return false; @@ -512,7 +518,7 @@ bool Kernel::BootIOS(Core::System& system, const u64 ios_title_id, HangPPC hang_ // Load the ARM binary to memory (if possible). // Because we do not actually emulate the Starlet, only load the sections that are in MEM1. - ARMBinary binary{ReadBootContent(GetFSDevice().get(), boot_content_path, 0xB00000)}; + ARMBinary binary{ReadBootContent(GetFSCore(), boot_content_path, 0xB00000)}; if (!binary.IsValid()) return false; diff --git a/Source/Core/Core/IOS/IOS.h b/Source/Core/Core/IOS/IOS.h index 564ee58225..4f7611bde6 100644 --- a/Source/Core/Core/IOS/IOS.h +++ b/Source/Core/Core/IOS/IOS.h @@ -35,6 +35,7 @@ class FileSystem; class Device; class ESCore; class ESDevice; +class FSCore; class FSDevice; class WiiSockMan; @@ -123,7 +124,7 @@ public: // These are *always* part of the IOS kernel and always available. // They are also the only available resource managers even before loading any module. std::shared_ptr GetFS(); - std::shared_ptr GetFSDevice(); + FSCore& GetFSCore(); ESCore& GetESCore(); void SetUidForPPC(u32 uid); @@ -145,6 +146,7 @@ protected: void AddDevice(std::unique_ptr device); std::shared_ptr GetDeviceByName(std::string_view device_name); + std::unique_ptr m_fs_core; std::unique_ptr m_es_core; bool m_is_responsible_for_nand_root = false; @@ -180,6 +182,7 @@ public: // This only works for devices which are part of the device map. std::shared_ptr GetDeviceByName(std::string_view device_name); + std::shared_ptr GetFSDevice(); std::shared_ptr GetESDevice(); void DoState(PointerWrap& p);