Skip to content

Commit

Permalink
Merge pull request #9511 from leoetlino/es-content-timings
Browse files Browse the repository at this point in the history
IOS: Emulate FS timings for ES content IPC commands
  • Loading branch information
leoetlino committed Feb 19, 2021
2 parents 9957d6c + e3bf5fc commit 93f9d67
Show file tree
Hide file tree
Showing 13 changed files with 341 additions and 191 deletions.
2 changes: 1 addition & 1 deletion Source/Core/Core/IOS/DI/DI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ void DIDevice::ProcessQueuedIOCtl()
auto finished = StartIOCtl(request);
if (finished)
{
CoreTiming::ScheduleEvent(2700 * SystemTimers::TIMER_RATIO, s_finish_executing_di_command,
CoreTiming::ScheduleEvent(IPC_OVERHEAD_TICKS, s_finish_executing_di_command,
static_cast<u64>(finished.value()));
return;
}
Expand Down
4 changes: 2 additions & 2 deletions Source/Core/Core/IOS/ES/ES.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ IPCReply ESDevice::GetTitleId(const IOCtlVRequest& request)

static bool UpdateUIDAndGID(Kernel& kernel, const ES::TMDReader& tmd)
{
ES::UIDSys uid_sys{kernel.GetFS()};
ES::UIDSys uid_sys{kernel.GetFSDevice()};
const u64 title_id = tmd.GetTitleId();
const u32 uid = uid_sys.GetOrInsertUIDForTitle(title_id);
if (uid == 0)
Expand All @@ -177,7 +177,7 @@ static bool UpdateUIDAndGID(Kernel& kernel, const ES::TMDReader& tmd)
static ReturnCode CheckIsAllowedToSetUID(Kernel& kernel, const u32 caller_uid,
const ES::TMDReader& active_tmd)
{
ES::UIDSys uid_map{kernel.GetFS()};
ES::UIDSys uid_map{kernel.GetFSDevice()};
const u32 system_menu_uid = uid_map.GetOrInsertUIDForTitle(Titles::SYSTEM_MENU);
if (!system_menu_uid)
return ES_SHORT_READ;
Expand Down
18 changes: 8 additions & 10 deletions Source/Core/Core/IOS/ES/ES.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ class ESDevice final : public Device
No = false,
};

ES::TMDReader FindImportTMD(u64 title_id) const;
ES::TMDReader FindInstalledTMD(u64 title_id) const;
ES::TMDReader FindImportTMD(u64 title_id, Ticks ticks = {}) const;
ES::TMDReader FindInstalledTMD(u64 title_id, Ticks ticks = {}) const;
ES::TicketReader FindSignedTicket(u64 title_id) const;

// Get installed titles (in /title) without checking for TMDs at all.
Expand All @@ -105,10 +105,10 @@ class ESDevice final : public Device
std::vector<std::array<u8, 20>> GetSharedContents() const;

// Title contents
s32 OpenContent(const ES::TMDReader& tmd, u16 content_index, u32 uid);
ReturnCode CloseContent(u32 cfd, u32 uid);
s32 ReadContent(u32 cfd, u8* buffer, u32 size, u32 uid);
s32 SeekContent(u32 cfd, u32 offset, SeekMode mode, u32 uid);
s32 OpenContent(const ES::TMDReader& tmd, u16 content_index, u32 uid, Ticks ticks = {});
s32 CloseContent(u32 cfd, u32 uid, Ticks ticks = {});
s32 ReadContent(u32 cfd, u8* buffer, u32 size, u32 uid, Ticks ticks = {});
s32 SeekContent(u32 cfd, u32 offset, SeekMode mode, u32 uid, Ticks ticks = {});

// Title management
enum class TicketImportType
Expand Down Expand Up @@ -364,14 +364,12 @@ class ESDevice final : public Device
void FinishStaleImport(u64 title_id);
void FinishAllStaleImports();

std::string GetContentPath(u64 title_id, const ES::Content& content,
const ES::SharedContentMap& map) const;
std::string GetContentPath(u64 title_id, const ES::Content& content) const;
std::string GetContentPath(u64 title_id, const ES::Content& content, Ticks ticks = {}) const;

struct OpenedContent
{
bool m_opened = false;
FS::Fd m_fd;
u64 m_fd;
u64 m_title_id = 0;
ES::Content m_content;
u32 m_uid = 0;
Expand Down
25 changes: 16 additions & 9 deletions Source/Core/Core/IOS/ES/Formats.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "Core/CommonTitles.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/FS/FileSystem.h"
#include "Core/IOS/FS/FileSystemProxy.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/IOSC.h"
#include "Core/IOS/Uids.h"
Expand Down Expand Up @@ -521,17 +522,21 @@ struct SharedContentMap::Entry
};

constexpr char CONTENT_MAP_PATH[] = "/shared1/content.map";
SharedContentMap::SharedContentMap(std::shared_ptr<HLE::FS::FileSystem> fs) : m_fs{fs}
SharedContentMap::SharedContentMap(std::shared_ptr<HLE::FSDevice> fs)
: m_fs_device{fs}, m_fs{fs->GetFS()}
{
static_assert(sizeof(Entry) == 28, "SharedContentMap::Entry has the wrong size");

Entry entry;
const auto file = fs->OpenFile(PID_KERNEL, PID_KERNEL, CONTENT_MAP_PATH, HLE::FS::Mode::Read);
while (file && file->Read(&entry, 1))
s64 fd = fs->Open(PID_KERNEL, PID_KERNEL, CONTENT_MAP_PATH, HLE::FS::Mode::Read, {}, &m_ticks);
if (fd < 0)
return;
while (fs->Read(fd, &entry, 1, &m_ticks) == sizeof(entry))
{
m_entries.push_back(entry);
m_last_id++;
}
fs->Close(fd, &m_ticks);
}

SharedContentMap::~SharedContentMap() = default;
Expand Down Expand Up @@ -600,32 +605,34 @@ bool SharedContentMap::WriteEntries() const
HLE::FS::ResultCode::Success;
}

static std::pair<u32, u64> ReadUidSysEntry(const HLE::FS::FileHandle& file)
static std::pair<u32, u64> ReadUidSysEntry(HLE::FSDevice& fs, u64 fd, u64* ticks)
{
u64 title_id = 0;
if (!file.Read(&title_id, 1))
if (fs.Read(fd, &title_id, 1, ticks) != sizeof(title_id))
return {};

u32 uid = 0;
if (!file.Read(&uid, 1))
if (fs.Read(fd, &uid, 1, ticks) != sizeof(uid))
return {};

return {Common::swap32(uid), Common::swap64(title_id)};
}

constexpr char UID_MAP_PATH[] = "/sys/uid.sys";
UIDSys::UIDSys(std::shared_ptr<HLE::FS::FileSystem> fs) : m_fs{fs}
UIDSys::UIDSys(std::shared_ptr<HLE::FSDevice> fs) : m_fs_device{fs}, m_fs{fs->GetFS()}
{
if (const auto file = fs->OpenFile(PID_KERNEL, PID_KERNEL, UID_MAP_PATH, HLE::FS::Mode::Read))
s64 fd = fs->Open(PID_KERNEL, PID_KERNEL, UID_MAP_PATH, HLE::FS::Mode::Read, {}, &m_ticks);
if (fd >= 0)
{
while (true)
{
std::pair<u32, u64> entry = ReadUidSysEntry(*file);
std::pair<u32, u64> entry = ReadUidSysEntry(*fs, fd, &m_ticks);
if (!entry.first && !entry.second)
break;

m_entries.insert(std::move(entry));
}
fs->Close(fd, &m_ticks);
}

if (m_entries.empty())
Expand Down
12 changes: 10 additions & 2 deletions Source/Core/Core/IOS/ES/Formats.h
Original file line number Diff line number Diff line change
Expand Up @@ -260,35 +260,43 @@ class TicketReader final : public SignedBlobReader
class SharedContentMap final
{
public:
explicit SharedContentMap(std::shared_ptr<HLE::FS::FileSystem> fs);
explicit SharedContentMap(std::shared_ptr<HLE::FSDevice> fs);
~SharedContentMap();

std::optional<std::string> GetFilenameFromSHA1(const std::array<u8, 20>& sha1) const;
std::string AddSharedContent(const std::array<u8, 20>& sha1);
bool DeleteSharedContent(const std::array<u8, 20>& sha1);
std::vector<std::array<u8, 20>> GetHashes() const;

u64 GetTicks() const { return m_ticks; }

private:
bool WriteEntries() const;

struct Entry;
u32 m_last_id = 0;
std::vector<Entry> m_entries;
std::shared_ptr<HLE::FSDevice> m_fs_device;
std::shared_ptr<HLE::FS::FileSystem> m_fs;
u64 m_ticks = 0;
};

class UIDSys final
{
public:
explicit UIDSys(std::shared_ptr<HLE::FS::FileSystem> fs);
explicit UIDSys(std::shared_ptr<HLE::FSDevice> fs);

u32 GetUIDFromTitle(u64 title_id) const;
u32 GetOrInsertUIDForTitle(u64 title_id);
u32 GetNextUID() const;

u64 GetTicks() const { return m_ticks; }

private:
std::shared_ptr<HLE::FSDevice> m_fs_device;
std::shared_ptr<HLE::FS::FileSystem> m_fs;
std::map<u32, u64> m_entries;
u64 m_ticks = 0;
};

class CertReader final : public SignedBlobReader
Expand Down
45 changes: 22 additions & 23 deletions Source/Core/Core/IOS/ES/NandUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
#include <array>
#include <cctype>
#include <functional>
#include <iterator>
#include <string>
#include <unordered_set>
#include <vector>
Expand All @@ -17,35 +16,38 @@
#include "Common/CommonTypes.h"
#include "Common/Logging/Log.h"
#include "Common/NandPaths.h"
#include "Common/ScopeGuard.h"
#include "Common/StringUtil.h"
#include "Core/IOS/ES/ES.h"
#include "Core/IOS/ES/Formats.h"
#include "Core/IOS/FS/FileSystemProxy.h"
#include "Core/IOS/Uids.h"

namespace IOS::HLE
{
static ES::TMDReader FindTMD(FS::FileSystem* fs, u64 title_id, const std::string& tmd_path)
static ES::TMDReader FindTMD(FSDevice& fs, const std::string& tmd_path, Ticks ticks)
{
const auto file = fs->OpenFile(PID_KERNEL, PID_KERNEL, tmd_path, FS::Mode::Read);
if (!file)
const s64 fd = fs.Open(PID_KERNEL, PID_KERNEL, tmd_path, FS::Mode::Read, {}, ticks);
if (fd < 0)
return {};
Common::ScopeGuard guard{[&] { fs.Close(fd, ticks); }};

std::vector<u8> tmd_bytes(file->GetStatus()->size);
if (!file->Read(tmd_bytes.data(), tmd_bytes.size()))
std::vector<u8> tmd_bytes(fs.GetFileStatus(fd, ticks)->size);
if (!fs.Read(fd, tmd_bytes.data(), tmd_bytes.size(), ticks))
return {};

return ES::TMDReader{std::move(tmd_bytes)};
}

ES::TMDReader ESDevice::FindImportTMD(u64 title_id) const
ES::TMDReader ESDevice::FindImportTMD(u64 title_id, Ticks ticks) const
{
return FindTMD(m_ios.GetFS().get(), title_id,
Common::GetImportTitlePath(title_id) + "/content/title.tmd");
return FindTMD(*m_ios.GetFSDevice(), Common::GetImportTitlePath(title_id) + "/content/title.tmd",
ticks);
}

ES::TMDReader ESDevice::FindInstalledTMD(u64 title_id) const
ES::TMDReader ESDevice::FindInstalledTMD(u64 title_id, Ticks ticks) const
{
return FindTMD(m_ios.GetFS().get(), title_id, Common::GetTMDFileName(title_id));
return FindTMD(*m_ios.GetFSDevice(), Common::GetTMDFileName(title_id), ticks);
}

ES::TicketReader ESDevice::FindSignedTicket(u64 title_id) const
Expand Down Expand Up @@ -171,16 +173,15 @@ ESDevice::GetStoredContentsFromTMD(const ES::TMDReader& tmd,
if (!tmd.IsValid())
return {};

const ES::SharedContentMap map{m_ios.GetFS()};
const std::vector<ES::Content> contents = tmd.GetContents();

std::vector<ES::Content> stored_contents;

std::copy_if(contents.begin(), contents.end(), std::back_inserter(stored_contents),
[this, &tmd, &map, check_content_hashes](const ES::Content& content) {
[this, &tmd, check_content_hashes](const ES::Content& content) {
const auto fs = m_ios.GetFS();

const std::string path = GetContentPath(tmd.GetTitleId(), content, map);
const std::string path = GetContentPath(tmd.GetTitleId(), content);
if (path.empty())
return false;

Expand Down Expand Up @@ -217,7 +218,7 @@ u32 ESDevice::GetSharedContentsCount() const

std::vector<std::array<u8, 20>> ESDevice::GetSharedContents() const
{
const ES::SharedContentMap map{m_ios.GetFS()};
const ES::SharedContentMap map{m_ios.GetFSDevice()};
return map.GetHashes();
}

Expand Down Expand Up @@ -267,7 +268,7 @@ bool ESDevice::CreateTitleDirectories(u64 title_id, u16 group_id) const
return false;
}

ES::UIDSys uid_sys{fs};
ES::UIDSys uid_sys{m_ios.GetFSDevice()};
const u32 uid = uid_sys.GetOrInsertUIDForTitle(title_id);
if (fs->SetMetadata(0, data_dir, uid, group_id, 0, data_dir_modes) != FS::ResultCode::Success)
{
Expand Down Expand Up @@ -382,16 +383,14 @@ void ESDevice::FinishAllStaleImports()
}

std::string ESDevice::GetContentPath(const u64 title_id, const ES::Content& content,
const ES::SharedContentMap& content_map) const
Ticks ticks) const
{
if (content.IsShared())
{
ES::SharedContentMap content_map{m_ios.GetFSDevice()};
ticks.Add(content_map.GetTicks());
return content_map.GetFilenameFromSHA1(content.sha1).value_or("");
}
return fmt::format("{}/{:08x}.app", Common::GetTitleContentPath(title_id), content.id);
}

std::string ESDevice::GetContentPath(const u64 title_id, const ES::Content& content) const
{
ES::SharedContentMap map{m_ios.GetFS()};
return GetContentPath(title_id, content, map);
}
} // namespace IOS::HLE
Loading

0 comments on commit 93f9d67

Please sign in to comment.