summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorLéo Lam <leo@innovatetechnologi.es>2017-03-13 12:33:50 +0100
committerLéo Lam <leo@innovatetechnologi.es>2017-03-26 12:16:28 +0200
commit7b17163a7adf398c948fbcd9e6ff078e616c8edb (patch)
treeb45798a2260418dee64ac9c8c93e2325e6db729c /Source/Core
parent0b6170cc3318bd496246a5c52e8162137fdae252 (diff)
IOS/ES: Move shared content map, uid.sys code
These are all specific to ES and belong there. The SharedContentMap and UIDSys classes were also modernised.
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/IOS/ES/ES.cpp2
-rw-r--r--Source/Core/Core/IOS/ES/Formats.cpp130
-rw-r--r--Source/Core/Core/IOS/ES/Formats.h32
-rw-r--r--Source/Core/Core/IOS/ES/NandUtils.cpp5
-rw-r--r--Source/Core/Core/IOS/ES/TitleManagement.cpp8
-rw-r--r--Source/Core/DiscIO/NANDContentLoader.cpp139
-rw-r--r--Source/Core/DiscIO/NANDContentLoader.h46
7 files changed, 176 insertions, 186 deletions
diff --git a/Source/Core/Core/IOS/ES/ES.cpp b/Source/Core/Core/IOS/ES/ES.cpp
index 4ef6020020..5f2eb983ec 100644
--- a/Source/Core/Core/IOS/ES/ES.cpp
+++ b/Source/Core/Core/IOS/ES/ES.cpp
@@ -494,7 +494,7 @@ s32 ES::DIVerify(const IOS::ES::TMDReader& tmd, const IOS::ES::TicketReader& tic
if (!tmd_file.WriteBytes(tmd_bytes.data(), tmd_bytes.size()))
ERROR_LOG(IOS_ES, "DIVerify failed to write disc TMD to NAND.");
}
- DiscIO::cUIDsys uid_sys{Common::FromWhichRoot::FROM_SESSION_ROOT};
+ IOS::ES::UIDSys uid_sys{Common::FromWhichRoot::FROM_SESSION_ROOT};
uid_sys.AddTitle(tmd.GetTitleId());
// DI_VERIFY writes to title.tmd, which is read and cached inside the NAND Content Manager.
// clear the cache to avoid content access mismatches.
diff --git a/Source/Core/Core/IOS/ES/Formats.cpp b/Source/Core/Core/IOS/ES/Formats.cpp
index ab24da1002..bab82dada1 100644
--- a/Source/Core/Core/IOS/ES/Formats.cpp
+++ b/Source/Core/Core/IOS/ES/Formats.cpp
@@ -13,9 +13,12 @@
#include <utility>
#include <vector>
+#include "Common/Assert.h"
#include "Common/ChunkFile.h"
#include "Common/CommonTypes.h"
#include "Common/Crypto/AES.h"
+#include "Common/FileUtil.h"
+#include "Common/Logging/Log.h"
#include "Common/StringUtil.h"
#include "Common/Swap.h"
#include "Core/ec_wii.h"
@@ -345,5 +348,132 @@ s32 TicketReader::Unpersonalise()
std::copy(key.cbegin(), key.cend(), ticket_begin + offsetof(Ticket, title_key));
return IOSC_OK;
}
+
+struct SharedContentMap::Entry
+{
+ // ID string
+ std::array<u8, 8> id;
+ // Binary SHA1 hash
+ std::array<u8, 20> sha1;
+};
+
+SharedContentMap::SharedContentMap(Common::FromWhichRoot root) : m_root(root)
+{
+ static_assert(sizeof(Entry) == 28, "SharedContentMap::Entry has the wrong size");
+
+ m_file_path = Common::RootUserPath(root) + "/shared1/content.map";
+
+ File::IOFile file(m_file_path, "rb");
+ Entry entry;
+ while (file.ReadArray(&entry, 1))
+ {
+ m_entries.push_back(entry);
+ m_last_id++;
+ }
+}
+
+SharedContentMap::~SharedContentMap() = default;
+
+std::string SharedContentMap::GetFilenameFromSHA1(const std::array<u8, 20>& sha1) const
+{
+ const auto it = std::find_if(m_entries.begin(), m_entries.end(),
+ [&sha1](const auto& entry) { return entry.sha1 == sha1; });
+ if (it == m_entries.end())
+ return "unk";
+
+ const std::string id_string(it->id.begin(), it->id.end());
+ return Common::RootUserPath(m_root) + StringFromFormat("/shared1/%s.app", id_string.c_str());
+}
+
+std::string SharedContentMap::AddSharedContent(const std::array<u8, 20>& sha1)
+{
+ std::string filename = GetFilenameFromSHA1(sha1);
+ if (filename != "unk")
+ return filename;
+
+ const std::string id = StringFromFormat("%08x", m_last_id);
+ Entry entry;
+ std::copy(id.cbegin(), id.cend(), entry.id.begin());
+ entry.sha1 = sha1;
+ m_entries.push_back(entry);
+
+ File::CreateFullPath(m_file_path);
+
+ File::IOFile file(m_file_path, "ab");
+ file.WriteArray(&entry, 1);
+
+ filename = Common::RootUserPath(m_root) + StringFromFormat("/shared1/%s.app", id.c_str());
+ m_last_id++;
+ return filename;
+}
+
+static std::pair<u32, u64> ReadUidSysEntry(File::IOFile& file)
+{
+ u64 title_id = 0;
+ if (!file.ReadBytes(&title_id, sizeof(title_id)))
+ return {};
+
+ u32 uid = 0;
+ if (!file.ReadBytes(&uid, sizeof(uid)))
+ return {};
+
+ return {Common::swap32(uid), Common::swap64(title_id)};
+}
+
+UIDSys::UIDSys(Common::FromWhichRoot root)
+{
+ m_file_path = Common::RootUserPath(root) + "/sys/uid.sys";
+
+ File::IOFile file(m_file_path, "rb");
+ while (true)
+ {
+ const std::pair<u32, u64> entry = ReadUidSysEntry(file);
+ if (!entry.first && !entry.second)
+ break;
+
+ m_entries.insert(std::move(entry));
+ }
+
+ if (m_entries.empty())
+ {
+ AddTitle(TITLEID_SYSMENU);
+ }
+}
+
+u32 UIDSys::GetUIDFromTitle(u64 title_id)
+{
+ const auto it = std::find_if(m_entries.begin(), m_entries.end(),
+ [title_id](const auto& entry) { return entry.second == title_id; });
+ return (it == m_entries.end()) ? 0 : it->first;
+}
+
+u32 UIDSys::GetNextUID() const
+{
+ if (m_entries.empty())
+ return 0x00001000;
+ return m_entries.rbegin()->first + 1;
+}
+
+void UIDSys::AddTitle(u64 title_id)
+{
+ if (GetUIDFromTitle(title_id))
+ {
+ INFO_LOG(IOS_ES, "Title %016" PRIx64 " already exists in uid.sys", title_id);
+ return;
+ }
+
+ u32 uid = GetNextUID();
+ m_entries.insert({uid, title_id});
+
+ // Byte swap before writing.
+ title_id = Common::swap64(title_id);
+ uid = Common::swap32(uid);
+
+ File::CreateFullPath(m_file_path);
+ File::IOFile file(m_file_path, "ab");
+
+ if (!file.WriteBytes(&title_id, sizeof(title_id)) || !file.WriteBytes(&uid, sizeof(uid)))
+ ERROR_LOG(IOS_ES, "Failed to write to /sys/uid.sys");
+}
} // namespace ES
} // namespace IOS
diff --git a/Source/Core/Core/IOS/ES/Formats.h b/Source/Core/Core/IOS/ES/Formats.h
index 740c2f7646..a994ff8bc2 100644
--- a/Source/Core/Core/IOS/ES/Formats.h
+++ b/Source/Core/Core/IOS/ES/Formats.h
@@ -13,6 +13,7 @@
#include "Common/ChunkFile.h"
#include "Common/CommonTypes.h"
+#include "Common/NandPaths.h"
#include "DiscIO/Enums.h"
namespace IOS
@@ -194,5 +195,36 @@ public:
private:
std::vector<u8> m_bytes;
};
+
+class SharedContentMap final
+{
+public:
+ explicit SharedContentMap(Common::FromWhichRoot root);
+ ~SharedContentMap();
+
+ std::string GetFilenameFromSHA1(const std::array<u8, 20>& sha1) const;
+ std::string AddSharedContent(const std::array<u8, 20>& sha1);
+
+private:
+ struct Entry;
+ Common::FromWhichRoot m_root;
+ u32 m_last_id = 0;
+ std::string m_file_path;
+ std::vector<Entry> m_entries;
+};
+
+class UIDSys final
+{
+public:
+ explicit UIDSys(Common::FromWhichRoot root);
+
+ u32 GetUIDFromTitle(u64 title_id);
+ void AddTitle(u64 title_id);
+ u32 GetNextUID() const;
+
+private:
+ std::string m_file_path;
+ std::map<u32, u64> m_entries;
+};
} // namespace ES
} // namespace IOS
diff --git a/Source/Core/Core/IOS/ES/NandUtils.cpp b/Source/Core/Core/IOS/ES/NandUtils.cpp
index b30609a255..51576d9c4e 100644
--- a/Source/Core/Core/IOS/ES/NandUtils.cpp
+++ b/Source/Core/Core/IOS/ES/NandUtils.cpp
@@ -15,7 +15,6 @@
#include "Common/StringUtil.h"
#include "Core/IOS/ES/Formats.h"
#include "Core/IOS/ES/NandUtils.h"
-#include "DiscIO/NANDContentLoader.h"
namespace IOS
{
@@ -142,7 +141,7 @@ std::vector<Content> GetStoredContentsFromTMD(const TMDReader& tmd)
if (!tmd.IsValid())
return {};
- const DiscIO::CSharedContent shared{Common::FROM_SESSION_ROOT};
+ const IOS::ES::SharedContentMap shared{Common::FROM_SESSION_ROOT};
const std::vector<Content> contents = tmd.GetContents();
std::vector<Content> stored_contents;
@@ -151,7 +150,7 @@ std::vector<Content> GetStoredContentsFromTMD(const TMDReader& tmd)
[&tmd, &shared](const auto& content) {
if (content.IsShared())
{
- const std::string path = shared.GetFilenameFromSHA1(content.sha1.data());
+ const std::string path = shared.GetFilenameFromSHA1(content.sha1);
return path != "unk" && File::Exists(path);
}
return File::Exists(
diff --git a/Source/Core/Core/IOS/ES/TitleManagement.cpp b/Source/Core/Core/IOS/ES/TitleManagement.cpp
index dd327ee1cb..eaeee998e5 100644
--- a/Source/Core/Core/IOS/ES/TitleManagement.cpp
+++ b/Source/Core/Core/IOS/ES/TitleManagement.cpp
@@ -102,7 +102,7 @@ IPCCommandResult ES::AddTMD(const IOCtlVRequest& request)
if (!m_addtitle_tmd.IsValid())
return GetDefaultReply(ES_INVALID_TMD);
- DiscIO::cUIDsys uid_sys{Common::FROM_CONFIGURED_ROOT};
+ IOS::ES::UIDSys uid_sys{Common::FROM_CONFIGURED_ROOT};
uid_sys.AddTitle(m_addtitle_tmd.GetTitleId());
return GetDefaultReply(IPC_SUCCESS);
@@ -124,7 +124,7 @@ IPCCommandResult ES::AddTitleStart(const IOCtlVRequest& request)
return GetDefaultReply(ES_INVALID_TMD);
}
- DiscIO::cUIDsys uid_sys{Common::FROM_CONFIGURED_ROOT};
+ IOS::ES::UIDSys uid_sys{Common::FROM_CONFIGURED_ROOT};
uid_sys.AddTitle(m_addtitle_tmd.GetTitleId());
// TODO: check and use the other vectors.
@@ -281,8 +281,8 @@ IPCCommandResult ES::AddTitleFinish(const IOCtlVRequest& request)
std::string content_path;
if (content_info.IsShared())
{
- DiscIO::CSharedContent shared_content{Common::FROM_SESSION_ROOT};
- content_path = shared_content.AddSharedContent(content_info.sha1.data());
+ IOS::ES::SharedContentMap shared_content{Common::FROM_SESSION_ROOT};
+ content_path = shared_content.AddSharedContent(content_info.sha1);
}
else
{
diff --git a/Source/Core/DiscIO/NANDContentLoader.cpp b/Source/Core/DiscIO/NANDContentLoader.cpp
index 559fd86eb2..58594d6fc5 100644
--- a/Source/Core/DiscIO/NANDContentLoader.cpp
+++ b/Source/Core/DiscIO/NANDContentLoader.cpp
@@ -25,6 +25,8 @@
#include "Common/NandPaths.h"
#include "Common/StringUtil.h"
#include "Common/Swap.h"
+// TODO: kill this dependency.
+#include "Core/IOS/ES/Formats.h"
#include "DiscIO/WiiWad.h"
@@ -32,61 +34,6 @@ namespace DiscIO
{
CNANDContentData::~CNANDContentData() = default;
-CSharedContent::CSharedContent(Common::FromWhichRoot root) : m_root(root)
-{
- m_Elements.clear();
- m_LastID = 0;
- m_ContentMap = Common::RootUserPath(root) + "/shared1/content.map";
-
- File::IOFile pFile(m_ContentMap, "rb");
- SElement Element;
- while (pFile.ReadArray(&Element, 1))
- {
- m_Elements.push_back(Element);
- m_LastID++;
- }
-}
-
-std::string CSharedContent::GetFilenameFromSHA1(const u8* hash) const
-{
- for (const auto& Element : m_Elements)
- {
- if (memcmp(hash, Element.SHA1Hash, 20) == 0)
- {
- return StringFromFormat(
- "%s/shared1/%c%c%c%c%c%c%c%c.app", Common::RootUserPath(m_root).c_str(),
- Element.FileName[0], Element.FileName[1], Element.FileName[2], Element.FileName[3],
- Element.FileName[4], Element.FileName[5], Element.FileName[6], Element.FileName[7]);
- }
- }
- return "unk";
-}
-
-std::string CSharedContent::AddSharedContent(const u8* hash)
-{
- std::string filename = GetFilenameFromSHA1(hash);
-
- if (strcasecmp(filename.c_str(), "unk") == 0)
- {
- std::string id = StringFromFormat("%08x", m_LastID);
- SElement Element;
- memcpy(Element.FileName, id.c_str(), 8);
- memcpy(Element.SHA1Hash, hash, 20);
- m_Elements.push_back(Element);
-
- File::CreateFullPath(m_ContentMap);
-
- File::IOFile pFile(m_ContentMap, "ab");
- pFile.WriteArray(&Element, 1);
-
- filename =
- StringFromFormat("%s/shared1/%s.app", Common::RootUserPath(m_root).c_str(), id.c_str());
- m_LastID++;
- }
-
- return filename;
-}
-
CNANDContentDataFile::CNANDContentDataFile(const std::string& filename) : m_filename{filename}
{
}
@@ -238,7 +185,7 @@ void CNANDContentLoader::InitializeContentEntries(const std::vector<u8>& data_ap
u32 data_app_offset = 0;
const std::vector<u8> title_key = m_ticket.GetTitleKey();
- CSharedContent shared_content{Common::FromWhichRoot::FROM_SESSION_ROOT};
+ IOS::ES::SharedContentMap shared_content{Common::FromWhichRoot::FROM_SESSION_ROOT};
for (size_t i = 0; i < contents.size(); ++i)
{
@@ -261,7 +208,7 @@ void CNANDContentLoader::InitializeContentEntries(const std::vector<u8>& data_ap
{
std::string filename;
if (content.IsShared())
- filename = shared_content.GetFilenameFromSHA1(content.sha1.data());
+ filename = shared_content.GetFilenameFromSHA1(content.sha1);
else
filename = StringFromFormat("%s/%08x.app", m_Path.c_str(), content.id);
@@ -328,78 +275,6 @@ void CNANDContentLoader::RemoveTitle() const
}
}
-cUIDsys::cUIDsys(Common::FromWhichRoot root)
-{
- m_Elements.clear();
- m_LastUID = 0x00001000;
- m_UidSys = Common::RootUserPath(root) + "/sys/uid.sys";
-
- File::IOFile pFile(m_UidSys, "rb");
- SElement Element;
- while (pFile.ReadArray(&Element, 1))
- {
- *(u32*)&(Element.UID) = Common::swap32(m_LastUID++);
- m_Elements.push_back(Element);
- }
- pFile.Close();
-
- if (m_Elements.empty())
- {
- *(u64*)&(Element.titleID) = Common::swap64(TITLEID_SYSMENU);
- *(u32*)&(Element.UID) = Common::swap32(m_LastUID++);
-
- File::CreateFullPath(m_UidSys);
- pFile.Open(m_UidSys, "wb");
- if (!pFile.WriteArray(&Element, 1))
- ERROR_LOG(DISCIO, "Failed to write to %s", m_UidSys.c_str());
- }
-}
-
-u32 cUIDsys::GetUIDFromTitle(u64 title_id)
-{
- for (auto& Element : m_Elements)
- {
- if (Common::swap64(title_id) == *(u64*)&(Element.titleID))
- {
- return Common::swap32(Element.UID);
- }
- }
- return 0;
-}
-
-void cUIDsys::AddTitle(u64 title_id)
-{
- if (GetUIDFromTitle(title_id))
- {
- INFO_LOG(DISCIO, "Title %08x%08x, already exists in uid.sys", (u32)(title_id >> 32),
- (u32)title_id);
- return;
- }
-
- SElement Element;
- *(u64*)&(Element.titleID) = Common::swap64(title_id);
- *(u32*)&(Element.UID) = Common::swap32(m_LastUID++);
- m_Elements.push_back(Element);
-
- File::CreateFullPath(m_UidSys);
- File::IOFile pFile(m_UidSys, "ab");
-
- if (!pFile.WriteArray(&Element, 1))
- ERROR_LOG(DISCIO, "fwrite failed");
-}
-
-void cUIDsys::GetTitleIDs(std::vector<u64>& title_ids, bool owned)
-{
- for (auto& Element : m_Elements)
- {
- if ((owned &&
- Common::CheckTitleTIK(Common::swap64(Element.titleID), Common::FROM_SESSION_ROOT)) ||
- (!owned &&
- Common::CheckTitleTMD(Common::swap64(Element.titleID), Common::FROM_SESSION_ROOT)))
- title_ids.push_back(Common::swap64(Element.titleID));
- }
-}
-
u64 CNANDContentManager::Install_WiiWAD(const std::string& filename)
{
if (filename.find(".wad") == std::string::npos)
@@ -426,12 +301,12 @@ u64 CNANDContentManager::Install_WiiWAD(const std::string& filename)
const auto& raw_tmd = content_loader.GetTMD().GetRawTMD();
tmd_file.WriteBytes(raw_tmd.data(), raw_tmd.size());
- CSharedContent shared_content{Common::FromWhichRoot::FROM_CONFIGURED_ROOT};
+ IOS::ES::SharedContentMap shared_content{Common::FromWhichRoot::FROM_CONFIGURED_ROOT};
for (const auto& content : content_loader.GetContent())
{
std::string app_filename;
if (content.m_metadata.IsShared())
- app_filename = shared_content.AddSharedContent(content.m_metadata.sha1.data());
+ app_filename = shared_content.AddSharedContent(content.m_metadata.sha1);
else
app_filename = StringFromFormat("%s%08x.app", content_path.c_str(), content.m_metadata.id);
@@ -460,7 +335,7 @@ u64 CNANDContentManager::Install_WiiWAD(const std::string& filename)
return 0;
}
- cUIDsys uid_sys{Common::FromWhichRoot::FROM_CONFIGURED_ROOT};
+ IOS::ES::UIDSys uid_sys{Common::FromWhichRoot::FROM_CONFIGURED_ROOT};
uid_sys.AddTitle(title_id);
ClearCache();
diff --git a/Source/Core/DiscIO/NANDContentLoader.h b/Source/Core/DiscIO/NANDContentLoader.h
index 5b428bf5b4..6e6a5d77e8 100644
--- a/Source/Core/DiscIO/NANDContentLoader.h
+++ b/Source/Core/DiscIO/NANDContentLoader.h
@@ -123,50 +123,4 @@ private:
std::unordered_map<std::string, std::unique_ptr<CNANDContentLoader>> m_map;
};
-
-class CSharedContent final
-{
-public:
- explicit CSharedContent(Common::FromWhichRoot root);
-
- std::string GetFilenameFromSHA1(const u8* hash) const;
- std::string AddSharedContent(const u8* hash);
-
-private:
-#pragma pack(push, 1)
- struct SElement
- {
- u8 FileName[8];
- u8 SHA1Hash[20];
- };
-#pragma pack(pop)
-
- Common::FromWhichRoot m_root;
- u32 m_LastID;
- std::string m_ContentMap;
- std::vector<SElement> m_Elements;
-};
-
-class cUIDsys final
-{
-public:
- explicit cUIDsys(Common::FromWhichRoot root);
-
- u32 GetUIDFromTitle(u64 title_id);
- void AddTitle(u64 title_id);
- void GetTitleIDs(std::vector<u64>& title_ids, bool owned = false);
-
-private:
-#pragma pack(push, 1)
- struct SElement
- {
- u8 titleID[8];
- u8 UID[4];
- };
-#pragma pack(pop)
-
- u32 m_LastUID;
- std::string m_UidSys;
- std::vector<SElement> m_Elements;
-};
}