IOS/ES: Allow various utility functions to return timing info

This commit is contained in:
Léo Lam 2021-02-16 12:30:29 +01:00
parent f214df5d2c
commit 5eca82a6f2
No known key found for this signature in database
GPG Key ID: 0DF30F9081000741
11 changed files with 98 additions and 55 deletions

View File

@ -161,7 +161,7 @@ IPCReply ESDevice::GetTitleId(const IOCtlVRequest& request)
static bool UpdateUIDAndGID(Kernel& kernel, const ES::TMDReader& tmd) 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 u64 title_id = tmd.GetTitleId();
const u32 uid = uid_sys.GetOrInsertUIDForTitle(title_id); const u32 uid = uid_sys.GetOrInsertUIDForTitle(title_id);
if (uid == 0) if (uid == 0)
@ -177,7 +177,7 @@ static bool UpdateUIDAndGID(Kernel& kernel, const ES::TMDReader& tmd)
static ReturnCode CheckIsAllowedToSetUID(Kernel& kernel, const u32 caller_uid, static ReturnCode CheckIsAllowedToSetUID(Kernel& kernel, const u32 caller_uid,
const ES::TMDReader& active_tmd) 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); const u32 system_menu_uid = uid_map.GetOrInsertUIDForTitle(Titles::SYSTEM_MENU);
if (!system_menu_uid) if (!system_menu_uid)
return ES_SHORT_READ; return ES_SHORT_READ;

View File

@ -87,8 +87,8 @@ public:
No = false, No = false,
}; };
ES::TMDReader FindImportTMD(u64 title_id) const; ES::TMDReader FindImportTMD(u64 title_id, Ticks ticks = {}) const;
ES::TMDReader FindInstalledTMD(u64 title_id) const; ES::TMDReader FindInstalledTMD(u64 title_id, Ticks ticks = {}) const;
ES::TicketReader FindSignedTicket(u64 title_id) const; ES::TicketReader FindSignedTicket(u64 title_id) const;
// Get installed titles (in /title) without checking for TMDs at all. // Get installed titles (in /title) without checking for TMDs at all.
@ -364,9 +364,9 @@ private:
void FinishStaleImport(u64 title_id); void FinishStaleImport(u64 title_id);
void FinishAllStaleImports(); void FinishAllStaleImports();
std::string GetContentPath(u64 title_id, const ES::Content& content, std::string GetContentPath(u64 title_id, const ES::Content& content, Ticks ticks = {}) const;
const ES::SharedContentMap& map) const;
std::string GetContentPath(u64 title_id, const ES::Content& content) const; static constexpr u64 IPC_OVERHEAD_TICKS = 2700_tbticks;
struct OpenedContent struct OpenedContent
{ {

View File

@ -27,6 +27,7 @@
#include "Core/CommonTitles.h" #include "Core/CommonTitles.h"
#include "Core/IOS/Device.h" #include "Core/IOS/Device.h"
#include "Core/IOS/FS/FileSystem.h" #include "Core/IOS/FS/FileSystem.h"
#include "Core/IOS/FS/FileSystemProxy.h"
#include "Core/IOS/IOS.h" #include "Core/IOS/IOS.h"
#include "Core/IOS/IOSC.h" #include "Core/IOS/IOSC.h"
#include "Core/IOS/Uids.h" #include "Core/IOS/Uids.h"
@ -521,17 +522,21 @@ struct SharedContentMap::Entry
}; };
constexpr char CONTENT_MAP_PATH[] = "/shared1/content.map"; 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"); static_assert(sizeof(Entry) == 28, "SharedContentMap::Entry has the wrong size");
Entry entry; Entry entry;
const auto file = fs->OpenFile(PID_KERNEL, PID_KERNEL, CONTENT_MAP_PATH, HLE::FS::Mode::Read); s64 fd = fs->Open(PID_KERNEL, PID_KERNEL, CONTENT_MAP_PATH, HLE::FS::Mode::Read, {}, &m_ticks);
while (file && file->Read(&entry, 1)) if (fd < 0)
return;
while (fs->Read(fd, &entry, 1, &m_ticks) == sizeof(entry))
{ {
m_entries.push_back(entry); m_entries.push_back(entry);
m_last_id++; m_last_id++;
} }
fs->Close(fd, &m_ticks);
} }
SharedContentMap::~SharedContentMap() = default; SharedContentMap::~SharedContentMap() = default;
@ -600,32 +605,34 @@ bool SharedContentMap::WriteEntries() const
HLE::FS::ResultCode::Success; 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; u64 title_id = 0;
if (!file.Read(&title_id, 1)) if (fs.Read(fd, &title_id, 1, ticks) != sizeof(title_id))
return {}; return {};
u32 uid = 0; u32 uid = 0;
if (!file.Read(&uid, 1)) if (fs.Read(fd, &uid, 1, ticks) != sizeof(uid))
return {}; return {};
return {Common::swap32(uid), Common::swap64(title_id)}; return {Common::swap32(uid), Common::swap64(title_id)};
} }
constexpr char UID_MAP_PATH[] = "/sys/uid.sys"; 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) while (true)
{ {
std::pair<u32, u64> entry = ReadUidSysEntry(*file); std::pair<u32, u64> entry = ReadUidSysEntry(*fs, fd, &m_ticks);
if (!entry.first && !entry.second) if (!entry.first && !entry.second)
break; break;
m_entries.insert(std::move(entry)); m_entries.insert(std::move(entry));
} }
fs->Close(fd, &m_ticks);
} }
if (m_entries.empty()) if (m_entries.empty())

