From c4136d03653f16ac36f70dece5e94d6b662c5337 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Thu, 27 Apr 2017 21:22:04 +0200 Subject: [PATCH] IOS/ES: Handle contexts properly This changes the IOS code to handle ES contexts inside of ES, instead of leaking out implementation details into the IPC request dispatcher. The intent is to clarify what's shared between every single ES context, and what is specific to an ES context. (Not much.) This should reduce the number of static members in the ES class. The other changes are there just because we now keep track of the IPC FD inside of ES. Future plans: * After the WAD direct launch hack is dropped, the title context will be made a class member. * Have proper function prototypes, instead of having every single one of them take ioctlv requests. This will allow reusing IOS code in other parts of the Dolphin codebase without having to construct ioctlv requests. --- Source/Core/Core/IOS/Device.cpp | 3 +- Source/Core/Core/IOS/Device.h | 2 +- Source/Core/Core/IOS/DeviceStub.cpp | 6 - Source/Core/Core/IOS/DeviceStub.h | 1 - Source/Core/Core/IOS/ES/ES.cpp | 121 +++++++++++------ Source/Core/Core/IOS/ES/ES.h | 107 +++++++++------ Source/Core/Core/IOS/ES/Identity.cpp | 4 +- Source/Core/Core/IOS/ES/TitleContents.cpp | 10 +- Source/Core/Core/IOS/ES/TitleManagement.cpp | 128 +++++++++--------- Source/Core/Core/IOS/FS/FileIO.cpp | 3 +- Source/Core/Core/IOS/FS/FileIO.h | 2 +- Source/Core/Core/IOS/IPC.cpp | 45 +----- Source/Core/Core/IOS/SDIO/SDIOSlot0.cpp | 4 +- Source/Core/Core/IOS/SDIO/SDIOSlot0.h | 2 +- Source/Core/Core/IOS/STM/STM.cpp | 4 +- Source/Core/Core/IOS/STM/STM.h | 2 +- Source/Core/Core/IOS/USB/Bluetooth/BTEmu.cpp | 4 +- Source/Core/Core/IOS/USB/Bluetooth/BTEmu.h | 2 +- Source/Core/Core/IOS/USB/Bluetooth/BTReal.cpp | 4 +- Source/Core/Core/IOS/USB/Bluetooth/BTReal.h | 2 +- Source/Core/Core/IOS/USB/OH0/OH0Device.cpp | 3 +- Source/Core/Core/IOS/USB/OH0/OH0Device.h | 2 +- Source/Core/Core/State.cpp | 2 +- 23 files changed, 241 insertions(+), 222 deletions(-) diff --git a/Source/Core/Core/IOS/Device.cpp b/Source/Core/Core/IOS/Device.cpp index 5d38c7efff..e407d54777 100644 --- a/Source/Core/Core/IOS/Device.cpp +++ b/Source/Core/Core/IOS/Device.cpp @@ -154,9 +154,10 @@ ReturnCode Device::Open(const OpenRequest& request) return IPC_SUCCESS; } -void Device::Close() +ReturnCode Device::Close(u32 fd) { m_is_active = false; + return IPC_SUCCESS; } IPCCommandResult Device::Unsupported(const Request& request) diff --git a/Source/Core/Core/IOS/Device.h b/Source/Core/Core/IOS/Device.h index 91d2dbbe36..c8dd0ccf30 100644 --- a/Source/Core/Core/IOS/Device.h +++ b/Source/Core/Core/IOS/Device.h @@ -185,7 +185,7 @@ public: // Replies to Open and Close requests are sent by the IPC request handler (HandleCommand), // not by the devices themselves. virtual ReturnCode Open(const OpenRequest& request); - virtual void Close(); + virtual ReturnCode Close(u32 fd); virtual IPCCommandResult Seek(const SeekRequest& seek) { return Unsupported(seek); } virtual IPCCommandResult Read(const ReadWriteRequest& read) { return Unsupported(read); } virtual IPCCommandResult Write(const ReadWriteRequest& write) { return Unsupported(write); } diff --git a/Source/Core/Core/IOS/DeviceStub.cpp b/Source/Core/Core/IOS/DeviceStub.cpp index cdd74ac1bc..2502c84769 100644 --- a/Source/Core/Core/IOS/DeviceStub.cpp +++ b/Source/Core/Core/IOS/DeviceStub.cpp @@ -22,12 +22,6 @@ ReturnCode Stub::Open(const OpenRequest& request) return IPC_SUCCESS; } -void Stub::Close() -{ - WARN_LOG(IOS, "%s faking Close()", m_name.c_str()); - m_is_active = false; -} - IPCCommandResult Stub::IOCtl(const IOCtlRequest& request) { WARN_LOG(IOS, "%s faking IOCtl()", m_name.c_str()); diff --git a/Source/Core/Core/IOS/DeviceStub.h b/Source/Core/Core/IOS/DeviceStub.h index 6b7298cc53..b6b60b0248 100644 --- a/Source/Core/Core/IOS/DeviceStub.h +++ b/Source/Core/Core/IOS/DeviceStub.h @@ -22,7 +22,6 @@ public: Stub(u32 device_id, const std::string& device_name); ReturnCode Open(const OpenRequest& request) override; - void Close() override; IPCCommandResult IOCtl(const IOCtlRequest& request) override; IPCCommandResult IOCtlV(const IOCtlVRequest& request) override; }; diff --git a/Source/Core/Core/IOS/ES/ES.cpp b/Source/Core/Core/IOS/ES/ES.cpp index 29ea0de0fb..1ff4064c1a 100644 --- a/Source/Core/Core/IOS/ES/ES.cpp +++ b/Source/Core/Core/IOS/ES/ES.cpp @@ -4,6 +4,7 @@ #include "Core/IOS/ES/ES.h" +#include #include #include #include @@ -27,17 +28,13 @@ namespace HLE { namespace Device { -// Shared across all ES instances. +// TODO: drop this and convert the title context into a member once the WAD launch hack is gone. static std::string s_content_file; static TitleContext s_title_context; // Title to launch after IOS has been reset and reloaded (similar to /sys/launch.sys). static u64 s_title_to_launch; -ES::ES(u32 device_id, const std::string& device_name) : Device(device_id, device_name) -{ -} - static void FinishAllStaleImports() { const std::vector titles = IOS::ES::GetTitleImports(); @@ -58,7 +55,7 @@ static void FinishAllStaleImports() File::CreateDir(import_dir); } -void ES::Init() +ES::ES(u32 device_id, const std::string& device_name) : Device(device_id, device_name) { FinishAllStaleImports(); @@ -182,14 +179,14 @@ static ReturnCode CheckIsAllowedToSetUID(const u32 caller_uid) return caller_uid == system_menu_uid ? IPC_SUCCESS : ES_EINVAL; } -IPCCommandResult ES::SetUID(const IOCtlVRequest& request) +IPCCommandResult ES::SetUID(u32 uid, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != 8) return GetDefaultReply(ES_EINVAL); const u64 title_id = Memory::Read_U64(request.in_vectors[0].address); - const s32 ret = CheckIsAllowedToSetUID(m_caller_uid); + const s32 ret = CheckIsAllowedToSetUID(uid); if (ret < 0) { ERROR_LOG(IOS_ES, "SetUID: Permission check failed with error %d", ret); @@ -279,6 +276,24 @@ bool ES::LaunchPPCTitle(u64 title_id, bool skip_reload) return BootstrapPPC(content_loader); } +void ES::Context::DoState(PointerWrap& p) +{ + p.Do(uid); + p.Do(gid); + + title_import.tmd.DoState(p); + p.Do(title_import.content_id); + p.Do(title_import.content_buffer); + + p.Do(title_export.valid); + title_export.tmd.DoState(p); + p.Do(title_export.title_key); + p.Do(title_export.contents); + + p.Do(active); + p.Do(ipc_fd); +} + void ES::DoState(PointerWrap& p) { Device::DoState(p); @@ -286,17 +301,8 @@ void ES::DoState(PointerWrap& p) p.Do(m_AccessIdentID); s_title_context.DoState(p); - m_addtitle_tmd.DoState(p); - p.Do(m_addtitle_content_id); - p.Do(m_addtitle_content_buffer); - - p.Do(m_caller_uid); - p.Do(m_caller_gid); - - p.Do(m_export_title_context.valid); - m_export_title_context.tmd.DoState(p); - p.Do(m_export_title_context.title_key); - p.Do(m_export_title_context.contents); + for (auto& context : m_contexts) + context.DoState(p); u32 Count = (u32)(m_ContentAccessMap.size()); p.Do(Count); @@ -322,16 +328,41 @@ void ES::DoState(PointerWrap& p) } } +ES::ContextArray::iterator ES::FindActiveContext(u32 fd) +{ + return std::find_if(m_contexts.begin(), m_contexts.end(), + [fd](const auto& context) { return context.ipc_fd == fd && context.active; }); +} + +ES::ContextArray::iterator ES::FindInactiveContext() +{ + return std::find_if(m_contexts.begin(), m_contexts.end(), + [](const auto& context) { return !context.active; }); +} + ReturnCode ES::Open(const OpenRequest& request) { - m_caller_uid = request.uid; - m_caller_gid = request.gid; + auto context = FindInactiveContext(); + if (context == m_contexts.end()) + return ES_FD_EXHAUSTED; + + context->active = true; + context->uid = request.uid; + context->gid = request.gid; + context->ipc_fd = request.fd; return Device::Open(request); } -void ES::Close() +ReturnCode ES::Close(u32 fd) { - // XXX: does IOS really clear the content access map here? + auto context = FindActiveContext(fd); + if (context == m_contexts.end()) + return ES_EINVAL; + + context->active = false; + context->ipc_fd = -1; + + // FIXME: IOS doesn't clear the content access map here. m_ContentAccessMap.clear(); m_AccessIdentID = 0; @@ -339,48 +370,52 @@ void ES::Close() m_is_active = false; // clear the NAND content cache to make sure nothing remains open. DiscIO::CNANDContentManager::Access().ClearCache(); + return IPC_SUCCESS; } IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request) { DEBUG_LOG(IOS_ES, "%s (0x%x)", GetDeviceName().c_str(), request.request); + auto context = FindActiveContext(request.fd); + if (context == m_contexts.end()) + return GetDefaultReply(ES_EINVAL); switch (request.request) { case IOCTL_ES_ADDTICKET: return AddTicket(request); case IOCTL_ES_ADDTMD: - return AddTMD(request); + return AddTMD(*context, request); case IOCTL_ES_ADDTITLESTART: - return AddTitleStart(request); + return AddTitleStart(*context, request); case IOCTL_ES_ADDCONTENTSTART: - return AddContentStart(request); + return AddContentStart(*context, request); case IOCTL_ES_ADDCONTENTDATA: - return AddContentData(request); + return AddContentData(*context, request); case IOCTL_ES_ADDCONTENTFINISH: - return AddContentFinish(request); + return AddContentFinish(*context, request); case IOCTL_ES_ADDTITLEFINISH: - return AddTitleFinish(request); + return AddTitleFinish(*context, request); case IOCTL_ES_ADDTITLECANCEL: - return AddTitleCancel(request); + return AddTitleCancel(*context, request); case IOCTL_ES_GETDEVICEID: return GetConsoleID(request); case IOCTL_ES_OPENTITLECONTENT: - return OpenTitleContent(request); + return OpenTitleContent(context->uid, request); case IOCTL_ES_OPENCONTENT: - return OpenContent(request); + return OpenContent(context->uid, request); case IOCTL_ES_READCONTENT: - return ReadContent(request); + return ReadContent(context->uid, request); case IOCTL_ES_CLOSECONTENT: - return CloseContent(request); + return CloseContent(context->uid, request); case IOCTL_ES_SEEKCONTENT: - return SeekContent(request); + return SeekContent(context->uid, request); case IOCTL_ES_GETTITLEDIR: return GetTitleDirectory(request); case IOCTL_ES_GETTITLEID: return GetTitleID(request); case IOCTL_ES_SETUID: - return SetUID(request); + return SetUID(context->uid, request); case IOCTL_ES_DIVERIFY: return DIVerify(request); @@ -441,23 +476,23 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request) case IOCTL_ES_GETSTOREDTMD: return GetStoredTMD(request); case IOCTL_ES_ENCRYPT: - return Encrypt(request); + return Encrypt(context->uid, request); case IOCTL_ES_DECRYPT: - return Decrypt(request); + return Decrypt(context->uid, request); case IOCTL_ES_LAUNCH: return Launch(request); case IOCTL_ES_LAUNCHBC: return LaunchBC(request); case IOCTL_ES_EXPORTTITLEINIT: - return ExportTitleInit(request); + return ExportTitleInit(*context, request); case IOCTL_ES_EXPORTCONTENTBEGIN: - return ExportContentBegin(request); + return ExportContentBegin(*context, request); case IOCTL_ES_EXPORTCONTENTDATA: - return ExportContentData(request); + return ExportContentData(*context, request); case IOCTL_ES_EXPORTCONTENTEND: - return ExportContentEnd(request); + return ExportContentEnd(*context, request); case IOCTL_ES_EXPORTTITLEDONE: - return ExportTitleDone(request); + return ExportTitleDone(*context, request); case IOCTL_ES_CHECKKOREAREGION: return CheckKoreaRegion(request); case IOCTL_ES_GETDEVICECERT: diff --git a/Source/Core/Core/IOS/ES/ES.h b/Source/Core/Core/IOS/ES/ES.h index e7cb5c6c45..e060f51af4 100644 --- a/Source/Core/Core/IOS/ES/ES.h +++ b/Source/Core/Core/IOS/ES/ES.h @@ -45,9 +45,6 @@ class ES final : public Device public: ES(u32 device_id, const std::string& device_name); - // Called after an IOS reload. - static void Init(); - static s32 DIVerify(const IOS::ES::TMDReader& tmd, const IOS::ES::TicketReader& ticket); static void LoadWAD(const std::string& _rContentFile); static bool LaunchTitle(u64 title_id, bool skip_reload = false); @@ -58,7 +55,7 @@ public: void DoState(PointerWrap& p) override; ReturnCode Open(const OpenRequest& request) override; - void Close() override; + ReturnCode Close(u32 fd) override; IPCCommandResult IOCtlV(const IOCtlVRequest& request) override; private: @@ -155,20 +152,57 @@ private: u8 padding[0x3c]; }; + struct TitleImportContext + { + IOS::ES::TMDReader tmd; + u32 content_id = 0xFFFFFFFF; + std::vector content_buffer; + }; + + // TODO: merge this with TitleImportContext. Also reuse the global content table. + struct TitleExportContext + { + struct ExportContent + { + OpenedContent content; + std::array iv{}; + }; + + bool valid = false; + IOS::ES::TMDReader tmd; + std::vector title_key; + std::map contents; + }; + + struct Context + { + void DoState(PointerWrap& p); + + u16 gid = 0; + u32 uid = 0; + TitleImportContext title_import; + TitleExportContext title_export; + bool active = false; + // We use this to associate an IPC fd with an ES context. + u32 ipc_fd = -1; + }; + // ES can only have 3 contexts at one time. + using ContextArray = std::array; + // Title management IPCCommandResult AddTicket(const IOCtlVRequest& request); - IPCCommandResult AddTMD(const IOCtlVRequest& request); - IPCCommandResult AddTitleStart(const IOCtlVRequest& request); - IPCCommandResult AddContentStart(const IOCtlVRequest& request); - IPCCommandResult AddContentData(const IOCtlVRequest& request); - IPCCommandResult AddContentFinish(const IOCtlVRequest& request); - IPCCommandResult AddTitleFinish(const IOCtlVRequest& request); - IPCCommandResult AddTitleCancel(const IOCtlVRequest& request); - IPCCommandResult ExportTitleInit(const IOCtlVRequest& request); - IPCCommandResult ExportContentBegin(const IOCtlVRequest& request); - IPCCommandResult ExportContentData(const IOCtlVRequest& request); - IPCCommandResult ExportContentEnd(const IOCtlVRequest& request); - IPCCommandResult ExportTitleDone(const IOCtlVRequest& request); + IPCCommandResult AddTMD(Context& context, const IOCtlVRequest& request); + IPCCommandResult AddTitleStart(Context& context, const IOCtlVRequest& request); + IPCCommandResult AddContentStart(Context& context, const IOCtlVRequest& request); + IPCCommandResult AddContentData(Context& context, const IOCtlVRequest& request); + IPCCommandResult AddContentFinish(Context& context, const IOCtlVRequest& request); + IPCCommandResult AddTitleFinish(Context& context, const IOCtlVRequest& request); + IPCCommandResult AddTitleCancel(Context& context, const IOCtlVRequest& request); + IPCCommandResult ExportTitleInit(Context& context, const IOCtlVRequest& request); + IPCCommandResult ExportContentBegin(Context& context, const IOCtlVRequest& request); + IPCCommandResult ExportContentData(Context& context, const IOCtlVRequest& request); + IPCCommandResult ExportContentEnd(Context& context, const IOCtlVRequest& request); + IPCCommandResult ExportTitleDone(Context& context, const IOCtlVRequest& request); IPCCommandResult DeleteTitle(const IOCtlVRequest& request); IPCCommandResult DeleteTicket(const IOCtlVRequest& request); IPCCommandResult DeleteTitleContent(const IOCtlVRequest& request); @@ -178,11 +212,11 @@ private: IPCCommandResult GetDeviceCertificate(const IOCtlVRequest& request); IPCCommandResult CheckKoreaRegion(const IOCtlVRequest& request); IPCCommandResult Sign(const IOCtlVRequest& request); - IPCCommandResult Encrypt(const IOCtlVRequest& request); - IPCCommandResult Decrypt(const IOCtlVRequest& request); + IPCCommandResult Encrypt(u32 uid, const IOCtlVRequest& request); + IPCCommandResult Decrypt(u32 uid, const IOCtlVRequest& request); // Misc - IPCCommandResult SetUID(const IOCtlVRequest& request); + IPCCommandResult SetUID(u32 uid, const IOCtlVRequest& request); IPCCommandResult GetTitleDirectory(const IOCtlVRequest& request); IPCCommandResult GetTitleID(const IOCtlVRequest& request); IPCCommandResult GetConsumption(const IOCtlVRequest& request); @@ -191,11 +225,11 @@ private: IPCCommandResult DIVerify(const IOCtlVRequest& request); // Title contents - IPCCommandResult OpenTitleContent(const IOCtlVRequest& request); - IPCCommandResult OpenContent(const IOCtlVRequest& request); - IPCCommandResult ReadContent(const IOCtlVRequest& request); - IPCCommandResult CloseContent(const IOCtlVRequest& request); - IPCCommandResult SeekContent(const IOCtlVRequest& request); + IPCCommandResult OpenTitleContent(u32 uid, const IOCtlVRequest& request); + IPCCommandResult OpenContent(u32 uid, const IOCtlVRequest& request); + IPCCommandResult ReadContent(u32 uid, const IOCtlVRequest& request); + IPCCommandResult CloseContent(u32 uid, const IOCtlVRequest& request); + IPCCommandResult SeekContent(u32 uid, const IOCtlVRequest& request); // Title information IPCCommandResult GetTitleCount(const std::vector& titles, const IOCtlVRequest& request); @@ -228,6 +262,9 @@ private: IPCCommandResult DIGetTMDSize(const IOCtlVRequest& request); IPCCommandResult DIGetTMD(const IOCtlVRequest& request); + ContextArray::iterator FindActiveContext(u32 fd); + ContextArray::iterator FindInactiveContext(); + static bool LaunchIOS(u64 ios_title_id); static bool LaunchPPCTitle(u64 title_id, bool skip_reload); static TitleContext& GetTitleContext(); @@ -241,27 +278,7 @@ private: u32 m_AccessIdentID = 0; - // For title installation (ioctls IOCTL_ES_ADDTITLE*). - IOS::ES::TMDReader m_addtitle_tmd; - u32 m_addtitle_content_id = 0xFFFFFFFF; - std::vector m_addtitle_content_buffer; - - u32 m_caller_uid = 0; - u16 m_caller_gid = 0; - - struct TitleExportContext - { - struct ExportContent - { - OpenedContent content; - std::array iv{}; - }; - - bool valid = false; - IOS::ES::TMDReader tmd; - std::vector title_key; - std::map contents; - } m_export_title_context; + ContextArray m_contexts; }; } // namespace Device } // namespace HLE diff --git a/Source/Core/Core/IOS/ES/Identity.cpp b/Source/Core/Core/IOS/ES/Identity.cpp index c4b5722ee0..3ae6ba5083 100644 --- a/Source/Core/Core/IOS/ES/Identity.cpp +++ b/Source/Core/Core/IOS/ES/Identity.cpp @@ -63,7 +63,7 @@ IPCCommandResult ES::GetConsoleID(const IOCtlVRequest& request) return GetDefaultReply(IPC_SUCCESS); } -IPCCommandResult ES::Encrypt(const IOCtlVRequest& request) +IPCCommandResult ES::Encrypt(u32 uid, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(3, 2)) return GetDefaultReply(ES_EINVAL); @@ -85,7 +85,7 @@ IPCCommandResult ES::Encrypt(const IOCtlVRequest& request) return GetDefaultReply(IPC_SUCCESS); } -IPCCommandResult ES::Decrypt(const IOCtlVRequest& request) +IPCCommandResult ES::Decrypt(u32 uid, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(3, 2)) return GetDefaultReply(ES_EINVAL); diff --git a/Source/Core/Core/IOS/ES/TitleContents.cpp b/Source/Core/Core/IOS/ES/TitleContents.cpp index d97b74d7d9..6a5fc64965 100644 --- a/Source/Core/Core/IOS/ES/TitleContents.cpp +++ b/Source/Core/Core/IOS/ES/TitleContents.cpp @@ -48,7 +48,7 @@ u32 ES::OpenTitleContent(u32 CFD, u64 TitleID, u16 Index) return CFD; } -IPCCommandResult ES::OpenTitleContent(const IOCtlVRequest& request) +IPCCommandResult ES::OpenTitleContent(u32 uid, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(3, 0)) return GetDefaultReply(ES_EINVAL); @@ -64,7 +64,7 @@ IPCCommandResult ES::OpenTitleContent(const IOCtlVRequest& request) return GetDefaultReply(CFD); } -IPCCommandResult ES::OpenContent(const IOCtlVRequest& request) +IPCCommandResult ES::OpenContent(u32 uid, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(1, 0)) return GetDefaultReply(ES_EINVAL); @@ -79,7 +79,7 @@ IPCCommandResult ES::OpenContent(const IOCtlVRequest& request) return GetDefaultReply(CFD); } -IPCCommandResult ES::ReadContent(const IOCtlVRequest& request) +IPCCommandResult ES::ReadContent(u32 uid, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(1, 1)) return GetDefaultReply(ES_EINVAL); @@ -131,7 +131,7 @@ IPCCommandResult ES::ReadContent(const IOCtlVRequest& request) return GetDefaultReply(Size); } -IPCCommandResult ES::CloseContent(const IOCtlVRequest& request) +IPCCommandResult ES::CloseContent(u32 uid, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(1, 0)) return GetDefaultReply(ES_EINVAL); @@ -160,7 +160,7 @@ IPCCommandResult ES::CloseContent(const IOCtlVRequest& request) return GetDefaultReply(IPC_SUCCESS); } -IPCCommandResult ES::SeekContent(const IOCtlVRequest& request) +IPCCommandResult ES::SeekContent(u32 uid, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(3, 0)) return GetDefaultReply(ES_EINVAL); diff --git a/Source/Core/Core/IOS/ES/TitleManagement.cpp b/Source/Core/Core/IOS/ES/TitleManagement.cpp index a01e0f758c..8426b15582 100644 --- a/Source/Core/Core/IOS/ES/TitleManagement.cpp +++ b/Source/Core/Core/IOS/ES/TitleManagement.cpp @@ -66,7 +66,7 @@ IPCCommandResult ES::AddTicket(const IOCtlVRequest& request) return GetDefaultReply(IPC_SUCCESS); } -IPCCommandResult ES::AddTMD(const IOCtlVRequest& request) +IPCCommandResult ES::AddTMD(Context& context, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(1, 0)) return GetDefaultReply(ES_EINVAL); @@ -76,18 +76,18 @@ IPCCommandResult ES::AddTMD(const IOCtlVRequest& request) // Ioctlv 0x2b writes the TMD to /tmp/title.tmd (for imports) and doesn't seem to write it // to either /import or /title. So here we simply have to set the import TMD. - m_addtitle_tmd.SetBytes(std::move(tmd)); + context.title_import.tmd.SetBytes(std::move(tmd)); // TODO: validate TMDs and return the proper error code (-1027) if the signature type is invalid. - if (!m_addtitle_tmd.IsValid()) + if (!context.title_import.tmd.IsValid()) return GetDefaultReply(ES_EINVAL); - if (!IOS::ES::InitImport(m_addtitle_tmd.GetTitleId())) + if (!IOS::ES::InitImport(context.title_import.tmd.GetTitleId())) return GetDefaultReply(FS_EIO); return GetDefaultReply(IPC_SUCCESS); } -IPCCommandResult ES::AddTitleStart(const IOCtlVRequest& request) +IPCCommandResult ES::AddTitleStart(Context& context, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(4, 0)) return GetDefaultReply(ES_EINVAL); @@ -96,19 +96,20 @@ IPCCommandResult ES::AddTitleStart(const IOCtlVRequest& request) std::vector tmd(request.in_vectors[0].size); Memory::CopyFromEmu(tmd.data(), request.in_vectors[0].address, request.in_vectors[0].size); - m_addtitle_tmd.SetBytes(tmd); - if (!m_addtitle_tmd.IsValid()) + context.title_import.tmd.SetBytes(tmd); + if (!context.title_import.tmd.IsValid()) { ERROR_LOG(IOS_ES, "Invalid TMD while adding title (size = %zd)", tmd.size()); return GetDefaultReply(ES_EINVAL); } // Finish a previous import (if it exists). - const IOS::ES::TMDReader previous_tmd = IOS::ES::FindImportTMD(m_addtitle_tmd.GetTitleId()); + const IOS::ES::TMDReader previous_tmd = + IOS::ES::FindImportTMD(context.title_import.tmd.GetTitleId()); if (previous_tmd.IsValid()) FinishImport(previous_tmd); - if (!IOS::ES::InitImport(m_addtitle_tmd.GetTitleId())) + if (!IOS::ES::InitImport(context.title_import.tmd.GetTitleId())) return GetDefaultReply(FS_EIO); // TODO: check and use the other vectors. @@ -116,7 +117,7 @@ IPCCommandResult ES::AddTitleStart(const IOCtlVRequest& request) return GetDefaultReply(IPC_SUCCESS); } -IPCCommandResult ES::AddContentStart(const IOCtlVRequest& request) +IPCCommandResult ES::AddContentStart(Context& context, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(2, 0)) return GetDefaultReply(ES_EINVAL); @@ -124,28 +125,28 @@ IPCCommandResult ES::AddContentStart(const IOCtlVRequest& request) u64 title_id = Memory::Read_U64(request.in_vectors[0].address); u32 content_id = Memory::Read_U32(request.in_vectors[1].address); - if (m_addtitle_content_id != 0xFFFFFFFF) + if (context.title_import.content_id != 0xFFFFFFFF) { ERROR_LOG(IOS_ES, "Trying to add content when we haven't finished adding " "another content. Unsupported."); return GetDefaultReply(ES_EINVAL); } - m_addtitle_content_id = content_id; + context.title_import.content_id = content_id; - m_addtitle_content_buffer.clear(); + context.title_import.content_buffer.clear(); INFO_LOG(IOS_ES, "IOCTL_ES_ADDCONTENTSTART: title id %016" PRIx64 ", " "content id %08x", - title_id, m_addtitle_content_id); + title_id, context.title_import.content_id); - if (!m_addtitle_tmd.IsValid()) + if (!context.title_import.tmd.IsValid()) return GetDefaultReply(ES_EINVAL); - if (title_id != m_addtitle_tmd.GetTitleId()) + if (title_id != context.title_import.tmd.GetTitleId()) { ERROR_LOG(IOS_ES, "IOCTL_ES_ADDCONTENTSTART: title id %016" PRIx64 " != " "TMD title id %016" PRIx64 ", ignoring", - title_id, m_addtitle_tmd.GetTitleId()); + title_id, context.title_import.tmd.GetTitleId()); } // We're supposed to return a "content file descriptor" here, which is @@ -156,7 +157,7 @@ IPCCommandResult ES::AddContentStart(const IOCtlVRequest& request) return GetDefaultReply(content_fd); } -IPCCommandResult ES::AddContentData(const IOCtlVRequest& request) +IPCCommandResult ES::AddContentData(Context& context, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(2, 0)) return GetDefaultReply(ES_EINVAL); @@ -168,7 +169,8 @@ IPCCommandResult ES::AddContentData(const IOCtlVRequest& request) u8* data_start = Memory::GetPointer(request.in_vectors[1].address); u8* data_end = data_start + request.in_vectors[1].size; - m_addtitle_content_buffer.insert(m_addtitle_content_buffer.end(), data_start, data_end); + context.title_import.content_buffer.insert(context.title_import.content_buffer.end(), data_start, + data_end); return GetDefaultReply(IPC_SUCCESS); } @@ -184,22 +186,22 @@ static std::string GetImportContentPath(u64 title_id, u32 content_id) return Common::GetImportTitlePath(title_id) + StringFromFormat("/content/%08x.app", content_id); } -IPCCommandResult ES::AddContentFinish(const IOCtlVRequest& request) +IPCCommandResult ES::AddContentFinish(Context& context, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(1, 0)) return GetDefaultReply(ES_EINVAL); - if (m_addtitle_content_id == 0xFFFFFFFF) + if (context.title_import.content_id == 0xFFFFFFFF) return GetDefaultReply(ES_EINVAL); u32 content_fd = Memory::Read_U32(request.in_vectors[0].address); INFO_LOG(IOS_ES, "IOCTL_ES_ADDCONTENTFINISH: content fd %08x", content_fd); - if (!m_addtitle_tmd.IsValid()) + if (!context.title_import.tmd.IsValid()) return GetDefaultReply(ES_EINVAL); // Try to find the title key from a pre-installed ticket. - IOS::ES::TicketReader ticket = DiscIO::FindSignedTicket(m_addtitle_tmd.GetTitleId()); + IOS::ES::TicketReader ticket = DiscIO::FindSignedTicket(context.title_import.tmd.GetTitleId()); if (!ticket.IsValid()) { return GetDefaultReply(ES_NO_TICKET); @@ -211,16 +213,16 @@ IPCCommandResult ES::AddContentFinish(const IOCtlVRequest& request) // The IV for title content decryption is the lower two bytes of the // content index, zero extended. IOS::ES::Content content_info; - if (!m_addtitle_tmd.FindContentById(m_addtitle_content_id, &content_info)) + if (!context.title_import.tmd.FindContentById(context.title_import.content_id, &content_info)) { return GetDefaultReply(ES_EINVAL); } u8 iv[16] = {0}; iv[0] = (content_info.index >> 8) & 0xFF; iv[1] = content_info.index & 0xFF; - std::vector decrypted_data(m_addtitle_content_buffer.size()); - mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_DECRYPT, m_addtitle_content_buffer.size(), iv, - m_addtitle_content_buffer.data(), decrypted_data.data()); + std::vector decrypted_data(context.title_import.content_buffer.size()); + mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_DECRYPT, context.title_import.content_buffer.size(), + iv, context.title_import.content_buffer.data(), decrypted_data.data()); if (!CheckIfContentHashMatches(decrypted_data, content_info)) { ERROR_LOG(IOS_ES, "AddContentFinish: Hash for content %08x doesn't match", content_info.id); @@ -235,12 +237,13 @@ IPCCommandResult ES::AddContentFinish(const IOCtlVRequest& request) } else { - content_path = GetImportContentPath(m_addtitle_tmd.GetTitleId(), m_addtitle_content_id); + content_path = GetImportContentPath(context.title_import.tmd.GetTitleId(), + context.title_import.content_id); } File::CreateFullPath(content_path); const std::string temp_path = Common::RootUserPath(Common::FROM_SESSION_ROOT) + - StringFromFormat("/tmp/%08x.app", m_addtitle_content_id); + StringFromFormat("/tmp/%08x.app", context.title_import.content_id); File::CreateFullPath(temp_path); { @@ -258,32 +261,33 @@ IPCCommandResult ES::AddContentFinish(const IOCtlVRequest& request) return GetDefaultReply(ES_EIO); } - m_addtitle_content_id = 0xFFFFFFFF; + context.title_import.content_id = 0xFFFFFFFF; return GetDefaultReply(IPC_SUCCESS); } -IPCCommandResult ES::AddTitleFinish(const IOCtlVRequest& request) +IPCCommandResult ES::AddTitleFinish(Context& context, const IOCtlVRequest& request) { - if (!request.HasNumberOfValidVectors(0, 0) || !m_addtitle_tmd.IsValid()) + if (!request.HasNumberOfValidVectors(0, 0) || !context.title_import.tmd.IsValid()) return GetDefaultReply(ES_EINVAL); - if (!WriteImportTMD(m_addtitle_tmd)) + if (!WriteImportTMD(context.title_import.tmd)) return GetDefaultReply(ES_EIO); - if (!FinishImport(m_addtitle_tmd)) + if (!FinishImport(context.title_import.tmd)) return GetDefaultReply(FS_EIO); INFO_LOG(IOS_ES, "IOCTL_ES_ADDTITLEFINISH"); - m_addtitle_tmd.SetBytes({}); + context.title_import.tmd.SetBytes({}); return GetDefaultReply(IPC_SUCCESS); } -IPCCommandResult ES::AddTitleCancel(const IOCtlVRequest& request) +IPCCommandResult ES::AddTitleCancel(Context& context, const IOCtlVRequest& request) { - if (!request.HasNumberOfValidVectors(0, 0) || !m_addtitle_tmd.IsValid()) + if (!request.HasNumberOfValidVectors(0, 0) || !context.title_import.tmd.IsValid()) return GetDefaultReply(ES_EINVAL); - const IOS::ES::TMDReader original_tmd = IOS::ES::FindInstalledTMD(m_addtitle_tmd.GetTitleId()); + const IOS::ES::TMDReader original_tmd = + IOS::ES::FindInstalledTMD(context.title_import.tmd.GetTitleId()); if (!original_tmd.IsValid()) { // This should never happen unless someone messed with the installed TMD directly. @@ -294,7 +298,7 @@ IPCCommandResult ES::AddTitleCancel(const IOCtlVRequest& request) if (!FinishImport(original_tmd)) return GetDefaultReply(FS_EIO); - m_addtitle_tmd.SetBytes({}); + context.title_import.tmd.SetBytes({}); return GetDefaultReply(IPC_SUCCESS); } @@ -363,40 +367,40 @@ IPCCommandResult ES::DeleteTitleContent(const IOCtlVRequest& request) return GetDefaultReply(IPC_SUCCESS); } -IPCCommandResult ES::ExportTitleInit(const IOCtlVRequest& request) +IPCCommandResult ES::ExportTitleInit(Context& context, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != 8) return GetDefaultReply(ES_EINVAL); // No concurrent title import/export is allowed. - if (m_export_title_context.valid) + if (context.title_export.valid) return GetDefaultReply(ES_EINVAL); const auto tmd = IOS::ES::FindInstalledTMD(Memory::Read_U64(request.in_vectors[0].address)); if (!tmd.IsValid()) return GetDefaultReply(FS_ENOENT); - m_export_title_context.tmd = tmd; + context.title_export.tmd = tmd; - const auto ticket = DiscIO::FindSignedTicket(m_export_title_context.tmd.GetTitleId()); + const auto ticket = DiscIO::FindSignedTicket(context.title_export.tmd.GetTitleId()); if (!ticket.IsValid()) return GetDefaultReply(ES_NO_TICKET); - if (ticket.GetTitleId() != m_export_title_context.tmd.GetTitleId()) + if (ticket.GetTitleId() != context.title_export.tmd.GetTitleId()) return GetDefaultReply(ES_EINVAL); - m_export_title_context.title_key = ticket.GetTitleKey(); + context.title_export.title_key = ticket.GetTitleKey(); - const auto& raw_tmd = m_export_title_context.tmd.GetRawTMD(); + const auto& raw_tmd = context.title_export.tmd.GetRawTMD(); if (request.io_vectors[0].size != raw_tmd.size()) return GetDefaultReply(ES_EINVAL); Memory::CopyToEmu(request.io_vectors[0].address, raw_tmd.data(), raw_tmd.size()); - m_export_title_context.valid = true; + context.title_export.valid = true; return GetDefaultReply(IPC_SUCCESS); } -IPCCommandResult ES::ExportContentBegin(const IOCtlVRequest& request) +IPCCommandResult ES::ExportContentBegin(Context& context, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(2, 0) || request.in_vectors[0].size != 8 || request.in_vectors[1].size != 4) @@ -405,7 +409,7 @@ IPCCommandResult ES::ExportContentBegin(const IOCtlVRequest& request) const u64 title_id = Memory::Read_U64(request.in_vectors[0].address); const u32 content_id = Memory::Read_U32(request.in_vectors[1].address); - if (!m_export_title_context.valid || m_export_title_context.tmd.GetTitleId() != title_id) + if (!context.title_export.valid || context.title_export.tmd.GetTitleId() != title_id) { ERROR_LOG(IOS_ES, "Tried to use ExportContentBegin with an invalid title export context."); return GetDefaultReply(ES_EINVAL); @@ -426,7 +430,7 @@ IPCCommandResult ES::ExportContentBegin(const IOCtlVRequest& request) content->m_Data->Open(); u32 cid = 0; - while (m_export_title_context.contents.find(cid) != m_export_title_context.contents.end()) + while (context.title_export.contents.find(cid) != context.title_export.contents.end()) cid++; TitleExportContext::ExportContent content_export; @@ -434,12 +438,12 @@ IPCCommandResult ES::ExportContentBegin(const IOCtlVRequest& request) content_export.iv[0] = (content->m_metadata.index >> 8) & 0xFF; content_export.iv[1] = content->m_metadata.index & 0xFF; - m_export_title_context.contents.emplace(cid, content_export); + context.title_export.contents.emplace(cid, content_export); // IOS returns a content ID which is passed to further content calls. return GetDefaultReply(cid); } -IPCCommandResult ES::ExportContentData(const IOCtlVRequest& request) +IPCCommandResult ES::ExportContentData(Context& context, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != 4 || request.io_vectors[0].size == 0) @@ -450,8 +454,8 @@ IPCCommandResult ES::ExportContentData(const IOCtlVRequest& request) const u32 content_id = Memory::Read_U32(request.in_vectors[0].address); const u32 bytes_to_read = request.io_vectors[0].size; - const auto iterator = m_export_title_context.contents.find(content_id); - if (!m_export_title_context.valid || iterator == m_export_title_context.contents.end() || + const auto iterator = context.title_export.contents.find(content_id); + if (!context.title_export.valid || iterator == context.title_export.contents.end() || iterator->second.content.m_position >= iterator->second.content.m_content.size) { return GetDefaultReply(ES_EINVAL); @@ -479,7 +483,7 @@ IPCCommandResult ES::ExportContentData(const IOCtlVRequest& request) std::vector output(buffer.size()); mbedtls_aes_context aes_ctx; - mbedtls_aes_setkey_enc(&aes_ctx, m_export_title_context.title_key.data(), 128); + mbedtls_aes_setkey_enc(&aes_ctx, context.title_export.title_key.data(), 128); const int ret = mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_ENCRYPT, buffer.size(), iterator->second.iv.data(), buffer.data(), output.data()); if (ret != 0) @@ -494,15 +498,15 @@ IPCCommandResult ES::ExportContentData(const IOCtlVRequest& request) return GetDefaultReply(IPC_SUCCESS); } -IPCCommandResult ES::ExportContentEnd(const IOCtlVRequest& request) +IPCCommandResult ES::ExportContentEnd(Context& context, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != 4) return GetDefaultReply(ES_EINVAL); const u32 content_id = Memory::Read_U32(request.in_vectors[0].address); - const auto iterator = m_export_title_context.contents.find(content_id); - if (!m_export_title_context.valid || iterator == m_export_title_context.contents.end() || + const auto iterator = context.title_export.contents.find(content_id); + if (!context.title_export.valid || iterator == context.title_export.contents.end() || iterator->second.content.m_position != iterator->second.content.m_content.size) { return GetDefaultReply(ES_EINVAL); @@ -513,16 +517,16 @@ IPCCommandResult ES::ExportContentEnd(const IOCtlVRequest& request) const auto& content_loader = AccessContentDevice(iterator->second.content.m_title_id); content_loader.GetContentByID(iterator->second.content.m_content.id)->m_Data->Close(); - m_export_title_context.contents.erase(iterator); + context.title_export.contents.erase(iterator); return GetDefaultReply(IPC_SUCCESS); } -IPCCommandResult ES::ExportTitleDone(const IOCtlVRequest& request) +IPCCommandResult ES::ExportTitleDone(Context& context, const IOCtlVRequest& request) { - if (!m_export_title_context.valid) + if (!context.title_export.valid) return GetDefaultReply(ES_EINVAL); - m_export_title_context.valid = false; + context.title_export.valid = false; return GetDefaultReply(IPC_SUCCESS); } } // namespace Device diff --git a/Source/Core/Core/IOS/FS/FileIO.cpp b/Source/Core/Core/IOS/FS/FileIO.cpp index dbc2f02014..4c11d8267c 100644 --- a/Source/Core/Core/IOS/FS/FileIO.cpp +++ b/Source/Core/Core/IOS/FS/FileIO.cpp @@ -76,7 +76,7 @@ FileIO::FileIO(u32 device_id, const std::string& device_name) { } -void FileIO::Close() +ReturnCode FileIO::Close(u32 fd) { INFO_LOG(IOS_FILEIO, "FileIO: Close %s (DeviceID=%08x)", m_name.c_str(), m_device_id); m_Mode = 0; @@ -86,6 +86,7 @@ void FileIO::Close() m_file.reset(); m_is_active = false; + return IPC_SUCCESS; } ReturnCode FileIO::Open(const OpenRequest& request) diff --git a/Source/Core/Core/IOS/FS/FileIO.h b/Source/Core/Core/IOS/FS/FileIO.h index 0e5698c5b5..f341208d9c 100644 --- a/Source/Core/Core/IOS/FS/FileIO.h +++ b/Source/Core/Core/IOS/FS/FileIO.h @@ -32,7 +32,7 @@ class FileIO : public Device public: FileIO(u32 device_id, const std::string& device_name); - void Close() override; + ReturnCode Close(u32 fd) override; ReturnCode Open(const OpenRequest& request) override; IPCCommandResult Seek(const SeekRequest& request) override; IPCCommandResult Read(const ReadWriteRequest& request) override; diff --git a/Source/Core/Core/IOS/IPC.cpp b/Source/Core/Core/IOS/IPC.cpp index 00d20877f9..2906f207c2 100644 --- a/Source/Core/Core/IOS/IPC.cpp +++ b/Source/Core/Core/IOS/IPC.cpp @@ -75,9 +75,7 @@ static std::mutex s_device_map_mutex; // STATE_TO_SAVE constexpr u8 IPC_MAX_FDS = 0x18; -constexpr u8 ES_MAX_COUNT = 3; static std::shared_ptr s_fdmap[IPC_MAX_FDS]; -static std::shared_ptr s_es_handles[ES_MAX_COUNT]; using IPCMsgQueue = std::deque; static IPCMsgQueue s_request_queue; // ppc -> arm @@ -595,11 +593,7 @@ static void AddStaticDevices() AddDevice("/dev/stm/immediate"); AddDevice("/dev/stm/eventhook"); AddDevice("/dev/fs"); - - // IOS allows three ES devices at a time - for (auto& es_device : s_es_handles) - es_device = AddDevice("/dev/es"); - + AddDevice("/dev/es"); AddDevice("/dev/di"); AddDevice("/dev/net/kd/request"); AddDevice("/dev/net/kd/time"); @@ -643,7 +637,7 @@ static void Reset() { if (!device) continue; - device->Close(); + device->Close(0); device.reset(); } @@ -701,7 +695,6 @@ bool Reload(const u64 ios_title_id) AddStaticDevices(); - Device::ES::Init(); return true; } @@ -855,13 +848,6 @@ void DoState(PointerWrap& p) } } } - - for (auto& es_device : s_es_handles) - { - const u32 handle_id = es_device->GetDeviceID(); - p.Do(handle_id); - es_device = std::static_pointer_cast(AccessDeviceByID(handle_id)); - } } else { @@ -884,24 +870,11 @@ void DoState(PointerWrap& p) } } } - - for (const auto& es_device : s_es_handles) - { - const u32 handle_id = es_device->GetDeviceID(); - p.Do(handle_id); - } } } -static std::shared_ptr GetUnusedESDevice() -{ - const auto iterator = std::find_if(std::begin(s_es_handles), std::end(s_es_handles), - [](const auto& es_device) { return !es_device->IsOpened(); }); - return (iterator != std::end(s_es_handles)) ? *iterator : nullptr; -} - // Returns the FD for the newly opened device (on success) or an error code. -static s32 OpenDevice(const OpenRequest& request) +static s32 OpenDevice(OpenRequest& request) { const s32 new_fd = GetFreeDeviceID(); INFO_LOG(IOS, "Opening %s (mode %d, fd %d)", request.path.c_str(), request.flags, new_fd); @@ -910,15 +883,10 @@ static s32 OpenDevice(const OpenRequest& request) ERROR_LOG(IOS, "Couldn't get a free fd, too many open files"); return FS_EFDEXHAUSTED; } + request.fd = new_fd; std::shared_ptr device; - if (request.path == "/dev/es") - { - device = GetUnusedESDevice(); - if (!device) - return ES_FD_EXHAUSTED; - } - else if (request.path.find("/dev/usb/oh0/") == 0 && !GetDeviceByName(request.path)) + if (request.path.find("/dev/usb/oh0/") == 0 && !GetDeviceByName(request.path)) { device = std::make_shared(new_fd, request.path); } @@ -961,8 +929,7 @@ static IPCCommandResult HandleCommand(const Request& request) { case IPC_CMD_CLOSE: s_fdmap[request.fd].reset(); - device->Close(); - return Device::Device::GetDefaultReply(IPC_SUCCESS); + return Device::Device::GetDefaultReply(device->Close(request.fd)); case IPC_CMD_READ: return device->Read(ReadWriteRequest{request.address}); case IPC_CMD_WRITE: diff --git a/Source/Core/Core/IOS/SDIO/SDIOSlot0.cpp b/Source/Core/Core/IOS/SDIO/SDIOSlot0.cpp index 96a2d48219..4987fae39b 100644 --- a/Source/Core/Core/IOS/SDIO/SDIOSlot0.cpp +++ b/Source/Core/Core/IOS/SDIO/SDIOSlot0.cpp @@ -83,13 +83,13 @@ ReturnCode SDIOSlot0::Open(const OpenRequest& request) return IPC_SUCCESS; } -void SDIOSlot0::Close() +ReturnCode SDIOSlot0::Close(u32 fd) { m_Card.Close(); m_BlockLength = 0; m_BusWidth = 0; - m_is_active = false; + return Device::Close(fd); } IPCCommandResult SDIOSlot0::IOCtl(const IOCtlRequest& request) diff --git a/Source/Core/Core/IOS/SDIO/SDIOSlot0.h b/Source/Core/Core/IOS/SDIO/SDIOSlot0.h index 6fd08a9b16..116625f29b 100644 --- a/Source/Core/Core/IOS/SDIO/SDIOSlot0.h +++ b/Source/Core/Core/IOS/SDIO/SDIOSlot0.h @@ -31,7 +31,7 @@ public: void DoState(PointerWrap& p) override; ReturnCode Open(const OpenRequest& request) override; - void Close() override; + ReturnCode Close(u32 fd) override; IPCCommandResult IOCtl(const IOCtlRequest& request) override; IPCCommandResult IOCtlV(const IOCtlVRequest& request) override; diff --git a/Source/Core/Core/IOS/STM/STM.cpp b/Source/Core/Core/IOS/STM/STM.cpp index 1330c42c65..aece7e39fa 100644 --- a/Source/Core/Core/IOS/STM/STM.cpp +++ b/Source/Core/Core/IOS/STM/STM.cpp @@ -67,10 +67,10 @@ IPCCommandResult STMImmediate::IOCtl(const IOCtlRequest& request) return GetDefaultReply(return_value); } -void STMEventHook::Close() +ReturnCode STMEventHook::Close(u32 fd) { s_event_hook_request.reset(); - m_is_active = false; + return Device::Close(fd); } IPCCommandResult STMEventHook::IOCtl(const IOCtlRequest& request) diff --git a/Source/Core/Core/IOS/STM/STM.h b/Source/Core/Core/IOS/STM/STM.h index 1a2f534d00..6721e3c28c 100644 --- a/Source/Core/Core/IOS/STM/STM.h +++ b/Source/Core/Core/IOS/STM/STM.h @@ -55,7 +55,7 @@ class STMEventHook final : public Device { public: STMEventHook(u32 device_id, const std::string& device_name) : Device(device_id, device_name) {} - void Close() override; + ReturnCode Close(u32 fd) override; IPCCommandResult IOCtl(const IOCtlRequest& request) override; void DoState(PointerWrap& p) override; diff --git a/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.cpp b/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.cpp index 901aa11ef8..bf6c1c15d6 100644 --- a/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.cpp +++ b/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.cpp @@ -147,7 +147,7 @@ bool BluetoothEmu::RemoteDisconnect(u16 _connectionHandle) return SendEventDisconnect(_connectionHandle, 0x13); } -void BluetoothEmu::Close() +ReturnCode BluetoothEmu::Close(u32 fd) { // Clean up state m_ScanEnable = 0; @@ -156,7 +156,7 @@ void BluetoothEmu::Close() m_HCIEndpoint.reset(); m_ACLEndpoint.reset(); - m_is_active = false; + return Device::Close(fd); } IPCCommandResult BluetoothEmu::IOCtlV(const IOCtlVRequest& request) diff --git a/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.h b/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.h index 45e42ef45a..efb60cf10d 100644 --- a/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.h +++ b/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.h @@ -49,7 +49,7 @@ public: virtual ~BluetoothEmu(); - void Close() override; + ReturnCode Close(u32 fd) override; IPCCommandResult IOCtlV(const IOCtlVRequest& request) override; void Update() override; diff --git a/Source/Core/Core/IOS/USB/Bluetooth/BTReal.cpp b/Source/Core/Core/IOS/USB/Bluetooth/BTReal.cpp index cba2a3f394..25633158c1 100644 --- a/Source/Core/Core/IOS/USB/Bluetooth/BTReal.cpp +++ b/Source/Core/Core/IOS/USB/Bluetooth/BTReal.cpp @@ -149,7 +149,7 @@ ReturnCode BluetoothReal::Open(const OpenRequest& request) return IPC_SUCCESS; } -void BluetoothReal::Close() +ReturnCode BluetoothReal::Close(u32 fd) { if (m_handle) { @@ -159,7 +159,7 @@ void BluetoothReal::Close() m_handle = nullptr; } - m_is_active = false; + return Device::Close(fd); } IPCCommandResult BluetoothReal::IOCtlV(const IOCtlVRequest& request) diff --git a/Source/Core/Core/IOS/USB/Bluetooth/BTReal.h b/Source/Core/Core/IOS/USB/Bluetooth/BTReal.h index dc1679925a..3acc462fc0 100644 --- a/Source/Core/Core/IOS/USB/Bluetooth/BTReal.h +++ b/Source/Core/Core/IOS/USB/Bluetooth/BTReal.h @@ -52,7 +52,7 @@ public: ~BluetoothReal() override; ReturnCode Open(const OpenRequest& request) override; - void Close() override; + ReturnCode Close(u32 fd) override; IPCCommandResult IOCtlV(const IOCtlVRequest& request) override; void DoState(PointerWrap& p) override; diff --git a/Source/Core/Core/IOS/USB/OH0/OH0Device.cpp b/Source/Core/Core/IOS/USB/OH0/OH0Device.cpp index 61bbd447db..03b3e7da2c 100644 --- a/Source/Core/Core/IOS/USB/OH0/OH0Device.cpp +++ b/Source/Core/Core/IOS/USB/OH0/OH0Device.cpp @@ -68,9 +68,10 @@ ReturnCode OH0Device::Open(const OpenRequest& request) return return_code; } -void OH0Device::Close() +ReturnCode OH0Device::Close(u32 fd) { m_oh0->DeviceClose(m_device_id); + return Device::Close(fd); } IPCCommandResult OH0Device::IOCtl(const IOCtlRequest& request) diff --git a/Source/Core/Core/IOS/USB/OH0/OH0Device.h b/Source/Core/Core/IOS/USB/OH0/OH0Device.h index 239622d227..c66ccc4b2f 100644 --- a/Source/Core/Core/IOS/USB/OH0/OH0Device.h +++ b/Source/Core/Core/IOS/USB/OH0/OH0Device.h @@ -25,7 +25,7 @@ public: OH0Device(u32 device_id, const std::string& device_name); ReturnCode Open(const OpenRequest& request) override; - void Close() override; + ReturnCode Close(u32 fd) override; IPCCommandResult IOCtl(const IOCtlRequest& request) override; IPCCommandResult IOCtlV(const IOCtlVRequest& request) override; void DoState(PointerWrap& p) override; diff --git a/Source/Core/Core/State.cpp b/Source/Core/Core/State.cpp index 41a52669fc..fc2418391e 100644 --- a/Source/Core/Core/State.cpp +++ b/Source/Core/Core/State.cpp @@ -71,7 +71,7 @@ static Common::Event g_compressAndDumpStateSyncEvent; static std::thread g_save_thread; // Don't forget to increase this after doing changes on the savestate system -static const u32 STATE_VERSION = 81; // Last changed in PR 5317 +static const u32 STATE_VERSION = 82; // Last changed in PR 5333 // Maps savestate versions to Dolphin versions. // Versions after 42 don't need to be added to this list,