IOS/ES: Implement ES_DIGetTMDView (and GetTMDViewSize)

This is required for online updates to work in the system menu.
This commit is contained in:
Léo Lam 2017-03-05 01:57:12 +01:00
parent 7fa14169e9
commit 5049451a85
2 changed files with 104 additions and 5 deletions

View File

@ -397,10 +397,19 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
return GetViewCount(request);
case IOCTL_ES_GETVIEWS:
return GetViews(request);
case IOCTL_ES_DIGETTICKETVIEW:
return DIGetTicketView(request);
case IOCTL_ES_GETTMDVIEWCNT:
return GetTMDViewSize(request);
case IOCTL_ES_GETTMDVIEWS:
return GetTMDViews(request);
case IOCTL_ES_DIGETTMDVIEWSIZE:
return DIGetTMDViewSize(request);
case IOCTL_ES_DIGETTMDVIEW:
return DIGetTMDView(request);
case IOCTL_ES_GETCONSUMPTION:
return GetConsumption(request);
case IOCTL_ES_DELETETITLE:
@ -439,8 +448,6 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
return Sign(request);
case IOCTL_ES_GETBOOT2VERSION:
return GetBoot2Version(request);
case IOCTL_ES_DIGETTICKETVIEW:
return DIGetTicketView(request);
default:
request.DumpUnknown(GetDeviceName(), LogTypes::IOS);
break;
@ -1104,6 +1111,93 @@ IPCCommandResult ES::GetTMDViews(const IOCtlVRequest& request)
return GetDefaultReply(IPC_SUCCESS);
}
IPCCommandResult ES::DIGetTMDViewSize(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 1))
return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT);
// Sanity check the TMD size.
if (request.in_vectors[0].size >= 4 * 1024 * 1024)
return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT);
if (request.io_vectors[0].size != sizeof(u32))
return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT);
const bool has_tmd = request.in_vectors[0].size != 0;
size_t tmd_view_size = 0;
if (has_tmd)
{
std::vector<u8> tmd_bytes(request.in_vectors[0].size);
Memory::CopyFromEmu(tmd_bytes.data(), request.in_vectors[0].address, tmd_bytes.size());
const IOS::ES::TMDReader tmd{std::move(tmd_bytes)};
// 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_PARAMETER_SIZE_OR_ALIGNMENT);
tmd_view_size = tmd.GetRawView().size();
}
else
{
// If no TMD was passed in and no title is active, IOS returns -1017.
if (!s_title_context.active)
return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT);
tmd_view_size = s_title_context.tmd.GetRawView().size();
}
Memory::Write_U32(static_cast<u32>(tmd_view_size), request.io_vectors[0].address);
return GetDefaultReply(IPC_SUCCESS);
}
IPCCommandResult ES::DIGetTMDView(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(2, 1))
return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT);
// Sanity check the TMD size.
if (request.in_vectors[0].size >= 4 * 1024 * 1024)
return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT);
// 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_PARAMETER_SIZE_OR_ALIGNMENT);
}
const bool has_tmd = request.in_vectors[0].size != 0;
std::vector<u8> tmd_view;
if (has_tmd)
{
std::vector<u8> tmd_bytes(request.in_vectors[0].size);
Memory::CopyFromEmu(tmd_bytes.data(), request.in_vectors[0].address, tmd_bytes.size());
const IOS::ES::TMDReader tmd{std::move(tmd_bytes)};
if (!tmd.IsValid())
return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT);
tmd_view = tmd.GetRawView();
}
else
{
// If no TMD was passed in and no title is active, IOS returns -1017.
if (!s_title_context.active)
return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT);
tmd_view = s_title_context.tmd.GetRawView();
}
if (tmd_view.size() != request.io_vectors[0].size)
return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT);
Memory::CopyToEmu(request.io_vectors[0].address, tmd_view.data(), tmd_view.size());
return GetDefaultReply(IPC_SUCCESS);
}
IPCCommandResult ES::GetConsumption(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 2))

View File

@ -77,8 +77,8 @@ private:
IOCTL_ES_GETCONSUMPTION = 0x16,
IOCTL_ES_DELETETITLE = 0x17,
IOCTL_ES_DELETETICKET = 0x18,
// IOCTL_ES_DIGETTMDVIEWSIZE = 0x19,
// IOCTL_ES_DIGETTMDVIEW = 0x1A,
IOCTL_ES_DIGETTMDVIEWSIZE = 0x19,
IOCTL_ES_DIGETTMDVIEW = 0x1A,
IOCTL_ES_DIGETTICKETVIEW = 0x1B,
IOCTL_ES_DIVERIFY = 0x1C,
IOCTL_ES_GETTITLEDIR = 0x1D,
@ -177,8 +177,14 @@ private:
IPCCommandResult GetViewCount(const IOCtlVRequest& request);
IPCCommandResult GetViews(const IOCtlVRequest& request);
IPCCommandResult DIGetTicketView(const IOCtlVRequest& request);
IPCCommandResult GetTMDViewSize(const IOCtlVRequest& request);
IPCCommandResult GetTMDViews(const IOCtlVRequest& request);
IPCCommandResult DIGetTMDViewSize(const IOCtlVRequest& request);
IPCCommandResult DIGetTMDView(const IOCtlVRequest& request);
IPCCommandResult GetConsumption(const IOCtlVRequest& request);
IPCCommandResult DeleteTitle(const IOCtlVRequest& request);
IPCCommandResult DeleteTicket(const IOCtlVRequest& request);
@ -200,7 +206,6 @@ private:
IPCCommandResult GetDeviceCertificate(const IOCtlVRequest& request);
IPCCommandResult Sign(const IOCtlVRequest& request);
IPCCommandResult GetBoot2Version(const IOCtlVRequest& request);
IPCCommandResult DIGetTicketView(const IOCtlVRequest& request);
static bool LaunchIOS(u64 ios_title_id);
static bool LaunchPPCTitle(u64 title_id, bool skip_reload);