From 194b0ae36dbfa11f720a130c3fc1f06b843935a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sun, 12 Mar 2017 19:58:44 +0100 Subject: [PATCH 1/4] IOS: Add NandUtils This keeps the ES specific NAND code in a single place and makes it reusable. Eventually, other ES specific code will be moved to it. --- Source/Core/Core/CMakeLists.txt | 1 + Source/Core/Core/Core.vcxproj | 2 + Source/Core/Core/Core.vcxproj.filters | 6 + Source/Core/Core/IOS/ES/NandUtils.cpp | 114 +++++++++++++++++++ Source/Core/Core/IOS/ES/NandUtils.h | 23 ++++ Source/Core/Core/IOS/ES/TitleInformation.cpp | 96 +--------------- Source/Core/DiscIO/NANDContentLoader.h | 1 + 7 files changed, 152 insertions(+), 91 deletions(-) create mode 100644 Source/Core/Core/IOS/ES/NandUtils.cpp create mode 100644 Source/Core/Core/IOS/ES/NandUtils.h diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt index 0c8ed8946a..c9704450ab 100644 --- a/Source/Core/Core/CMakeLists.txt +++ b/Source/Core/Core/CMakeLists.txt @@ -150,6 +150,7 @@ set(SRCS IOS/ES/ES.cpp IOS/ES/Formats.cpp IOS/ES/Identity.cpp + IOS/ES/NandUtils.cpp IOS/ES/TitleContents.cpp IOS/ES/TitleInformation.cpp IOS/ES/TitleManagement.cpp diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj index 549bc38c35..86edd95d87 100644 --- a/Source/Core/Core/Core.vcxproj +++ b/Source/Core/Core/Core.vcxproj @@ -177,6 +177,7 @@ + @@ -427,6 +428,7 @@ + diff --git a/Source/Core/Core/Core.vcxproj.filters b/Source/Core/Core/Core.vcxproj.filters index 1d5792cc33..18bce72497 100644 --- a/Source/Core/Core/Core.vcxproj.filters +++ b/Source/Core/Core/Core.vcxproj.filters @@ -759,6 +759,9 @@ IOS\ES + + IOS\ES + IOS\ES @@ -1370,6 +1373,9 @@ IOS\ES + + IOS\ES + IOS\FS diff --git a/Source/Core/Core/IOS/ES/NandUtils.cpp b/Source/Core/Core/IOS/ES/NandUtils.cpp new file mode 100644 index 0000000000..15a313c94d --- /dev/null +++ b/Source/Core/Core/IOS/ES/NandUtils.cpp @@ -0,0 +1,114 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include +#include +#include +#include + +#include "Common/CommonTypes.h" +#include "Common/FileUtil.h" +#include "Common/Logging/Log.h" +#include "Common/NandPaths.h" +#include "Core/IOS/ES/Formats.h" +#include "Core/IOS/ES/NandUtils.h" + +namespace IOS +{ +namespace ES +{ +static bool IsValidPartOfTitleID(const std::string& string) +{ + if (string.length() != 8) + return false; + return std::all_of(string.begin(), string.end(), + [](const auto character) { return std::isxdigit(character) != 0; }); +} + +static std::vector GetTitlesInTitleOrImport(const std::string& titles_dir) +{ + if (!File::IsDirectory(titles_dir)) + { + ERROR_LOG(IOS_ES, "%s is not a directory", titles_dir.c_str()); + return {}; + } + + std::vector title_ids; + + // The /title and /import directories contain one directory per title type, and each of them has + // a directory per title (where the name is the low 32 bits of the title ID in %08x format). + const auto entries = File::ScanDirectoryTree(titles_dir, true); + for (const File::FSTEntry& title_type : entries.children) + { + if (!title_type.isDirectory || !IsValidPartOfTitleID(title_type.virtualName)) + continue; + + if (title_type.children.empty()) + continue; + + for (const File::FSTEntry& title_identifier : title_type.children) + { + if (!title_identifier.isDirectory || !IsValidPartOfTitleID(title_identifier.virtualName)) + continue; + + const u32 type = std::stoul(title_type.virtualName, nullptr, 16); + const u32 identifier = std::stoul(title_identifier.virtualName, nullptr, 16); + title_ids.push_back(static_cast(type) << 32 | identifier); + } + } + + return title_ids; +} + +std::vector GetInstalledTitles() +{ + return GetTitlesInTitleOrImport(Common::RootUserPath(Common::FROM_SESSION_ROOT) + "/title"); +} + +std::vector GetTitleImports() +{ + return GetTitlesInTitleOrImport(Common::RootUserPath(Common::FROM_SESSION_ROOT) + "/import"); +} + +std::vector GetTitlesWithTickets() +{ + const std::string tickets_dir = Common::RootUserPath(Common::FROM_SESSION_ROOT) + "/ticket"; + if (!File::IsDirectory(tickets_dir)) + { + ERROR_LOG(IOS_ES, "/ticket is not a directory"); + return {}; + } + + std::vector title_ids; + + // The /ticket directory contains one directory per title type, and each of them contains + // one ticket per title (where the name is the low 32 bits of the title ID in %08x format). + const auto entries = File::ScanDirectoryTree(tickets_dir, true); + for (const File::FSTEntry& title_type : entries.children) + { + if (!title_type.isDirectory || !IsValidPartOfTitleID(title_type.virtualName)) + continue; + + if (title_type.children.empty()) + continue; + + for (const File::FSTEntry& ticket : title_type.children) + { + const std::string name_without_ext = ticket.virtualName.substr(0, 8); + if (ticket.isDirectory || !IsValidPartOfTitleID(name_without_ext) || + name_without_ext + ".tik" != ticket.virtualName) + { + continue; + } + + const u32 type = std::stoul(title_type.virtualName, nullptr, 16); + const u32 identifier = std::stoul(name_without_ext, nullptr, 16); + title_ids.push_back(static_cast(type) << 32 | identifier); + } + } + + return title_ids; +} +} // namespace ES +} // namespace IOS diff --git a/Source/Core/Core/IOS/ES/NandUtils.h b/Source/Core/Core/IOS/ES/NandUtils.h new file mode 100644 index 0000000000..0cd9363290 --- /dev/null +++ b/Source/Core/Core/IOS/ES/NandUtils.h @@ -0,0 +1,23 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include + +#include "Common/CommonTypes.h" +#include "Core/IOS/ES/Formats.h" + +namespace IOS +{ +namespace ES +{ +// Get installed titles (in /title) without checking for TMDs at all. +std::vector GetInstalledTitles(); +// Get titles which are being imported (in /import) without checking for TMDs at all. +std::vector GetTitleImports(); +// Get titles for which there is a ticket (in /ticket). +std::vector GetTitlesWithTickets(); +} // namespace ES +} // namespace IOS diff --git a/Source/Core/Core/IOS/ES/TitleInformation.cpp b/Source/Core/Core/IOS/ES/TitleInformation.cpp index dea38aa386..47f0870973 100644 --- a/Source/Core/Core/IOS/ES/TitleInformation.cpp +++ b/Source/Core/Core/IOS/ES/TitleInformation.cpp @@ -5,7 +5,6 @@ #include "Core/IOS/ES/ES.h" #include -#include #include #include #include @@ -18,6 +17,7 @@ #include "Common/StringUtil.h" #include "Core/HW/Memmap.h" #include "Core/IOS/ES/Formats.h" +#include "Core/IOS/ES/NandUtils.h" #include "DiscIO/NANDContentLoader.h" namespace IOS @@ -132,92 +132,6 @@ IPCCommandResult ES::GetTMDStoredContents(const IOCtlVRequest& request) return GetStoredContents(IOS::ES::TMDReader{std::move(tmd_bytes)}, request); } -static bool IsValidPartOfTitleID(const std::string& string) -{ - if (string.length() != 8) - return false; - return std::all_of(string.begin(), string.end(), - [](const auto character) { return std::isxdigit(character) != 0; }); -} - -// Returns a vector of title IDs. IOS does not check the TMD at all here. -static std::vector GetInstalledTitles() -{ - const std::string titles_dir = Common::RootUserPath(Common::FROM_SESSION_ROOT) + "/title"; - if (!File::IsDirectory(titles_dir)) - { - ERROR_LOG(IOS_ES, "/title is not a directory"); - return {}; - } - - std::vector title_ids; - - // The /title directory contains one directory per title type, and each of them contains - // a directory per title (where the name is the low 32 bits of the title ID in %08x format). - const auto entries = File::ScanDirectoryTree(titles_dir, true); - for (const File::FSTEntry& title_type : entries.children) - { - if (!title_type.isDirectory || !IsValidPartOfTitleID(title_type.virtualName)) - continue; - - if (title_type.children.empty()) - continue; - - for (const File::FSTEntry& title_identifier : title_type.children) - { - if (!title_identifier.isDirectory || !IsValidPartOfTitleID(title_identifier.virtualName)) - continue; - - const u32 type = std::stoul(title_type.virtualName, nullptr, 16); - const u32 identifier = std::stoul(title_identifier.virtualName, nullptr, 16); - title_ids.push_back(static_cast(type) << 32 | identifier); - } - } - - return title_ids; -} - -// Returns a vector of title IDs for which there is a ticket. -static std::vector GetTitlesWithTickets() -{ - const std::string titles_dir = Common::RootUserPath(Common::FROM_SESSION_ROOT) + "/ticket"; - if (!File::IsDirectory(titles_dir)) - { - ERROR_LOG(IOS_ES, "/ticket is not a directory"); - return {}; - } - - std::vector title_ids; - - // The /ticket directory contains one directory per title type, and each of them contains - // one ticket per title (where the name is the low 32 bits of the title ID in %08x format). - const auto entries = File::ScanDirectoryTree(titles_dir, true); - for (const File::FSTEntry& title_type : entries.children) - { - if (!title_type.isDirectory || !IsValidPartOfTitleID(title_type.virtualName)) - continue; - - if (title_type.children.empty()) - continue; - - for (const File::FSTEntry& ticket : title_type.children) - { - const std::string name_without_ext = ticket.virtualName.substr(0, 8); - if (ticket.isDirectory || !IsValidPartOfTitleID(name_without_ext) || - name_without_ext + ".tik" != ticket.virtualName) - { - continue; - } - - const u32 type = std::stoul(title_type.virtualName, nullptr, 16); - const u32 identifier = std::stoul(name_without_ext, nullptr, 16); - title_ids.push_back(static_cast(type) << 32 | identifier); - } - } - - return title_ids; -} - IPCCommandResult ES::GetTitleCount(const std::vector& titles, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(0, 1) || request.io_vectors[0].size != 4) @@ -244,14 +158,14 @@ IPCCommandResult ES::GetTitles(const std::vector& titles, const IOCtlVReque IPCCommandResult ES::GetTitleCount(const IOCtlVRequest& request) { - const std::vector titles = GetInstalledTitles(); + const std::vector titles = IOS::ES::GetInstalledTitles(); INFO_LOG(IOS_ES, "GetTitleCount: %zu titles", titles.size()); return GetTitleCount(titles, request); } IPCCommandResult ES::GetTitles(const IOCtlVRequest& request) { - return GetTitles(GetInstalledTitles(), request); + return GetTitles(IOS::ES::GetInstalledTitles(), request); } IPCCommandResult ES::GetStoredTMDSize(const IOCtlVRequest& request) @@ -300,14 +214,14 @@ IPCCommandResult ES::GetStoredTMD(const IOCtlVRequest& request) IPCCommandResult ES::GetOwnedTitleCount(const IOCtlVRequest& request) { - const std::vector titles = GetTitlesWithTickets(); + const std::vector titles = IOS::ES::GetTitlesWithTickets(); INFO_LOG(IOS_ES, "GetOwnedTitleCount: %zu titles", titles.size()); return GetTitleCount(titles, request); } IPCCommandResult ES::GetOwnedTitles(const IOCtlVRequest& request) { - return GetTitles(GetTitlesWithTickets(), request); + return GetTitles(IOS::ES::GetTitlesWithTickets(), request); } IPCCommandResult ES::GetBoot2Version(const IOCtlVRequest& request) diff --git a/Source/Core/DiscIO/NANDContentLoader.h b/Source/Core/DiscIO/NANDContentLoader.h index edeea6431a..5b428bf5b4 100644 --- a/Source/Core/DiscIO/NANDContentLoader.h +++ b/Source/Core/DiscIO/NANDContentLoader.h @@ -23,6 +23,7 @@ namespace DiscIO { enum class Region; +// TODO: move some of these to Core/IOS/ES. bool AddTicket(const IOS::ES::TicketReader& signed_ticket); IOS::ES::TicketReader FindSignedTicket(u64 title_id); From 0ed8d681929f4c7ce12377643d1481b9965105fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sun, 12 Mar 2017 21:05:13 +0100 Subject: [PATCH 2/4] IOS/ES: Add functions to get TMDs --- Source/Core/Core/IOS/ES/NandUtils.cpp | 23 +++++++++++++++++++++++ Source/Core/Core/IOS/ES/NandUtils.h | 3 +++ 2 files changed, 26 insertions(+) diff --git a/Source/Core/Core/IOS/ES/NandUtils.cpp b/Source/Core/Core/IOS/ES/NandUtils.cpp index 15a313c94d..6f4df68a21 100644 --- a/Source/Core/Core/IOS/ES/NandUtils.cpp +++ b/Source/Core/Core/IOS/ES/NandUtils.cpp @@ -18,6 +18,29 @@ namespace IOS { namespace ES { +static TMDReader FindTMD(u64 title_id, const std::string& tmd_path) +{ + File::IOFile file(tmd_path, "rb"); + if (!file) + return {}; + + std::vector tmd_bytes(file.GetSize()); + if (!file.ReadBytes(tmd_bytes.data(), tmd_bytes.size())) + return {}; + + return TMDReader{std::move(tmd_bytes)}; +} + +TMDReader FindImportTMD(u64 title_id) +{ + return FindTMD(title_id, Common::GetImportTitlePath(title_id) + "/content/title.tmd"); +} + +TMDReader FindInstalledTMD(u64 title_id) +{ + return FindTMD(title_id, Common::GetTMDFileName(title_id, Common::FROM_SESSION_ROOT)); +} + static bool IsValidPartOfTitleID(const std::string& string) { if (string.length() != 8) diff --git a/Source/Core/Core/IOS/ES/NandUtils.h b/Source/Core/Core/IOS/ES/NandUtils.h index 0cd9363290..ff681ea7fc 100644 --- a/Source/Core/Core/IOS/ES/NandUtils.h +++ b/Source/Core/Core/IOS/ES/NandUtils.h @@ -13,6 +13,9 @@ namespace IOS { namespace ES { +TMDReader FindImportTMD(u64 title_id); +TMDReader FindInstalledTMD(u64 title_id); + // Get installed titles (in /title) without checking for TMDs at all. std::vector GetInstalledTitles(); // Get titles which are being imported (in /import) without checking for TMDs at all. From 89841125014b0e6008c3e8d8de14d11b59f6e557 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sun, 12 Mar 2017 21:12:19 +0100 Subject: [PATCH 3/4] IOS/ES: Move GetStoredContentsFromTMD to NandUtils --- Source/Core/Core/IOS/ES/NandUtils.cpp | 28 ++++++++++++++++++ Source/Core/Core/IOS/ES/NandUtils.h | 6 +++- Source/Core/Core/IOS/ES/TitleInformation.cpp | 31 ++------------------ 3 files changed, 35 insertions(+), 30 deletions(-) diff --git a/Source/Core/Core/IOS/ES/NandUtils.cpp b/Source/Core/Core/IOS/ES/NandUtils.cpp index 6f4df68a21..b30609a255 100644 --- a/Source/Core/Core/IOS/ES/NandUtils.cpp +++ b/Source/Core/Core/IOS/ES/NandUtils.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -11,8 +12,10 @@ #include "Common/FileUtil.h" #include "Common/Logging/Log.h" #include "Common/NandPaths.h" +#include "Common/StringUtil.h" #include "Core/IOS/ES/Formats.h" #include "Core/IOS/ES/NandUtils.h" +#include "DiscIO/NANDContentLoader.h" namespace IOS { @@ -133,5 +136,30 @@ std::vector GetTitlesWithTickets() return title_ids; } + +std::vector GetStoredContentsFromTMD(const TMDReader& tmd) +{ + if (!tmd.IsValid()) + return {}; + + const DiscIO::CSharedContent shared{Common::FROM_SESSION_ROOT}; + const std::vector contents = tmd.GetContents(); + + std::vector stored_contents; + + std::copy_if(contents.begin(), contents.end(), std::back_inserter(stored_contents), + [&tmd, &shared](const auto& content) { + if (content.IsShared()) + { + const std::string path = shared.GetFilenameFromSHA1(content.sha1.data()); + return path != "unk" && File::Exists(path); + } + return File::Exists( + Common::GetTitleContentPath(tmd.GetTitleId(), Common::FROM_SESSION_ROOT) + + StringFromFormat("%08x.app", content.id)); + }); + + return stored_contents; +} } // namespace ES } // namespace IOS diff --git a/Source/Core/Core/IOS/ES/NandUtils.h b/Source/Core/Core/IOS/ES/NandUtils.h index ff681ea7fc..d9df9a74f2 100644 --- a/Source/Core/Core/IOS/ES/NandUtils.h +++ b/Source/Core/Core/IOS/ES/NandUtils.h @@ -7,12 +7,14 @@ #include #include "Common/CommonTypes.h" -#include "Core/IOS/ES/Formats.h" namespace IOS { namespace ES { +struct Content; +class TMDReader; + TMDReader FindImportTMD(u64 title_id); TMDReader FindInstalledTMD(u64 title_id); @@ -22,5 +24,7 @@ std::vector GetInstalledTitles(); std::vector GetTitleImports(); // Get titles for which there is a ticket (in /ticket). std::vector GetTitlesWithTickets(); + +std::vector GetStoredContentsFromTMD(const TMDReader& tmd); } // namespace ES } // namespace IOS diff --git a/Source/Core/Core/IOS/ES/TitleInformation.cpp b/Source/Core/Core/IOS/ES/TitleInformation.cpp index 47f0870973..a608764e31 100644 --- a/Source/Core/Core/IOS/ES/TitleInformation.cpp +++ b/Source/Core/Core/IOS/ES/TitleInformation.cpp @@ -4,10 +4,8 @@ #include "Core/IOS/ES/ES.h" -#include #include #include -#include #include #include @@ -26,31 +24,6 @@ namespace HLE { namespace Device { -static std::vector GetStoredContentsFromTMD(const IOS::ES::TMDReader& tmd) -{ - if (!tmd.IsValid()) - return {}; - - const DiscIO::CSharedContent shared{Common::FROM_SESSION_ROOT}; - const std::vector contents = tmd.GetContents(); - - std::vector stored_contents; - - std::copy_if(contents.begin(), contents.end(), std::back_inserter(stored_contents), - [&tmd, &shared](const auto& content) { - if (content.IsShared()) - { - const std::string path = shared.GetFilenameFromSHA1(content.sha1.data()); - return path != "unk" && File::Exists(path); - } - return File::Exists( - Common::GetTitleContentPath(tmd.GetTitleId(), Common::FROM_SESSION_ROOT) + - StringFromFormat("%08x.app", content.id)); - }); - - return stored_contents; -} - // Used by the GetStoredContents ioctlvs. This assumes that the first output vector // is used for the content count (u32). IPCCommandResult ES::GetStoredContentsCount(const IOS::ES::TMDReader& tmd, @@ -59,7 +32,7 @@ IPCCommandResult ES::GetStoredContentsCount(const IOS::ES::TMDReader& tmd, if (request.io_vectors[0].size != sizeof(u32) || !tmd.IsValid()) return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT); - const u16 num_contents = static_cast(GetStoredContentsFromTMD(tmd).size()); + const u16 num_contents = static_cast(IOS::ES::GetStoredContentsFromTMD(tmd).size()); Memory::Write_U32(num_contents, request.io_vectors[0].address); INFO_LOG(IOS_ES, "GetStoredContentsCount (0x%x): %u content(s) for %016" PRIx64, request.request, @@ -80,7 +53,7 @@ IPCCommandResult ES::GetStoredContents(const IOS::ES::TMDReader& tmd, const IOCt return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT); } - const auto contents = GetStoredContentsFromTMD(tmd); + const auto contents = IOS::ES::GetStoredContentsFromTMD(tmd); const u32 max_content_count = Memory::Read_U32(request.in_vectors[1].address); for (u32 i = 0; i < std::min(static_cast(contents.size()), max_content_count); ++i) Memory::Write_U32(contents[i].id, request.io_vectors[0].address + i * sizeof(u32)); From 98e27ad9cb3cacc678f703b3cdd44c74ad77c2c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Fri, 17 Mar 2017 18:59:04 +0100 Subject: [PATCH 4/4] IOS/ES: Use FindInstalledTMD instead of content loader Proper semantics. IOS only cares about the TMD and nothing else, so we should use FindInstalledTMD, instead of reading/parsing/decrypting a bunch of useless stuff, which is slow *and* causes issues because of the cache. --- Source/Core/Core/IOS/ES/TitleInformation.cpp | 45 +++++++++----------- Source/Core/Core/IOS/ES/TitleManagement.cpp | 9 ++-- Source/Core/Core/IOS/ES/Views.cpp | 22 ++++------ 3 files changed, 34 insertions(+), 42 deletions(-) diff --git a/Source/Core/Core/IOS/ES/TitleInformation.cpp b/Source/Core/Core/IOS/ES/TitleInformation.cpp index a608764e31..a70ac5b247 100644 --- a/Source/Core/Core/IOS/ES/TitleInformation.cpp +++ b/Source/Core/Core/IOS/ES/TitleInformation.cpp @@ -67,10 +67,10 @@ IPCCommandResult ES::GetStoredContentsCount(const IOCtlVRequest& request) return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT); const u64 title_id = Memory::Read_U64(request.in_vectors[0].address); - const DiscIO::CNANDContentLoader& content_loader = AccessContentDevice(title_id); - if (!content_loader.IsValid()) - return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT); - return GetStoredContentsCount(content_loader.GetTMD(), request); + const IOS::ES::TMDReader tmd = IOS::ES::FindInstalledTMD(title_id); + if (!tmd.IsValid()) + return GetDefaultReply(FS_ENOENT); + return GetStoredContentsCount(tmd, request); } IPCCommandResult ES::GetStoredContents(const IOCtlVRequest& request) @@ -79,10 +79,10 @@ IPCCommandResult ES::GetStoredContents(const IOCtlVRequest& request) return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT); const u64 title_id = Memory::Read_U64(request.in_vectors[0].address); - const DiscIO::CNANDContentLoader& content_loader = AccessContentDevice(title_id); - if (!content_loader.IsValid()) - return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT); - return GetStoredContents(content_loader.GetTMD(), request); + const IOS::ES::TMDReader tmd = IOS::ES::FindInstalledTMD(title_id); + if (!tmd.IsValid()) + return GetDefaultReply(FS_ENOENT); + return GetStoredContents(tmd, request); } IPCCommandResult ES::GetTMDStoredContentsCount(const IOCtlVRequest& request) @@ -146,17 +146,15 @@ IPCCommandResult ES::GetStoredTMDSize(const IOCtlVRequest& request) if (!request.HasNumberOfValidVectors(1, 1)) return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT); - u64 TitleID = Memory::Read_U64(request.in_vectors[0].address); - const DiscIO::CNANDContentLoader& Loader = AccessContentDevice(TitleID); - - if (!Loader.IsValid() || !Loader.GetTMD().IsValid()) + const u64 title_id = Memory::Read_U64(request.in_vectors[0].address); + const IOS::ES::TMDReader tmd = IOS::ES::FindInstalledTMD(title_id); + if (!tmd.IsValid()) return GetDefaultReply(FS_ENOENT); - const u32 tmd_size = static_cast(Loader.GetTMD().GetRawTMD().size()); + const u32 tmd_size = static_cast(tmd.GetRawTMD().size()); Memory::Write_U32(tmd_size, request.io_vectors[0].address); - INFO_LOG(IOS_ES, "IOCTL_ES_GETSTOREDTMDSIZE: title: %08x/%08x (view size %i)", - (u32)(TitleID >> 32), (u32)TitleID, tmd_size); + INFO_LOG(IOS_ES, "GetStoredTMDSize: %u bytes for %016" PRIx64, tmd_size, title_id); return GetDefaultReply(IPC_SUCCESS); } @@ -166,22 +164,21 @@ IPCCommandResult ES::GetStoredTMD(const IOCtlVRequest& request) if (!request.HasNumberOfValidVectors(2, 1)) return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT); - u64 TitleID = Memory::Read_U64(request.in_vectors[0].address); - // TODO: actually use this param in when writing to the outbuffer :/ - const u32 MaxCount = Memory::Read_U32(request.in_vectors[1].address); - const DiscIO::CNANDContentLoader& Loader = AccessContentDevice(TitleID); - - if (!Loader.IsValid() || !Loader.GetTMD().IsValid()) + const u64 title_id = Memory::Read_U64(request.in_vectors[0].address); + const IOS::ES::TMDReader tmd = IOS::ES::FindInstalledTMD(title_id); + if (!tmd.IsValid()) return GetDefaultReply(FS_ENOENT); - const std::vector raw_tmd = Loader.GetTMD().GetRawTMD(); + // TODO: actually use this param in when writing to the outbuffer :/ + const u32 MaxCount = Memory::Read_U32(request.in_vectors[1].address); + + const std::vector raw_tmd = tmd.GetRawTMD(); if (raw_tmd.size() != request.io_vectors[0].size) return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT); Memory::CopyToEmu(request.io_vectors[0].address, raw_tmd.data(), raw_tmd.size()); - INFO_LOG(IOS_ES, "IOCTL_ES_GETSTOREDTMD: title: %08x/%08x (buffer size: %i)", - (u32)(TitleID >> 32), (u32)TitleID, MaxCount); + INFO_LOG(IOS_ES, "GetStoredTMD: title %016" PRIx64 " (buffer size: %u)", title_id, MaxCount); return GetDefaultReply(IPC_SUCCESS); } diff --git a/Source/Core/Core/IOS/ES/TitleManagement.cpp b/Source/Core/Core/IOS/ES/TitleManagement.cpp index 5a275fa954..dd327ee1cb 100644 --- a/Source/Core/Core/IOS/ES/TitleManagement.cpp +++ b/Source/Core/Core/IOS/ES/TitleManagement.cpp @@ -19,6 +19,7 @@ #include "Common/StringUtil.h" #include "Core/HW/Memmap.h" #include "Core/IOS/ES/Formats.h" +#include "Core/IOS/ES/NandUtils.h" #include "Core/ec_wii.h" #include "DiscIO/NANDContentLoader.h" @@ -403,13 +404,11 @@ IPCCommandResult ES::ExportTitleInit(const IOCtlVRequest& request) if (m_export_title_context.valid) return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT); - const auto& content_loader = AccessContentDevice(Memory::Read_U64(request.in_vectors[0].address)); - if (!content_loader.IsValid()) + const auto tmd = IOS::ES::FindInstalledTMD(Memory::Read_U64(request.in_vectors[0].address)); + if (!tmd.IsValid()) return GetDefaultReply(FS_ENOENT); - if (!content_loader.GetTMD().IsValid()) - return GetDefaultReply(ES_INVALID_TMD); - m_export_title_context.tmd = content_loader.GetTMD(); + m_export_title_context.tmd = tmd; const auto ticket = DiscIO::FindSignedTicket(m_export_title_context.tmd.GetTitleId()); if (!ticket.IsValid()) diff --git a/Source/Core/Core/IOS/ES/Views.cpp b/Source/Core/Core/IOS/ES/Views.cpp index 3e18385078..e5b6bdb75a 100644 --- a/Source/Core/Core/IOS/ES/Views.cpp +++ b/Source/Core/Core/IOS/ES/Views.cpp @@ -14,6 +14,7 @@ #include "Core/ConfigManager.h" #include "Core/HW/Memmap.h" #include "Core/IOS/ES/Formats.h" +#include "Core/IOS/ES/NandUtils.h" #include "DiscIO/NANDContentLoader.h" namespace IOS @@ -96,16 +97,15 @@ IPCCommandResult ES::GetTMDViewSize(const IOCtlVRequest& request) u64 TitleID = Memory::Read_U64(request.in_vectors[0].address); - const DiscIO::CNANDContentLoader& Loader = AccessContentDevice(TitleID); + const IOS::ES::TMDReader tmd = IOS::ES::FindInstalledTMD(TitleID); - if (!Loader.IsValid()) + if (!tmd.IsValid()) return GetDefaultReply(FS_ENOENT); - const u32 view_size = static_cast(Loader.GetTMD().GetRawView().size()); + const u32 view_size = static_cast(tmd.GetRawView().size()); Memory::Write_U32(view_size, request.io_vectors[0].address); - INFO_LOG(IOS_ES, "IOCTL_ES_GETTMDVIEWCNT: title: %08x/%08x (view size %i)", (u32)(TitleID >> 32), - (u32)TitleID, view_size); + INFO_LOG(IOS_ES, "GetTMDViewSize: %u bytes for title %016" PRIx64, view_size, TitleID); return GetDefaultReply(IPC_SUCCESS); } @@ -117,22 +117,18 @@ IPCCommandResult ES::GetTMDViews(const IOCtlVRequest& request) u64 TitleID = Memory::Read_U64(request.in_vectors[0].address); u32 MaxCount = Memory::Read_U32(request.in_vectors[1].address); - const DiscIO::CNANDContentLoader& Loader = AccessContentDevice(TitleID); + const IOS::ES::TMDReader tmd = IOS::ES::FindInstalledTMD(TitleID); - INFO_LOG(IOS_ES, "IOCTL_ES_GETTMDVIEWCNT: title: %08x/%08x buffer size: %i", - (u32)(TitleID >> 32), (u32)TitleID, MaxCount); - - if (!Loader.IsValid()) + if (!tmd.IsValid()) return GetDefaultReply(FS_ENOENT); - const std::vector raw_view = Loader.GetTMD().GetRawView(); + const std::vector raw_view = tmd.GetRawView(); if (raw_view.size() != request.io_vectors[0].size) return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT); Memory::CopyToEmu(request.io_vectors[0].address, raw_view.data(), raw_view.size()); - INFO_LOG(IOS_ES, "IOCTL_ES_GETTMDVIEWS: title: %08x/%08x (buffer size: %i)", (u32)(TitleID >> 32), - (u32)TitleID, MaxCount); + INFO_LOG(IOS_ES, "GetTMDView: %u bytes for title %016" PRIx64, MaxCount, TitleID); return GetDefaultReply(IPC_SUCCESS); }