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 committed 2021-02-13 20:15:30 +01:00
1 parent f52aa3d041
commit d0136dd7c2
61 files changed
+872 -873

No files matched your search

+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