View File

@ -260,7 +260,7 @@ public:
class SharedContentMap final class SharedContentMap final
{ {
public: public:
explicit SharedContentMap(std::shared_ptr<HLE::FS::FileSystem> fs); explicit SharedContentMap(std::shared_ptr<HLE::FSDevice> fs);
~SharedContentMap(); ~SharedContentMap();
std::optional<std::string> GetFilenameFromSHA1(const std::array<u8, 20>& sha1) const; std::optional<std::string> GetFilenameFromSHA1(const std::array<u8, 20>& sha1) const;
@ -268,27 +268,35 @@ public:
bool DeleteSharedContent(const std::array<u8, 20>& sha1); bool DeleteSharedContent(const std::array<u8, 20>& sha1);
std::vector<std::array<u8, 20>> GetHashes() const; std::vector<std::array<u8, 20>> GetHashes() const;
u64 GetTicks() const { return m_ticks; }
private: private:
bool WriteEntries() const; bool WriteEntries() const;
struct Entry; struct Entry;
u32 m_last_id = 0; u32 m_last_id = 0;
std::vector<Entry> m_entries; std::vector<Entry> m_entries;
std::shared_ptr<HLE::FSDevice> m_fs_device;
std::shared_ptr<HLE::FS::FileSystem> m_fs; std::shared_ptr<HLE::FS::FileSystem> m_fs;
u64 m_ticks = 0;
}; };
class UIDSys final class UIDSys final
{ {
public: 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 GetUIDFromTitle(u64 title_id) const;
u32 GetOrInsertUIDForTitle(u64 title_id); u32 GetOrInsertUIDForTitle(u64 title_id);
u32 GetNextUID() const; u32 GetNextUID() const;
u64 GetTicks() const { return m_ticks; }
private: private:
std::shared_ptr<HLE::FSDevice> m_fs_device;
std::shared_ptr<HLE::FS::FileSystem> m_fs; std::shared_ptr<HLE::FS::FileSystem> m_fs;
std::map<u32, u64> m_entries; std::map<u32, u64> m_entries;
u64 m_ticks = 0;
}; };
class CertReader final : public SignedBlobReader class CertReader final : public SignedBlobReader

