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.
This commit is contained in:
Léo Lam
2017-03-13 12:33:50 +01:00
parent 0b6170cc33
commit 7b17163a7a
7 changed files with 176 additions and 186 deletions

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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(

View File

@ -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
{