IOS: Clean up the way IPC replies are constructed

Instead of constructing IPCCommandResult with static member functions
in the Device class, we can just add the relevant constructors to the
reply struct itself. Makes more sense than putting it in Device
when the struct is used in the kernel code and doesn't use any Device
specific members...

This commit also changes the IPC command handlers to return an optional
IPCCommandResult rather than an IPCCommandResult. This removes the need
for a separate boolean that indicates whether the "result" is actually
a reply, and also avoids the need to set dummy result values and ticks.

It also makes it really obvious which commands can result in no reply
being generated.

Finally, this commit renames IPCCommandResult to IPCReply since the
struct is now only used for actual replies. This new name is less
verbose in my opinion.

The diff is quite large since this touches every command handler, but
the only functional change is that I fixed EnqueueIPCReply to
take a s64 for cycles_in_future to match IPCReply.
This commit is contained in:
Léo Lam
2021-02-13 20:15:30 +01:00
parent f52aa3d041
commit d0136dd7c2
61 changed files with 872 additions and 873 deletions
+6 -6
View File
@@ -57,13 +57,13 @@ void DIDevice::DoState(PointerWrap& p)
p.Do(m_last_length);
}
IPCCommandResult DIDevice::Open(const OpenRequest& request)
std::optional<IPCReply> DIDevice::Open(const OpenRequest& request)
{
InitializeIfFirstTime();
return Device::Open(request);
}
IPCCommandResult DIDevice::IOCtl(const IOCtlRequest& request)
std::optional<IPCReply> DIDevice::IOCtl(const IOCtlRequest& request)
{
InitializeIfFirstTime();
@@ -91,7 +91,7 @@ IPCCommandResult DIDevice::IOCtl(const IOCtlRequest& request)
// FinishIOCtl will be called after the command has been executed
// to reply to the request, so we shouldn't reply here.
return GetNoReply();
return std::nullopt;
}
void DIDevice::ProcessQueuedIOCtl()
@@ -612,7 +612,7 @@ void DIDevice::FinishDICommand(DIResult result)
}
}
IPCCommandResult DIDevice::IOCtlV(const IOCtlVRequest& request)
std::optional<IPCReply> DIDevice::IOCtlV(const IOCtlVRequest& request)
{
// IOCtlVs are not queued since they don't (currently) go into DVDInterface and act
// asynchronously. This does mean that an IOCtlV can be executed while an IOCtl is in progress,
@@ -623,7 +623,7 @@ IPCCommandResult DIDevice::IOCtlV(const IOCtlVRequest& request)
{
ERROR_LOG_FMT(IOS_DI, "IOCtlV: Received bad input buffer size {:#04x}, should be 0x20",
request.in_vectors[0].size);
return GetDefaultReply(static_cast<s32>(DIResult::BadArgument));
return IPCReply{static_cast<s32>(DIResult::BadArgument)};
}
const u8 command = Memory::Read_U8(request.in_vectors[0].address);
if (request.request != command)
@@ -704,7 +704,7 @@ IPCCommandResult DIDevice::IOCtlV(const IOCtlVRequest& request)
ERROR_LOG_FMT(IOS_DI, "Unknown ioctlv {:#04x}", request.request);
request.DumpUnknown(GetDeviceName(), Common::Log::IOS_DI);
}
return GetDefaultReply(static_cast<s32>(return_value));
return IPCReply{static_cast<s32>(return_value)};
}
void DIDevice::ChangePartition(const DiscIO::Partition partition)
+3 -3
View File
@@ -42,9 +42,9 @@ public:
void DoState(PointerWrap& p) override;
IPCCommandResult Open(const OpenRequest& request) override;
IPCCommandResult IOCtl(const IOCtlRequest& request) override;
IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;
std::optional<IPCReply> Open(const OpenRequest& request) override;
std::optional<IPCReply> IOCtl(const IOCtlRequest& request) override;
std::optional<IPCReply> IOCtlV(const IOCtlVRequest& request) override;
enum class DIIoctl : u32
{
+6 -27
View File
@@ -160,19 +160,19 @@ void Device::DoStateShared(PointerWrap& p)
p.Do(m_is_active);
}
IPCCommandResult Device::Open(const OpenRequest& request)
std::optional<IPCReply> Device::Open(const OpenRequest& request)
{
m_is_active = true;
return GetDefaultReply(IPC_SUCCESS);
return IPCReply{IPC_SUCCESS};
}
IPCCommandResult Device::Close(u32 fd)
std::optional<IPCReply> Device::Close(u32 fd)
{
m_is_active = false;
return GetDefaultReply(IPC_SUCCESS);
return IPCReply{IPC_SUCCESS};
}
IPCCommandResult Device::Unsupported(const Request& request)
std::optional<IPCReply> Device::Unsupported(const Request& request)
{
static const std::map<IPCCommandType, std::string_view> names{{
{IPC_CMD_READ, "Read"},
@@ -183,27 +183,6 @@ IPCCommandResult Device::Unsupported(const Request& request)
}};
WARN_LOG_FMT(IOS, "{} does not support {}()", m_name, names.at(request.command));
return GetDefaultReply(IPC_EINVAL);
}
// Returns an IPCCommandResult for a reply with an average reply time for devices
// Please avoid using this function if more accurate timings are known.
IPCCommandResult Device::GetDefaultReply(const s32 return_value)
{
// Based on a hardware test, a device takes at least ~2700 ticks to reply to an IPC request.
// Depending on how much work a command performs, this can take much longer (10000+)
// especially if the NAND filesystem is accessed.
//
// Because we currently don't emulate timing very accurately, we should not return
// the minimum possible reply time (~960 ticks from the kernel or ~2700 from devices)
// but an average time, otherwise we are going to be much too fast in most cases.
return {return_value, true, 4000 * SystemTimers::TIMER_RATIO};
}
// Returns an IPCCommandResult with no reply. Useful for async commands that will generate a reply
// later. This takes no return value because it won't be used.
IPCCommandResult Device::GetNoReply()
{
return {IPC_SUCCESS, false, 0};
return IPCReply{IPC_EINVAL};
}
} // namespace IOS::HLE
+15 -10
View File
@@ -5,6 +5,7 @@
#pragma once
#include <cstddef>
#include <optional>
#include <string>
#include <vector>
@@ -186,19 +187,23 @@ public:
const std::string& GetDeviceName() const { return m_name; }
// Replies to Open and Close requests are sent by the IPC request handler (HandleCommand),
// not by the devices themselves.
virtual IPCCommandResult Open(const OpenRequest& request);
virtual IPCCommandResult Close(u32 fd);
virtual IPCCommandResult Seek(const SeekRequest& seek) { return Unsupported(seek); }
virtual IPCCommandResult Read(const ReadWriteRequest& read) { return Unsupported(read); }
virtual IPCCommandResult Write(const ReadWriteRequest& write) { return Unsupported(write); }
virtual IPCCommandResult IOCtl(const IOCtlRequest& ioctl) { return Unsupported(ioctl); }
virtual IPCCommandResult IOCtlV(const IOCtlVRequest& ioctlv) { return Unsupported(ioctlv); }
virtual std::optional<IPCReply> Open(const OpenRequest& request);
virtual std::optional<IPCReply> Close(u32 fd);
virtual std::optional<IPCReply> Seek(const SeekRequest& seek) { return Unsupported(seek); }
virtual std::optional<IPCReply> Read(const ReadWriteRequest& read) { return Unsupported(read); }
virtual std::optional<IPCReply> Write(const ReadWriteRequest& write)
{
return Unsupported(write);
}
virtual std::optional<IPCReply> IOCtl(const IOCtlRequest& ioctl) { return Unsupported(ioctl); }
virtual std::optional<IPCReply> IOCtlV(const IOCtlVRequest& ioctlv)
{
return Unsupported(ioctlv);
}
virtual void Update() {}
virtual void UpdateWantDeterminism(bool new_want_determinism) {}
virtual DeviceType GetDeviceType() const { return m_device_type; }
virtual bool IsOpened() const { return m_is_active; }
static IPCCommandResult GetDefaultReply(s32 return_value);
static IPCCommandResult GetNoReply();
protected:
Kernel& m_ios;
@@ -209,6 +214,6 @@ protected:
bool m_is_active = false;
private:
IPCCommandResult Unsupported(const Request& request);
std::optional<IPCReply> Unsupported(const Request& request);
};
} // namespace IOS::HLE
+6 -6
View File
@@ -8,22 +8,22 @@
namespace IOS::HLE
{
IPCCommandResult DeviceStub::Open(const OpenRequest& request)
std::optional<IPCReply> DeviceStub::Open(const OpenRequest& request)
{
WARN_LOG_FMT(IOS, "{} faking Open()", m_name);
m_is_active = true;
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult DeviceStub::IOCtl(const IOCtlRequest& request)
std::optional<IPCReply> DeviceStub::IOCtl(const IOCtlRequest& request)
{
WARN_LOG_FMT(IOS, "{} faking IOCtl()", m_name);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult DeviceStub::IOCtlV(const IOCtlVRequest& request)
std::optional<IPCReply> DeviceStub::IOCtlV(const IOCtlVRequest& request)
{
WARN_LOG_FMT(IOS, "{} faking IOCtlV()", m_name);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
} // namespace IOS::HLE
+3 -3
View File
@@ -17,8 +17,8 @@ class DeviceStub final : public Device
public:
// Inherit the constructor from the Device class, since we don't need to do anything special.
using Device::Device;
IPCCommandResult Open(const OpenRequest& request) override;
IPCCommandResult IOCtl(const IOCtlRequest& request) override;
IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;
std::optional<IPCReply> Open(const OpenRequest& request) override;
std::optional<IPCReply> IOCtl(const IOCtlRequest& request) override;
std::optional<IPCReply> IOCtlV(const IOCtlVRequest& request) override;
};
} // namespace IOS::HLE
+28 -30
View File
@@ -34,29 +34,29 @@ enum
};
IPCCommandResult GetSystemTime(const IOCtlVRequest& request)
IPCReply GetSystemTime(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(0, 1))
{
return DolphinDevice::GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
}
if (request.io_vectors[0].size != 4)
{
return DolphinDevice::GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
}
const u32 milliseconds = Common::Timer::GetTimeMs();
Memory::Write_U32(milliseconds, request.io_vectors[0].address);
return DolphinDevice::GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult GetVersion(const IOCtlVRequest& request)
IPCReply GetVersion(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(0, 1))
{
return DolphinDevice::GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
}
const auto length = std::min(size_t(request.io_vectors[0].size), std::strlen(SCM_DESC_STR));
@@ -64,19 +64,19 @@ IPCCommandResult GetVersion(const IOCtlVRequest& request)
Memory::Memset(request.io_vectors[0].address, 0, request.io_vectors[0].size);
Memory::CopyToEmu(request.io_vectors[0].address, SCM_DESC_STR, length);
return DolphinDevice::GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult GetCPUSpeed(const IOCtlVRequest& request)
IPCReply GetCPUSpeed(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(0, 1))
{
return DolphinDevice::GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
}
if (request.io_vectors[0].size != 4)
{
return DolphinDevice::GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
}
const SConfig& config = SConfig::GetInstance();
@@ -86,66 +86,66 @@ IPCCommandResult GetCPUSpeed(const IOCtlVRequest& request)
Memory::Write_U32(core_clock, request.io_vectors[0].address);
return DolphinDevice::GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult GetSpeedLimit(const IOCtlVRequest& request)
IPCReply GetSpeedLimit(const IOCtlVRequest& request)
{
// get current speed limit
if (!request.HasNumberOfValidVectors(0, 1))
{
return DolphinDevice::GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
}
if (request.io_vectors[0].size != 4)
{
return DolphinDevice::GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
}
const SConfig& config = SConfig::GetInstance();
const u32 speed_percent = config.m_EmulationSpeed * 100;
Memory::Write_U32(speed_percent, request.io_vectors[0].address);
return DolphinDevice::GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult SetSpeedLimit(const IOCtlVRequest& request)
IPCReply SetSpeedLimit(const IOCtlVRequest& request)
{
// set current speed limit
if (!request.HasNumberOfValidVectors(1, 0))
{
return DolphinDevice::GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
}
if (request.in_vectors[0].size != 4)
{
return DolphinDevice::GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
}
const float speed = float(Memory::Read_U32(request.in_vectors[0].address)) / 100.0f;
SConfig::GetInstance().m_EmulationSpeed = speed;
BootManager::SetEmulationSpeedReset(true);
return DolphinDevice::GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult GetRealProductCode(const IOCtlVRequest& request)
IPCReply GetRealProductCode(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(0, 1))
{
return DolphinDevice::GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
}
const std::string backup_file_path = File::GetUserPath(D_BACKUP_IDX) + DIR_SEP + WII_SETTING;
File::IOFile file(backup_file_path, "rb");
if (!file)
return DolphinDevice::GetDefaultReply(IPC_ENOENT);
return IPCReply(IPC_ENOENT);
Common::SettingsHandler::Buffer data;
if (!file.ReadBytes(data.data(), data.size()))
return DolphinDevice::GetDefaultReply(IPC_ENOENT);
return IPCReply(IPC_ENOENT);
Common::SettingsHandler gen;
gen.SetBytes(std::move(data));
@@ -153,21 +153,19 @@ IPCCommandResult GetRealProductCode(const IOCtlVRequest& request)
const size_t length = std::min<size_t>(request.io_vectors[0].size, code.length());
if (length == 0)
return DolphinDevice::GetDefaultReply(IPC_ENOENT);
return IPCReply(IPC_ENOENT);
Memory::Memset(request.io_vectors[0].address, 0, request.io_vectors[0].size);
Memory::CopyToEmu(request.io_vectors[0].address, code.c_str(), length);
return DolphinDevice::GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
} // namespace
IPCCommandResult DolphinDevice::IOCtlV(const IOCtlVRequest& request)
std::optional<IPCReply> DolphinDevice::IOCtlV(const IOCtlVRequest& request)
{
if (Core::WantsDeterminism())
{
return DolphinDevice::GetDefaultReply(IPC_EACCES);
}
return IPCReply(IPC_EACCES);
switch (request.request)
{
@@ -184,7 +182,7 @@ IPCCommandResult DolphinDevice::IOCtlV(const IOCtlVRequest& request)
case IOCTL_DOLPHIN_GET_REAL_PRODUCTCODE:
return GetRealProductCode(request);
default:
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
}
}
} // namespace IOS::HLE
+1 -1
View File
@@ -13,6 +13,6 @@ class DolphinDevice final : public Device
public:
// Inherit the constructor from the Device class, since we don't need to do anything special.
using Device::Device;
IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;
std::optional<IPCReply> IOCtlV(const IOCtlVRequest& request) override;
};
} // namespace IOS::HLE
+44 -44
View File
@@ -120,10 +120,10 @@ void TitleContext::Update(const ES::TMDReader& tmd_, const ES::TicketReader& tic
}
}
IPCCommandResult ESDevice::GetTitleDirectory(const IOCtlVRequest& request)
IPCReply ESDevice::GetTitleDirectory(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 1))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
@@ -132,7 +132,7 @@ IPCCommandResult ESDevice::GetTitleDirectory(const IOCtlVRequest& request)
static_cast<u32>(title_id));
INFO_LOG_FMT(IOS_ES, "IOCTL_ES_GETTITLEDIR: {}", path);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
ReturnCode ESDevice::GetTitleId(u64* title_id) const
@@ -143,20 +143,20 @@ ReturnCode ESDevice::GetTitleId(u64* title_id) const
return IPC_SUCCESS;
}
IPCCommandResult ESDevice::GetTitleId(const IOCtlVRequest& request)
IPCReply ESDevice::GetTitleId(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(0, 1))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
u64 title_id;
const ReturnCode ret = GetTitleId(&title_id);
if (ret != IPC_SUCCESS)
return GetDefaultReply(ret);
return IPCReply(ret);
Memory::Write_U64(title_id, request.io_vectors[0].address);
INFO_LOG_FMT(IOS_ES, "IOCTL_ES_GETTITLEID: {:08x}/{:08x}", static_cast<u32>(title_id >> 32),
static_cast<u32>(title_id));
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
static bool UpdateUIDAndGID(Kernel& kernel, const ES::TMDReader& tmd)
@@ -196,10 +196,10 @@ static ReturnCode CheckIsAllowedToSetUID(Kernel& kernel, const u32 caller_uid,
return ES_EINVAL;
}
IPCCommandResult ESDevice::SetUID(u32 uid, const IOCtlVRequest& request)
IPCReply ESDevice::SetUID(u32 uid, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != 8)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
@@ -207,20 +207,20 @@ IPCCommandResult ESDevice::SetUID(u32 uid, const IOCtlVRequest& request)
if (ret < 0)
{
ERROR_LOG_FMT(IOS_ES, "SetUID: Permission check failed with error {}", ret);
return GetDefaultReply(ret);
return IPCReply(ret);
}
const auto tmd = FindInstalledTMD(title_id);
if (!tmd.IsValid())
return GetDefaultReply(FS_ENOENT);
return IPCReply(FS_ENOENT);
if (!UpdateUIDAndGID(m_ios, tmd))
{
ERROR_LOG_FMT(IOS_ES, "SetUID: Failed to get UID for title {:016x}", title_id);
return GetDefaultReply(ES_SHORT_READ);
return IPCReply(ES_SHORT_READ);
}
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
bool ESDevice::LaunchTitle(u64 title_id, bool skip_reload)
@@ -380,11 +380,11 @@ ESDevice::ContextArray::iterator ESDevice::FindInactiveContext()
[](const auto& context) { return !context.active; });
}
IPCCommandResult ESDevice::Open(const OpenRequest& request)
std::optional<IPCReply> ESDevice::Open(const OpenRequest& request)
{
auto context = FindInactiveContext();
if (context == m_contexts.end())
return GetDefaultReply(ES_FD_EXHAUSTED);
return IPCReply{ES_FD_EXHAUSTED};
context->active = true;
context->uid = request.uid;
@@ -393,26 +393,26 @@ IPCCommandResult ESDevice::Open(const OpenRequest& request)
return Device::Open(request);
}
IPCCommandResult ESDevice::Close(u32 fd)
std::optional<IPCReply> ESDevice::Close(u32 fd)
{
auto context = FindActiveContext(fd);
if (context == m_contexts.end())
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
context->active = false;
context->ipc_fd = -1;
INFO_LOG_FMT(IOS_ES, "ES: Close");
m_is_active = false;
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult ESDevice::IOCtlV(const IOCtlVRequest& request)
std::optional<IPCReply> ESDevice::IOCtlV(const IOCtlVRequest& request)
{
DEBUG_LOG_FMT(IOS_ES, "{} ({:#x})", GetDeviceName(), request.request);
auto context = FindActiveContext(request.fd);
if (context == m_contexts.end())
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
switch (request.request)
{
@@ -562,29 +562,29 @@ IPCCommandResult ESDevice::IOCtlV(const IOCtlVRequest& request)
PanicAlertFmt("IOS-ES: Unimplemented ioctlv {:#x} ({} in vectors, {} io vectors)",
request.request, request.in_vectors.size(), request.io_vectors.size());
request.DumpUnknown(GetDeviceName(), Common::Log::IOS_ES, Common::Log::LERROR);
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
case IOCTL_ES_INVALID_3F:
default:
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
}
}
IPCCommandResult ESDevice::GetConsumption(const IOCtlVRequest& request)
IPCReply ESDevice::GetConsumption(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 2))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
// This is at least what crediar's ES module does
Memory::Write_U32(0, request.io_vectors[1].address);
INFO_LOG_FMT(IOS_ES, "IOCTL_ES_GETCONSUMPTION");
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult ESDevice::Launch(const IOCtlVRequest& request)
std::optional<IPCReply> ESDevice::Launch(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(2, 0))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
const u32 view = Memory::Read_U32(request.in_vectors[1].address);
@@ -598,41 +598,41 @@ IPCCommandResult ESDevice::Launch(const IOCtlVRequest& request)
// Prevent loading installed IOSes that are not emulated.
if (!IsEmulated(title_id))
return GetDefaultReply(FS_ENOENT);
return IPCReply(FS_ENOENT);
// IOS replies to the request through the mailbox on failure, and acks if the launch succeeds.
// Note: Launch will potentially reset the whole IOS state -- including this ES instance.
if (!LaunchTitle(title_id))
return GetDefaultReply(FS_ENOENT);
return IPCReply(FS_ENOENT);
// ES_LAUNCH involves restarting IOS, which results in two acknowledgements in a row
// (one from the previous IOS for this IPC request, and one from the new one as it boots).
// Nothing should be written to the command buffer if the launch succeeded for obvious reasons.
return GetNoReply();
return std::nullopt;
}
IPCCommandResult ESDevice::LaunchBC(const IOCtlVRequest& request)
std::optional<IPCReply> ESDevice::LaunchBC(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(0, 0))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
// Here, IOS checks the clock speed and prevents ioctlv 0x25 from being used in GC mode.
// An alternative way to do this is to check whether the current active IOS is MIOS.
if (m_ios.GetVersion() == 0x101)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
if (!LaunchTitle(0x0000000100000100))
return GetDefaultReply(FS_ENOENT);
return IPCReply(FS_ENOENT);
return GetNoReply();
return std::nullopt;
}
// This is technically an ioctlv in IOS's ES, but it is an internal API which cannot be
// used from the PowerPC (for unpatched and up-to-date IOSes anyway).
// So we block access to it from the IPC interface.
IPCCommandResult ESDevice::DIVerify(const IOCtlVRequest& request)
IPCReply ESDevice::DIVerify(const IOCtlVRequest& request)
{
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
}
static ReturnCode WriteTmdForDiVerify(FS::FileSystem* fs, const ES::TMDReader& tmd)
@@ -796,13 +796,13 @@ ReturnCode ESDevice::SetUpStreamKey(const u32 uid, const u8* ticket_view, const
&ticket_bytes[offsetof(ES::Ticket, title_key)], PID_ES);
}
IPCCommandResult ESDevice::SetUpStreamKey(const Context& context, const IOCtlVRequest& request)
IPCReply ESDevice::SetUpStreamKey(const Context& context, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(2, 1) ||
request.in_vectors[0].size != sizeof(ES::TicketView) ||
!ES::IsValidTMDSize(request.in_vectors[1].size) || request.io_vectors[0].size != sizeof(u32))
{
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
}
std::vector<u8> tmd_bytes(request.in_vectors[1].size);
@@ -810,22 +810,22 @@ IPCCommandResult ESDevice::SetUpStreamKey(const Context& context, const IOCtlVRe
const ES::TMDReader tmd{std::move(tmd_bytes)};
if (!tmd.IsValid())
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
u32 handle;
const ReturnCode ret =
SetUpStreamKey(context.uid, Memory::GetPointer(request.in_vectors[0].address), tmd, &handle);
Memory::Write_U32(handle, request.io_vectors[0].address);
return GetDefaultReply(ret);
return IPCReply(ret);
}
IPCCommandResult ESDevice::DeleteStreamKey(const IOCtlVRequest& request)
IPCReply ESDevice::DeleteStreamKey(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sizeof(u32))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u32 handle = Memory::Read_U32(request.in_vectors[0].address);
return GetDefaultReply(m_ios.GetIOSC().DeleteObject(handle, PID_ES));
return IPCReply(m_ios.GetIOSC().DeleteObject(handle, PID_ES));
}
bool ESDevice::IsActiveTitlePermittedByTicket(const u8* ticket_view) const
+71 -71
View File
@@ -48,9 +48,9 @@ public:
void DoState(PointerWrap& p) override;
IPCCommandResult Open(const OpenRequest& request) override;
IPCCommandResult Close(u32 fd) override;
IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;
std::optional<IPCReply> Open(const OpenRequest& request) override;
std::optional<IPCReply> Close(u32 fd) override;
std::optional<IPCReply> IOCtlV(const IOCtlVRequest& request) override;
struct TitleImportExportContext
{
@@ -261,84 +261,84 @@ private:
using ContextArray = std::array<Context, 3>;
// Title management
IPCCommandResult ImportTicket(const IOCtlVRequest& request);
IPCCommandResult ImportTmd(Context& context, const IOCtlVRequest& request);
IPCCommandResult ImportTitleInit(Context& context, const IOCtlVRequest& request);
IPCCommandResult ImportContentBegin(Context& context, const IOCtlVRequest& request);
IPCCommandResult ImportContentData(Context& context, const IOCtlVRequest& request);
IPCCommandResult ImportContentEnd(Context& context, const IOCtlVRequest& request);
IPCCommandResult ImportTitleDone(Context& context, const IOCtlVRequest& request);
IPCCommandResult ImportTitleCancel(Context& context, const IOCtlVRequest& request);
IPCCommandResult ExportTitleInit(Context& context, const IOCtlVRequest& request);
IPCCommandResult ExportContentBegin(Context& context, const IOCtlVRequest& request);
IPCCommandResult ExportContentData(Context& context, const IOCtlVRequest& request);
IPCCommandResult ExportContentEnd(Context& context, const IOCtlVRequest& request);
IPCCommandResult ExportTitleDone(Context& context, const IOCtlVRequest& request);
IPCCommandResult DeleteTitle(const IOCtlVRequest& request);
IPCCommandResult DeleteTitleContent(const IOCtlVRequest& request);
IPCCommandResult DeleteTicket(const IOCtlVRequest& request);
IPCCommandResult DeleteSharedContent(const IOCtlVRequest& request);
IPCCommandResult DeleteContent(const IOCtlVRequest& request);
IPCReply ImportTicket(const IOCtlVRequest& request);
IPCReply ImportTmd(Context& context, const IOCtlVRequest& request);
IPCReply ImportTitleInit(Context& context, const IOCtlVRequest& request);
IPCReply ImportContentBegin(Context& context, const IOCtlVRequest& request);
IPCReply ImportContentData(Context& context, const IOCtlVRequest& request);
IPCReply ImportContentEnd(Context& context, const IOCtlVRequest& request);
IPCReply ImportTitleDone(Context& context, const IOCtlVRequest& request);
IPCReply ImportTitleCancel(Context& context, const IOCtlVRequest& request);
IPCReply ExportTitleInit(Context& context, const IOCtlVRequest& request);
IPCReply ExportContentBegin(Context& context, const IOCtlVRequest& request);
IPCReply ExportContentData(Context& context, const IOCtlVRequest& request);
IPCReply ExportContentEnd(Context& context, const IOCtlVRequest& request);
IPCReply ExportTitleDone(Context& context, const IOCtlVRequest& request);
IPCReply DeleteTitle(const IOCtlVRequest& request);
IPCReply DeleteTitleContent(const IOCtlVRequest& request);
IPCReply DeleteTicket(const IOCtlVRequest& request);
IPCReply DeleteSharedContent(const IOCtlVRequest& request);
IPCReply DeleteContent(const IOCtlVRequest& request);
// Device identity and encryption
IPCCommandResult GetDeviceId(const IOCtlVRequest& request);
IPCCommandResult GetDeviceCertificate(const IOCtlVRequest& request);
IPCCommandResult CheckKoreaRegion(const IOCtlVRequest& request);
IPCCommandResult Sign(const IOCtlVRequest& request);
IPCCommandResult VerifySign(const IOCtlVRequest& request);
IPCCommandResult Encrypt(u32 uid, const IOCtlVRequest& request);
IPCCommandResult Decrypt(u32 uid, const IOCtlVRequest& request);
IPCReply GetDeviceId(const IOCtlVRequest& request);
IPCReply GetDeviceCertificate(const IOCtlVRequest& request);
IPCReply CheckKoreaRegion(const IOCtlVRequest& request);
IPCReply Sign(const IOCtlVRequest& request);
IPCReply VerifySign(const IOCtlVRequest& request);
IPCReply Encrypt(u32 uid, const IOCtlVRequest& request);
IPCReply Decrypt(u32 uid, const IOCtlVRequest& request);
// Misc
IPCCommandResult SetUID(u32 uid, const IOCtlVRequest& request);
IPCCommandResult GetTitleDirectory(const IOCtlVRequest& request);
IPCCommandResult GetTitleId(const IOCtlVRequest& request);
IPCCommandResult GetConsumption(const IOCtlVRequest& request);
IPCCommandResult Launch(const IOCtlVRequest& request);
IPCCommandResult LaunchBC(const IOCtlVRequest& request);
IPCCommandResult DIVerify(const IOCtlVRequest& request);
IPCCommandResult SetUpStreamKey(const Context& context, const IOCtlVRequest& request);
IPCCommandResult DeleteStreamKey(const IOCtlVRequest& request);
IPCReply SetUID(u32 uid, const IOCtlVRequest& request);
IPCReply GetTitleDirectory(const IOCtlVRequest& request);
IPCReply GetTitleId(const IOCtlVRequest& request);
IPCReply GetConsumption(const IOCtlVRequest& request);
std::optional<IPCReply> Launch(const IOCtlVRequest& request);
std::optional<IPCReply> LaunchBC(const IOCtlVRequest& request);
IPCReply DIVerify(const IOCtlVRequest& request);
IPCReply SetUpStreamKey(const Context& context, const IOCtlVRequest& request);
IPCReply DeleteStreamKey(const IOCtlVRequest& request);
// Title contents
IPCCommandResult OpenActiveTitleContent(u32 uid, const IOCtlVRequest& request);
IPCCommandResult OpenContent(u32 uid, const IOCtlVRequest& request);
IPCCommandResult ReadContent(u32 uid, const IOCtlVRequest& request);
IPCCommandResult CloseContent(u32 uid, const IOCtlVRequest& request);
IPCCommandResult SeekContent(u32 uid, const IOCtlVRequest& request);
IPCReply OpenActiveTitleContent(u32 uid, const IOCtlVRequest& request);
IPCReply OpenContent(u32 uid, const IOCtlVRequest& request);
IPCReply ReadContent(u32 uid, const IOCtlVRequest& request);
IPCReply CloseContent(u32 uid, const IOCtlVRequest& request);
IPCReply SeekContent(u32 uid, const IOCtlVRequest& request);
// Title information
IPCCommandResult GetTitleCount(const std::vector<u64>& titles, const IOCtlVRequest& request);
IPCCommandResult GetTitles(const std::vector<u64>& titles, const IOCtlVRequest& request);
IPCCommandResult GetOwnedTitleCount(const IOCtlVRequest& request);
IPCCommandResult GetOwnedTitles(const IOCtlVRequest& request);
IPCCommandResult GetTitleCount(const IOCtlVRequest& request);
IPCCommandResult GetTitles(const IOCtlVRequest& request);
IPCCommandResult GetBoot2Version(const IOCtlVRequest& request);
IPCCommandResult GetStoredContentsCount(const ES::TMDReader& tmd, const IOCtlVRequest& request);
IPCCommandResult GetStoredContents(const ES::TMDReader& tmd, const IOCtlVRequest& request);
IPCCommandResult GetStoredContentsCount(const IOCtlVRequest& request);
IPCCommandResult GetStoredContents(const IOCtlVRequest& request);
IPCCommandResult GetTMDStoredContentsCount(const IOCtlVRequest& request);
IPCCommandResult GetTMDStoredContents(const IOCtlVRequest& request);
IPCCommandResult GetStoredTMDSize(const IOCtlVRequest& request);
IPCCommandResult GetStoredTMD(const IOCtlVRequest& request);
IPCCommandResult GetSharedContentsCount(const IOCtlVRequest& request) const;
IPCCommandResult GetSharedContents(const IOCtlVRequest& request) const;
IPCReply GetTitleCount(const std::vector<u64>& titles, const IOCtlVRequest& request);
IPCReply GetTitles(const std::vector<u64>& titles, const IOCtlVRequest& request);
IPCReply GetOwnedTitleCount(const IOCtlVRequest& request);
IPCReply GetOwnedTitles(const IOCtlVRequest& request);
IPCReply GetTitleCount(const IOCtlVRequest& request);
IPCReply GetTitles(const IOCtlVRequest& request);
IPCReply GetBoot2Version(const IOCtlVRequest& request);
IPCReply GetStoredContentsCount(const ES::TMDReader& tmd, const IOCtlVRequest& request);
IPCReply GetStoredContents(const ES::TMDReader& tmd, const IOCtlVRequest& request);
IPCReply GetStoredContentsCount(const IOCtlVRequest& request);
IPCReply GetStoredContents(const IOCtlVRequest& request);
IPCReply GetTMDStoredContentsCount(const IOCtlVRequest& request);
IPCReply GetTMDStoredContents(const IOCtlVRequest& request);
IPCReply GetStoredTMDSize(const IOCtlVRequest& request);
IPCReply GetStoredTMD(const IOCtlVRequest& request);
IPCReply GetSharedContentsCount(const IOCtlVRequest& request) const;
IPCReply GetSharedContents(const IOCtlVRequest& request) const;
// Views for tickets and TMDs
IPCCommandResult GetTicketViewCount(const IOCtlVRequest& request);
IPCCommandResult GetTicketViews(const IOCtlVRequest& request);
IPCCommandResult GetV0TicketFromView(const IOCtlVRequest& request);
IPCCommandResult GetTicketSizeFromView(const IOCtlVRequest& request);
IPCCommandResult GetTicketFromView(const IOCtlVRequest& request);
IPCCommandResult GetTMDViewSize(const IOCtlVRequest& request);
IPCCommandResult GetTMDViews(const IOCtlVRequest& request);
IPCCommandResult DIGetTicketView(const IOCtlVRequest& request);
IPCCommandResult DIGetTMDViewSize(const IOCtlVRequest& request);
IPCCommandResult DIGetTMDView(const IOCtlVRequest& request);
IPCCommandResult DIGetTMDSize(const IOCtlVRequest& request);
IPCCommandResult DIGetTMD(const IOCtlVRequest& request);
IPCReply GetTicketViewCount(const IOCtlVRequest& request);
IPCReply GetTicketViews(const IOCtlVRequest& request);
IPCReply GetV0TicketFromView(const IOCtlVRequest& request);
IPCReply GetTicketSizeFromView(const IOCtlVRequest& request);
IPCReply GetTicketFromView(const IOCtlVRequest& request);
IPCReply GetTMDViewSize(const IOCtlVRequest& request);
IPCReply GetTMDViews(const IOCtlVRequest& request);
IPCReply DIGetTicketView(const IOCtlVRequest& request);
IPCReply DIGetTMDViewSize(const IOCtlVRequest& request);
IPCReply DIGetTMDView(const IOCtlVRequest& request);
IPCReply DIGetTMDSize(const IOCtlVRequest& request);
IPCReply DIGetTMD(const IOCtlVRequest& request);
ContextArray::iterator FindActiveContext(s32 fd);
ContextArray::iterator FindInactiveContext();
+24 -24
View File
@@ -27,23 +27,23 @@ ReturnCode ESDevice::GetDeviceId(u32* device_id) const
return IPC_SUCCESS;
}
IPCCommandResult ESDevice::GetDeviceId(const IOCtlVRequest& request)
IPCReply ESDevice::GetDeviceId(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(0, 1) || request.io_vectors[0].size != sizeof(u32))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
u32 device_id;
const ReturnCode ret = GetDeviceId(&device_id);
if (ret != IPC_SUCCESS)
return GetDefaultReply(ret);
return IPCReply(ret);
Memory::Write_U32(device_id, request.io_vectors[0].address);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult ESDevice::Encrypt(u32 uid, const IOCtlVRequest& request)
IPCReply ESDevice::Encrypt(u32 uid, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(3, 2))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
u32 keyIndex = Memory::Read_U32(request.in_vectors[0].address);
u8* source = Memory::GetPointer(request.in_vectors[2].address);
@@ -54,13 +54,13 @@ IPCCommandResult ESDevice::Encrypt(u32 uid, const IOCtlVRequest& request)
// TODO: Check whether the active title is allowed to encrypt.
const ReturnCode ret = m_ios.GetIOSC().Encrypt(keyIndex, iv, source, size, destination, PID_ES);
return GetDefaultReply(ret);
return IPCReply(ret);
}
IPCCommandResult ESDevice::Decrypt(u32 uid, const IOCtlVRequest& request)
IPCReply ESDevice::Decrypt(u32 uid, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(3, 2))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
u32 keyIndex = Memory::Read_U32(request.in_vectors[0].address);
u8* source = Memory::GetPointer(request.in_vectors[2].address);
@@ -71,38 +71,38 @@ IPCCommandResult ESDevice::Decrypt(u32 uid, const IOCtlVRequest& request)
// TODO: Check whether the active title is allowed to decrypt.
const ReturnCode ret = m_ios.GetIOSC().Decrypt(keyIndex, iv, source, size, destination, PID_ES);
return GetDefaultReply(ret);
return IPCReply(ret);
}
IPCCommandResult ESDevice::CheckKoreaRegion(const IOCtlVRequest& request)
IPCReply ESDevice::CheckKoreaRegion(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(0, 0))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
// note by DacoTaco : name is unknown, I just tried to name it SOMETHING.
// IOS70 has this to let system menu 4.2 check if the console is region changed. it returns
// -1017
// if the IOS didn't find the Korean keys and 0 if it does. 0 leads to a error 003
INFO_LOG_FMT(IOS_ES, "IOCTL_ES_CHECKKOREAREGION: Title checked for Korean keys.");
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
}
IPCCommandResult ESDevice::GetDeviceCertificate(const IOCtlVRequest& request)
IPCReply ESDevice::GetDeviceCertificate(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(0, 1) || request.io_vectors[0].size != 0x180)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
INFO_LOG_FMT(IOS_ES, "IOCTL_ES_GETDEVICECERT");
const IOS::CertECC cert = m_ios.GetIOSC().GetDeviceCertificate();
Memory::CopyToEmu(request.io_vectors[0].address, &cert, sizeof(cert));
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult ESDevice::Sign(const IOCtlVRequest& request)
IPCReply ESDevice::Sign(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 2))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
INFO_LOG_FMT(IOS_ES, "IOCTL_ES_SIGN");
u8* ap_cert_out = Memory::GetPointer(request.io_vectors[1].address);
@@ -111,10 +111,10 @@ IPCCommandResult ESDevice::Sign(const IOCtlVRequest& request)
u8* sig_out = Memory::GetPointer(request.io_vectors[0].address);
if (!m_title_context.active)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
m_ios.GetIOSC().Sign(sig_out, ap_cert_out, m_title_context.tmd.GetTitleId(), data, data_size);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
ReturnCode ESDevice::VerifySign(const std::vector<u8>& hash, const std::vector<u8>& ecc_signature,
@@ -185,12 +185,12 @@ ReturnCode ESDevice::VerifySign(const std::vector<u8>& hash, const std::vector<u
return IPC_SUCCESS;
}
IPCCommandResult ESDevice::VerifySign(const IOCtlVRequest& request)
IPCReply ESDevice::VerifySign(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(3, 0))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
if (request.in_vectors[1].size != sizeof(Common::ec::Signature))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
std::vector<u8> hash(request.in_vectors[0].size);
Memory::CopyFromEmu(hash.data(), request.in_vectors[0].address, hash.size());
@@ -201,6 +201,6 @@ IPCCommandResult ESDevice::VerifySign(const IOCtlVRequest& request)
std::vector<u8> certs(request.in_vectors[2].size);
Memory::CopyFromEmu(certs.data(), request.in_vectors[2].address, certs.size());
return GetDefaultReply(VerifySign(hash, ecc_signature, certs));
return IPCReply(VerifySign(hash, ecc_signature, certs));
}
} // namespace IOS::HLE
+18 -18
View File
@@ -46,13 +46,13 @@ s32 ESDevice::OpenContent(const ES::TMDReader& tmd, u16 content_index, u32 uid)
return FS_EFDEXHAUSTED;
}
IPCCommandResult ESDevice::OpenContent(u32 uid, const IOCtlVRequest& request)
IPCReply ESDevice::OpenContent(u32 uid, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(3, 0) || request.in_vectors[0].size != sizeof(u64) ||
request.in_vectors[1].size != sizeof(ES::TicketView) ||
request.in_vectors[2].size != sizeof(u32))
{
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
}
const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
@@ -61,27 +61,27 @@ IPCCommandResult ESDevice::OpenContent(u32 uid, const IOCtlVRequest& request)
const auto tmd = FindInstalledTMD(title_id);
if (!tmd.IsValid())
return GetDefaultReply(FS_ENOENT);
return IPCReply(FS_ENOENT);
return GetDefaultReply(OpenContent(tmd, content_index, uid));
return IPCReply(OpenContent(tmd, content_index, uid));
}
IPCCommandResult ESDevice::OpenActiveTitleContent(u32 caller_uid, const IOCtlVRequest& request)
IPCReply ESDevice::OpenActiveTitleContent(u32 caller_uid, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sizeof(u32))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u32 content_index = Memory::Read_U32(request.in_vectors[0].address);
if (!m_title_context.active)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
ES::UIDSys uid_map{m_ios.GetFS()};
const u32 uid = uid_map.GetOrInsertUIDForTitle(m_title_context.tmd.GetTitleId());
if (caller_uid != 0 && caller_uid != uid)
return GetDefaultReply(ES_EACCES);
return IPCReply(ES_EACCES);
return GetDefaultReply(OpenContent(m_title_context.tmd, content_index, caller_uid));
return IPCReply(OpenContent(m_title_context.tmd, content_index, caller_uid));
}
s32 ESDevice::ReadContent(u32 cfd, u8* buffer, u32 size, u32 uid)
@@ -99,16 +99,16 @@ s32 ESDevice::ReadContent(u32 cfd, u8* buffer, u32 size, u32 uid)
return result.Succeeded() ? *result : FS::ConvertResult(result.Error());
}
IPCCommandResult ESDevice::ReadContent(u32 uid, const IOCtlVRequest& request)
IPCReply ESDevice::ReadContent(u32 uid, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != sizeof(u32))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u32 cfd = Memory::Read_U32(request.in_vectors[0].address);
const u32 size = request.io_vectors[0].size;
const u32 addr = request.io_vectors[0].address;
return GetDefaultReply(ReadContent(cfd, Memory::GetPointer(addr), size, uid));
return IPCReply(ReadContent(cfd, Memory::GetPointer(addr), size, uid));
}
ReturnCode ESDevice::CloseContent(u32 cfd, u32 uid)
@@ -128,13 +128,13 @@ ReturnCode ESDevice::CloseContent(u32 cfd, u32 uid)
return IPC_SUCCESS;
}
IPCCommandResult ESDevice::CloseContent(u32 uid, const IOCtlVRequest& request)
IPCReply ESDevice::CloseContent(u32 uid, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sizeof(u32))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u32 cfd = Memory::Read_U32(request.in_vectors[0].address);
return GetDefaultReply(CloseContent(cfd, uid));
return IPCReply(CloseContent(cfd, uid));
}
s32 ESDevice::SeekContent(u32 cfd, u32 offset, SeekMode mode, u32 uid)
@@ -152,15 +152,15 @@ s32 ESDevice::SeekContent(u32 cfd, u32 offset, SeekMode mode, u32 uid)
return result.Succeeded() ? *result : FS::ConvertResult(result.Error());
}
IPCCommandResult ESDevice::SeekContent(u32 uid, const IOCtlVRequest& request)
IPCReply ESDevice::SeekContent(u32 uid, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(3, 0))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u32 cfd = Memory::Read_U32(request.in_vectors[0].address);
const u32 offset = Memory::Read_U32(request.in_vectors[1].address);
const SeekMode mode = static_cast<SeekMode>(Memory::Read_U32(request.in_vectors[2].address));
return GetDefaultReply(SeekContent(cfd, offset, mode, uid));
return IPCReply(SeekContent(cfd, offset, mode, uid));
}
} // namespace IOS::HLE
+49 -51
View File
@@ -16,31 +16,30 @@ namespace IOS::HLE
{
// Used by the GetStoredContents ioctlvs. This assumes that the first output vector
// is used for the content count (u32).
IPCCommandResult ESDevice::GetStoredContentsCount(const ES::TMDReader& tmd,
const IOCtlVRequest& request)
IPCReply ESDevice::GetStoredContentsCount(const ES::TMDReader& tmd, const IOCtlVRequest& request)
{
if (request.io_vectors[0].size != sizeof(u32) || !tmd.IsValid())
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u16 num_contents = static_cast<u16>(GetStoredContentsFromTMD(tmd).size());
Memory::Write_U32(num_contents, request.io_vectors[0].address);
INFO_LOG_FMT(IOS_ES, "GetStoredContentsCount ({:#x}): {} content(s) for {:016x}",
request.request, num_contents, tmd.GetTitleId());
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
// Used by the GetStoredContents ioctlvs. This assumes that the second input vector is used
// for the content count and the output vector is used to store a list of content IDs (u32s).
IPCCommandResult ESDevice::GetStoredContents(const ES::TMDReader& tmd, const IOCtlVRequest& request)
IPCReply ESDevice::GetStoredContents(const ES::TMDReader& tmd, const IOCtlVRequest& request)
{
if (!tmd.IsValid())
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
if (request.in_vectors[1].size != sizeof(u32) ||
request.io_vectors[0].size != Memory::Read_U32(request.in_vectors[1].address) * sizeof(u32))
{
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
}
const auto contents = GetStoredContentsFromTMD(tmd);
@@ -48,82 +47,81 @@ IPCCommandResult ESDevice::GetStoredContents(const ES::TMDReader& tmd, const IOC
for (u32 i = 0; i < std::min(static_cast<u32>(contents.size()), max_content_count); ++i)
Memory::Write_U32(contents[i].id, request.io_vectors[0].address + i * sizeof(u32));
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult ESDevice::GetStoredContentsCount(const IOCtlVRequest& request)
IPCReply ESDevice::GetStoredContentsCount(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != sizeof(u64))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
const ES::TMDReader tmd = FindInstalledTMD(title_id);
if (!tmd.IsValid())
return GetDefaultReply(FS_ENOENT);
return IPCReply(FS_ENOENT);
return GetStoredContentsCount(tmd, request);
}
IPCCommandResult ESDevice::GetStoredContents(const IOCtlVRequest& request)
IPCReply ESDevice::GetStoredContents(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(2, 1) || request.in_vectors[0].size != sizeof(u64))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
const ES::TMDReader tmd = FindInstalledTMD(title_id);
if (!tmd.IsValid())
return GetDefaultReply(FS_ENOENT);
return IPCReply(FS_ENOENT);
return GetStoredContents(tmd, request);
}
IPCCommandResult ESDevice::GetTMDStoredContentsCount(const IOCtlVRequest& request)
IPCReply ESDevice::GetTMDStoredContentsCount(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 1))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
std::vector<u8> tmd_bytes(request.in_vectors[0].size);
Memory::CopyFromEmu(tmd_bytes.data(), request.in_vectors[0].address, tmd_bytes.size());
return GetStoredContentsCount(ES::TMDReader{std::move(tmd_bytes)}, request);
}
IPCCommandResult ESDevice::GetTMDStoredContents(const IOCtlVRequest& request)
IPCReply ESDevice::GetTMDStoredContents(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(2, 1))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
std::vector<u8> tmd_bytes(request.in_vectors[0].size);
Memory::CopyFromEmu(tmd_bytes.data(), request.in_vectors[0].address, tmd_bytes.size());
const ES::TMDReader tmd{std::move(tmd_bytes)};
if (!tmd.IsValid())
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
std::vector<u8> cert_store;
ReturnCode ret = ReadCertStore(&cert_store);
if (ret != IPC_SUCCESS)
return GetDefaultReply(ret);
return IPCReply(ret);
ret = VerifyContainer(VerifyContainerType::TMD, VerifyMode::UpdateCertStore, tmd, cert_store);
if (ret != IPC_SUCCESS)
return GetDefaultReply(ret);
return IPCReply(ret);
return GetStoredContents(tmd, request);
}
IPCCommandResult ESDevice::GetTitleCount(const std::vector<u64>& titles,
const IOCtlVRequest& request)
IPCReply ESDevice::GetTitleCount(const std::vector<u64>& titles, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(0, 1) || request.io_vectors[0].size != 4)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
Memory::Write_U32(static_cast<u32>(titles.size()), request.io_vectors[0].address);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult ESDevice::GetTitles(const std::vector<u64>& titles, const IOCtlVRequest& request)
IPCReply ESDevice::GetTitles(const std::vector<u64>& titles, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 1))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const size_t max_count = Memory::Read_U32(request.in_vectors[0].address);
for (size_t i = 0; i < std::min(max_count, titles.size()); i++)
@@ -131,112 +129,112 @@ IPCCommandResult ESDevice::GetTitles(const std::vector<u64>& titles, const IOCtl
Memory::Write_U64(titles[i], request.io_vectors[0].address + static_cast<u32>(i) * sizeof(u64));
INFO_LOG_FMT(IOS_ES, " title {:016x}", titles[i]);
}
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult ESDevice::GetTitleCount(const IOCtlVRequest& request)
IPCReply ESDevice::GetTitleCount(const IOCtlVRequest& request)
{
const std::vector<u64> titles = GetInstalledTitles();
INFO_LOG_FMT(IOS_ES, "GetTitleCount: {} titles", titles.size());
return GetTitleCount(titles, request);
}
IPCCommandResult ESDevice::GetTitles(const IOCtlVRequest& request)
IPCReply ESDevice::GetTitles(const IOCtlVRequest& request)
{
return GetTitles(GetInstalledTitles(), request);
}
IPCCommandResult ESDevice::GetStoredTMDSize(const IOCtlVRequest& request)
IPCReply ESDevice::GetStoredTMDSize(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 1))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
const ES::TMDReader tmd = FindInstalledTMD(title_id);
if (!tmd.IsValid())
return GetDefaultReply(FS_ENOENT);
return IPCReply(FS_ENOENT);
const u32 tmd_size = static_cast<u32>(tmd.GetBytes().size());
Memory::Write_U32(tmd_size, request.io_vectors[0].address);
INFO_LOG_FMT(IOS_ES, "GetStoredTMDSize: {} bytes for {:016x}", tmd_size, title_id);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult ESDevice::GetStoredTMD(const IOCtlVRequest& request)
IPCReply ESDevice::GetStoredTMD(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(2, 1))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
const ES::TMDReader tmd = FindInstalledTMD(title_id);
if (!tmd.IsValid())
return GetDefaultReply(FS_ENOENT);
return IPCReply(FS_ENOENT);
// 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<u8>& raw_tmd = tmd.GetBytes();
if (raw_tmd.size() != request.io_vectors[0].size)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
Memory::CopyToEmu(request.io_vectors[0].address, raw_tmd.data(), raw_tmd.size());
INFO_LOG_FMT(IOS_ES, "GetStoredTMD: title {:016x} (buffer size: {})", title_id, MaxCount);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult ESDevice::GetOwnedTitleCount(const IOCtlVRequest& request)
IPCReply ESDevice::GetOwnedTitleCount(const IOCtlVRequest& request)
{
const std::vector<u64> titles = GetTitlesWithTickets();
INFO_LOG_FMT(IOS_ES, "GetOwnedTitleCount: {} titles", titles.size());
return GetTitleCount(titles, request);
}
IPCCommandResult ESDevice::GetOwnedTitles(const IOCtlVRequest& request)
IPCReply ESDevice::GetOwnedTitles(const IOCtlVRequest& request)
{
return GetTitles(GetTitlesWithTickets(), request);
}
IPCCommandResult ESDevice::GetBoot2Version(const IOCtlVRequest& request)
IPCReply ESDevice::GetBoot2Version(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(0, 1))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
INFO_LOG_FMT(IOS_ES, "IOCTL_ES_GETBOOT2VERSION");
// as of 26/02/2012, this was latest bootmii version
Memory::Write_U32(4, request.io_vectors[0].address);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult ESDevice::GetSharedContentsCount(const IOCtlVRequest& request) const
IPCReply ESDevice::GetSharedContentsCount(const IOCtlVRequest& request) const
{
if (!request.HasNumberOfValidVectors(0, 1) || request.io_vectors[0].size != sizeof(u32))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u32 count = GetSharedContentsCount();
Memory::Write_U32(count, request.io_vectors[0].address);
INFO_LOG_FMT(IOS_ES, "GetSharedContentsCount: {} contents", count);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult ESDevice::GetSharedContents(const IOCtlVRequest& request) const
IPCReply ESDevice::GetSharedContents(const IOCtlVRequest& request) const
{
if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != sizeof(u32))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u32 max_count = Memory::Read_U32(request.in_vectors[0].address);
if (request.io_vectors[0].size != 20 * max_count)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const std::vector<std::array<u8, 20>> hashes = GetSharedContents();
const u32 count = std::min(static_cast<u32>(hashes.size()), max_count);
Memory::CopyToEmu(request.io_vectors[0].address, hashes.data(), 20 * count);
INFO_LOG_FMT(IOS_ES, "GetSharedContents: {} contents ({} requested)", count, max_count);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
} // namespace IOS::HLE
+59 -60
View File
@@ -93,16 +93,16 @@ ReturnCode ESDevice::ImportTicket(const std::vector<u8>& ticket_bytes,
return IPC_SUCCESS;
}
IPCCommandResult ESDevice::ImportTicket(const IOCtlVRequest& request)
IPCReply ESDevice::ImportTicket(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(3, 0))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
std::vector<u8> bytes(request.in_vectors[0].size);
Memory::CopyFromEmu(bytes.data(), request.in_vectors[0].address, request.in_vectors[0].size);
std::vector<u8> cert_chain(request.in_vectors[1].size);
Memory::CopyFromEmu(cert_chain.data(), request.in_vectors[1].address, request.in_vectors[1].size);
return GetDefaultReply(ImportTicket(bytes, cert_chain));
return IPCReply(ImportTicket(bytes, cert_chain));
}
constexpr std::array<u8, 16> NULL_KEY{};
@@ -180,18 +180,18 @@ ReturnCode ESDevice::ImportTmd(Context& context, const std::vector<u8>& tmd_byte
return IPC_SUCCESS;
}
IPCCommandResult ESDevice::ImportTmd(Context& context, const IOCtlVRequest& request)
IPCReply ESDevice::ImportTmd(Context& context, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 0))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
if (!ES::IsValidTMDSize(request.in_vectors[0].size))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
std::vector<u8> tmd(request.in_vectors[0].size);
Memory::CopyFromEmu(tmd.data(), request.in_vectors[0].address, request.in_vectors[0].size);
return GetDefaultReply(ImportTmd(context, tmd, m_title_context.tmd.GetTitleId(),
m_title_context.tmd.GetTitleFlags()));
return IPCReply(ImportTmd(context, tmd, m_title_context.tmd.GetTitleId(),
m_title_context.tmd.GetTitleFlags()));
}
static ReturnCode InitTitleImportKey(const std::vector<u8>& ticket_bytes, IOSC& iosc,
@@ -266,19 +266,19 @@ ReturnCode ESDevice::ImportTitleInit(Context& context, const std::vector<u8>& tm
return IPC_SUCCESS;
}
IPCCommandResult ESDevice::ImportTitleInit(Context& context, const IOCtlVRequest& request)
IPCReply ESDevice::ImportTitleInit(Context& context, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(4, 0))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
if (!ES::IsValidTMDSize(request.in_vectors[0].size))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
std::vector<u8> tmd(request.in_vectors[0].size);
Memory::CopyFromEmu(tmd.data(), request.in_vectors[0].address, request.in_vectors[0].size);
std::vector<u8> certs(request.in_vectors[1].size);
Memory::CopyFromEmu(certs.data(), request.in_vectors[1].address, request.in_vectors[1].size);
return GetDefaultReply(ImportTitleInit(context, tmd, certs));
return IPCReply(ImportTitleInit(context, tmd, certs));
}
ReturnCode ESDevice::ImportContentBegin(Context& context, u64 title_id, u32 content_id)
@@ -324,14 +324,14 @@ ReturnCode ESDevice::ImportContentBegin(Context& context, u64 title_id, u32 cont
return static_cast<ReturnCode>(content_fd);
}
IPCCommandResult ESDevice::ImportContentBegin(Context& context, const IOCtlVRequest& request)
IPCReply ESDevice::ImportContentBegin(Context& context, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(2, 0))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
u32 content_id = Memory::Read_U32(request.in_vectors[1].address);
return GetDefaultReply(ImportContentBegin(context, title_id, content_id));
return IPCReply(ImportContentBegin(context, title_id, content_id));
}
ReturnCode ESDevice::ImportContentData(Context& context, u32 content_fd, const u8* data,
@@ -343,15 +343,14 @@ ReturnCode ESDevice::ImportContentData(Context& context, u32 content_fd, const u
return IPC_SUCCESS;
}
IPCCommandResult ESDevice::ImportContentData(Context& context, const IOCtlVRequest& request)
IPCReply ESDevice::ImportContentData(Context& context, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(2, 0))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
u32 content_fd = Memory::Read_U32(request.in_vectors[0].address);
u8* data_start = Memory::GetPointer(request.in_vectors[1].address);
return GetDefaultReply(
ImportContentData(context, content_fd, data_start, request.in_vectors[1].size));
return IPCReply(ImportContentData(context, content_fd, data_start, request.in_vectors[1].size));
}
static bool CheckIfContentHashMatches(const std::vector<u8>& content, const ES::Content& info)
@@ -429,13 +428,13 @@ ReturnCode ESDevice::ImportContentEnd(Context& context, u32 content_fd)
return IPC_SUCCESS;
}
IPCCommandResult ESDevice::ImportContentEnd(Context& context, const IOCtlVRequest& request)
IPCReply ESDevice::ImportContentEnd(Context& context, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 0))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
u32 content_fd = Memory::Read_U32(request.in_vectors[0].address);
return GetDefaultReply(ImportContentEnd(context, content_fd));
return IPCReply(ImportContentEnd(context, content_fd));
}
static bool HasAllRequiredContents(Kernel& ios, const ES::TMDReader& tmd)
@@ -492,12 +491,12 @@ ReturnCode ESDevice::ImportTitleDone(Context& context)
return IPC_SUCCESS;
}
IPCCommandResult ESDevice::ImportTitleDone(Context& context, const IOCtlVRequest& request)
IPCReply ESDevice::ImportTitleDone(Context& context, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(0, 0))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
return GetDefaultReply(ImportTitleDone(context));
return IPCReply(ImportTitleDone(context));
}
ReturnCode ESDevice::ImportTitleCancel(Context& context)
@@ -518,12 +517,12 @@ ReturnCode ESDevice::ImportTitleCancel(Context& context)
return IPC_SUCCESS;
}
IPCCommandResult ESDevice::ImportTitleCancel(Context& context, const IOCtlVRequest& request)
IPCReply ESDevice::ImportTitleCancel(Context& context, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(0, 0))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
return GetDefaultReply(ImportTitleCancel(context));
return IPCReply(ImportTitleCancel(context));
}
static bool CanDeleteTitle(u64 title_id)
@@ -541,13 +540,13 @@ ReturnCode ESDevice::DeleteTitle(u64 title_id)
return FS::ConvertResult(m_ios.GetFS()->Delete(PID_KERNEL, PID_KERNEL, title_dir));
}
IPCCommandResult ESDevice::DeleteTitle(const IOCtlVRequest& request)
IPCReply ESDevice::DeleteTitle(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != 8)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
return GetDefaultReply(DeleteTitle(title_id));
return IPCReply(DeleteTitle(title_id));
}
ReturnCode ESDevice::DeleteTicket(const u8* ticket_view)
@@ -590,14 +589,14 @@ ReturnCode ESDevice::DeleteTicket(const u8* ticket_view)
return IPC_SUCCESS;
}
IPCCommandResult ESDevice::DeleteTicket(const IOCtlVRequest& request)
IPCReply ESDevice::DeleteTicket(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 0) ||
request.in_vectors[0].size != sizeof(ES::TicketView))
{
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
}
return GetDefaultReply(DeleteTicket(Memory::GetPointer(request.in_vectors[0].address)));
return IPCReply(DeleteTicket(Memory::GetPointer(request.in_vectors[0].address)));
}
ReturnCode ESDevice::DeleteTitleContent(u64 title_id) const
@@ -619,11 +618,11 @@ ReturnCode ESDevice::DeleteTitleContent(u64 title_id) const
return IPC_SUCCESS;
}
IPCCommandResult ESDevice::DeleteTitleContent(const IOCtlVRequest& request)
IPCReply ESDevice::DeleteTitleContent(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sizeof(u64))
return GetDefaultReply(ES_EINVAL);
return GetDefaultReply(DeleteTitleContent(Memory::Read_U64(request.in_vectors[0].address)));
return IPCReply(ES_EINVAL);
return IPCReply(DeleteTitleContent(Memory::Read_U64(request.in_vectors[0].address)));
}
ReturnCode ESDevice::DeleteContent(u64 title_id, u32 content_id) const
@@ -644,15 +643,15 @@ ReturnCode ESDevice::DeleteContent(u64 title_id, u32 content_id) const
return FS::ConvertResult(m_ios.GetFS()->Delete(PID_KERNEL, PID_KERNEL, path));
}
IPCCommandResult ESDevice::DeleteContent(const IOCtlVRequest& request)
IPCReply ESDevice::DeleteContent(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(2, 0) || request.in_vectors[0].size != sizeof(u64) ||
request.in_vectors[1].size != sizeof(u32))
{
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
}
return GetDefaultReply(DeleteContent(Memory::Read_U64(request.in_vectors[0].address),
Memory::Read_U32(request.in_vectors[1].address)));
return IPCReply(DeleteContent(Memory::Read_U64(request.in_vectors[0].address),
Memory::Read_U32(request.in_vectors[1].address)));
}
ReturnCode ESDevice::ExportTitleInit(Context& context, u64 title_id, u8* tmd_bytes, u32 tmd_size,
@@ -684,18 +683,18 @@ ReturnCode ESDevice::ExportTitleInit(Context& context, u64 title_id, u8* tmd_byt
return IPC_SUCCESS;
}
IPCCommandResult ESDevice::ExportTitleInit(Context& context, const IOCtlVRequest& request)
IPCReply ESDevice::ExportTitleInit(Context& context, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != 8)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
u8* tmd_bytes = Memory::GetPointer(request.io_vectors[0].address);
const u32 tmd_size = request.io_vectors[0].size;
return GetDefaultReply(ExportTitleInit(context, title_id, tmd_bytes, tmd_size,
m_title_context.tmd.GetTitleId(),
m_title_context.tmd.GetTitleFlags()));
return IPCReply(ExportTitleInit(context, title_id, tmd_bytes, tmd_size,
m_title_context.tmd.GetTitleId(),
m_title_context.tmd.GetTitleFlags()));
}
ReturnCode ESDevice::ExportContentBegin(Context& context, u64 title_id, u32 content_id)
@@ -729,16 +728,16 @@ ReturnCode ESDevice::ExportContentBegin(Context& context, u64 title_id, u32 cont
return static_cast<ReturnCode>(ret);
}
IPCCommandResult ESDevice::ExportContentBegin(Context& context, const IOCtlVRequest& request)
IPCReply ESDevice::ExportContentBegin(Context& context, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(2, 0) || request.in_vectors[0].size != 8 ||
request.in_vectors[1].size != 4)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
const u32 content_id = Memory::Read_U32(request.in_vectors[1].address);
return GetDefaultReply(ExportContentBegin(context, title_id, content_id));
return IPCReply(ExportContentBegin(context, title_id, content_id));
}
ReturnCode ESDevice::ExportContentData(Context& context, u32 content_fd, u8* data, u32 data_size)
@@ -775,19 +774,19 @@ ReturnCode ESDevice::ExportContentData(Context& context, u32 content_fd, u8* dat
return IPC_SUCCESS;
}
IPCCommandResult ESDevice::ExportContentData(Context& context, const IOCtlVRequest& request)
IPCReply ESDevice::ExportContentData(Context& context, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != 4 ||
request.io_vectors[0].size == 0)
{
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
}
const u32 content_fd = Memory::Read_U32(request.in_vectors[0].address);
u8* data = Memory::GetPointer(request.io_vectors[0].address);
const u32 bytes_to_read = request.io_vectors[0].size;
return GetDefaultReply(ExportContentData(context, content_fd, data, bytes_to_read));
return IPCReply(ExportContentData(context, content_fd, data, bytes_to_read));
}
ReturnCode ESDevice::ExportContentEnd(Context& context, u32 content_fd)
@@ -797,13 +796,13 @@ ReturnCode ESDevice::ExportContentEnd(Context& context, u32 content_fd)
return CloseContent(content_fd, 0);
}
IPCCommandResult ESDevice::ExportContentEnd(Context& context, const IOCtlVRequest& request)
IPCReply ESDevice::ExportContentEnd(Context& context, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != 4)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u32 content_fd = Memory::Read_U32(request.in_vectors[0].address);
return GetDefaultReply(ExportContentEnd(context, content_fd));
return IPCReply(ExportContentEnd(context, content_fd));
}
ReturnCode ESDevice::ExportTitleDone(Context& context)
@@ -812,9 +811,9 @@ ReturnCode ESDevice::ExportTitleDone(Context& context)
return IPC_SUCCESS;
}
IPCCommandResult ESDevice::ExportTitleDone(Context& context, const IOCtlVRequest& request)
IPCReply ESDevice::ExportTitleDone(Context& context, const IOCtlVRequest& request)
{
return GetDefaultReply(ExportTitleDone(context));
return IPCReply(ExportTitleDone(context));
}
ReturnCode ESDevice::DeleteSharedContent(const std::array<u8, 20>& sha1) const
@@ -854,12 +853,12 @@ ReturnCode ESDevice::DeleteSharedContent(const std::array<u8, 20>& sha1) const
return IPC_SUCCESS;
}
IPCCommandResult ESDevice::DeleteSharedContent(const IOCtlVRequest& request)
IPCReply ESDevice::DeleteSharedContent(const IOCtlVRequest& request)
{
std::array<u8, 20> sha1;
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sha1.size())
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
Memory::CopyFromEmu(sha1.data(), request.in_vectors[0].address, request.in_vectors[0].size);
return GetDefaultReply(DeleteSharedContent(sha1));
return IPCReply(DeleteSharedContent(sha1));
}
} // namespace IOS::HLE
+58 -58
View File
@@ -36,10 +36,10 @@ static bool ShouldReturnFakeViewsForIOSes(u64 title_id, const TitleContext& cont
(ios && SConfig::GetInstance().m_disc_booted_from_game_list && disc_title);
}
IPCCommandResult ESDevice::GetTicketViewCount(const IOCtlVRequest& request)
IPCReply ESDevice::GetTicketViewCount(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 1))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
@@ -61,13 +61,13 @@ IPCCommandResult ESDevice::GetTicketViewCount(const IOCtlVRequest& request)
view_count);
Memory::Write_U32(view_count, request.io_vectors[0].address);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult ESDevice::GetTicketViews(const IOCtlVRequest& request)
IPCReply ESDevice::GetTicketViews(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(2, 1))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
const u32 maxViews = Memory::Read_U32(request.in_vectors[1].address);
@@ -96,7 +96,7 @@ IPCCommandResult ESDevice::GetTicketViews(const IOCtlVRequest& request)
INFO_LOG_FMT(IOS_ES, "IOCTL_ES_GETVIEWS for titleID: {:016x} (MaxViews = {})", TitleID, maxViews);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
ReturnCode ESDevice::GetV0TicketFromView(const u8* ticket_view, u8* ticket) const
@@ -157,106 +157,106 @@ ReturnCode ESDevice::GetTicketFromView(const u8* ticket_view, u8* ticket, u32* t
return IPC_SUCCESS;
}
IPCCommandResult ESDevice::GetV0TicketFromView(const IOCtlVRequest& request)
IPCReply ESDevice::GetV0TicketFromView(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 1) ||
request.in_vectors[0].size != sizeof(ES::TicketView) ||
request.io_vectors[0].size != sizeof(ES::Ticket))
{
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
}
return GetDefaultReply(GetV0TicketFromView(Memory::GetPointer(request.in_vectors[0].address),
Memory::GetPointer(request.io_vectors[0].address)));
return IPCReply(GetV0TicketFromView(Memory::GetPointer(request.in_vectors[0].address),
Memory::GetPointer(request.io_vectors[0].address)));
}
IPCCommandResult ESDevice::GetTicketSizeFromView(const IOCtlVRequest& request)
IPCReply ESDevice::GetTicketSizeFromView(const IOCtlVRequest& request)
{
u32 ticket_size = 0;
if (!request.HasNumberOfValidVectors(1, 1) ||
request.in_vectors[0].size != sizeof(ES::TicketView) ||
request.io_vectors[0].size != sizeof(ticket_size))
{
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
}
const ReturnCode ret =
GetTicketFromView(Memory::GetPointer(request.in_vectors[0].address), nullptr, &ticket_size);
Memory::Write_U32(ticket_size, request.io_vectors[0].address);
return GetDefaultReply(ret);
return IPCReply(ret);
}
IPCCommandResult ESDevice::GetTicketFromView(const IOCtlVRequest& request)
IPCReply ESDevice::GetTicketFromView(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(2, 1) ||
request.in_vectors[0].size != sizeof(ES::TicketView) ||
request.in_vectors[1].size != sizeof(u32))
{
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
}
u32 ticket_size = Memory::Read_U32(request.in_vectors[1].address);
if (ticket_size != request.io_vectors[0].size)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
return GetDefaultReply(GetTicketFromView(Memory::GetPointer(request.in_vectors[0].address),
Memory::GetPointer(request.io_vectors[0].address),
&ticket_size));
return IPCReply(GetTicketFromView(Memory::GetPointer(request.in_vectors[0].address),
Memory::GetPointer(request.io_vectors[0].address),
&ticket_size));
}
IPCCommandResult ESDevice::GetTMDViewSize(const IOCtlVRequest& request)
IPCReply ESDevice::GetTMDViewSize(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 1))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
const ES::TMDReader tmd = FindInstalledTMD(TitleID);
if (!tmd.IsValid())
return GetDefaultReply(FS_ENOENT);
return IPCReply(FS_ENOENT);
const u32 view_size = static_cast<u32>(tmd.GetRawView().size());
Memory::Write_U32(view_size, request.io_vectors[0].address);
INFO_LOG_FMT(IOS_ES, "GetTMDViewSize: {} bytes for title {:016x}", view_size, TitleID);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult ESDevice::GetTMDViews(const IOCtlVRequest& request)
IPCReply ESDevice::GetTMDViews(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(2, 1) ||
request.in_vectors[0].size != sizeof(ES::TMDHeader::title_id) ||
request.in_vectors[1].size != sizeof(u32) ||
Memory::Read_U32(request.in_vectors[1].address) != request.io_vectors[0].size)
{
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
}
const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
const ES::TMDReader tmd = FindInstalledTMD(title_id);
if (!tmd.IsValid())
return GetDefaultReply(FS_ENOENT);
return IPCReply(FS_ENOENT);
const std::vector<u8> raw_view = tmd.GetRawView();
if (request.io_vectors[0].size < raw_view.size())
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
Memory::CopyToEmu(request.io_vectors[0].address, raw_view.data(), raw_view.size());
INFO_LOG_FMT(IOS_ES, "GetTMDView: {} bytes for title {:016x}", raw_view.size(), title_id);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult ESDevice::DIGetTMDViewSize(const IOCtlVRequest& request)
IPCReply ESDevice::DIGetTMDViewSize(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 1))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
// Sanity check the TMD size.
if (request.in_vectors[0].size >= 4 * 1024 * 1024)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
if (request.io_vectors[0].size != sizeof(u32))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const bool has_tmd = request.in_vectors[0].size != 0;
size_t tmd_view_size = 0;
@@ -270,7 +270,7 @@ IPCCommandResult ESDevice::DIGetTMDViewSize(const IOCtlVRequest& request)
// Yes, this returns -1017, not ES_INVALID_TMD.
// IOS simply checks whether the TMD has all required content entries.
if (!tmd.IsValid())
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
tmd_view_size = tmd.GetRawView().size();
}
@@ -278,29 +278,29 @@ IPCCommandResult ESDevice::DIGetTMDViewSize(const IOCtlVRequest& request)
{
// If no TMD was passed in and no title is active, IOS returns -1017.
if (!m_title_context.active)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
tmd_view_size = m_title_context.tmd.GetRawView().size();
}
Memory::Write_U32(static_cast<u32>(tmd_view_size), request.io_vectors[0].address);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult ESDevice::DIGetTMDView(const IOCtlVRequest& request)
IPCReply ESDevice::DIGetTMDView(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(2, 1))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
// Sanity check the TMD size.
if (request.in_vectors[0].size >= 4 * 1024 * 1024)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
// Check whether the TMD view size is consistent.
if (request.in_vectors[1].size != sizeof(u32) ||
Memory::Read_U32(request.in_vectors[1].address) != request.io_vectors[0].size)
{
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
}
const bool has_tmd = request.in_vectors[0].size != 0;
@@ -313,7 +313,7 @@ IPCCommandResult ESDevice::DIGetTMDView(const IOCtlVRequest& request)
const ES::TMDReader tmd{std::move(tmd_bytes)};
if (!tmd.IsValid())
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
tmd_view = tmd.GetRawView();
}
@@ -321,31 +321,31 @@ IPCCommandResult ESDevice::DIGetTMDView(const IOCtlVRequest& request)
{
// If no TMD was passed in and no title is active, IOS returns -1017.
if (!m_title_context.active)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
tmd_view = m_title_context.tmd.GetRawView();
}
if (tmd_view.size() > request.io_vectors[0].size)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
Memory::CopyToEmu(request.io_vectors[0].address, tmd_view.data(), tmd_view.size());
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult ESDevice::DIGetTicketView(const IOCtlVRequest& request)
IPCReply ESDevice::DIGetTicketView(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 1) ||
request.io_vectors[0].size != sizeof(ES::TicketView))
{
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
}
const bool has_ticket_vector = request.in_vectors[0].size == sizeof(ES::Ticket);
// This ioctlv takes either a signed ticket or no ticket, in which case the ticket size must be 0.
if (!has_ticket_vector && request.in_vectors[0].size != 0)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
std::vector<u8> view;
@@ -354,7 +354,7 @@ IPCCommandResult ESDevice::DIGetTicketView(const IOCtlVRequest& request)
if (!has_ticket_vector)
{
if (!m_title_context.active)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
view = m_title_context.ticket.GetRawTicketView(0);
}
@@ -368,40 +368,40 @@ IPCCommandResult ESDevice::DIGetTicketView(const IOCtlVRequest& request)
}
Memory::CopyToEmu(request.io_vectors[0].address, view.data(), view.size());
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult ESDevice::DIGetTMDSize(const IOCtlVRequest& request)
IPCReply ESDevice::DIGetTMDSize(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(0, 1) || request.io_vectors[0].size != sizeof(u32))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
if (!m_title_context.active)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
Memory::Write_U32(static_cast<u32>(m_title_context.tmd.GetBytes().size()),
request.io_vectors[0].address);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult ESDevice::DIGetTMD(const IOCtlVRequest& request)
IPCReply ESDevice::DIGetTMD(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != sizeof(u32))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u32 tmd_size = Memory::Read_U32(request.in_vectors[0].address);
if (tmd_size != request.io_vectors[0].size)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
if (!m_title_context.active)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const std::vector<u8>& tmd_bytes = m_title_context.tmd.GetBytes();
if (static_cast<u32>(tmd_bytes.size()) > tmd_size)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
Memory::CopyToEmu(request.io_vectors[0].address, tmd_bytes.data(), tmd_bytes.size());
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
} // namespace IOS::HLE
+29 -29
View File
@@ -22,10 +22,10 @@ namespace IOS::HLE
{
using namespace IOS::HLE::FS;
static IPCCommandResult GetFSReply(s32 return_value, u64 extra_tb_ticks = 0)
static IPCReply GetFSReply(s32 return_value, u64 extra_tb_ticks = 0)
{
// According to hardware tests, FS takes at least 2700 TB ticks to reply to commands.
return {return_value, true, (2700 + extra_tb_ticks) * SystemTimers::TIMER_RATIO};
return IPCReply{return_value, (2700 + extra_tb_ticks) * SystemTimers::TIMER_RATIO};
}
/// Amount of TB ticks required for a superblock write to complete.
@@ -97,13 +97,13 @@ static u64 EstimateFileLookupTicks(const std::string& path, FileLookupMode mode)
///
/// A superblock flush takes a very large amount of time, so other delays are ignored
/// to simplify the implementation as they are insignificant.
static IPCCommandResult GetReplyForSuperblockOperation(ResultCode result)
static IPCReply GetReplyForSuperblockOperation(ResultCode result)
{
const u64 ticks = result == ResultCode::Success ? SUPERBLOCK_WRITE_TICKS : 0;
return GetFSReply(ConvertResult(result), ticks);
}
IPCCommandResult FSDevice::Open(const OpenRequest& request)
std::optional<IPCReply> FSDevice::Open(const OpenRequest& request)
{
if (m_fd_map.size() >= 16)
return GetFSReply(ConvertResult(ResultCode::NoFreeHandle));
@@ -130,7 +130,7 @@ IPCCommandResult FSDevice::Open(const OpenRequest& request)
return GetFSReply(IPC_SUCCESS, ticks);
}
IPCCommandResult FSDevice::Close(u32 fd)
std::optional<IPCReply> FSDevice::Close(u32 fd)
{
u64 ticks = 0;
if (m_fd_map[fd].fs_fd != INVALID_FD)
@@ -229,7 +229,7 @@ bool FSDevice::HasCacheForFile(u32 fd, u32 offset) const
return m_cache_fd == fd && m_cache_chain_index == chain_index;
}
IPCCommandResult FSDevice::Read(const ReadWriteRequest& request)
std::optional<IPCReply> FSDevice::Read(const ReadWriteRequest& request)
{
const Handle& handle = m_fd_map[request.fd];
if (handle.fs_fd == INVALID_FD)
@@ -247,7 +247,7 @@ IPCCommandResult FSDevice::Read(const ReadWriteRequest& request)
return GetFSReply(*result, ticks);
}
IPCCommandResult FSDevice::Write(const ReadWriteRequest& request)
std::optional<IPCReply> FSDevice::Write(const ReadWriteRequest& request)
{
const Handle& handle = m_fd_map[request.fd];
if (handle.fs_fd == INVALID_FD)
@@ -265,7 +265,7 @@ IPCCommandResult FSDevice::Write(const ReadWriteRequest& request)
return GetFSReply(*result, ticks);
}
IPCCommandResult FSDevice::Seek(const SeekRequest& request)
std::optional<IPCReply> FSDevice::Seek(const SeekRequest& request)
{
const Handle& handle = m_fd_map[request.fd];
if (handle.fs_fd == INVALID_FD)
@@ -318,11 +318,11 @@ static Result<T> GetParams(const IOCtlRequest& request)
return params;
}
IPCCommandResult FSDevice::IOCtl(const IOCtlRequest& request)
std::optional<IPCReply> FSDevice::IOCtl(const IOCtlRequest& request)
{
const auto it = m_fd_map.find(request.fd);
if (it == m_fd_map.end())
return GetDefaultReply(ConvertResult(ResultCode::Invalid));
return IPCReply(ConvertResult(ResultCode::Invalid));
switch (request.request)
{
@@ -353,11 +353,11 @@ IPCCommandResult FSDevice::IOCtl(const IOCtlRequest& request)
}
}
IPCCommandResult FSDevice::IOCtlV(const IOCtlVRequest& request)
std::optional<IPCReply> FSDevice::IOCtlV(const IOCtlVRequest& request)
{
const auto it = m_fd_map.find(request.fd);
if (it == m_fd_map.end())
return GetDefaultReply(ConvertResult(ResultCode::Invalid));
return IPCReply(ConvertResult(ResultCode::Invalid));
switch (request.request)
{
@@ -370,7 +370,7 @@ IPCCommandResult FSDevice::IOCtlV(const IOCtlVRequest& request)
}
}
IPCCommandResult FSDevice::Format(const Handle& handle, const IOCtlRequest& request)
IPCReply FSDevice::Format(const Handle& handle, const IOCtlRequest& request)
{
if (handle.uid != 0)
return GetFSReply(ConvertResult(ResultCode::AccessDenied));
@@ -379,7 +379,7 @@ IPCCommandResult FSDevice::Format(const Handle& handle, const IOCtlRequest& requ
return GetReplyForSuperblockOperation(result);
}
IPCCommandResult FSDevice::GetStats(const Handle& handle, const IOCtlRequest& request)
IPCReply FSDevice::GetStats(const Handle& handle, const IOCtlRequest& request)
{
if (request.buffer_out_size < sizeof(ISFSNandStats))
return GetFSReply(ConvertResult(ResultCode::Invalid));
@@ -387,7 +387,7 @@ IPCCommandResult FSDevice::GetStats(const Handle& handle, const IOCtlRequest& re
const Result<NandStats> stats = m_ios.GetFS()->GetNandStats();
LogResult(stats, "GetNandStats");
if (!stats)
return GetDefaultReply(ConvertResult(stats.Error()));
return IPCReply(ConvertResult(stats.Error()));
ISFSNandStats out;
out.cluster_size = stats->cluster_size;
@@ -398,10 +398,10 @@ IPCCommandResult FSDevice::GetStats(const Handle& handle, const IOCtlRequest& re
out.free_inodes = stats->free_inodes;
out.used_inodes = stats->used_inodes;
Memory::CopyToEmu(request.buffer_out, &out, sizeof(out));
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult FSDevice::CreateDirectory(const Handle& handle, const IOCtlRequest& request)
IPCReply FSDevice::CreateDirectory(const Handle& handle, const IOCtlRequest& request)
{
const auto params = GetParams<ISFSParams>(request);
if (!params)
@@ -413,7 +413,7 @@ IPCCommandResult FSDevice::CreateDirectory(const Handle& handle, const IOCtlRequ
return GetReplyForSuperblockOperation(result);
}
IPCCommandResult FSDevice::ReadDirectory(const Handle& handle, const IOCtlVRequest& request)
IPCReply FSDevice::ReadDirectory(const Handle& handle, const IOCtlVRequest& request)
{
if (request.in_vectors.empty() || request.in_vectors.size() != request.io_vectors.size() ||
request.in_vectors.size() > 2 || request.in_vectors[0].size != 64)
@@ -467,7 +467,7 @@ IPCCommandResult FSDevice::ReadDirectory(const Handle& handle, const IOCtlVReque
return GetFSReply(IPC_SUCCESS);
}
IPCCommandResult FSDevice::SetAttribute(const Handle& handle, const IOCtlRequest& request)
IPCReply FSDevice::SetAttribute(const Handle& handle, const IOCtlRequest& request)
{
const auto params = GetParams<ISFSParams>(request);
if (!params)
@@ -479,7 +479,7 @@ IPCCommandResult FSDevice::SetAttribute(const Handle& handle, const IOCtlRequest
return GetReplyForSuperblockOperation(result);
}
IPCCommandResult FSDevice::GetAttribute(const Handle& handle, const IOCtlRequest& request)
IPCReply FSDevice::GetAttribute(const Handle& handle, const IOCtlRequest& request)
{
if (request.buffer_in_size < 64 || request.buffer_out_size < sizeof(ISFSParams))
return GetFSReply(ConvertResult(ResultCode::Invalid));
@@ -503,7 +503,7 @@ IPCCommandResult FSDevice::GetAttribute(const Handle& handle, const IOCtlRequest
return GetFSReply(IPC_SUCCESS, ticks);
}
IPCCommandResult FSDevice::DeleteFile(const Handle& handle, const IOCtlRequest& request)
IPCReply FSDevice::DeleteFile(const Handle& handle, const IOCtlRequest& request)
{
if (request.buffer_in_size < 64)
return GetFSReply(ConvertResult(ResultCode::Invalid));
@@ -514,7 +514,7 @@ IPCCommandResult FSDevice::DeleteFile(const Handle& handle, const IOCtlRequest&
return GetReplyForSuperblockOperation(result);
}
IPCCommandResult FSDevice::RenameFile(const Handle& handle, const IOCtlRequest& request)
IPCReply FSDevice::RenameFile(const Handle& handle, const IOCtlRequest& request)
{
if (request.buffer_in_size < 64 * 2)
return GetFSReply(ConvertResult(ResultCode::Invalid));
@@ -526,7 +526,7 @@ IPCCommandResult FSDevice::RenameFile(const Handle& handle, const IOCtlRequest&
return GetReplyForSuperblockOperation(result);
}
IPCCommandResult FSDevice::CreateFile(const Handle& handle, const IOCtlRequest& request)
IPCReply FSDevice::CreateFile(const Handle& handle, const IOCtlRequest& request)
{
const auto params = GetParams<ISFSParams>(request);
if (!params)
@@ -538,7 +538,7 @@ IPCCommandResult FSDevice::CreateFile(const Handle& handle, const IOCtlRequest&
return GetReplyForSuperblockOperation(result);
}
IPCCommandResult FSDevice::SetFileVersionControl(const Handle& handle, const IOCtlRequest& request)
IPCReply FSDevice::SetFileVersionControl(const Handle& handle, const IOCtlRequest& request)
{
const auto params = GetParams<ISFSParams>(request);
if (!params)
@@ -550,7 +550,7 @@ IPCCommandResult FSDevice::SetFileVersionControl(const Handle& handle, const IOC
return GetFSReply(IPC_SUCCESS);
}
IPCCommandResult 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)
return GetFSReply(ConvertResult(ResultCode::Invalid));
@@ -558,16 +558,16 @@ IPCCommandResult FSDevice::GetFileStats(const Handle& handle, const IOCtlRequest
const Result<FileStatus> status = m_ios.GetFS()->GetFileStatus(handle.fs_fd);
LogResult(status, "GetFileStatus({})", handle.name.data());
if (!status)
return GetDefaultReply(ConvertResult(status.Error()));
return IPCReply(ConvertResult(status.Error()));
ISFSFileStats out;
out.size = status->size;
out.seek_position = status->offset;
Memory::CopyToEmu(request.buffer_out, &out, sizeof(out));
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult FSDevice::GetUsage(const Handle& handle, const IOCtlVRequest& request)
IPCReply FSDevice::GetUsage(const Handle& handle, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 2) || request.in_vectors[0].size != 64 ||
request.io_vectors[0].size != 4 || request.io_vectors[1].size != 4)
@@ -586,7 +586,7 @@ IPCCommandResult FSDevice::GetUsage(const Handle& handle, const IOCtlVRequest& r
return GetFSReply(IPC_SUCCESS);
}
IPCCommandResult FSDevice::Shutdown(const Handle& handle, const IOCtlRequest& request)
IPCReply FSDevice::Shutdown(const Handle& handle, const IOCtlRequest& request)
{
INFO_LOG_FMT(IOS_FS, "Shutdown");
return GetFSReply(IPC_SUCCESS);
+20 -20
View File
@@ -26,13 +26,13 @@ public:
void DoState(PointerWrap& p) override;
IPCCommandResult Open(const OpenRequest& request) override;
IPCCommandResult Close(u32 fd) override;
IPCCommandResult Read(const ReadWriteRequest& request) override;
IPCCommandResult Write(const ReadWriteRequest& request) override;
IPCCommandResult Seek(const SeekRequest& request) override;
IPCCommandResult IOCtl(const IOCtlRequest& request) override;
IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;
std::optional<IPCReply> Open(const OpenRequest& request) override;
std::optional<IPCReply> Close(u32 fd) override;
std::optional<IPCReply> Read(const ReadWriteRequest& request) override;
std::optional<IPCReply> Write(const ReadWriteRequest& request) override;
std::optional<IPCReply> Seek(const SeekRequest& request) override;
std::optional<IPCReply> IOCtl(const IOCtlRequest& request) override;
std::optional<IPCReply> IOCtlV(const IOCtlVRequest& request) override;
private:
struct Handle
@@ -62,19 +62,19 @@ private:
ISFS_IOCTL_SHUTDOWN = 13,
};
IPCCommandResult Format(const Handle& handle, const IOCtlRequest& request);
IPCCommandResult GetStats(const Handle& handle, const IOCtlRequest& request);
IPCCommandResult CreateDirectory(const Handle& handle, const IOCtlRequest& request);
IPCCommandResult ReadDirectory(const Handle& handle, const IOCtlVRequest& request);
IPCCommandResult SetAttribute(const Handle& handle, const IOCtlRequest& request);
IPCCommandResult GetAttribute(const Handle& handle, const IOCtlRequest& request);
IPCCommandResult DeleteFile(const Handle& handle, const IOCtlRequest& request);
IPCCommandResult RenameFile(const Handle& handle, const IOCtlRequest& request);
IPCCommandResult CreateFile(const Handle& handle, const IOCtlRequest& request);
IPCCommandResult SetFileVersionControl(const Handle& handle, const IOCtlRequest& request);
IPCCommandResult GetFileStats(const Handle& handle, const IOCtlRequest& request);
IPCCommandResult GetUsage(const Handle& handle, const IOCtlVRequest& request);
IPCCommandResult Shutdown(const Handle& handle, const IOCtlRequest& request);
IPCReply Format(const Handle& handle, const IOCtlRequest& request);
IPCReply GetStats(const Handle& handle, const IOCtlRequest& request);
IPCReply CreateDirectory(const Handle& handle, const IOCtlRequest& request);
IPCReply ReadDirectory(const Handle& handle, const IOCtlVRequest& request);
IPCReply SetAttribute(const Handle& handle, const IOCtlRequest& request);
IPCReply GetAttribute(const Handle& handle, const IOCtlRequest& request);
IPCReply DeleteFile(const Handle& handle, const IOCtlRequest& request);
IPCReply RenameFile(const Handle& handle, const IOCtlRequest& request);
IPCReply CreateFile(const Handle& handle, const IOCtlRequest& request);
IPCReply SetFileVersionControl(const Handle& handle, const IOCtlRequest& request);
IPCReply GetFileStats(const Handle& handle, const IOCtlRequest& request);
IPCReply GetUsage(const Handle& handle, const IOCtlVRequest& request);
IPCReply Shutdown(const Handle& handle, const IOCtlRequest& request);
u64 EstimateTicksForReadWrite(const Handle& handle, const ReadWriteRequest& request);
u64 SimulatePopulateFileCache(u32 fd, u32 offset, u32 file_size);
+34 -19
View File
@@ -518,14 +518,14 @@ std::shared_ptr<Device> EmulationKernel::GetDeviceByName(std::string_view device
}
// Returns the FD for the newly opened device (on success) or an error code.
IPCCommandResult Kernel::OpenDevice(OpenRequest& request)
std::optional<IPCReply> Kernel::OpenDevice(OpenRequest& request)
{
const s32 new_fd = GetFreeDeviceID();
INFO_LOG_FMT(IOS, "Opening {} (mode {}, fd {})", request.path, request.flags, new_fd);
if (new_fd < 0 || new_fd >= IPC_MAX_FDS)
{
ERROR_LOG_FMT(IOS, "Couldn't get a free fd, too many open files");
return IPCCommandResult{IPC_EMAX, true, 5000 * SystemTimers::TIMER_RATIO};
return IPCReply{IPC_EMAX, 5000_tbticks};
}
request.fd = new_fd;
@@ -547,22 +547,22 @@ IPCCommandResult Kernel::OpenDevice(OpenRequest& request)
if (!device)
{
ERROR_LOG_FMT(IOS, "Unknown device: {}", request.path);
return {IPC_ENOENT, true, 3700 * SystemTimers::TIMER_RATIO};
return IPCReply{IPC_ENOENT, 3700_tbticks};
}
IPCCommandResult result = device->Open(request);
if (result.return_value >= IPC_SUCCESS)
std::optional<IPCReply> result = device->Open(request);
if (result && result->return_value >= IPC_SUCCESS)
{
m_fdmap[new_fd] = device;
result.return_value = new_fd;
result->return_value = new_fd;
}
return result;
}
IPCCommandResult Kernel::HandleIPCCommand(const Request& request)
std::optional<IPCReply> Kernel::HandleIPCCommand(const Request& request)
{
if (request.command < IPC_CMD_OPEN || request.command > IPC_CMD_IOCTLV)
return IPCCommandResult{IPC_EINVAL, true, 978 * SystemTimers::TIMER_RATIO};
return IPCReply{IPC_EINVAL, 978_tbticks};
if (request.command == IPC_CMD_OPEN)
{
@@ -572,9 +572,9 @@ IPCCommandResult Kernel::HandleIPCCommand(const Request& request)
const auto device = (request.fd < IPC_MAX_FDS) ? m_fdmap[request.fd] : nullptr;
if (!device)
return IPCCommandResult{IPC_EINVAL, true, 550 * SystemTimers::TIMER_RATIO};
return IPCReply{IPC_EINVAL, 550_tbticks};
IPCCommandResult ret;
std::optional<IPCReply> ret;
const u64 wall_time_before = Common::Timer::GetTimeUs();
switch (request.command)
@@ -600,7 +600,7 @@ IPCCommandResult Kernel::HandleIPCCommand(const Request& request)
break;
default:
ASSERT_MSG(IOS, false, "Unexpected command: %x", request.command);
ret = IPCCommandResult{IPC_EINVAL, true, 978 * SystemTimers::TIMER_RATIO};
ret = IPCReply{IPC_EINVAL, 978_tbticks};
break;
}
@@ -618,18 +618,18 @@ IPCCommandResult Kernel::HandleIPCCommand(const Request& request)
void Kernel::ExecuteIPCCommand(const u32 address)
{
Request request{address};
IPCCommandResult result = HandleIPCCommand(request);
std::optional<IPCReply> result = HandleIPCCommand(request);
if (!result.send_reply)
if (!result)
return;
// Ensure replies happen in order
const s64 ticks_until_last_reply = m_last_reply_time - CoreTiming::GetTicks();
if (ticks_until_last_reply > 0)
result.reply_delay_ticks += ticks_until_last_reply;
m_last_reply_time = CoreTiming::GetTicks() + result.reply_delay_ticks;
result->reply_delay_ticks += ticks_until_last_reply;
m_last_reply_time = CoreTiming::GetTicks() + result->reply_delay_ticks;
EnqueueIPCReply(request, result.return_value, static_cast<int>(result.reply_delay_ticks));
EnqueueIPCReply(request, result->return_value, result->reply_delay_ticks);
}
// Happens AS SOON AS IPC gets a new pointer!
@@ -638,12 +638,11 @@ void Kernel::EnqueueIPCRequest(u32 address)
// Based on hardware tests, IOS takes between 5µs and 10µs to acknowledge an IPC request.
// Console 1: 456 TB ticks before ACK
// Console 2: 658 TB ticks before ACK
CoreTiming::ScheduleEvent(500 * SystemTimers::TIMER_RATIO, s_event_enqueue,
address | ENQUEUE_REQUEST_FLAG);
CoreTiming::ScheduleEvent(500_tbticks, s_event_enqueue, address | ENQUEUE_REQUEST_FLAG);
}
// Called to send a reply to an IOS syscall
void Kernel::EnqueueIPCReply(const Request& request, const s32 return_value, int cycles_in_future,
void Kernel::EnqueueIPCReply(const Request& request, const s32 return_value, s64 cycles_in_future,
CoreTiming::FromThread from)
{
Memory::Write_U32(static_cast<u32>(return_value), request.address + 4);
@@ -852,4 +851,20 @@ EmulationKernel* GetIOS()
{
return s_ios.get();
}
// Based on a hardware test, a device takes at least ~2700 ticks to reply to an IPC request.
// Depending on how much work a command performs, this can take much longer (10000+)
// especially if the NAND filesystem is accessed.
//
// Because we currently don't emulate timing very accurately, we should not return
// the minimum possible reply time (~960 ticks from the kernel or ~2700 from devices)
// but an average value, otherwise we are going to be much too fast in most cases.
IPCReply::IPCReply(s32 return_value_) : IPCReply(return_value_, 4000_tbticks)
{
}
IPCReply::IPCReply(s32 return_value_, u64 reply_delay_ticks_)
: return_value(return_value_), reply_delay_ticks(reply_delay_ticks_)
{
}
} // namespace IOS::HLE
+10 -5
View File
@@ -9,6 +9,7 @@
#include <map>
#include <memory>
#include <mutex>
#include <optional>
#include <string>
#include <string_view>
#include <vector>
@@ -33,10 +34,14 @@ class ESDevice;
struct Request;
struct OpenRequest;
struct IPCCommandResult
struct IPCReply
{
/// Constructs a reply with an average reply time.
/// Please avoid using this function if more accurate timings are known.
explicit IPCReply(s32 return_value_);
explicit IPCReply(s32 return_value_, u64 reply_delay_ticks_);
s32 return_value;
bool send_reply;
u64 reply_delay_ticks;
};
@@ -84,7 +89,7 @@ public:
void SDIO_EventNotify();
void EnqueueIPCRequest(u32 address);
void EnqueueIPCReply(const Request& request, s32 return_value, int cycles_in_future = 0,
void EnqueueIPCReply(const Request& request, s32 return_value, s64 cycles_in_future = 0,
CoreTiming::FromThread from = CoreTiming::FromThread::CPU);
void SetUidForPPC(u32 uid);
@@ -102,7 +107,7 @@ protected:
explicit Kernel(u64 title_id);
void ExecuteIPCCommand(u32 address);
IPCCommandResult HandleIPCCommand(const Request& request);
std::optional<IPCReply> HandleIPCCommand(const Request& request);
void EnqueueIPCAcknowledgement(u32 address, int cycles_in_future = 0);
void AddDevice(std::unique_ptr<Device> device);
@@ -110,7 +115,7 @@ protected:
void AddStaticDevices();
std::shared_ptr<Device> GetDeviceByName(std::string_view device_name);
s32 GetFreeDeviceID();
IPCCommandResult OpenDevice(OpenRequest& request);
std::optional<IPCReply> OpenDevice(OpenRequest& request);
bool m_is_responsible_for_nand_root = false;
u64 m_title_id = 0;
+60 -60
View File
@@ -285,11 +285,11 @@ static DefaultInterface GetSystemDefaultInterfaceOrFallback()
return GetSystemDefaultInterface().value_or(FALLBACK_VALUES);
}
IPCCommandResult NetIPTopDevice::IOCtl(const IOCtlRequest& request)
std::optional<IPCReply> NetIPTopDevice::IOCtl(const IOCtlRequest& request)
{
if (Core::WantsDeterminism())
{
return GetDefaultReply(IPC_EACCES);
return IPCReply(IPC_EACCES);
}
switch (request.request)
@@ -339,10 +339,10 @@ IPCCommandResult NetIPTopDevice::IOCtl(const IOCtlRequest& request)
break;
}
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult NetIPTopDevice::IOCtlV(const IOCtlVRequest& request)
std::optional<IPCReply> NetIPTopDevice::IOCtlV(const IOCtlVRequest& request)
{
switch (request.request)
{
@@ -361,7 +361,7 @@ IPCCommandResult NetIPTopDevice::IOCtlV(const IOCtlVRequest& request)
break;
}
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
void NetIPTopDevice::Update()
@@ -369,13 +369,13 @@ void NetIPTopDevice::Update()
WiiSockMan::GetInstance().Update();
}
IPCCommandResult NetIPTopDevice::HandleInitInterfaceRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleInitInterfaceRequest(const IOCtlRequest& request)
{
request.Log(GetDeviceName(), Common::Log::IOS_WC24);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult NetIPTopDevice::HandleSocketRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleSocketRequest(const IOCtlRequest& request)
{
const u32 af = Memory::Read_U32(request.buffer_in);
const u32 type = Memory::Read_U32(request.buffer_in + 4);
@@ -389,20 +389,20 @@ IPCCommandResult NetIPTopDevice::HandleSocketRequest(const IOCtlRequest& request
return_value, af, type, prot, request.buffer_in, request.buffer_in_size,
request.buffer_out, request.buffer_out_size);
return GetDefaultReply(return_value);
return IPCReply(return_value);
}
IPCCommandResult NetIPTopDevice::HandleICMPSocketRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleICMPSocketRequest(const IOCtlRequest& request)
{
const u32 pf = Memory::Read_U32(request.buffer_in);
WiiSockMan& sm = WiiSockMan::GetInstance();
const s32 return_value = sm.NewSocket(pf, SOCK_RAW, IPPROTO_ICMP);
INFO_LOG_FMT(IOS_NET, "IOCTL_SO_ICMPSOCKET({:x}) {}", pf, return_value);
return GetDefaultReply(return_value);
return IPCReply(return_value);
}
IPCCommandResult NetIPTopDevice::HandleCloseRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleCloseRequest(const IOCtlRequest& request)
{
const u32 fd = Memory::Read_U32(request.buffer_in);
WiiSockMan& sm = WiiSockMan::GetInstance();
@@ -412,24 +412,24 @@ IPCCommandResult NetIPTopDevice::HandleCloseRequest(const IOCtlRequest& request)
INFO_LOG_FMT(IOS_NET, "{}({:x}) {:x}", close_fn, fd, return_value);
return GetDefaultReply(return_value);
return IPCReply(return_value);
}
IPCCommandResult NetIPTopDevice::HandleDoSockRequest(const IOCtlRequest& request)
std::optional<IPCReply> NetIPTopDevice::HandleDoSockRequest(const IOCtlRequest& request)
{
const u32 fd = Memory::Read_U32(request.buffer_in);
WiiSockMan& sm = WiiSockMan::GetInstance();
sm.DoSock(fd, request, static_cast<NET_IOCTL>(request.request));
return GetNoReply();
return std::nullopt;
}
IPCCommandResult NetIPTopDevice::HandleShutdownRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleShutdownRequest(const IOCtlRequest& request)
{
if (request.buffer_in == 0 || request.buffer_in_size < 8)
{
ERROR_LOG_FMT(IOS_NET, "IOCTL_SO_SHUTDOWN = EINVAL, BufferIn: ({:08x}, {})", request.buffer_in,
request.buffer_in_size);
return GetDefaultReply(-SO_EINVAL);
return IPCReply(-SO_EINVAL);
}
const u32 fd = Memory::Read_U32(request.buffer_in);
@@ -438,20 +438,20 @@ IPCCommandResult NetIPTopDevice::HandleShutdownRequest(const IOCtlRequest& reque
const s32 return_value = sm.ShutdownSocket(fd, how);
INFO_LOG_FMT(IOS_NET, "IOCTL_SO_SHUTDOWN(fd={}, how={}) = {}", fd, how, return_value);
return GetDefaultReply(return_value);
return IPCReply(return_value);
}
IPCCommandResult NetIPTopDevice::HandleListenRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleListenRequest(const IOCtlRequest& request)
{
u32 fd = Memory::Read_U32(request.buffer_in);
u32 BACKLOG = Memory::Read_U32(request.buffer_in + 0x04);
u32 ret = listen(WiiSockMan::GetInstance().GetHostSocket(fd), BACKLOG);
request.Log(GetDeviceName(), Common::Log::IOS_WC24);
return GetDefaultReply(WiiSockMan::GetNetErrorCode(ret, "SO_LISTEN", false));
return IPCReply(WiiSockMan::GetNetErrorCode(ret, "SO_LISTEN", false));
}
IPCCommandResult NetIPTopDevice::HandleGetSockOptRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleGetSockOptRequest(const IOCtlRequest& request)
{
u32 fd = Memory::Read_U32(request.buffer_out);
u32 level = Memory::Read_U32(request.buffer_out + 4);
@@ -481,10 +481,10 @@ IPCCommandResult NetIPTopDevice::HandleGetSockOptRequest(const IOCtlRequest& req
Memory::Write_U32(last_error, request.buffer_out + 0x10);
}
return GetDefaultReply(return_value);
return IPCReply(return_value);
}
IPCCommandResult NetIPTopDevice::HandleSetSockOptRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleSetSockOptRequest(const IOCtlRequest& request)
{
const u32 fd = Memory::Read_U32(request.buffer_in);
const u32 level = Memory::Read_U32(request.buffer_in + 4);
@@ -508,7 +508,7 @@ IPCCommandResult NetIPTopDevice::HandleSetSockOptRequest(const IOCtlRequest& req
// TODO: bug booto about this, 0x2005 most likely timeout related, default value on Wii is ,
// 0x2001 is most likely tcpnodelay
if (level == 6 && (optname == 0x2005 || optname == 0x2001))
return GetDefaultReply(0);
return IPCReply(0);
// Do the level/optname translation
const int nat_level = MapWiiSockOptLevelToNative(level);
@@ -516,10 +516,10 @@ IPCCommandResult NetIPTopDevice::HandleSetSockOptRequest(const IOCtlRequest& req
const int ret = setsockopt(WiiSockMan::GetInstance().GetHostSocket(fd), nat_level, nat_optname,
reinterpret_cast<char*>(optval), optlen);
return GetDefaultReply(WiiSockMan::GetNetErrorCode(ret, "SO_SETSOCKOPT", false));
return IPCReply(WiiSockMan::GetNetErrorCode(ret, "SO_SETSOCKOPT", false));
}
IPCCommandResult NetIPTopDevice::HandleGetSockNameRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleGetSockNameRequest(const IOCtlRequest& request)
{
u32 fd = Memory::Read_U32(request.buffer_in);
@@ -542,10 +542,10 @@ IPCCommandResult NetIPTopDevice::HandleGetSockNameRequest(const IOCtlRequest& re
std::min<size_t>(sizeof(sa.sa_data), request.buffer_out_size - 2));
}
return GetDefaultReply(ret);
return IPCReply(ret);
}
IPCCommandResult NetIPTopDevice::HandleGetPeerNameRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleGetPeerNameRequest(const IOCtlRequest& request)
{
u32 fd = Memory::Read_U32(request.buffer_in);
@@ -567,19 +567,19 @@ IPCCommandResult NetIPTopDevice::HandleGetPeerNameRequest(const IOCtlRequest& re
}
INFO_LOG_FMT(IOS_NET, "IOCTL_SO_GETPEERNAME({:x})", fd);
return GetDefaultReply(ret);
return IPCReply(ret);
}
IPCCommandResult NetIPTopDevice::HandleGetHostIDRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleGetHostIDRequest(const IOCtlRequest& request)
{
const DefaultInterface interface = GetSystemDefaultInterfaceOrFallback();
const u32 host_ip = Common::swap32(interface.inet);
INFO_LOG_FMT(IOS_NET, "IOCTL_SO_GETHOSTID = {}.{}.{}.{}", host_ip >> 24, (host_ip >> 16) & 0xFF,
(host_ip >> 8) & 0xFF, host_ip & 0xFF);
return GetDefaultReply(host_ip);
return IPCReply(host_ip);
}
IPCCommandResult NetIPTopDevice::HandleInetAToNRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleInetAToNRequest(const IOCtlRequest& request)
{
const std::string hostname = Memory::GetString(request.buffer_in);
struct hostent* remoteHost = gethostbyname(hostname.c_str());
@@ -593,7 +593,7 @@ IPCCommandResult NetIPTopDevice::HandleInetAToNRequest(const IOCtlRequest& reque
hostname, request.buffer_in, request.buffer_in_size, request.buffer_out,
request.buffer_out_size);
return GetDefaultReply(0);
return IPCReply(0);
}
const auto ip = Common::swap32(reinterpret_cast<u8*>(remoteHost->h_addr_list[0]));
@@ -605,17 +605,17 @@ IPCCommandResult NetIPTopDevice::HandleInetAToNRequest(const IOCtlRequest& reque
hostname, request.buffer_in, request.buffer_in_size, request.buffer_out,
request.buffer_out_size, ip);
return GetDefaultReply(1);
return IPCReply(1);
}
IPCCommandResult NetIPTopDevice::HandleInetPToNRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleInetPToNRequest(const IOCtlRequest& request)
{
const std::string address = Memory::GetString(request.buffer_in);
INFO_LOG_FMT(IOS_NET, "IOCTL_SO_INETPTON (Translating: {})", address);
return GetDefaultReply(inet_pton(address.c_str(), Memory::GetPointer(request.buffer_out + 4)));
return IPCReply(inet_pton(address.c_str(), Memory::GetPointer(request.buffer_out + 4)));
}
IPCCommandResult NetIPTopDevice::HandleInetNToPRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleInetNToPRequest(const IOCtlRequest& request)
{
// u32 af = Memory::Read_U32(BufferIn);
// u32 validAddress = Memory::Read_U32(request.buffer_in + 4);
@@ -628,15 +628,15 @@ IPCCommandResult NetIPTopDevice::HandleInetNToPRequest(const IOCtlRequest& reque
INFO_LOG_FMT(IOS_NET, "IOCTL_SO_INETNTOP {}", ip_s);
Memory::CopyToEmu(request.buffer_out, reinterpret_cast<u8*>(ip_s), std::strlen(ip_s));
return GetDefaultReply(0);
return IPCReply(0);
}
IPCCommandResult NetIPTopDevice::HandlePollRequest(const IOCtlRequest& request)
std::optional<IPCReply> NetIPTopDevice::HandlePollRequest(const IOCtlRequest& request)
{
WiiSockMan& sm = WiiSockMan::GetInstance();
if (!request.buffer_in || !request.buffer_out)
return GetDefaultReply(-SO_EINVAL);
return IPCReply(-SO_EINVAL);
// Negative timeout indicates wait forever
const s64 timeout = static_cast<s64>(Memory::Read_U64(request.buffer_in));
@@ -645,7 +645,7 @@ IPCCommandResult NetIPTopDevice::HandlePollRequest(const IOCtlRequest& request)
if (nfds == 0 || nfds > WII_SOCKET_FD_MAX)
{
ERROR_LOG_FMT(IOS_NET, "IOCTL_SO_POLL failed: Invalid array size {}, ret={}", nfds, -SO_EINVAL);
return GetDefaultReply(-SO_EINVAL);
return IPCReply(-SO_EINVAL);
}
std::vector<pollfd_t> ufds(nfds);
@@ -671,15 +671,15 @@ IPCCommandResult NetIPTopDevice::HandlePollRequest(const IOCtlRequest& request)
// Prevents blocking emulation on a blocking poll
sm.AddPollCommand({request.address, request.buffer_out, std::move(ufds), timeout});
return GetNoReply();
return std::nullopt;
}
IPCCommandResult NetIPTopDevice::HandleGetHostByNameRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleGetHostByNameRequest(const IOCtlRequest& request)
{
if (request.buffer_out_size != 0x460)
{
ERROR_LOG_FMT(IOS_NET, "Bad buffer size for IOCTL_SO_GETHOSTBYNAME");
return GetDefaultReply(-1);
return IPCReply(-1);
}
const std::string hostname = Memory::GetString(request.buffer_in);
@@ -692,7 +692,7 @@ IPCCommandResult NetIPTopDevice::HandleGetHostByNameRequest(const IOCtlRequest&
request.buffer_out_size);
if (remoteHost == nullptr)
return GetDefaultReply(-1);
return IPCReply(-1);
for (int i = 0; remoteHost->h_aliases[i]; ++i)
{
@@ -715,7 +715,7 @@ IPCCommandResult NetIPTopDevice::HandleGetHostByNameRequest(const IOCtlRequest&
if (name_length > (GETHOSTBYNAME_IP_LIST_OFFSET - GETHOSTBYNAME_STRUCT_SIZE))
{
ERROR_LOG_FMT(IOS_NET, "Hostname too long in IOCTL_SO_GETHOSTBYNAME");
return GetDefaultReply(-1);
return IPCReply(-1);
}
Memory::CopyToEmu(request.buffer_out + GETHOSTBYNAME_STRUCT_SIZE, remoteHost->h_name,
name_length);
@@ -757,16 +757,16 @@ IPCCommandResult NetIPTopDevice::HandleGetHostByNameRequest(const IOCtlRequest&
Memory::Write_U16(AF_INET, request.buffer_out + 8);
Memory::Write_U16(sizeof(u32), request.buffer_out + 10);
return GetDefaultReply(0);
return IPCReply(0);
}
IPCCommandResult NetIPTopDevice::HandleICMPCancelRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleICMPCancelRequest(const IOCtlRequest& request)
{
ERROR_LOG_FMT(IOS_NET, "IOCTL_SO_ICMPCANCEL");
return GetDefaultReply(0);
return IPCReply(0);
}
IPCCommandResult NetIPTopDevice::HandleGetInterfaceOptRequest(const IOCtlVRequest& request)
IPCReply NetIPTopDevice::HandleGetInterfaceOptRequest(const IOCtlVRequest& request)
{
const u32 param = Memory::Read_U32(request.in_vectors[0].address);
const u32 param2 = Memory::Read_U32(request.in_vectors[0].address + 4);
@@ -777,7 +777,7 @@ IPCCommandResult NetIPTopDevice::HandleGetInterfaceOptRequest(const IOCtlVReques
if (param != 0xfffe)
{
WARN_LOG_FMT(IOS_NET, "GetInterfaceOpt: received invalid request with param0={:08x}", param);
return GetDefaultReply(SO_ERROR_INVALID_REQUEST);
return IPCReply(SO_ERROR_INVALID_REQUEST);
}
if (request.io_vectors[0].size >= 8)
@@ -939,26 +939,26 @@ IPCCommandResult NetIPTopDevice::HandleGetInterfaceOptRequest(const IOCtlVReques
break;
}
return GetDefaultReply(0);
return IPCReply(0);
}
IPCCommandResult NetIPTopDevice::HandleSendToRequest(const IOCtlVRequest& request)
std::optional<IPCReply> NetIPTopDevice::HandleSendToRequest(const IOCtlVRequest& request)
{
u32 fd = Memory::Read_U32(request.in_vectors[1].address);
WiiSockMan& sm = WiiSockMan::GetInstance();
sm.DoSock(fd, request, IOCTLV_SO_SENDTO);
return GetNoReply();
return std::nullopt;
}
IPCCommandResult NetIPTopDevice::HandleRecvFromRequest(const IOCtlVRequest& request)
std::optional<IPCReply> NetIPTopDevice::HandleRecvFromRequest(const IOCtlVRequest& request)
{
u32 fd = Memory::Read_U32(request.in_vectors[0].address);
WiiSockMan& sm = WiiSockMan::GetInstance();
sm.DoSock(fd, request, IOCTLV_SO_RECVFROM);
return GetNoReply();
return std::nullopt;
}
IPCCommandResult NetIPTopDevice::HandleGetAddressInfoRequest(const IOCtlVRequest& request)
IPCReply NetIPTopDevice::HandleGetAddressInfoRequest(const IOCtlVRequest& request)
{
addrinfo hints;
const bool hints_valid = request.in_vectors.size() > 2 && request.in_vectors[2].size;
@@ -1044,10 +1044,10 @@ IPCCommandResult NetIPTopDevice::HandleGetAddressInfoRequest(const IOCtlVRequest
}
request.Dump(GetDeviceName(), Common::Log::IOS_NET, Common::Log::LINFO);
return GetDefaultReply(ret);
return IPCReply(ret);
}
IPCCommandResult NetIPTopDevice::HandleICMPPingRequest(const IOCtlVRequest& request)
IPCReply NetIPTopDevice::HandleICMPPingRequest(const IOCtlVRequest& request)
{
struct
{
@@ -1111,6 +1111,6 @@ IPCCommandResult NetIPTopDevice::HandleICMPPingRequest(const IOCtlVRequest& requ
}
// TODO proper error codes
return GetDefaultReply(0);
return IPCReply(0);
}
} // namespace IOS::HLE

Some files were not shown because too many files have changed in this diff Show More