View File

@ -6,7 +6,6 @@
#include <array> #include <array>
#include <cctype> #include <cctype>
#include <functional> #include <functional>
#include <iterator>
#include <string> #include <string>
#include <unordered_set> #include <unordered_set>
#include <vector> #include <vector>
@ -17,35 +16,38 @@
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/Logging/Log.h" #include "Common/Logging/Log.h"
#include "Common/NandPaths.h" #include "Common/NandPaths.h"
#include "Common/ScopeGuard.h"
#include "Common/StringUtil.h" #include "Common/StringUtil.h"
#include "Core/IOS/ES/ES.h" #include "Core/IOS/ES/ES.h"
#include "Core/IOS/ES/Formats.h" #include "Core/IOS/ES/Formats.h"
#include "Core/IOS/FS/FileSystemProxy.h"
#include "Core/IOS/Uids.h" #include "Core/IOS/Uids.h"
namespace IOS::HLE 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); const s64 fd = fs.Open(PID_KERNEL, PID_KERNEL, tmd_path, FS::Mode::Read, {}, ticks);
if (!file) if (fd < 0)
return {}; return {};
Common::ScopeGuard guard{[&] { fs.Close(fd, ticks); }};
std::vector<u8> tmd_bytes(file->GetStatus()->size); std::vector<u8> tmd_bytes(fs.GetFileStatus(fd, ticks)->size);
if (!file->Read(tmd_bytes.data(), tmd_bytes.size())) if (!fs.Read(fd, tmd_bytes.data(), tmd_bytes.size(), ticks))
return {}; return {};
return ES::TMDReader{std::move(tmd_bytes)}; 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, return FindTMD(*m_ios.GetFSDevice(), Common::GetImportTitlePath(title_id) + "/content/title.tmd",
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 ES::TicketReader ESDevice::FindSignedTicket(u64 title_id) const
@ -171,16 +173,15 @@ ESDevice::GetStoredContentsFromTMD(const ES::TMDReader& tmd,
if (!tmd.IsValid()) if (!tmd.IsValid())
return {}; return {};
const ES::SharedContentMap map{m_ios.GetFS()};
const std::vector<ES::Content> contents = tmd.GetContents(); const std::vector<ES::Content> contents = tmd.GetContents();
std::vector<ES::Content> stored_contents; std::vector<ES::Content> stored_contents;
std::copy_if(contents.begin(), contents.end(), std::back_inserter(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 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()) if (path.empty())
return false; return false;
@ -217,7 +218,7 @@ u32 ESDevice::GetSharedContentsCount() const
std::vector<std::array<u8, 20>> ESDevice::GetSharedContents() 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(); return map.GetHashes();
} }
@ -267,7 +268,7 @@ bool ESDevice::CreateTitleDirectories(u64 title_id, u16 group_id) const
return false; return false;
} }
ES::UIDSys uid_sys{fs}; ES::UIDSys uid_sys{m_ios.GetFSDevice()};
const u32 uid = uid_sys.GetOrInsertUIDForTitle(title_id); const u32 uid = uid_sys.GetOrInsertUIDForTitle(title_id);
if (fs->SetMetadata(0, data_dir, uid, group_id, 0, data_dir_modes) != FS::ResultCode::Success) if (fs->SetMetadata(0, data_dir, uid, group_id, 0, data_dir_modes) != FS::ResultCode::Success)
{ {
@ -382,16 +383,14 @@ void ESDevice::FinishAllStaleImports()
} }
std::string ESDevice::GetContentPath(const u64 title_id, const ES::Content& content, std::string ESDevice::GetContentPath(const u64 title_id, const ES::Content& content,
const ES::SharedContentMap& content_map) const Ticks ticks) const
{ {
if (content.IsShared()) if (content.IsShared())
{
ES::SharedContentMap content_map{m_ios.GetFSDevice()};
ticks.Add(content_map.GetTicks());
return content_map.GetFilenameFromSHA1(content.sha1).value_or(""); return content_map.GetFilenameFromSHA1(content.sha1).value_or("");
}
return fmt::format("{}/{:08x}.app", Common::GetTitleContentPath(title_id), content.id); 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 } // namespace IOS::HLE

View File

@ -78,7 +78,7 @@ IPCReply ESDevice::OpenActiveTitleContent(u32 caller_uid, const IOCtlVRequest& r
if (!m_title_context.active) if (!m_title_context.active)
return IPCReply(ES_EINVAL); return IPCReply(ES_EINVAL);
ES::UIDSys uid_map{m_ios.GetFS()}; ES::UIDSys uid_map{m_ios.GetFSDevice()};
const u32 uid = uid_map.GetOrInsertUIDForTitle(m_title_context.tmd.GetTitleId()); const u32 uid = uid_map.GetOrInsertUIDForTitle(m_title_context.tmd.GetTitleId());
if (caller_uid != 0 && caller_uid != uid) if (caller_uid != 0 && caller_uid != uid)
return IPCReply(ES_EACCES); return IPCReply(ES_EACCES);

View File

@ -394,7 +394,7 @@ ReturnCode ESDevice::ImportContentEnd(Context& context, u32 content_fd)
std::string content_path; std::string content_path;
if (content_info.IsShared()) if (content_info.IsShared())
{ {
ES::SharedContentMap shared_content{fs}; ES::SharedContentMap shared_content{m_ios.GetFSDevice()};
content_path = shared_content.AddSharedContent(content_info.sha1); content_path = shared_content.AddSharedContent(content_info.sha1);
} }
else else
@ -441,7 +441,7 @@ static bool HasAllRequiredContents(Kernel& ios, const ES::TMDReader& tmd)
{ {
const u64 title_id = tmd.GetTitleId(); const u64 title_id = tmd.GetTitleId();
const std::vector<ES::Content> contents = tmd.GetContents(); const std::vector<ES::Content> contents = tmd.GetContents();
const ES::SharedContentMap shared_content_map{ios.GetFS()}; const ES::SharedContentMap shared_content_map{ios.GetFSDevice()};
return std::all_of(contents.cbegin(), contents.cend(), [&](const ES::Content& content) { return std::all_of(contents.cbegin(), contents.cend(), [&](const ES::Content& content) {
if (content.IsOptional()) if (content.IsOptional())
return true; return true;
@ -818,7 +818,7 @@ IPCReply ESDevice::ExportTitleDone(Context& context, const IOCtlVRequest& reques
ReturnCode ESDevice::DeleteSharedContent(const std::array<u8, 20>& sha1) const ReturnCode ESDevice::DeleteSharedContent(const std::array<u8, 20>& sha1) const
{ {
ES::SharedContentMap map{m_ios.GetFS()}; ES::SharedContentMap map{m_ios.GetFSDevice()};
const auto content_path = map.GetFilenameFromSHA1(sha1); const auto content_path = map.GetFilenameFromSHA1(sha1);
if (!content_path) if (!content_path)
return ES_EINVAL; return ES_EINVAL;

View File

@ -661,19 +661,32 @@ IPCReply FSDevice::SetFileVersionControl(const Handle& handle, const IOCtlReques
IPCReply FSDevice::GetFileStats(const Handle& handle, const IOCtlRequest& request) IPCReply FSDevice::GetFileStats(const Handle& handle, const IOCtlRequest& request)
{ {
if (request.buffer_out_size < 8 || handle.fs_fd == INVALID_FD) if (request.buffer_out_size < 8)
return GetFSReply(ConvertResult(ResultCode::Invalid)); return GetFSReply(ConvertResult(ResultCode::Invalid));
const Result<FileStatus> status = m_ios.GetFS()->GetFileStatus(handle.fs_fd); return MakeIPCReply([&](Ticks ticks) {
LogResult(status, "GetFileStatus({})", handle.name.data()); const Result<FileStatus> status = GetFileStatus(request.fd, ticks);
if (!status) if (!status)
return IPCReply(ConvertResult(status.Error())); return ConvertResult(status.Error());
ISFSFileStats out; ISFSFileStats out;
out.size = status->size; out.size = status->size;
out.seek_position = status->offset; out.seek_position = status->offset;
Memory::CopyToEmu(request.buffer_out, &out, sizeof(out)); Memory::CopyToEmu(request.buffer_out, &out, sizeof(out));
return IPCReply(IPC_SUCCESS); return IPC_SUCCESS;
});
}
FS::Result<FS::FileStatus> FSDevice::GetFileStatus(u64 fd, Ticks ticks)
{
ticks.AddTimeBaseTicks(GetIPCOverheadTicks());
const auto& handle = m_fd_map[fd];
if (handle.fs_fd == INVALID_FD)
return ResultCode::Invalid;
auto status = m_ios.GetFS()->GetFileStatus(handle.fs_fd);
LogResult(status, "GetFileStatus({})", handle.name.data());
return status;
} }
IPCReply FSDevice::GetUsage(const Handle& handle, const IOCtlVRequest& request) IPCReply FSDevice::GetUsage(const Handle& handle, const IOCtlVRequest& request)

View File

@ -35,6 +35,15 @@ public:
s32 Write(u64 fd, const u8* data, u32 size, std::optional<u32> ipc_buffer_addr = {}, s32 Write(u64 fd, const u8* data, u32 size, std::optional<u32> ipc_buffer_addr = {},
Ticks ticks = {}); Ticks ticks = {});
s32 Seek(u64 fd, u32 offset, FS::SeekMode mode, Ticks ticks = {}); s32 Seek(u64 fd, u32 offset, FS::SeekMode mode, Ticks ticks = {});
FS::Result<FS::FileStatus> GetFileStatus(u64 fd, Ticks ticks = {});
template <typename T>
s32 Read(u64 fd, T* data, size_t count, Ticks ticks = {})
{
return Read(fd, reinterpret_cast<u8*>(data), static_cast<u32>(sizeof(T) * count), {}, ticks);
}
std::shared_ptr<FS::FileSystem> GetFS() const { return m_ios.GetFS(); }
void DoState(PointerWrap& p) override; void DoState(PointerWrap& p) override;

View File

@ -285,6 +285,11 @@ std::shared_ptr<FS::FileSystem> Kernel::GetFS()
return m_fs; return m_fs;
} }
std::shared_ptr<FSDevice> Kernel::GetFSDevice()
{
return std::static_pointer_cast<FSDevice>(m_device_map.at("/dev/fs"));
}
std::shared_ptr<ESDevice> Kernel::GetES() std::shared_ptr<ESDevice> Kernel::GetES()
{ {
return std::static_pointer_cast<ESDevice>(m_device_map.at("/dev/es")); return std::static_pointer_cast<ESDevice>(m_device_map.at("/dev/es"));

View File

@ -30,6 +30,7 @@ class FileSystem;
class Device; class Device;
class ESDevice; class ESDevice;
class FSDevice;
struct Request; struct Request;
struct OpenRequest; struct OpenRequest;
@ -116,6 +117,7 @@ public:
// These are *always* part of the IOS kernel and always available. // These are *always* part of the IOS kernel and always available.
// They are also the only available resource managers even before loading any module. // They are also the only available resource managers even before loading any module.
std::shared_ptr<FS::FileSystem> GetFS(); std::shared_ptr<FS::FileSystem> GetFS();
std::shared_ptr<FSDevice> GetFSDevice();
std::shared_ptr<ESDevice> GetES(); std::shared_ptr<ESDevice> GetES();
void SDIO_EventNotify(); void SDIO_EventNotify();