From 9c18eea812b5fe299d0d80d1d3a639c60b63d5b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sun, 26 Feb 2017 17:48:15 +0100 Subject: [PATCH] IOS/ES: Mark members shared between instances as static Some members are shared between ES instances, and they are just global variables in IOS. This is more efficient than getting the installed titles or setting the current active title tons of times for no reason. --- Source/Core/Core/IOS/ES/ES.cpp | 125 ++++++++++++++++++++------------- Source/Core/Core/IOS/ES/ES.h | 35 +++------ Source/Core/Core/IOS/IPC.cpp | 14 +--- Source/Core/Core/IOS/IPC.h | 2 - 4 files changed, 89 insertions(+), 87 deletions(-) diff --git a/Source/Core/Core/IOS/ES/ES.cpp b/Source/Core/Core/IOS/ES/ES.cpp index d2b30b6da7..abd458cc22 100644 --- a/Source/Core/Core/IOS/ES/ES.cpp +++ b/Source/Core/Core/IOS/ES/ES.cpp @@ -38,8 +38,25 @@ namespace HLE { namespace Device { -std::string ES::m_ContentFile; -ES::TitleContext ES::m_title_context; +struct TitleContext +{ + void Clear(); + void DoState(PointerWrap& p); + void Update(const DiscIO::CNANDContentLoader& content_loader); + void Update(const IOS::ES::TMDReader& tmd_, const IOS::ES::TicketReader& ticket_); + + IOS::ES::TicketReader ticket; + IOS::ES::TMDReader tmd; + bool active = false; +}; + +// Shared across all ES instances. +static std::string s_content_file; +static std::vector s_title_ids; +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; constexpr u8 s_key_sd[0x10] = {0xab, 0x01, 0xb9, 0xd8, 0xe1, 0x62, 0x2b, 0x08, 0xaf, 0xba, 0xd8, 0x4d, 0xbf, 0xc2, 0xa5, 0x5d}; @@ -66,39 +83,51 @@ constexpr const u8* s_key_table[11] = { ES::ES(u32 device_id, const std::string& device_name) : Device(device_id, device_name) { - m_title_context.Clear(); - - m_TitleIDs.clear(); - DiscIO::cUIDsys uid_sys{Common::FromWhichRoot::FROM_SESSION_ROOT}; - uid_sys.GetTitleIDs(m_TitleIDs); - - // uncomment if ES_GetOwnedTitlesCount / ES_GetOwnedTitles is implemented - // m_TitleIDsOwned.clear(); - // DiscIO::cUIDsys::AccessInstance().GetTitleIDs(m_TitleIDsOwned, true); } -void ES::TitleContext::Clear() +void ES::Init() +{ + s_content_file = ""; + s_title_context = TitleContext{}; + + s_title_ids.clear(); + DiscIO::cUIDsys uid_sys{Common::FromWhichRoot::FROM_SESSION_ROOT}; + uid_sys.GetTitleIDs(s_title_ids); + + // uncomment if ES_GetOwnedTitlesCount / ES_GetOwnedTitles is implemented + // s_title_idsOwned.clear(); + // DiscIO::cUIDsys::AccessInstance().GetTitleIDs(s_title_idsOwned, true); + + if (s_title_to_launch != 0) + { + NOTICE_LOG(IOS, "Re-launching title after IOS reload."); + LaunchTitle(s_title_to_launch, true); + s_title_to_launch = 0; + } +} + +void TitleContext::Clear() { ticket.SetBytes({}); tmd.SetBytes({}); active = false; } -void ES::TitleContext::DoState(PointerWrap& p) +void TitleContext::DoState(PointerWrap& p) { ticket.DoState(p); tmd.DoState(p); p.Do(active); } -void ES::TitleContext::Update(const DiscIO::CNANDContentLoader& content_loader) +void TitleContext::Update(const DiscIO::CNANDContentLoader& content_loader) { if (!content_loader.IsValid()) return; Update(content_loader.GetTMD(), content_loader.GetTicket()); } -void ES::TitleContext::Update(const IOS::ES::TMDReader& tmd_, const IOS::ES::TicketReader& ticket_) +void TitleContext::Update(const IOS::ES::TMDReader& tmd_, const IOS::ES::TicketReader& ticket_) { if (!tmd_.IsValid() || !ticket_.IsValid()) { @@ -113,11 +142,11 @@ void ES::TitleContext::Update(const IOS::ES::TMDReader& tmd_, const IOS::ES::Tic void ES::LoadWAD(const std::string& _rContentFile) { - m_ContentFile = _rContentFile; + s_content_file = _rContentFile; // XXX: Ideally, this should be done during a launch, but because we support launching WADs // without installing them (which is a bit of a hack), we have to do this manually here. - const auto& content_loader = DiscIO::CNANDContentManager::Access().GetNANDLoader(m_ContentFile); - m_title_context.Update(content_loader); + const auto& content_loader = DiscIO::CNANDContentManager::Access().GetNANDLoader(s_content_file); + s_title_context.Update(content_loader); } void ES::DecryptContent(u32 key_index, u8* iv, u8* input, u32 size, u8* new_iv, u8* output) @@ -128,9 +157,9 @@ void ES::DecryptContent(u32 key_index, u8* iv, u8* input, u32 size, u8* new_iv, mbedtls_aes_crypt_cbc(&AES_ctx, MBEDTLS_AES_DECRYPT, size, new_iv, input, output); } -bool ES::LaunchTitle(u64 title_id, bool skip_reload) const +bool ES::LaunchTitle(u64 title_id, bool skip_reload) { - m_title_context.Clear(); + s_title_context.Clear(); NOTICE_LOG(IOS_ES, "Launching title %016" PRIx64 "...", title_id); @@ -144,12 +173,12 @@ bool ES::LaunchTitle(u64 title_id, bool skip_reload) const return LaunchPPCTitle(title_id, skip_reload); } -bool ES::LaunchIOS(u64 ios_title_id) const +bool ES::LaunchIOS(u64 ios_title_id) { return Reload(ios_title_id); } -bool ES::LaunchPPCTitle(u64 title_id, bool skip_reload) const +bool ES::LaunchPPCTitle(u64 title_id, bool skip_reload) { const DiscIO::CNANDContentLoader& content_loader = AccessContentDevice(title_id); if (!content_loader.IsValid()) @@ -165,23 +194,22 @@ bool ES::LaunchPPCTitle(u64 title_id, bool skip_reload) const // again with the reload skipped, and the PPC will be bootstrapped then. if (!skip_reload) { - SetTitleToLaunch(title_id); + s_title_to_launch = title_id; const u64 required_ios = content_loader.GetTMD().GetIOSId(); return LaunchTitle(required_ios); } - m_title_context.Update(content_loader); - SetDefaultContentFile(Common::GetTitleContentPath(title_id, Common::FROM_SESSION_ROOT)); + s_title_context.Update(content_loader); return BootstrapPPC(content_loader); } void ES::DoState(PointerWrap& p) { Device::DoState(p); - p.Do(m_ContentFile); + p.Do(s_content_file); p.Do(m_AccessIdentID); - p.Do(m_TitleIDs); - m_title_context.DoState(p); + p.Do(s_title_ids); + s_title_context.DoState(p); m_addtitle_tmd.DoState(p); p.Do(m_addtitle_content_id); @@ -646,10 +674,10 @@ IPCCommandResult ES::OpenContent(const IOCtlVRequest& request) return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT); u32 Index = Memory::Read_U32(request.in_vectors[0].address); - if (!m_title_context.active) + if (!s_title_context.active) return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT); - s32 CFD = OpenTitleContent(m_AccessIdentID++, m_title_context.tmd.GetTitleId(), Index); + s32 CFD = OpenTitleContent(m_AccessIdentID++, s_title_context.tmd.GetTitleId(), Index); INFO_LOG(IOS_ES, "IOCTL_ES_OPENCONTENT: Index %i -> got CFD %x", Index, CFD); return GetDefaultReply(CFD); @@ -792,10 +820,10 @@ IPCCommandResult ES::GetTitleID(const IOCtlVRequest& request) if (!request.HasNumberOfValidVectors(0, 1)) return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT); - if (!m_title_context.active) + if (!s_title_context.active) return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT); - const u64 title_id = m_title_context.tmd.GetTitleId(); + const u64 title_id = s_title_context.tmd.GetTitleId(); Memory::Write_U64(title_id, request.io_vectors[0].address); INFO_LOG(IOS_ES, "IOCTL_ES_GETTITLEID: %08x/%08x", static_cast(title_id >> 32), static_cast(title_id)); @@ -818,9 +846,9 @@ IPCCommandResult ES::GetTitleCount(const IOCtlVRequest& request) if (!request.HasNumberOfValidVectors(0, 1) || request.io_vectors[0].size != 4) return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT); - Memory::Write_U32((u32)m_TitleIDs.size(), request.io_vectors[0].address); + Memory::Write_U32((u32)s_title_ids.size(), request.io_vectors[0].address); - INFO_LOG(IOS_ES, "IOCTL_ES_GETTITLECNT: Number of Titles %zu", m_TitleIDs.size()); + INFO_LOG(IOS_ES, "IOCTL_ES_GETTITLECNT: Number of Titles %zu", s_title_ids.size()); return GetDefaultReply(IPC_SUCCESS); } @@ -832,11 +860,11 @@ IPCCommandResult ES::GetTitles(const IOCtlVRequest& request) u32 MaxCount = Memory::Read_U32(request.in_vectors[0].address); u32 Count = 0; - for (int i = 0; i < (int)m_TitleIDs.size(); i++) + for (int i = 0; i < (int)s_title_ids.size(); i++) { - Memory::Write_U64(m_TitleIDs[i], request.io_vectors[0].address + i * 8); - INFO_LOG(IOS_ES, "IOCTL_ES_GETTITLES: %08x/%08x", (u32)(m_TitleIDs[i] >> 32), - (u32)m_TitleIDs[i]); + Memory::Write_U64(s_title_ids[i], request.io_vectors[0].address + i * 8); + INFO_LOG(IOS_ES, "IOCTL_ES_GETTITLES: %08x/%08x", (u32)(s_title_ids[i] >> 32), + (u32)s_title_ids[i]); Count++; if (Count >= MaxCount) break; @@ -1353,11 +1381,11 @@ IPCCommandResult ES::Sign(const IOCtlVRequest& request) u32 data_size = request.in_vectors[0].size; u8* sig_out = Memory::GetPointer(request.io_vectors[0].address); - if (!m_title_context.active) + if (!s_title_context.active) return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT); const EcWii& ec = EcWii::GetInstance(); - MakeAPSigAndCert(sig_out, ap_cert_out, m_title_context.tmd.GetTitleId(), data, data_size, + MakeAPSigAndCert(sig_out, ap_cert_out, s_title_context.tmd.GetTitleId(), data, data_size, ec.GetNGPriv(), ec.GetNGID()); return GetDefaultReply(IPC_SUCCESS); @@ -1395,24 +1423,27 @@ IPCCommandResult ES::GetOwnedTitleCount(const IOCtlVRequest& request) return GetDefaultReply(IPC_SUCCESS); } -const DiscIO::CNANDContentLoader& ES::AccessContentDevice(u64 title_id) const +const DiscIO::CNANDContentLoader& ES::AccessContentDevice(u64 title_id) { - // for WADs, the passed title id and the stored title id match; along with m_ContentFile being set + // for WADs, the passed title id and the stored title id match; along with s_content_file being + // set // to the // actual WAD file name. We cannot simply get a NAND Loader for the title id in those cases, since // the WAD // need not be installed in the NAND, but it could be opened directly from a WAD file anywhere on // disk. - if (m_title_context.active && m_title_context.tmd.GetTitleId() == title_id && - !m_ContentFile.empty()) - return DiscIO::CNANDContentManager::Access().GetNANDLoader(m_ContentFile); + if (s_title_context.active && s_title_context.tmd.GetTitleId() == title_id && + !s_content_file.empty()) + { + return DiscIO::CNANDContentManager::Access().GetNANDLoader(s_content_file); + } return DiscIO::CNANDContentManager::Access().GetNANDLoader(title_id, Common::FROM_SESSION_ROOT); } s32 ES::DIVerify(const IOS::ES::TMDReader& tmd, const IOS::ES::TicketReader& ticket) { - m_title_context.Clear(); + s_title_context.Clear(); if (!tmd.IsValid() || !ticket.IsValid()) return ES_PARAMETER_SIZE_OR_ALIGNMENT; @@ -1438,7 +1469,7 @@ s32 ES::DIVerify(const IOS::ES::TMDReader& tmd, const IOS::ES::TicketReader& tic // clear the cache to avoid content access mismatches. DiscIO::CNANDContentManager::Access().ClearCache(); - m_title_context.Update(tmd, ticket); + s_title_context.Update(tmd, ticket); return IPC_SUCCESS; } } // namespace Device diff --git a/Source/Core/Core/IOS/ES/ES.h b/Source/Core/Core/IOS/ES/ES.h index 120effcd8c..8adb54e8e9 100644 --- a/Source/Core/Core/IOS/ES/ES.h +++ b/Source/Core/Core/IOS/ES/ES.h @@ -34,11 +34,15 @@ class ES : public Device public: ES(u32 device_id, const std::string& device_name); - void LoadWAD(const std::string& _rContentFile); - bool LaunchTitle(u64 title_id, bool skip_reload = false) const; + // 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); // Internal implementation of the ES_DECRYPT ioctlv. - void DecryptContent(u32 key_index, u8* iv, u8* input, u32 size, u8* new_iv, u8* output); + static void DecryptContent(u32 key_index, u8* iv, u8* input, u32 size, u8* new_iv, u8* output); void DoState(PointerWrap& p) override; @@ -46,11 +50,6 @@ public: void Close() override; IPCCommandResult IOCtlV(const IOCtlVRequest& request) override; - static s32 DIVerify(const IOS::ES::TMDReader& tmd, const IOS::ES::TicketReader& ticket); - - // This should only be cleared on power reset - static std::string m_ContentFile; - private: enum { @@ -198,32 +197,18 @@ private: IPCCommandResult DIGetTicketView(const IOCtlVRequest& request); IPCCommandResult GetOwnedTitleCount(const IOCtlVRequest& request); - bool LaunchIOS(u64 ios_title_id) const; - bool LaunchPPCTitle(u64 title_id, bool skip_reload) const; + static bool LaunchIOS(u64 ios_title_id); + static bool LaunchPPCTitle(u64 title_id, bool skip_reload); - const DiscIO::CNANDContentLoader& AccessContentDevice(u64 title_id) const; + static const DiscIO::CNANDContentLoader& AccessContentDevice(u64 title_id); u32 OpenTitleContent(u32 CFD, u64 TitleID, u16 Index); using ContentAccessMap = std::map; ContentAccessMap m_ContentAccessMap; - std::vector m_TitleIDs; u32 m_AccessIdentID = 0; - // Shared across all ES instances. - static struct TitleContext - { - void Clear(); - void DoState(PointerWrap& p); - void Update(const DiscIO::CNANDContentLoader& content_loader); - void Update(const IOS::ES::TMDReader& tmd_, const IOS::ES::TicketReader& ticket_); - - IOS::ES::TicketReader ticket; - IOS::ES::TMDReader tmd; - bool active = false; - } m_title_context; - // For title installation (ioctls IOCTL_ES_ADDTITLE*). IOS::ES::TMDReader m_addtitle_tmd; u32 m_addtitle_content_id = 0xFFFFFFFF; diff --git a/Source/Core/Core/IOS/IPC.cpp b/Source/Core/Core/IOS/IPC.cpp index a8295db851..8dff5a90a6 100644 --- a/Source/Core/Core/IOS/IPC.cpp +++ b/Source/Core/Core/IOS/IPC.cpp @@ -95,7 +95,6 @@ static CoreTiming::EventType* s_event_sdio_notify; static u64 s_last_reply_time; static u64 s_active_title_id; -static u64 s_title_to_launch; static constexpr u64 ENQUEUE_REQUEST_FLAG = 0x100000000ULL; static constexpr u64 ENQUEUE_ACKNOWLEDGEMENT_FLAG = 0x200000000ULL; @@ -586,7 +585,6 @@ static void AddStaticDevices() { std::lock_guard lock(s_device_map_mutex); _assert_msg_(IOS, s_device_map.empty(), "Reinit called while already initialized"); - Device::ES::m_ContentFile = ""; num_devices = 0; @@ -706,20 +704,10 @@ bool Reload(const u64 ios_title_id) AddStaticDevices(); - if (s_title_to_launch != 0) - { - NOTICE_LOG(IOS, "Re-launching title after IOS reload."); - s_es_handles[0]->LaunchTitle(s_title_to_launch, true); - s_title_to_launch = 0; - } + Device::ES::Init(); return true; } -void SetTitleToLaunch(const u64 title_id) -{ - s_title_to_launch = title_id; -} - // This corresponds to syscall 0x41, which loads a binary from the NAND and bootstraps the PPC. // Unlike 0x42, IOS will set up some constants in memory before booting the PPC. bool BootstrapPPC(const DiscIO::CNANDContentLoader& content_loader) diff --git a/Source/Core/Core/IOS/IPC.h b/Source/Core/Core/IOS/IPC.h index ae2c7470d9..901699c545 100644 --- a/Source/Core/Core/IOS/IPC.h +++ b/Source/Core/Core/IOS/IPC.h @@ -68,8 +68,6 @@ bool Reload(u64 ios_title_id); u32 GetVersion(); bool BootstrapPPC(const DiscIO::CNANDContentLoader& content_loader); -// This sets a title to launch after IOS has been reset and reloaded (similar to /sys/launch.sys). -void SetTitleToLaunch(u64 title_id); // Do State void DoState(PointerWrap& p);