Merge pull request #4743 from lioncash/es

ES: Separate IOCtlV code out into constituent functions
This commit is contained in:
Mat M 2017-01-28 15:33:34 -05:00 committed by GitHub
commit 66160c2781
2 changed files with 1044 additions and 930 deletions

View File

@ -249,16 +249,102 @@ u32 ES::OpenTitleContent(u32 CFD, u64 TitleID, u16 Index)
IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request) IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
{ {
DEBUG_LOG(IOS_ES, "%s (0x%x)", GetDeviceName().c_str(), request.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. // Clear the IO buffers. Note that this is unsafe for other ioctlvs.
for (const auto& io_vector : request.io_vectors) for (const auto& io_vector : request.io_vectors)
{ {
if (!request.HasInputVectorWithAddress(io_vector.address)) if (!request.HasInputVectorWithAddress(io_vector.address))
Memory::Memset(io_vector.address, 0, io_vector.size); Memory::Memset(io_vector.address, 0, io_vector.size);
} }
switch (request.request) switch (request.request)
{ {
case IOCTL_ES_ADDTICKET: 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, _dbg_assert_msg_(IOS_ES, request.in_vectors.size() == 3,
"IOCTL_ES_ADDTICKET wrong number of inputs"); "IOCTL_ES_ADDTICKET wrong number of inputs");
@ -266,11 +352,12 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
std::vector<u8> ticket(request.in_vectors[0].size); std::vector<u8> ticket(request.in_vectors[0].size);
Memory::CopyFromEmu(ticket.data(), request.in_vectors[0].address, request.in_vectors[0].size); Memory::CopyFromEmu(ticket.data(), request.in_vectors[0].address, request.in_vectors[0].size);
DiscIO::AddTicket(ticket); DiscIO::AddTicket(ticket);
break;
}
case IOCTL_ES_ADDTITLESTART: return GetDefaultReply(IPC_SUCCESS);
{ }
IPCCommandResult ES::AddTitleStart(const IOCtlVRequest& request)
{
_dbg_assert_msg_(IOS_ES, request.in_vectors.size() == 4, _dbg_assert_msg_(IOS_ES, request.in_vectors.size() == 4,
"IOCTL_ES_ADDTITLESTART wrong number of inputs"); "IOCTL_ES_ADDTITLESTART wrong number of inputs");
@ -292,11 +379,12 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
File::IOFile fp(tmd_path, "wb"); File::IOFile fp(tmd_path, "wb");
fp.WriteBytes(tmd.data(), tmd.size()); fp.WriteBytes(tmd.data(), tmd.size());
break;
}
case IOCTL_ES_ADDCONTENTSTART: return GetDefaultReply(IPC_SUCCESS);
{ }
IPCCommandResult ES::AddContentStart(const IOCtlVRequest& request)
{
_dbg_assert_msg_(IOS_ES, request.in_vectors.size() == 2, _dbg_assert_msg_(IOS_ES, request.in_vectors.size() == 2,
"IOCTL_ES_ADDCONTENTSTART wrong number of inputs"); "IOCTL_ES_ADDCONTENTSTART wrong number of inputs");
@ -330,10 +418,10 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
// Instead we just log an error (see above) if this condition is detected. // Instead we just log an error (see above) if this condition is detected.
s32 content_fd = 0; s32 content_fd = 0;
return GetDefaultReply(content_fd); return GetDefaultReply(content_fd);
} }
case IOCTL_ES_ADDCONTENTDATA: IPCCommandResult ES::AddContentData(const IOCtlVRequest& request)
{ {
_dbg_assert_msg_(IOS_ES, request.in_vectors.size() == 2, _dbg_assert_msg_(IOS_ES, request.in_vectors.size() == 2,
"IOCTL_ES_ADDCONTENTDATA wrong number of inputs"); "IOCTL_ES_ADDCONTENTDATA wrong number of inputs");
@ -345,11 +433,11 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
u8* data_start = Memory::GetPointer(request.in_vectors[1].address); u8* data_start = Memory::GetPointer(request.in_vectors[1].address);
u8* data_end = data_start + request.in_vectors[1].size; u8* data_end = data_start + request.in_vectors[1].size;
m_addtitle_content_buffer.insert(m_addtitle_content_buffer.end(), data_start, data_end); 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, _dbg_assert_msg_(IOS_ES, request.in_vectors.size() == 1,
"IOCTL_ES_ADDCONTENTFINISH wrong number of inputs"); "IOCTL_ES_ADDCONTENTFINISH wrong number of inputs");
@ -389,27 +477,27 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
fp.WriteBytes(decrypted_data.data(), decrypted_data.size()); fp.WriteBytes(decrypted_data.data(), decrypted_data.size());
m_addtitle_content_id = 0xFFFFFFFF; 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"); 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"); _dbg_assert_msg_(IOS_ES, request.io_vectors.size() == 1, "IOCTL_ES_GETDEVICEID no io vectors");
EcWii& ec = EcWii::GetInstance(); EcWii& ec = EcWii::GetInstance();
INFO_LOG(IOS_ES, "IOCTL_ES_GETDEVICEID %08X", ec.getNgId()); INFO_LOG(IOS_ES, "IOCTL_ES_GETDEVICEID %08X", ec.getNgId());
Memory::Write_U32(ec.getNgId(), request.io_vectors[0].address); Memory::Write_U32(ec.getNgId(), request.io_vectors[0].address);
return GetDefaultReply(IPC_SUCCESS); 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.in_vectors.size() == 1);
_dbg_assert_(IOS_ES, request.io_vectors.size() == 1); _dbg_assert_(IOS_ES, request.io_vectors.size() == 1);
@ -437,11 +525,10 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
rNANDContent.IsValid() ? NumberOfPrivateContent : (u32)rNANDContent.GetContentSize()); rNANDContent.IsValid() ? NumberOfPrivateContent : (u32)rNANDContent.GetContentSize());
return GetDefaultReply(return_value); 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, _dbg_assert_msg_(IOS_ES, request.in_vectors.size() == 2,
"IOCTL_ES_GETTITLECONTENTS bad in buffer"); "IOCTL_ES_GETTITLECONTENTS bad in buffer");
_dbg_assert_msg_(IOS_ES, request.io_vectors.size() == 1, _dbg_assert_msg_(IOS_ES, request.io_vectors.size() == 1,
@ -469,11 +556,10 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
} }
return GetDefaultReply(return_value); 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.in_vectors.size() == 3);
_dbg_assert_(IOS_ES, request.io_vectors.size() == 0); _dbg_assert_(IOS_ES, request.io_vectors.size() == 0);
@ -486,11 +572,10 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
(u32)(TitleID >> 32), (u32)TitleID, Index, CFD); (u32)(TitleID >> 32), (u32)TitleID, Index, CFD);
return GetDefaultReply(CFD); 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.in_vectors.size() == 1);
_dbg_assert_(IOS_ES, request.io_vectors.size() == 0); _dbg_assert_(IOS_ES, request.io_vectors.size() == 0);
u32 Index = Memory::Read_U32(request.in_vectors[0].address); u32 Index = Memory::Read_U32(request.in_vectors[0].address);
@ -499,11 +584,10 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
INFO_LOG(IOS_ES, "IOCTL_ES_OPENCONTENT: Index %i -> got CFD %x", Index, CFD); INFO_LOG(IOS_ES, "IOCTL_ES_OPENCONTENT: Index %i -> got CFD %x", Index, CFD);
return GetDefaultReply(CFD); 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.in_vectors.size() == 1);
_dbg_assert_(IOS_ES, request.io_vectors.size() == 1); _dbg_assert_(IOS_ES, request.io_vectors.size() == 1);
@ -547,15 +631,14 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
} }
DEBUG_LOG(IOS_ES, DEBUG_LOG(IOS_ES,
"IOCTL_ES_READCONTENT: CFD %x, Address 0x%x, Size %i -> stream pos %i (Index %i)", "IOCTL_ES_READCONTENT: CFD %x, Address 0x%x, Size %i -> stream pos %i (Index %i)", CFD,
CFD, Addr, Size, rContent.m_Position, rContent.m_Index); Addr, Size, rContent.m_Position, rContent.m_Index);
return GetDefaultReply(Size); 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.in_vectors.size() == 1);
_dbg_assert_(IOS_ES, request.io_vectors.size() == 0); _dbg_assert_(IOS_ES, request.io_vectors.size() == 0);
@ -580,11 +663,10 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
m_ContentAccessMap.erase(itr); m_ContentAccessMap.erase(itr);
return GetDefaultReply(IPC_SUCCESS); 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.in_vectors.size() == 3);
_dbg_assert_(IOS_ES, request.io_vectors.size() == 0); _dbg_assert_(IOS_ES, request.io_vectors.size() == 0);
@ -618,11 +700,10 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
Mode, rContent.m_Position); Mode, rContent.m_Position);
return GetDefaultReply(rContent.m_Position); 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.in_vectors.size() == 1);
_dbg_assert_(IOS_ES, request.io_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); sprintf(Path, "/title/%08x/%08x/data", (u32)(TitleID >> 32), (u32)TitleID);
INFO_LOG(IOS_ES, "IOCTL_ES_GETTITLEDIR: %s", Path); 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_(IOS_ES, request.in_vectors.size() == 0);
_dbg_assert_msg_(IOS_ES, request.io_vectors.size() == 1, "IOCTL_ES_GETTITLEID no out buffer"); _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); 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); 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.in_vectors.size() == 1, "IOCTL_ES_SETUID no in buffer");
_dbg_assert_msg_(IOS_ES, request.io_vectors.size() == 0, _dbg_assert_msg_(IOS_ES, request.io_vectors.size() == 0,
"IOCTL_ES_SETUID has a payload, it shouldn't"); "IOCTL_ES_SETUID has a payload, it shouldn't");
// TODO: fs permissions based on this // TODO: fs permissions based on this
u64 TitleID = Memory::Read_U64(request.in_vectors[0].address); 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); 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, _dbg_assert_msg_(IOS_ES, request.in_vectors.size() == 0, "IOCTL_ES_GETTITLECNT has an in buffer");
"IOCTL_ES_GETTITLECNT has an in buffer");
_dbg_assert_msg_(IOS_ES, request.io_vectors.size() == 1, _dbg_assert_msg_(IOS_ES, request.io_vectors.size() == 1,
"IOCTL_ES_GETTITLECNT has no out buffer"); "IOCTL_ES_GETTITLECNT has no out buffer");
_dbg_assert_msg_(IOS_ES, request.io_vectors[0].size == 4, _dbg_assert_msg_(IOS_ES, request.io_vectors[0].size == 4,
@ -670,14 +751,12 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
INFO_LOG(IOS_ES, "IOCTL_ES_GETTITLECNT: Number of Titles %zu", m_TitleIDs.size()); INFO_LOG(IOS_ES, "IOCTL_ES_GETTITLECNT: Number of Titles %zu", m_TitleIDs.size());
return GetDefaultReply(IPC_SUCCESS); 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.in_vectors.size() == 1, "IOCTL_ES_GETTITLES has an in buffer");
_dbg_assert_msg_(IOS_ES, request.io_vectors.size() == 1, _dbg_assert_msg_(IOS_ES, request.io_vectors.size() == 1, "IOCTL_ES_GETTITLES has no out buffer");
"IOCTL_ES_GETTITLES has no out buffer");
u32 MaxCount = Memory::Read_U32(request.in_vectors[0].address); u32 MaxCount = Memory::Read_U32(request.in_vectors[0].address);
u32 Count = 0; u32 Count = 0;
@ -693,11 +772,10 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
INFO_LOG(IOS_ES, "IOCTL_ES_GETTITLES: Number of titles returned %i", Count); INFO_LOG(IOS_ES, "IOCTL_ES_GETTITLES: Number of titles returned %i", Count);
return GetDefaultReply(IPC_SUCCESS); 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.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"); _dbg_assert_msg_(IOS_ES, request.io_vectors.size() == 1, "IOCTL_ES_GETVIEWCNT no out buffer");
@ -743,11 +821,10 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
Memory::Write_U32(ViewCount, request.io_vectors[0].address); Memory::Write_U32(ViewCount, request.io_vectors[0].address);
return GetDefaultReply(retVal); 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.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"); _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)", INFO_LOG(IOS_ES, "IOCTL_ES_GETVIEWS for titleID: %08x/%08x (MaxViews = %i)", (u32)(TitleID >> 32),
(u32)(TitleID >> 32), (u32)TitleID, maxViews); (u32)TitleID, maxViews);
return GetDefaultReply(retVal); 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.in_vectors.size() == 1, "IOCTL_ES_GETTMDVIEWCNT no in buffer");
_dbg_assert_msg_(IOS_ES, request.io_vectors.size() == 1, _dbg_assert_msg_(IOS_ES, request.io_vectors.size() == 1, "IOCTL_ES_GETTMDVIEWCNT no out buffer");
"IOCTL_ES_GETTMDVIEWCNT no out buffer");
u64 TitleID = Memory::Read_U64(request.in_vectors[0].address); 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 += DiscIO::CNANDContentLoader::TMD_VIEW_SIZE;
TMDViewCnt += 2; // title version TMDViewCnt += 2; // title version
TMDViewCnt += 2; // num entries TMDViewCnt += 2; // num entries
TMDViewCnt += TMDViewCnt += (u32)Loader.GetContentSize() * (4 + 2 + 2 + 8); // content id, index, type, size
(u32)Loader.GetContentSize() * (4 + 2 + 2 + 8); // content id, index, type, size
} }
Memory::Write_U32(TMDViewCnt, request.io_vectors[0].address); Memory::Write_U32(TMDViewCnt, request.io_vectors[0].address);
INFO_LOG(IOS_ES, "IOCTL_ES_GETTMDVIEWCNT: title: %08x/%08x (view size %i)", INFO_LOG(IOS_ES, "IOCTL_ES_GETTMDVIEWCNT: title: %08x/%08x (view size %i)", (u32)(TitleID >> 32),
(u32)(TitleID >> 32), (u32)TitleID, TMDViewCnt); (u32)TitleID, TMDViewCnt);
return GetDefaultReply(IPC_SUCCESS); 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.in_vectors.size() == 2, "IOCTL_ES_GETTMDVIEWCNT no in buffer");
_dbg_assert_msg_(IOS_ES, request.io_vectors.size() == 1, _dbg_assert_msg_(IOS_ES, request.io_vectors.size() == 1, "IOCTL_ES_GETTMDVIEWCNT no out buffer");
"IOCTL_ES_GETTMDVIEWCNT no out buffer");
u64 TitleID = Memory::Read_U64(request.in_vectors[0].address); u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
u32 MaxCount = Memory::Read_U32(request.in_vectors[1].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); _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)", INFO_LOG(IOS_ES, "IOCTL_ES_GETTMDVIEWS: title: %08x/%08x (buffer size: %i)", (u32)(TitleID >> 32),
(u32)(TitleID >> 32), (u32)TitleID, MaxCount); (u32)TitleID, MaxCount);
return GetDefaultReply(IPC_SUCCESS); 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); Memory::Write_U32(0, request.io_vectors[1].address);
INFO_LOG(IOS_ES, "IOCTL_ES_GETCONSUMPTION"); INFO_LOG(IOS_ES, "IOCTL_ES_GETCONSUMPTION");
return GetDefaultReply(IPC_SUCCESS); return GetDefaultReply(IPC_SUCCESS);
}
case IOCTL_ES_DELETETICKET: IPCCommandResult ES::DeleteTicket(const IOCtlVRequest& request)
{ {
u64 TitleID = Memory::Read_U64(request.in_vectors[0].address); 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); INFO_LOG(IOS_ES, "IOCTL_ES_DELETETICKET: title: %08x/%08x", (u32)(TitleID >> 32), (u32)TitleID);
// Presumably return -1017 when delete fails // Presumably return -1017 when delete fails
if (!File::Delete(Common::GetTicketFileName(TitleID, Common::FROM_SESSION_ROOT))) if (!File::Delete(Common::GetTicketFileName(TitleID, Common::FROM_SESSION_ROOT)))
return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT); return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT);
return GetDefaultReply(IPC_SUCCESS);
}
case IOCTL_ES_DELETETITLECONTENT: return GetDefaultReply(IPC_SUCCESS);
{ }
IPCCommandResult ES::DeleteTitleContent(const IOCtlVRequest& request)
{
u64 TitleID = Memory::Read_U64(request.in_vectors[0].address); u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
INFO_LOG(IOS_ES, "IOCTL_ES_DELETETITLECONTENT: title: %08x/%08x", (u32)(TitleID >> 32), INFO_LOG(IOS_ES, "IOCTL_ES_DELETETITLECONTENT: title: %08x/%08x", (u32)(TitleID >> 32),
(u32)TitleID); (u32)TitleID);
// Presumably return -1017 when title not installed TODO verify // Presumably return -1017 when title not installed TODO verify
if (!DiscIO::CNANDContentManager::Access().RemoveTitle(TitleID, Common::FROM_SESSION_ROOT)) if (!DiscIO::CNANDContentManager::Access().RemoveTitle(TitleID, Common::FROM_SESSION_ROOT))
return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT); return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT);
return GetDefaultReply(IPC_SUCCESS);
}
case IOCTL_ES_GETSTOREDTMDSIZE: return GetDefaultReply(IPC_SUCCESS);
{ }
IPCCommandResult ES::GetStoredTMDSize(const IOCtlVRequest& request)
{
_dbg_assert_msg_(IOS_ES, request.in_vectors.size() == 1, _dbg_assert_msg_(IOS_ES, request.in_vectors.size() == 1,
"IOCTL_ES_GETSTOREDTMDSIZE no in buffer"); "IOCTL_ES_GETSTOREDTMDSIZE no in buffer");
// _dbg_assert_msg_(IOS_ES, request.io_vectors.size() == 1, "IOCTL_ES_ES_GETSTOREDTMDSIZE // _dbg_assert_msg_(IOS_ES, request.io_vectors.size() == 1,
// no out buffer"); // "IOCTL_ES_ES_GETSTOREDTMDSIZE no out buffer");
u64 TitleID = Memory::Read_U64(request.in_vectors[0].address); u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
const DiscIO::CNANDContentLoader& Loader = AccessContentDevice(TitleID); const DiscIO::CNANDContentLoader& Loader = AccessContentDevice(TitleID);
@ -936,22 +1014,24 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
TMDCnt += DiscIO::CNANDContentLoader::TMD_HEADER_SIZE; TMDCnt += DiscIO::CNANDContentLoader::TMD_HEADER_SIZE;
TMDCnt += (u32)Loader.GetContentSize() * DiscIO::CNANDContentLoader::CONTENT_HEADER_SIZE; TMDCnt += (u32)Loader.GetContentSize() * DiscIO::CNANDContentLoader::CONTENT_HEADER_SIZE;
} }
if (request.io_vectors.size()) if (request.io_vectors.size())
Memory::Write_U32(TMDCnt, request.io_vectors[0].address); Memory::Write_U32(TMDCnt, request.io_vectors[0].address);
INFO_LOG(IOS_ES, "IOCTL_ES_GETSTOREDTMDSIZE: title: %08x/%08x (view size %i)", INFO_LOG(IOS_ES, "IOCTL_ES_GETSTOREDTMDSIZE: title: %08x/%08x (view size %i)",
(u32)(TitleID >> 32), (u32)TitleID, TMDCnt); (u32)(TitleID >> 32), (u32)TitleID, TMDCnt);
return GetDefaultReply(IPC_SUCCESS); 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"); _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 // requires 1 inbuffer and no outbuffer, presumably outbuffer required when second inbuffer is
// used for maxcount (allocated mem?) // used for maxcount (allocated mem?)
// called with 1 inbuffer after deleting a titleid // called with 1 inbuffer after deleting a titleid
//_dbg_assert_msg_(IOS_ES, request.io_vectors.size() == 1, "IOCTL_ES_GETSTOREDTMD no out //_dbg_assert_msg_(IOS_ES, request.io_vectors.size() == 1,
// buffer"); // "IOCTL_ES_GETSTOREDTMD no out buffer");
u64 TitleID = Memory::Read_U64(request.in_vectors[0].address); u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
u32 MaxCount = 0; u32 MaxCount = 0;
@ -969,8 +1049,7 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
{ {
u32 Address = request.io_vectors[0].address; u32 Address = request.io_vectors[0].address;
Memory::CopyToEmu(Address, Loader.GetTMDHeader(), Memory::CopyToEmu(Address, Loader.GetTMDHeader(), DiscIO::CNANDContentLoader::TMD_HEADER_SIZE);
DiscIO::CNANDContentLoader::TMD_HEADER_SIZE);
Address += DiscIO::CNANDContentLoader::TMD_HEADER_SIZE; Address += DiscIO::CNANDContentLoader::TMD_HEADER_SIZE;
const std::vector<DiscIO::SNANDContent>& rContent = Loader.GetContent(); const std::vector<DiscIO::SNANDContent>& rContent = Loader.GetContent();
@ -987,11 +1066,10 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
INFO_LOG(IOS_ES, "IOCTL_ES_GETSTOREDTMD: title: %08x/%08x (buffer size: %i)", INFO_LOG(IOS_ES, "IOCTL_ES_GETSTOREDTMD: title: %08x/%08x (buffer size: %i)",
(u32)(TitleID >> 32), (u32)TitleID, MaxCount); (u32)(TitleID >> 32), (u32)TitleID, MaxCount);
return GetDefaultReply(IPC_SUCCESS); 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); u32 keyIndex = Memory::Read_U32(request.in_vectors[0].address);
u8* IV = Memory::GetPointer(request.in_vectors[1].address); u8* IV = Memory::GetPointer(request.in_vectors[1].address);
u8* source = Memory::GetPointer(request.in_vectors[2].address); u8* source = Memory::GetPointer(request.in_vectors[2].address);
@ -1006,11 +1084,11 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
_dbg_assert_msg_(IOS_ES, keyIndex == 6, _dbg_assert_msg_(IOS_ES, keyIndex == 6,
"IOCTL_ES_ENCRYPT: Key type is not SD, data will be crap"); "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); u32 keyIndex = Memory::Read_U32(request.in_vectors[0].address);
u8* IV = Memory::GetPointer(request.in_vectors[1].address); u8* IV = Memory::GetPointer(request.in_vectors[1].address);
u8* source = Memory::GetPointer(request.in_vectors[2].address); u8* source = Memory::GetPointer(request.in_vectors[2].address);
@ -1022,11 +1100,11 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
_dbg_assert_msg_(IOS_ES, keyIndex == 6, _dbg_assert_msg_(IOS_ES, keyIndex == 6,
"IOCTL_ES_DECRYPT: Key type is not SD, data will be crap"); "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); _dbg_assert_(IOS_ES, request.in_vectors.size() == 2);
bool bSuccess = false; bool bSuccess = false;
bool bReset = false; bool bReset = false;
@ -1149,30 +1227,32 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
// involves restarting IOS; IOS generates two acknowledgements in a row. // involves restarting IOS; IOS generates two acknowledgements in a row.
EnqueueCommandAcknowledgement(request.address, 0); EnqueueCommandAcknowledgement(request.address, 0);
return GetNoReply(); return GetNoReply();
} }
break;
case IOCTL_ES_CHECKKOREAREGION: // note by DacoTaco : name is unknown, i just tried to name it IPCCommandResult ES::CheckKoreaRegion(const IOCtlVRequest& request)
// SOMETHING {
// 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 // IOS70 has this to let system menu 4.2 check if the console is region changed. it returns
// -1017 // -1017
// if the IOS didn't find the Korean keys and 0 if it does. 0 leads to a error 003 // 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."); INFO_LOG(IOS_ES, "IOCTL_ES_CHECKKOREAREGION: Title checked for Korean keys.");
return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT); 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"); INFO_LOG(IOS_ES, "IOCTL_ES_GETDEVICECERT");
_dbg_assert_(IOS_ES, request.io_vectors.size() == 1); _dbg_assert_(IOS_ES, request.io_vectors.size() == 1);
u8* destination = Memory::GetPointer(request.io_vectors[0].address); u8* destination = Memory::GetPointer(request.io_vectors[0].address);
EcWii& ec = EcWii::GetInstance(); EcWii& ec = EcWii::GetInstance();
get_ng_cert(destination, ec.getNgId(), ec.getNgKeyId(), ec.getNgPriv(), ec.getNgSig()); 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"); INFO_LOG(IOS_ES, "IOCTL_ES_SIGN");
u8* ap_cert_out = Memory::GetPointer(request.io_vectors[1].address); u8* ap_cert_out = Memory::GetPointer(request.io_vectors[1].address);
u8* data = Memory::GetPointer(request.in_vectors[0].address); u8* data = Memory::GetPointer(request.in_vectors[0].address);
@ -1182,34 +1262,30 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
EcWii& ec = EcWii::GetInstance(); EcWii& ec = EcWii::GetInstance();
get_ap_sig_and_cert(sig_out, ap_cert_out, m_TitleID, data, data_size, ec.getNgPriv(), get_ap_sig_and_cert(sig_out, ap_cert_out, m_TitleID, data, data_size, ec.getNgPriv(),
ec.getNgId()); ec.getNgId());
}
break;
case IOCTL_ES_GETBOOT2VERSION: return GetDefaultReply(IPC_SUCCESS);
{ }
IPCCommandResult ES::GetBoot2Version(const IOCtlVRequest& request)
{
INFO_LOG(IOS_ES, "IOCTL_ES_GETBOOT2VERSION"); INFO_LOG(IOS_ES, "IOCTL_ES_GETBOOT2VERSION");
Memory::Write_U32( // as of 26/02/2012, this was latest bootmii version
4, request.io_vectors[0].address); // as of 26/02/2012, this was latest bootmii version Memory::Write_U32(4, request.io_vectors[0].address);
} return GetDefaultReply(IPC_SUCCESS);
break; }
// =============================================================================================== IPCCommandResult ES::DIGetTicketView(const IOCtlVRequest& request)
// unsupported functions {
// =============================================================================================== // (Input: none, Output: 216 bytes) bug crediar :D
case IOCTL_ES_DIGETTICKETVIEW: // (Input: none, Output: 216 bytes) bug crediar :D
WARN_LOG(IOS_ES, "IOCTL_ES_DIGETTICKETVIEW: this looks really wrong..."); 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"); INFO_LOG(IOS_ES, "IOCTL_ES_GETOWNEDTITLECNT");
Memory::Write_U32(0, request.io_vectors[0].address); Memory::Write_U32(0, request.io_vectors[0].address);
break;
default:
request.DumpUnknown(GetDeviceName(), LogTypes::IOS);
}
return GetDefaultReply(IPC_SUCCESS); return GetDefaultReply(IPC_SUCCESS);
} }

View File

@ -138,21 +138,6 @@ private:
u32 m_Size; 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 struct ecc_cert_t
{ {
u32 sig_type; u32 sig_type;
@ -165,6 +150,59 @@ private:
u8 ecc_pubkey[0x3c]; u8 ecc_pubkey[0x3c];
u8 padding[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 Device
} // namespace HLE } // namespace HLE