Merge pull request #4743 from lioncash/es
ES: Separate IOCtlV code out into constituent functions
This commit is contained in:
commit
66160c2781
|
@ -249,15 +249,101 @@ u32 ES::OpenTitleContent(u32 CFD, u64 TitleID, u16 Index)
|
|||
IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
|
||||
{
|
||||
DEBUG_LOG(IOS_ES, "%s (0x%x)", GetDeviceName().c_str(), request.request);
|
||||
|
||||
// Clear the IO buffers. Note that this is unsafe for other ioctlvs.
|
||||
for (const auto& io_vector : request.io_vectors)
|
||||
{
|
||||
if (!request.HasInputVectorWithAddress(io_vector.address))
|
||||
Memory::Memset(io_vector.address, 0, io_vector.size);
|
||||
}
|
||||
|
||||
switch (request.request)
|
||||
{
|
||||
case IOCTL_ES_ADDTICKET:
|
||||
return AddTicket(request);
|
||||
case IOCTL_ES_ADDTITLESTART:
|
||||
return AddTitleStart(request);
|
||||
case IOCTL_ES_ADDCONTENTSTART:
|
||||
return AddContentStart(request);
|
||||
case IOCTL_ES_ADDCONTENTDATA:
|
||||
return AddContentData(request);
|
||||
case IOCTL_ES_ADDCONTENTFINISH:
|
||||
return AddContentFinish(request);
|
||||
case IOCTL_ES_ADDTITLEFINISH:
|
||||
return AddTitleFinish(request);
|
||||
case IOCTL_ES_GETDEVICEID:
|
||||
return ESGetDeviceID(request);
|
||||
case IOCTL_ES_GETTITLECONTENTSCNT:
|
||||
return GetTitleContentsCount(request);
|
||||
case IOCTL_ES_GETTITLECONTENTS:
|
||||
return GetTitleContents(request);
|
||||
case IOCTL_ES_OPENTITLECONTENT:
|
||||
return OpenTitleContent(request);
|
||||
case IOCTL_ES_OPENCONTENT:
|
||||
return OpenContent(request);
|
||||
case IOCTL_ES_READCONTENT:
|
||||
return ReadContent(request);
|
||||
case IOCTL_ES_CLOSECONTENT:
|
||||
return CloseContent(request);
|
||||
case IOCTL_ES_SEEKCONTENT:
|
||||
return SeekContent(request);
|
||||
case IOCTL_ES_GETTITLEDIR:
|
||||
return GetTitleDirectory(request);
|
||||
case IOCTL_ES_GETTITLEID:
|
||||
return GetTitleID(request);
|
||||
case IOCTL_ES_SETUID:
|
||||
return SetUID(request);
|
||||
case IOCTL_ES_GETTITLECNT:
|
||||
return GetTitleCount(request);
|
||||
case IOCTL_ES_GETTITLES:
|
||||
return GetTitles(request);
|
||||
case IOCTL_ES_GETVIEWCNT:
|
||||
return GetViewCount(request);
|
||||
case IOCTL_ES_GETVIEWS:
|
||||
return GetViews(request);
|
||||
case IOCTL_ES_GETTMDVIEWCNT:
|
||||
return GetTMDViewCount(request);
|
||||
case IOCTL_ES_GETTMDVIEWS:
|
||||
return GetTMDViews(request);
|
||||
case IOCTL_ES_GETCONSUMPTION:
|
||||
return GetConsumption(request);
|
||||
case IOCTL_ES_DELETETICKET:
|
||||
return DeleteTicket(request);
|
||||
case IOCTL_ES_DELETETITLECONTENT:
|
||||
return DeleteTitleContent(request);
|
||||
case IOCTL_ES_GETSTOREDTMDSIZE:
|
||||
return GetStoredTMDSize(request);
|
||||
case IOCTL_ES_GETSTOREDTMD:
|
||||
return GetStoredTMD(request);
|
||||
case IOCTL_ES_ENCRYPT:
|
||||
return Encrypt(request);
|
||||
case IOCTL_ES_DECRYPT:
|
||||
return Decrypt(request);
|
||||
case IOCTL_ES_LAUNCH:
|
||||
return Launch(request);
|
||||
case IOCTL_ES_CHECKKOREAREGION:
|
||||
return CheckKoreaRegion(request);
|
||||
case IOCTL_ES_GETDEVICECERT:
|
||||
return GetDeviceCertificate(request);
|
||||
case IOCTL_ES_SIGN:
|
||||
return Sign(request);
|
||||
case IOCTL_ES_GETBOOT2VERSION:
|
||||
return GetBoot2Version(request);
|
||||
|
||||
// Unsupported functions
|
||||
case IOCTL_ES_DIGETTICKETVIEW:
|
||||
return DIGetTicketView(request);
|
||||
case IOCTL_ES_GETOWNEDTITLECNT:
|
||||
return GetOwnedTitleCount(request);
|
||||
default:
|
||||
request.DumpUnknown(GetDeviceName(), LogTypes::IOS);
|
||||
break;
|
||||
}
|
||||
|
||||
return GetDefaultReply(IPC_SUCCESS);
|
||||
}
|
||||
|
||||
IPCCommandResult ES::AddTicket(const IOCtlVRequest& request)
|
||||
{
|
||||
_dbg_assert_msg_(IOS_ES, request.in_vectors.size() == 3,
|
||||
"IOCTL_ES_ADDTICKET wrong number of inputs");
|
||||
|
@ -266,10 +352,11 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
|
|||
std::vector<u8> ticket(request.in_vectors[0].size);
|
||||
Memory::CopyFromEmu(ticket.data(), request.in_vectors[0].address, request.in_vectors[0].size);
|
||||
DiscIO::AddTicket(ticket);
|
||||
break;
|
||||
|
||||
return GetDefaultReply(IPC_SUCCESS);
|
||||
}
|
||||
|
||||
case IOCTL_ES_ADDTITLESTART:
|
||||
IPCCommandResult ES::AddTitleStart(const IOCtlVRequest& request)
|
||||
{
|
||||
_dbg_assert_msg_(IOS_ES, request.in_vectors.size() == 4,
|
||||
"IOCTL_ES_ADDTITLESTART wrong number of inputs");
|
||||
|
@ -292,10 +379,11 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
|
|||
|
||||
File::IOFile fp(tmd_path, "wb");
|
||||
fp.WriteBytes(tmd.data(), tmd.size());
|
||||
break;
|
||||
|
||||
return GetDefaultReply(IPC_SUCCESS);
|
||||
}
|
||||
|
||||
case IOCTL_ES_ADDCONTENTSTART:
|
||||
IPCCommandResult ES::AddContentStart(const IOCtlVRequest& request)
|
||||
{
|
||||
_dbg_assert_msg_(IOS_ES, request.in_vectors.size() == 2,
|
||||
"IOCTL_ES_ADDCONTENTSTART wrong number of inputs");
|
||||
|
@ -332,7 +420,7 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
|
|||
return GetDefaultReply(content_fd);
|
||||
}
|
||||
|
||||
case IOCTL_ES_ADDCONTENTDATA:
|
||||
IPCCommandResult ES::AddContentData(const IOCtlVRequest& request)
|
||||
{
|
||||
_dbg_assert_msg_(IOS_ES, request.in_vectors.size() == 2,
|
||||
"IOCTL_ES_ADDCONTENTDATA wrong number of inputs");
|
||||
|
@ -345,10 +433,10 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
|
|||
u8* data_start = Memory::GetPointer(request.in_vectors[1].address);
|
||||
u8* data_end = data_start + request.in_vectors[1].size;
|
||||
m_addtitle_content_buffer.insert(m_addtitle_content_buffer.end(), data_start, data_end);
|
||||
break;
|
||||
return GetDefaultReply(IPC_SUCCESS);
|
||||
}
|
||||
|
||||
case IOCTL_ES_ADDCONTENTFINISH:
|
||||
IPCCommandResult ES::AddContentFinish(const IOCtlVRequest& request)
|
||||
{
|
||||
_dbg_assert_msg_(IOS_ES, request.in_vectors.size() == 1,
|
||||
"IOCTL_ES_ADDCONTENTFINISH wrong number of inputs");
|
||||
|
@ -389,16 +477,16 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
|
|||
fp.WriteBytes(decrypted_data.data(), decrypted_data.size());
|
||||
|
||||
m_addtitle_content_id = 0xFFFFFFFF;
|
||||
break;
|
||||
return GetDefaultReply(IPC_SUCCESS);
|
||||
}
|
||||
|
||||
case IOCTL_ES_ADDTITLEFINISH:
|
||||
IPCCommandResult ES::AddTitleFinish(const IOCtlVRequest& request)
|
||||
{
|
||||
INFO_LOG(IOS_ES, "IOCTL_ES_ADDTITLEFINISH");
|
||||
break;
|
||||
return GetDefaultReply(IPC_SUCCESS);
|
||||
}
|
||||
|
||||
case IOCTL_ES_GETDEVICEID:
|
||||
IPCCommandResult ES::ESGetDeviceID(const IOCtlVRequest& request)
|
||||
{
|
||||
_dbg_assert_msg_(IOS_ES, request.io_vectors.size() == 1, "IOCTL_ES_GETDEVICEID no io vectors");
|
||||
|
||||
|
@ -408,7 +496,7 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
|
|||
return GetDefaultReply(IPC_SUCCESS);
|
||||
}
|
||||
|
||||
case IOCTL_ES_GETTITLECONTENTSCNT:
|
||||
IPCCommandResult ES::GetTitleContentsCount(const IOCtlVRequest& request)
|
||||
{
|
||||
_dbg_assert_(IOS_ES, request.in_vectors.size() == 1);
|
||||
_dbg_assert_(IOS_ES, request.io_vectors.size() == 1);
|
||||
|
@ -438,9 +526,8 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
|
|||
|
||||
return GetDefaultReply(return_value);
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_ES_GETTITLECONTENTS:
|
||||
IPCCommandResult ES::GetTitleContents(const IOCtlVRequest& request)
|
||||
{
|
||||
_dbg_assert_msg_(IOS_ES, request.in_vectors.size() == 2,
|
||||
"IOCTL_ES_GETTITLECONTENTS bad in buffer");
|
||||
|
@ -470,9 +557,8 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
|
|||
|
||||
return GetDefaultReply(return_value);
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_ES_OPENTITLECONTENT:
|
||||
IPCCommandResult ES::OpenTitleContent(const IOCtlVRequest& request)
|
||||
{
|
||||
_dbg_assert_(IOS_ES, request.in_vectors.size() == 3);
|
||||
_dbg_assert_(IOS_ES, request.io_vectors.size() == 0);
|
||||
|
@ -487,9 +573,8 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
|
|||
|
||||
return GetDefaultReply(CFD);
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_ES_OPENCONTENT:
|
||||
IPCCommandResult ES::OpenContent(const IOCtlVRequest& request)
|
||||
{
|
||||
_dbg_assert_(IOS_ES, request.in_vectors.size() == 1);
|
||||
_dbg_assert_(IOS_ES, request.io_vectors.size() == 0);
|
||||
|
@ -500,9 +585,8 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
|
|||
|
||||
return GetDefaultReply(CFD);
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_ES_READCONTENT:
|
||||
IPCCommandResult ES::ReadContent(const IOCtlVRequest& request)
|
||||
{
|
||||
_dbg_assert_(IOS_ES, request.in_vectors.size() == 1);
|
||||
_dbg_assert_(IOS_ES, request.io_vectors.size() == 1);
|
||||
|
@ -547,14 +631,13 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
|
|||
}
|
||||
|
||||
DEBUG_LOG(IOS_ES,
|
||||
"IOCTL_ES_READCONTENT: CFD %x, Address 0x%x, Size %i -> stream pos %i (Index %i)",
|
||||
CFD, Addr, Size, rContent.m_Position, rContent.m_Index);
|
||||
"IOCTL_ES_READCONTENT: CFD %x, Address 0x%x, Size %i -> stream pos %i (Index %i)", CFD,
|
||||
Addr, Size, rContent.m_Position, rContent.m_Index);
|
||||
|
||||
return GetDefaultReply(Size);
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_ES_CLOSECONTENT:
|
||||
IPCCommandResult ES::CloseContent(const IOCtlVRequest& request)
|
||||
{
|
||||
_dbg_assert_(IOS_ES, request.in_vectors.size() == 1);
|
||||
_dbg_assert_(IOS_ES, request.io_vectors.size() == 0);
|
||||
|
@ -581,9 +664,8 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
|
|||
|
||||
return GetDefaultReply(IPC_SUCCESS);
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_ES_SEEKCONTENT:
|
||||
IPCCommandResult ES::SeekContent(const IOCtlVRequest& request)
|
||||
{
|
||||
_dbg_assert_(IOS_ES, request.in_vectors.size() == 3);
|
||||
_dbg_assert_(IOS_ES, request.io_vectors.size() == 0);
|
||||
|
@ -619,9 +701,8 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
|
|||
|
||||
return GetDefaultReply(rContent.m_Position);
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_ES_GETTITLEDIR:
|
||||
IPCCommandResult ES::GetTitleDirectory(const IOCtlVRequest& request)
|
||||
{
|
||||
_dbg_assert_(IOS_ES, request.in_vectors.size() == 1);
|
||||
_dbg_assert_(IOS_ES, request.io_vectors.size() == 1);
|
||||
|
@ -632,34 +713,34 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
|
|||
sprintf(Path, "/title/%08x/%08x/data", (u32)(TitleID >> 32), (u32)TitleID);
|
||||
|
||||
INFO_LOG(IOS_ES, "IOCTL_ES_GETTITLEDIR: %s", Path);
|
||||
return GetDefaultReply(IPC_SUCCESS);
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_ES_GETTITLEID:
|
||||
IPCCommandResult ES::GetTitleID(const IOCtlVRequest& request)
|
||||
{
|
||||
_dbg_assert_(IOS_ES, request.in_vectors.size() == 0);
|
||||
_dbg_assert_msg_(IOS_ES, request.io_vectors.size() == 1, "IOCTL_ES_GETTITLEID no out buffer");
|
||||
|
||||
Memory::Write_U64(m_TitleID, request.io_vectors[0].address);
|
||||
INFO_LOG(IOS_ES, "IOCTL_ES_GETTITLEID: %08x/%08x", (u32)(m_TitleID >> 32), (u32)m_TitleID);
|
||||
return GetDefaultReply(IPC_SUCCESS);
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_ES_SETUID:
|
||||
IPCCommandResult ES::SetUID(const IOCtlVRequest& request)
|
||||
{
|
||||
_dbg_assert_msg_(IOS_ES, request.in_vectors.size() == 1, "IOCTL_ES_SETUID no in buffer");
|
||||
_dbg_assert_msg_(IOS_ES, request.io_vectors.size() == 0,
|
||||
"IOCTL_ES_SETUID has a payload, it shouldn't");
|
||||
|
||||
// TODO: fs permissions based on this
|
||||
u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
|
||||
INFO_LOG(IOS_ES, "IOCTL_ES_SETUID titleID: %08x/%08x", (u32)(TitleID >> 32), (u32)TitleID);
|
||||
return GetDefaultReply(IPC_SUCCESS);
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_ES_GETTITLECNT:
|
||||
IPCCommandResult ES::GetTitleCount(const IOCtlVRequest& request)
|
||||
{
|
||||
_dbg_assert_msg_(IOS_ES, request.in_vectors.size() == 0,
|
||||
"IOCTL_ES_GETTITLECNT has an in buffer");
|
||||
_dbg_assert_msg_(IOS_ES, request.in_vectors.size() == 0, "IOCTL_ES_GETTITLECNT has an in buffer");
|
||||
_dbg_assert_msg_(IOS_ES, request.io_vectors.size() == 1,
|
||||
"IOCTL_ES_GETTITLECNT has no out buffer");
|
||||
_dbg_assert_msg_(IOS_ES, request.io_vectors[0].size == 4,
|
||||
|
@ -671,13 +752,11 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
|
|||
|
||||
return GetDefaultReply(IPC_SUCCESS);
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_ES_GETTITLES:
|
||||
IPCCommandResult ES::GetTitles(const IOCtlVRequest& request)
|
||||
{
|
||||
_dbg_assert_msg_(IOS_ES, request.in_vectors.size() == 1, "IOCTL_ES_GETTITLES has an in buffer");
|
||||
_dbg_assert_msg_(IOS_ES, request.io_vectors.size() == 1,
|
||||
"IOCTL_ES_GETTITLES has no out buffer");
|
||||
_dbg_assert_msg_(IOS_ES, request.io_vectors.size() == 1, "IOCTL_ES_GETTITLES has no out buffer");
|
||||
|
||||
u32 MaxCount = Memory::Read_U32(request.in_vectors[0].address);
|
||||
u32 Count = 0;
|
||||
|
@ -694,9 +773,8 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
|
|||
INFO_LOG(IOS_ES, "IOCTL_ES_GETTITLES: Number of titles returned %i", Count);
|
||||
return GetDefaultReply(IPC_SUCCESS);
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_ES_GETVIEWCNT:
|
||||
IPCCommandResult ES::GetViewCount(const IOCtlVRequest& request)
|
||||
{
|
||||
_dbg_assert_msg_(IOS_ES, request.in_vectors.size() == 1, "IOCTL_ES_GETVIEWCNT no in buffer");
|
||||
_dbg_assert_msg_(IOS_ES, request.io_vectors.size() == 1, "IOCTL_ES_GETVIEWCNT no out buffer");
|
||||
|
@ -744,9 +822,8 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
|
|||
Memory::Write_U32(ViewCount, request.io_vectors[0].address);
|
||||
return GetDefaultReply(retVal);
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_ES_GETVIEWS:
|
||||
IPCCommandResult ES::GetViews(const IOCtlVRequest& request)
|
||||
{
|
||||
_dbg_assert_msg_(IOS_ES, request.in_vectors.size() == 2, "IOCTL_ES_GETVIEWS no in buffer");
|
||||
_dbg_assert_msg_(IOS_ES, request.io_vectors.size() == 1, "IOCTL_ES_GETVIEWS no out buffer");
|
||||
|
@ -811,18 +888,16 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
|
|||
}
|
||||
}
|
||||
|
||||
INFO_LOG(IOS_ES, "IOCTL_ES_GETVIEWS for titleID: %08x/%08x (MaxViews = %i)",
|
||||
(u32)(TitleID >> 32), (u32)TitleID, maxViews);
|
||||
INFO_LOG(IOS_ES, "IOCTL_ES_GETVIEWS for titleID: %08x/%08x (MaxViews = %i)", (u32)(TitleID >> 32),
|
||||
(u32)TitleID, maxViews);
|
||||
|
||||
return GetDefaultReply(retVal);
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_ES_GETTMDVIEWCNT:
|
||||
IPCCommandResult ES::GetTMDViewCount(const IOCtlVRequest& request)
|
||||
{
|
||||
_dbg_assert_msg_(IOS_ES, request.in_vectors.size() == 1, "IOCTL_ES_GETTMDVIEWCNT no in buffer");
|
||||
_dbg_assert_msg_(IOS_ES, request.io_vectors.size() == 1,
|
||||
"IOCTL_ES_GETTMDVIEWCNT no out buffer");
|
||||
_dbg_assert_msg_(IOS_ES, request.io_vectors.size() == 1, "IOCTL_ES_GETTMDVIEWCNT no out buffer");
|
||||
|
||||
u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
|
||||
|
||||
|
@ -834,22 +909,19 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
|
|||
TMDViewCnt += DiscIO::CNANDContentLoader::TMD_VIEW_SIZE;
|
||||
TMDViewCnt += 2; // title version
|
||||
TMDViewCnt += 2; // num entries
|
||||
TMDViewCnt +=
|
||||
(u32)Loader.GetContentSize() * (4 + 2 + 2 + 8); // content id, index, type, size
|
||||
TMDViewCnt += (u32)Loader.GetContentSize() * (4 + 2 + 2 + 8); // content id, index, type, size
|
||||
}
|
||||
Memory::Write_U32(TMDViewCnt, request.io_vectors[0].address);
|
||||
|
||||
INFO_LOG(IOS_ES, "IOCTL_ES_GETTMDVIEWCNT: title: %08x/%08x (view size %i)",
|
||||
(u32)(TitleID >> 32), (u32)TitleID, TMDViewCnt);
|
||||
INFO_LOG(IOS_ES, "IOCTL_ES_GETTMDVIEWCNT: title: %08x/%08x (view size %i)", (u32)(TitleID >> 32),
|
||||
(u32)TitleID, TMDViewCnt);
|
||||
return GetDefaultReply(IPC_SUCCESS);
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_ES_GETTMDVIEWS:
|
||||
IPCCommandResult ES::GetTMDViews(const IOCtlVRequest& request)
|
||||
{
|
||||
_dbg_assert_msg_(IOS_ES, request.in_vectors.size() == 2, "IOCTL_ES_GETTMDVIEWCNT no in buffer");
|
||||
_dbg_assert_msg_(IOS_ES, request.io_vectors.size() == 1,
|
||||
"IOCTL_ES_GETTMDVIEWCNT no out buffer");
|
||||
_dbg_assert_msg_(IOS_ES, request.io_vectors.size() == 1, "IOCTL_ES_GETTMDVIEWCNT no out buffer");
|
||||
|
||||
u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
|
||||
u32 MaxCount = Memory::Read_U32(request.in_vectors[1].address);
|
||||
|
@ -887,44 +959,50 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
|
|||
_dbg_assert_(IOS_ES, (Address - request.io_vectors[0].address) == request.io_vectors[0].size);
|
||||
}
|
||||
|
||||
INFO_LOG(IOS_ES, "IOCTL_ES_GETTMDVIEWS: title: %08x/%08x (buffer size: %i)",
|
||||
(u32)(TitleID >> 32), (u32)TitleID, MaxCount);
|
||||
INFO_LOG(IOS_ES, "IOCTL_ES_GETTMDVIEWS: title: %08x/%08x (buffer size: %i)", (u32)(TitleID >> 32),
|
||||
(u32)TitleID, MaxCount);
|
||||
return GetDefaultReply(IPC_SUCCESS);
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_ES_GETCONSUMPTION: // This is at least what crediar's ES module does
|
||||
IPCCommandResult ES::GetConsumption(const IOCtlVRequest& request)
|
||||
{
|
||||
// This is at least what crediar's ES module does
|
||||
Memory::Write_U32(0, request.io_vectors[1].address);
|
||||
INFO_LOG(IOS_ES, "IOCTL_ES_GETCONSUMPTION");
|
||||
return GetDefaultReply(IPC_SUCCESS);
|
||||
}
|
||||
|
||||
case IOCTL_ES_DELETETICKET:
|
||||
IPCCommandResult ES::DeleteTicket(const IOCtlVRequest& request)
|
||||
{
|
||||
u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
|
||||
INFO_LOG(IOS_ES, "IOCTL_ES_DELETETICKET: title: %08x/%08x", (u32)(TitleID >> 32), (u32)TitleID);
|
||||
|
||||
// Presumably return -1017 when delete fails
|
||||
if (!File::Delete(Common::GetTicketFileName(TitleID, Common::FROM_SESSION_ROOT)))
|
||||
return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT);
|
||||
|
||||
return GetDefaultReply(IPC_SUCCESS);
|
||||
}
|
||||
|
||||
case IOCTL_ES_DELETETITLECONTENT:
|
||||
IPCCommandResult ES::DeleteTitleContent(const IOCtlVRequest& request)
|
||||
{
|
||||
u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
|
||||
INFO_LOG(IOS_ES, "IOCTL_ES_DELETETITLECONTENT: title: %08x/%08x", (u32)(TitleID >> 32),
|
||||
(u32)TitleID);
|
||||
|
||||
// Presumably return -1017 when title not installed TODO verify
|
||||
if (!DiscIO::CNANDContentManager::Access().RemoveTitle(TitleID, Common::FROM_SESSION_ROOT))
|
||||
return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT);
|
||||
|
||||
return GetDefaultReply(IPC_SUCCESS);
|
||||
}
|
||||
|
||||
case IOCTL_ES_GETSTOREDTMDSIZE:
|
||||
IPCCommandResult ES::GetStoredTMDSize(const IOCtlVRequest& request)
|
||||
{
|
||||
_dbg_assert_msg_(IOS_ES, request.in_vectors.size() == 1,
|
||||
"IOCTL_ES_GETSTOREDTMDSIZE no in buffer");
|
||||
// _dbg_assert_msg_(IOS_ES, request.io_vectors.size() == 1, "IOCTL_ES_ES_GETSTOREDTMDSIZE
|
||||
// no out buffer");
|
||||
// _dbg_assert_msg_(IOS_ES, request.io_vectors.size() == 1,
|
||||
// "IOCTL_ES_ES_GETSTOREDTMDSIZE no out buffer");
|
||||
|
||||
u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
|
||||
const DiscIO::CNANDContentLoader& Loader = AccessContentDevice(TitleID);
|
||||
|
@ -936,22 +1014,24 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
|
|||
TMDCnt += DiscIO::CNANDContentLoader::TMD_HEADER_SIZE;
|
||||
TMDCnt += (u32)Loader.GetContentSize() * DiscIO::CNANDContentLoader::CONTENT_HEADER_SIZE;
|
||||
}
|
||||
|
||||
if (request.io_vectors.size())
|
||||
Memory::Write_U32(TMDCnt, request.io_vectors[0].address);
|
||||
|
||||
INFO_LOG(IOS_ES, "IOCTL_ES_GETSTOREDTMDSIZE: title: %08x/%08x (view size %i)",
|
||||
(u32)(TitleID >> 32), (u32)TitleID, TMDCnt);
|
||||
|
||||
return GetDefaultReply(IPC_SUCCESS);
|
||||
}
|
||||
break;
|
||||
case IOCTL_ES_GETSTOREDTMD:
|
||||
|
||||
IPCCommandResult ES::GetStoredTMD(const IOCtlVRequest& request)
|
||||
{
|
||||
_dbg_assert_msg_(IOS_ES, request.in_vectors.size() > 0, "IOCTL_ES_GETSTOREDTMD no in buffer");
|
||||
// requires 1 inbuffer and no outbuffer, presumably outbuffer required when second inbuffer is
|
||||
// used for maxcount (allocated mem?)
|
||||
// called with 1 inbuffer after deleting a titleid
|
||||
//_dbg_assert_msg_(IOS_ES, request.io_vectors.size() == 1, "IOCTL_ES_GETSTOREDTMD no out
|
||||
// buffer");
|
||||
//_dbg_assert_msg_(IOS_ES, request.io_vectors.size() == 1,
|
||||
// "IOCTL_ES_GETSTOREDTMD no out buffer");
|
||||
|
||||
u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
|
||||
u32 MaxCount = 0;
|
||||
|
@ -969,8 +1049,7 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
|
|||
{
|
||||
u32 Address = request.io_vectors[0].address;
|
||||
|
||||
Memory::CopyToEmu(Address, Loader.GetTMDHeader(),
|
||||
DiscIO::CNANDContentLoader::TMD_HEADER_SIZE);
|
||||
Memory::CopyToEmu(Address, Loader.GetTMDHeader(), DiscIO::CNANDContentLoader::TMD_HEADER_SIZE);
|
||||
Address += DiscIO::CNANDContentLoader::TMD_HEADER_SIZE;
|
||||
|
||||
const std::vector<DiscIO::SNANDContent>& rContent = Loader.GetContent();
|
||||
|
@ -988,9 +1067,8 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
|
|||
(u32)(TitleID >> 32), (u32)TitleID, MaxCount);
|
||||
return GetDefaultReply(IPC_SUCCESS);
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_ES_ENCRYPT:
|
||||
IPCCommandResult ES::Encrypt(const IOCtlVRequest& request)
|
||||
{
|
||||
u32 keyIndex = Memory::Read_U32(request.in_vectors[0].address);
|
||||
u8* IV = Memory::GetPointer(request.in_vectors[1].address);
|
||||
|
@ -1006,10 +1084,10 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
|
|||
|
||||
_dbg_assert_msg_(IOS_ES, keyIndex == 6,
|
||||
"IOCTL_ES_ENCRYPT: Key type is not SD, data will be crap");
|
||||
return GetDefaultReply(IPC_SUCCESS);
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_ES_DECRYPT:
|
||||
IPCCommandResult ES::Decrypt(const IOCtlVRequest& request)
|
||||
{
|
||||
u32 keyIndex = Memory::Read_U32(request.in_vectors[0].address);
|
||||
u8* IV = Memory::GetPointer(request.in_vectors[1].address);
|
||||
|
@ -1022,10 +1100,10 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
|
|||
|
||||
_dbg_assert_msg_(IOS_ES, keyIndex == 6,
|
||||
"IOCTL_ES_DECRYPT: Key type is not SD, data will be crap");
|
||||
return GetDefaultReply(IPC_SUCCESS);
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_ES_LAUNCH:
|
||||
IPCCommandResult ES::Launch(const IOCtlVRequest& request)
|
||||
{
|
||||
_dbg_assert_(IOS_ES, request.in_vectors.size() == 2);
|
||||
bool bSuccess = false;
|
||||
|
@ -1150,28 +1228,30 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
|
|||
EnqueueCommandAcknowledgement(request.address, 0);
|
||||
return GetNoReply();
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_ES_CHECKKOREAREGION: // note by DacoTaco : name is unknown, i just tried to name it
|
||||
// SOMETHING
|
||||
IPCCommandResult ES::CheckKoreaRegion(const IOCtlVRequest& request)
|
||||
{
|
||||
// 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(IOS_ES, "IOCTL_ES_CHECKKOREAREGION: Title checked for Korean keys.");
|
||||
return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT);
|
||||
}
|
||||
|
||||
case IOCTL_ES_GETDEVICECERT: // (Input: none, Output: 384 bytes)
|
||||
IPCCommandResult ES::GetDeviceCertificate(const IOCtlVRequest& request)
|
||||
{
|
||||
// (Input: none, Output: 384 bytes)
|
||||
INFO_LOG(IOS_ES, "IOCTL_ES_GETDEVICECERT");
|
||||
_dbg_assert_(IOS_ES, request.io_vectors.size() == 1);
|
||||
u8* destination = Memory::GetPointer(request.io_vectors[0].address);
|
||||
|
||||
EcWii& ec = EcWii::GetInstance();
|
||||
get_ng_cert(destination, ec.getNgId(), ec.getNgKeyId(), ec.getNgPriv(), ec.getNgSig());
|
||||
return GetDefaultReply(IPC_SUCCESS);
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_ES_SIGN:
|
||||
IPCCommandResult ES::Sign(const IOCtlVRequest& request)
|
||||
{
|
||||
INFO_LOG(IOS_ES, "IOCTL_ES_SIGN");
|
||||
u8* ap_cert_out = Memory::GetPointer(request.io_vectors[1].address);
|
||||
|
@ -1182,34 +1262,30 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
|
|||
EcWii& ec = EcWii::GetInstance();
|
||||
get_ap_sig_and_cert(sig_out, ap_cert_out, m_TitleID, data, data_size, ec.getNgPriv(),
|
||||
ec.getNgId());
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_ES_GETBOOT2VERSION:
|
||||
return GetDefaultReply(IPC_SUCCESS);
|
||||
}
|
||||
|
||||
IPCCommandResult ES::GetBoot2Version(const IOCtlVRequest& request)
|
||||
{
|
||||
INFO_LOG(IOS_ES, "IOCTL_ES_GETBOOT2VERSION");
|
||||
|
||||
Memory::Write_U32(
|
||||
4, request.io_vectors[0].address); // as of 26/02/2012, this was latest bootmii version
|
||||
// as of 26/02/2012, this was latest bootmii version
|
||||
Memory::Write_U32(4, request.io_vectors[0].address);
|
||||
return GetDefaultReply(IPC_SUCCESS);
|
||||
}
|
||||
break;
|
||||
|
||||
// ===============================================================================================
|
||||
// unsupported functions
|
||||
// ===============================================================================================
|
||||
case IOCTL_ES_DIGETTICKETVIEW: // (Input: none, Output: 216 bytes) bug crediar :D
|
||||
IPCCommandResult ES::DIGetTicketView(const IOCtlVRequest& request)
|
||||
{
|
||||
// (Input: none, Output: 216 bytes) bug crediar :D
|
||||
WARN_LOG(IOS_ES, "IOCTL_ES_DIGETTICKETVIEW: this looks really wrong...");
|
||||
break;
|
||||
return GetDefaultReply(IPC_SUCCESS);
|
||||
}
|
||||
|
||||
case IOCTL_ES_GETOWNEDTITLECNT:
|
||||
IPCCommandResult ES::GetOwnedTitleCount(const IOCtlVRequest& request)
|
||||
{
|
||||
INFO_LOG(IOS_ES, "IOCTL_ES_GETOWNEDTITLECNT");
|
||||
Memory::Write_U32(0, request.io_vectors[0].address);
|
||||
break;
|
||||
|
||||
default:
|
||||
request.DumpUnknown(GetDeviceName(), LogTypes::IOS);
|
||||
}
|
||||
|
||||
return GetDefaultReply(IPC_SUCCESS);
|
||||
}
|
||||
|
||||
|
|
|
@ -138,21 +138,6 @@ private:
|
|||
u32 m_Size;
|
||||
};
|
||||
|
||||
typedef std::map<u32, SContentAccess> CContentAccessMap;
|
||||
CContentAccessMap m_ContentAccessMap;
|
||||
|
||||
std::vector<u64> m_TitleIDs;
|
||||
u64 m_TitleID = -1;
|
||||
u32 m_AccessIdentID = 0x6000000;
|
||||
|
||||
// For title installation (ioctls IOCTL_ES_ADDTITLE*).
|
||||
TMDReader m_addtitle_tmd;
|
||||
u32 m_addtitle_content_id = 0xFFFFFFFF;
|
||||
std::vector<u8> m_addtitle_content_buffer;
|
||||
|
||||
const DiscIO::CNANDContentLoader& AccessContentDevice(u64 title_id);
|
||||
u32 OpenTitleContent(u32 CFD, u64 TitleID, u16 Index);
|
||||
|
||||
struct ecc_cert_t
|
||||
{
|
||||
u32 sig_type;
|
||||
|
@ -165,6 +150,59 @@ private:
|
|||
u8 ecc_pubkey[0x3c];
|
||||
u8 padding[0x3c];
|
||||
};
|
||||
|
||||
IPCCommandResult AddTicket(const IOCtlVRequest& request);
|
||||
IPCCommandResult AddTitleStart(const IOCtlVRequest& request);
|
||||
IPCCommandResult AddContentStart(const IOCtlVRequest& request);
|
||||
IPCCommandResult AddContentData(const IOCtlVRequest& request);
|
||||
IPCCommandResult AddContentFinish(const IOCtlVRequest& request);
|
||||
IPCCommandResult AddTitleFinish(const IOCtlVRequest& request);
|
||||
IPCCommandResult ESGetDeviceID(const IOCtlVRequest& request);
|
||||
IPCCommandResult GetTitleContentsCount(const IOCtlVRequest& request);
|
||||
IPCCommandResult GetTitleContents(const IOCtlVRequest& request);
|
||||
IPCCommandResult OpenTitleContent(const IOCtlVRequest& request);
|
||||
IPCCommandResult OpenContent(const IOCtlVRequest& request);
|
||||
IPCCommandResult ReadContent(const IOCtlVRequest& request);
|
||||
IPCCommandResult CloseContent(const IOCtlVRequest& request);
|
||||
IPCCommandResult SeekContent(const IOCtlVRequest& request);
|
||||
IPCCommandResult GetTitleDirectory(const IOCtlVRequest& request);
|
||||
IPCCommandResult GetTitleID(const IOCtlVRequest& request);
|
||||
IPCCommandResult SetUID(const IOCtlVRequest& request);
|
||||
IPCCommandResult GetTitleCount(const IOCtlVRequest& request);
|
||||
IPCCommandResult GetTitles(const IOCtlVRequest& request);
|
||||
IPCCommandResult GetViewCount(const IOCtlVRequest& request);
|
||||
IPCCommandResult GetViews(const IOCtlVRequest& request);
|
||||
IPCCommandResult GetTMDViewCount(const IOCtlVRequest& request);
|
||||
IPCCommandResult GetTMDViews(const IOCtlVRequest& request);
|
||||
IPCCommandResult GetConsumption(const IOCtlVRequest& request);
|
||||
IPCCommandResult DeleteTicket(const IOCtlVRequest& request);
|
||||
IPCCommandResult DeleteTitleContent(const IOCtlVRequest& request);
|
||||
IPCCommandResult GetStoredTMDSize(const IOCtlVRequest& request);
|
||||
IPCCommandResult GetStoredTMD(const IOCtlVRequest& request);
|
||||
IPCCommandResult Encrypt(const IOCtlVRequest& request);
|
||||
IPCCommandResult Decrypt(const IOCtlVRequest& request);
|
||||
IPCCommandResult Launch(const IOCtlVRequest& request);
|
||||
IPCCommandResult CheckKoreaRegion(const IOCtlVRequest& request);
|
||||
IPCCommandResult GetDeviceCertificate(const IOCtlVRequest& request);
|
||||
IPCCommandResult Sign(const IOCtlVRequest& request);
|
||||
IPCCommandResult GetBoot2Version(const IOCtlVRequest& request);
|
||||
IPCCommandResult DIGetTicketView(const IOCtlVRequest& request);
|
||||
IPCCommandResult GetOwnedTitleCount(const IOCtlVRequest& request);
|
||||
|
||||
const DiscIO::CNANDContentLoader& AccessContentDevice(u64 title_id);
|
||||
u32 OpenTitleContent(u32 CFD, u64 TitleID, u16 Index);
|
||||
|
||||
using CContentAccessMap = std::map<u32, SContentAccess>;
|
||||
CContentAccessMap m_ContentAccessMap;
|
||||
|
||||
std::vector<u64> m_TitleIDs;
|
||||
u64 m_TitleID = -1;
|
||||
u32 m_AccessIdentID = 0x6000000;
|
||||
|
||||
// For title installation (ioctls IOCTL_ES_ADDTITLE*).
|
||||
TMDReader m_addtitle_tmd;
|
||||
u32 m_addtitle_content_id = 0xFFFFFFFF;
|
||||
std::vector<u8> m_addtitle_content_buffer;
|
||||
};
|
||||
} // namespace Device
|
||||
} // namespace HLE
|
||||
|
|
Loading…
Reference in New Issue