IOS HLE: Deduplicate request code in ES

This commit is contained in:
Léo Lam 2017-01-15 11:49:03 +01:00
parent 6bf0b487d1
commit 4af67abb55
2 changed files with 195 additions and 214 deletions

View file

@ -97,10 +97,6 @@ u8* CWII_IPC_HLE_Device_es::keyTable[11] = {
key_empty, // Unknown key_empty, // Unknown
}; };
CWII_IPC_HLE_Device_es::~CWII_IPC_HLE_Device_es()
{
}
void CWII_IPC_HLE_Device_es::LoadWAD(const std::string& _rContentFile) void CWII_IPC_HLE_Device_es::LoadWAD(const std::string& _rContentFile)
{ {
m_ContentFile = _rContentFile; m_ContentFile = _rContentFile;
@ -195,17 +191,16 @@ void CWII_IPC_HLE_Device_es::DoState(PointerWrap& p)
} }
} }
IPCCommandResult CWII_IPC_HLE_Device_es::Open(u32 _CommandAddress, u32 _Mode) IOSReturnCode CWII_IPC_HLE_Device_es::Open(const IOSOpenRequest& request)
{ {
OpenInternal(); OpenInternal();
if (m_is_active) if (m_is_active)
INFO_LOG(WII_IPC_ES, "Device was re-opened."); INFO_LOG(WII_IPC_ES, "Device was re-opened.");
m_is_active = true; return IWII_IPC_HLE_Device::Open(request);
return GetDefaultReply();
} }
IPCCommandResult CWII_IPC_HLE_Device_es::Close(u32 _CommandAddress, bool _bForce) void CWII_IPC_HLE_Device_es::Close()
{ {
m_ContentAccessMap.clear(); m_ContentAccessMap.clear();
m_TitleIDs.clear(); m_TitleIDs.clear();
@ -216,7 +211,6 @@ IPCCommandResult CWII_IPC_HLE_Device_es::Close(u32 _CommandAddress, bool _bForce
m_is_active = false; m_is_active = false;
// clear the NAND content cache to make sure nothing remains open. // clear the NAND content cache to make sure nothing remains open.
DiscIO::CNANDContentManager::Access().ClearCache(); DiscIO::CNANDContentManager::Access().ClearCache();
return GetDefaultReply();
} }
u32 CWII_IPC_HLE_Device_es::OpenTitleContent(u32 CFD, u64 TitleID, u16 Index) u32 CWII_IPC_HLE_Device_es::OpenTitleContent(u32 CFD, u64 TitleID, u16 Index)
@ -248,53 +242,43 @@ u32 CWII_IPC_HLE_Device_es::OpenTitleContent(u32 CFD, u64 TitleID, u16 Index)
return CFD; return CFD;
} }
IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(const IOSIOCtlVRequest& request)
{ {
SIOCtlVBuffer Buffer(_CommandAddress); DEBUG_LOG(WII_IPC_ES, "%s (0x%x)", GetDeviceName().c_str(), request.request);
// Clear the IO buffers. Note that this is unsafe for other ioctlvs.
DEBUG_LOG(WII_IPC_ES, "%s (0x%x)", GetDeviceName().c_str(), Buffer.Parameter); for (const auto& io_vector : request.io_vectors)
// Prepare the out buffer(s) with zeroes as a safety precaution
// to avoid returning bad values
for (const auto& buffer : Buffer.PayloadBuffer)
{ {
// Don't zero an out buffer which is also one of the in buffers. if (!request.HasInputVectorWithAddress(io_vector.address))
if (std::any_of(Buffer.InBuffer.begin(), Buffer.InBuffer.end(), Memory::Memset(io_vector.address, 0, io_vector.size);
[&](const auto& in_buffer) { return in_buffer.m_Address == buffer.m_Address; }))
{
continue;
} }
Memory::Memset(buffer.m_Address, 0, buffer.m_Size); switch (request.request)
}
switch (Buffer.Parameter)
{ {
case IOCTL_ES_ADDTICKET: case IOCTL_ES_ADDTICKET:
{ {
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 3, _dbg_assert_msg_(WII_IPC_ES, request.in_vectors.size() == 3,
"IOCTL_ES_ADDTICKET wrong number of inputs"); "IOCTL_ES_ADDTICKET wrong number of inputs");
INFO_LOG(WII_IPC_ES, "IOCTL_ES_ADDTICKET"); INFO_LOG(WII_IPC_ES, "IOCTL_ES_ADDTICKET");
std::vector<u8> ticket(Buffer.InBuffer[0].m_Size); std::vector<u8> ticket(request.in_vectors[0].size);
Memory::CopyFromEmu(ticket.data(), Buffer.InBuffer[0].m_Address, Buffer.InBuffer[0].m_Size); Memory::CopyFromEmu(ticket.data(), request.in_vectors[0].address, request.in_vectors[0].size);
DiscIO::AddTicket(ticket); DiscIO::AddTicket(ticket);
break; break;
} }
case IOCTL_ES_ADDTITLESTART: case IOCTL_ES_ADDTITLESTART:
{ {
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 4, _dbg_assert_msg_(WII_IPC_ES, request.in_vectors.size() == 4,
"IOCTL_ES_ADDTITLESTART wrong number of inputs"); "IOCTL_ES_ADDTITLESTART wrong number of inputs");
INFO_LOG(WII_IPC_ES, "IOCTL_ES_ADDTITLESTART"); INFO_LOG(WII_IPC_ES, "IOCTL_ES_ADDTITLESTART");
std::vector<u8> tmd(Buffer.InBuffer[0].m_Size); std::vector<u8> tmd(request.in_vectors[0].size);
Memory::CopyFromEmu(tmd.data(), Buffer.InBuffer[0].m_Address, Buffer.InBuffer[0].m_Size); Memory::CopyFromEmu(tmd.data(), request.in_vectors[0].address, request.in_vectors[0].size);
m_addtitle_tmd.SetBytes(tmd); m_addtitle_tmd.SetBytes(tmd);
if (!m_addtitle_tmd.IsValid()) if (!m_addtitle_tmd.IsValid())
{ {
ERROR_LOG(WII_IPC_ES, "Invalid TMD while adding title (size = %zd)", tmd.size()); ERROR_LOG(WII_IPC_ES, "Invalid TMD while adding title (size = %zd)", tmd.size());
Memory::Write_U32(ES_INVALID_TMD, _CommandAddress + 0x4); request.SetReturnValue(ES_INVALID_TMD);
return GetDefaultReply(); return GetDefaultReply();
} }
@ -310,17 +294,17 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
case IOCTL_ES_ADDCONTENTSTART: case IOCTL_ES_ADDCONTENTSTART:
{ {
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 2, _dbg_assert_msg_(WII_IPC_ES, request.in_vectors.size() == 2,
"IOCTL_ES_ADDCONTENTSTART wrong number of inputs"); "IOCTL_ES_ADDCONTENTSTART wrong number of inputs");
u64 title_id = Memory::Read_U64(Buffer.InBuffer[0].m_Address); u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
u32 content_id = Memory::Read_U32(Buffer.InBuffer[1].m_Address); u32 content_id = Memory::Read_U32(request.in_vectors[1].address);
if (m_addtitle_content_id != 0xFFFFFFFF) if (m_addtitle_content_id != 0xFFFFFFFF)
{ {
ERROR_LOG(WII_IPC_ES, "Trying to add content when we haven't finished adding " ERROR_LOG(WII_IPC_ES, "Trying to add content when we haven't finished adding "
"another content. Unsupported."); "another content. Unsupported.");
Memory::Write_U32(ES_WRITE_FAILURE, _CommandAddress + 0x4); request.SetReturnValue(ES_WRITE_FAILURE);
return GetDefaultReply(); return GetDefaultReply();
} }
m_addtitle_content_id = content_id; m_addtitle_content_id = content_id;
@ -343,39 +327,39 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
// no known content installer which performs content addition concurrently. // no known content installer which performs content addition concurrently.
// 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;
Memory::Write_U32(content_fd, _CommandAddress + 0x4); request.SetReturnValue(content_fd);
return GetDefaultReply(); return GetDefaultReply();
} }
case IOCTL_ES_ADDCONTENTDATA: case IOCTL_ES_ADDCONTENTDATA:
{ {
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 2, _dbg_assert_msg_(WII_IPC_ES, request.in_vectors.size() == 2,
"IOCTL_ES_ADDCONTENTDATA wrong number of inputs"); "IOCTL_ES_ADDCONTENTDATA wrong number of inputs");
u32 content_fd = Memory::Read_U32(Buffer.InBuffer[0].m_Address); u32 content_fd = Memory::Read_U32(request.in_vectors[0].address);
INFO_LOG(WII_IPC_ES, "IOCTL_ES_ADDCONTENTDATA: content fd %08x, " INFO_LOG(WII_IPC_ES, "IOCTL_ES_ADDCONTENTDATA: content fd %08x, "
"size %d", "size %d",
content_fd, Buffer.InBuffer[1].m_Size); content_fd, request.in_vectors[1].size);
u8* data_start = Memory::GetPointer(Buffer.InBuffer[1].m_Address); u8* data_start = Memory::GetPointer(request.in_vectors[1].address);
u8* data_end = data_start + Buffer.InBuffer[1].m_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; break;
} }
case IOCTL_ES_ADDCONTENTFINISH: case IOCTL_ES_ADDCONTENTFINISH:
{ {
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 1, _dbg_assert_msg_(WII_IPC_ES, request.in_vectors.size() == 1,
"IOCTL_ES_ADDCONTENTFINISH wrong number of inputs"); "IOCTL_ES_ADDCONTENTFINISH wrong number of inputs");
u32 content_fd = Memory::Read_U32(Buffer.InBuffer[0].m_Address); u32 content_fd = Memory::Read_U32(request.in_vectors[0].address);
INFO_LOG(WII_IPC_ES, "IOCTL_ES_ADDCONTENTFINISH: content fd %08x", content_fd); INFO_LOG(WII_IPC_ES, "IOCTL_ES_ADDCONTENTFINISH: content fd %08x", content_fd);
// Try to find the title key from a pre-installed ticket. // Try to find the title key from a pre-installed ticket.
std::vector<u8> ticket = DiscIO::FindSignedTicket(m_addtitle_tmd.GetTitleId()); std::vector<u8> ticket = DiscIO::FindSignedTicket(m_addtitle_tmd.GetTitleId());
if (ticket.size() == 0) if (ticket.size() == 0)
{ {
Memory::Write_U32(ES_NO_TICKET_INSTALLED, _CommandAddress + 0x4); request.SetReturnValue(ES_NO_TICKET_INSTALLED);
return GetDefaultReply(); return GetDefaultReply();
} }
@ -387,7 +371,7 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
TMDReader::Content content_info; TMDReader::Content content_info;
if (!m_addtitle_tmd.FindContentById(m_addtitle_content_id, &content_info)) if (!m_addtitle_tmd.FindContentById(m_addtitle_content_id, &content_info))
{ {
Memory::Write_U32(ES_INVALID_TMD, _CommandAddress + 0x4); request.SetReturnValue(ES_INVALID_TMD);
return GetDefaultReply(); return GetDefaultReply();
} }
u8 iv[16] = {0}; u8 iv[16] = {0};
@ -417,23 +401,22 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
case IOCTL_ES_GETDEVICEID: case IOCTL_ES_GETDEVICEID:
{ {
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1, _dbg_assert_msg_(WII_IPC_ES, request.io_vectors.size() == 1,
"IOCTL_ES_GETDEVICEID no out buffer"); "IOCTL_ES_GETDEVICEID no io vectors");
EcWii& ec = EcWii::GetInstance(); EcWii& ec = EcWii::GetInstance();
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETDEVICEID %08X", ec.getNgId()); INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETDEVICEID %08X", ec.getNgId());
Memory::Write_U32(ec.getNgId(), Buffer.PayloadBuffer[0].m_Address); Memory::Write_U32(ec.getNgId(), request.io_vectors[0].address);
Memory::Write_U32(0, _CommandAddress + 0x4); request.SetReturnValue(IPC_SUCCESS);
return GetDefaultReply(); return GetDefaultReply();
} }
break;
case IOCTL_ES_GETTITLECONTENTSCNT: case IOCTL_ES_GETTITLECONTENTSCNT:
{ {
_dbg_assert_(WII_IPC_ES, Buffer.NumberInBuffer == 1); _dbg_assert_(WII_IPC_ES, request.in_vectors.size() == 1);
_dbg_assert_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1); _dbg_assert_(WII_IPC_ES, request.io_vectors.size() == 1);
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
const DiscIO::CNANDContentLoader& rNANDContent = AccessContentDevice(TitleID); const DiscIO::CNANDContentLoader& rNANDContent = AccessContentDevice(TitleID);
u16 NumberOfPrivateContent = 0; u16 NumberOfPrivateContent = 0;
@ -442,14 +425,16 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
NumberOfPrivateContent = rNANDContent.GetNumEntries(); NumberOfPrivateContent = rNANDContent.GetNumEntries();
if ((u32)(TitleID >> 32) == 0x00010000) if ((u32)(TitleID >> 32) == 0x00010000)
Memory::Write_U32(0, Buffer.PayloadBuffer[0].m_Address); Memory::Write_U32(0, request.io_vectors[0].address);
else else
Memory::Write_U32(NumberOfPrivateContent, Buffer.PayloadBuffer[0].m_Address); Memory::Write_U32(NumberOfPrivateContent, request.io_vectors[0].address);
Memory::Write_U32(0, _CommandAddress + 0x4); request.SetReturnValue(IPC_SUCCESS);
} }
else else
Memory::Write_U32((u32)rNANDContent.GetContentSize(), _CommandAddress + 0x4); {
request.SetReturnValue(static_cast<s32>(rNANDContent.GetContentSize()));
}
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLECONTENTSCNT: TitleID: %08x/%08x content count %i", INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLECONTENTSCNT: TitleID: %08x/%08x content count %i",
(u32)(TitleID >> 32), (u32)TitleID, (u32)(TitleID >> 32), (u32)TitleID,
@ -461,12 +446,12 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
case IOCTL_ES_GETTITLECONTENTS: case IOCTL_ES_GETTITLECONTENTS:
{ {
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 2, _dbg_assert_msg_(WII_IPC_ES, request.in_vectors.size() == 2,
"IOCTL_ES_GETTITLECONTENTS bad in buffer"); "IOCTL_ES_GETTITLECONTENTS bad in buffer");
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1, _dbg_assert_msg_(WII_IPC_ES, request.io_vectors.size() == 1,
"IOCTL_ES_GETTITLECONTENTS bad out buffer"); "IOCTL_ES_GETTITLECONTENTS bad out buffer");
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
const DiscIO::CNANDContentLoader& rNANDContent = AccessContentDevice(TitleID); const DiscIO::CNANDContentLoader& rNANDContent = AccessContentDevice(TitleID);
if (rNANDContent.IsValid()) // Not sure if dolphin will ever fail this check if (rNANDContent.IsValid()) // Not sure if dolphin will ever fail this check
@ -474,15 +459,15 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
for (u16 i = 0; i < rNANDContent.GetNumEntries(); i++) for (u16 i = 0; i < rNANDContent.GetNumEntries(); i++)
{ {
Memory::Write_U32(rNANDContent.GetContentByIndex(i)->m_ContentID, Memory::Write_U32(rNANDContent.GetContentByIndex(i)->m_ContentID,
Buffer.PayloadBuffer[0].m_Address + i * 4); request.io_vectors[0].address + i * 4);
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLECONTENTS: Index %d: %08x", i, INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLECONTENTS: Index %d: %08x", i,
rNANDContent.GetContentByIndex(i)->m_ContentID); rNANDContent.GetContentByIndex(i)->m_ContentID);
} }
Memory::Write_U32(0, _CommandAddress + 0x4); request.SetReturnValue(IPC_SUCCESS);
} }
else else
{ {
Memory::Write_U32((u32)rNANDContent.GetContentSize(), _CommandAddress + 0x4); request.SetReturnValue(static_cast<s32>(rNANDContent.GetContentSize()));
ERROR_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLECONTENTS: Unable to open content %zu", ERROR_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLECONTENTS: Unable to open content %zu",
rNANDContent.GetContentSize()); rNANDContent.GetContentSize());
} }
@ -493,14 +478,14 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
case IOCTL_ES_OPENTITLECONTENT: case IOCTL_ES_OPENTITLECONTENT:
{ {
_dbg_assert_(WII_IPC_ES, Buffer.NumberInBuffer == 3); _dbg_assert_(WII_IPC_ES, request.in_vectors.size() == 3);
_dbg_assert_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 0); _dbg_assert_(WII_IPC_ES, request.io_vectors.size() == 0);
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
u32 Index = Memory::Read_U32(Buffer.InBuffer[2].m_Address); u32 Index = Memory::Read_U32(request.in_vectors[2].address);
u32 CFD = OpenTitleContent(m_AccessIdentID++, TitleID, Index); s32 CFD = OpenTitleContent(m_AccessIdentID++, TitleID, Index);
Memory::Write_U32(CFD, _CommandAddress + 0x4); request.SetReturnValue(CFD);
INFO_LOG(WII_IPC_ES, "IOCTL_ES_OPENTITLECONTENT: TitleID: %08x/%08x Index %i -> got CFD %x", INFO_LOG(WII_IPC_ES, "IOCTL_ES_OPENTITLECONTENT: TitleID: %08x/%08x Index %i -> got CFD %x",
(u32)(TitleID >> 32), (u32)TitleID, Index, CFD); (u32)(TitleID >> 32), (u32)TitleID, Index, CFD);
@ -511,12 +496,12 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
case IOCTL_ES_OPENCONTENT: case IOCTL_ES_OPENCONTENT:
{ {
_dbg_assert_(WII_IPC_ES, Buffer.NumberInBuffer == 1); _dbg_assert_(WII_IPC_ES, request.in_vectors.size() == 1);
_dbg_assert_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 0); _dbg_assert_(WII_IPC_ES, request.io_vectors.size() == 0);
u32 Index = Memory::Read_U32(Buffer.InBuffer[0].m_Address); u32 Index = Memory::Read_U32(request.in_vectors[0].address);
u32 CFD = OpenTitleContent(m_AccessIdentID++, m_TitleID, Index); s32 CFD = OpenTitleContent(m_AccessIdentID++, m_TitleID, Index);
Memory::Write_U32(CFD, _CommandAddress + 0x4); request.SetReturnValue(CFD);
INFO_LOG(WII_IPC_ES, "IOCTL_ES_OPENCONTENT: Index %i -> got CFD %x", Index, CFD); INFO_LOG(WII_IPC_ES, "IOCTL_ES_OPENCONTENT: Index %i -> got CFD %x", Index, CFD);
return GetDefaultReply(); return GetDefaultReply();
@ -525,17 +510,17 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
case IOCTL_ES_READCONTENT: case IOCTL_ES_READCONTENT:
{ {
_dbg_assert_(WII_IPC_ES, Buffer.NumberInBuffer == 1); _dbg_assert_(WII_IPC_ES, request.in_vectors.size() == 1);
_dbg_assert_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1); _dbg_assert_(WII_IPC_ES, request.io_vectors.size() == 1);
u32 CFD = Memory::Read_U32(Buffer.InBuffer[0].m_Address); u32 CFD = Memory::Read_U32(request.in_vectors[0].address);
u32 Size = Buffer.PayloadBuffer[0].m_Size; u32 Size = request.io_vectors[0].size;
u32 Addr = Buffer.PayloadBuffer[0].m_Address; u32 Addr = request.io_vectors[0].address;
auto itr = m_ContentAccessMap.find(CFD); auto itr = m_ContentAccessMap.find(CFD);
if (itr == m_ContentAccessMap.end()) if (itr == m_ContentAccessMap.end())
{ {
Memory::Write_U32(-1, _CommandAddress + 0x4); request.SetReturnValue(-1);
return GetDefaultReply(); return GetDefaultReply();
} }
SContentAccess& rContent = itr->second; SContentAccess& rContent = itr->second;
@ -573,24 +558,24 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
"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, Addr, Size, rContent.m_Position, rContent.m_Index); CFD, Addr, Size, rContent.m_Position, rContent.m_Index);
Memory::Write_U32(Size, _CommandAddress + 0x4); request.SetReturnValue(Size);
return GetDefaultReply(); return GetDefaultReply();
} }
break; break;
case IOCTL_ES_CLOSECONTENT: case IOCTL_ES_CLOSECONTENT:
{ {
_dbg_assert_(WII_IPC_ES, Buffer.NumberInBuffer == 1); _dbg_assert_(WII_IPC_ES, request.in_vectors.size() == 1);
_dbg_assert_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 0); _dbg_assert_(WII_IPC_ES, request.io_vectors.size() == 0);
u32 CFD = Memory::Read_U32(Buffer.InBuffer[0].m_Address); u32 CFD = Memory::Read_U32(request.in_vectors[0].address);
INFO_LOG(WII_IPC_ES, "IOCTL_ES_CLOSECONTENT: CFD %x", CFD); INFO_LOG(WII_IPC_ES, "IOCTL_ES_CLOSECONTENT: CFD %x", CFD);
auto itr = m_ContentAccessMap.find(CFD); auto itr = m_ContentAccessMap.find(CFD);
if (itr == m_ContentAccessMap.end()) if (itr == m_ContentAccessMap.end())
{ {
Memory::Write_U32(-1, _CommandAddress + 0x4); request.SetReturnValue(-1);
return GetDefaultReply(); return GetDefaultReply();
} }
@ -604,24 +589,24 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
m_ContentAccessMap.erase(itr); m_ContentAccessMap.erase(itr);
Memory::Write_U32(0, _CommandAddress + 0x4); request.SetReturnValue(IPC_SUCCESS);
return GetDefaultReply(); return GetDefaultReply();
} }
break; break;
case IOCTL_ES_SEEKCONTENT: case IOCTL_ES_SEEKCONTENT:
{ {
_dbg_assert_(WII_IPC_ES, Buffer.NumberInBuffer == 3); _dbg_assert_(WII_IPC_ES, request.in_vectors.size() == 3);
_dbg_assert_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 0); _dbg_assert_(WII_IPC_ES, request.io_vectors.size() == 0);
u32 CFD = Memory::Read_U32(Buffer.InBuffer[0].m_Address); u32 CFD = Memory::Read_U32(request.in_vectors[0].address);
u32 Addr = Memory::Read_U32(Buffer.InBuffer[1].m_Address); u32 Addr = Memory::Read_U32(request.in_vectors[1].address);
u32 Mode = Memory::Read_U32(Buffer.InBuffer[2].m_Address); u32 Mode = Memory::Read_U32(request.in_vectors[2].address);
auto itr = m_ContentAccessMap.find(CFD); auto itr = m_ContentAccessMap.find(CFD);
if (itr == m_ContentAccessMap.end()) if (itr == m_ContentAccessMap.end())
{ {
Memory::Write_U32(-1, _CommandAddress + 0x4); request.SetReturnValue(-1);
return GetDefaultReply(); return GetDefaultReply();
} }
SContentAccess& rContent = itr->second; SContentAccess& rContent = itr->second;
@ -644,19 +629,19 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
DEBUG_LOG(WII_IPC_ES, "IOCTL_ES_SEEKCONTENT: CFD %x, Address 0x%x, Mode %i -> Pos %i", CFD, DEBUG_LOG(WII_IPC_ES, "IOCTL_ES_SEEKCONTENT: CFD %x, Address 0x%x, Mode %i -> Pos %i", CFD,
Addr, Mode, rContent.m_Position); Addr, Mode, rContent.m_Position);
Memory::Write_U32(rContent.m_Position, _CommandAddress + 0x4); request.SetReturnValue(rContent.m_Position);
return GetDefaultReply(); return GetDefaultReply();
} }
break; break;
case IOCTL_ES_GETTITLEDIR: case IOCTL_ES_GETTITLEDIR:
{ {
_dbg_assert_(WII_IPC_ES, Buffer.NumberInBuffer == 1); _dbg_assert_(WII_IPC_ES, request.in_vectors.size() == 1);
_dbg_assert_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1); _dbg_assert_(WII_IPC_ES, request.io_vectors.size() == 1);
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
char* Path = (char*)Memory::GetPointer(Buffer.PayloadBuffer[0].m_Address); char* Path = (char*)Memory::GetPointer(request.io_vectors[0].address);
sprintf(Path, "/title/%08x/%08x/data", (u32)(TitleID >> 32), (u32)TitleID); sprintf(Path, "/title/%08x/%08x/data", (u32)(TitleID >> 32), (u32)TitleID);
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLEDIR: %s", Path); INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLEDIR: %s", Path);
@ -665,56 +650,56 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
case IOCTL_ES_GETTITLEID: case IOCTL_ES_GETTITLEID:
{ {
_dbg_assert_(WII_IPC_ES, Buffer.NumberInBuffer == 0); _dbg_assert_(WII_IPC_ES, request.in_vectors.size() == 0);
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1, _dbg_assert_msg_(WII_IPC_ES, request.io_vectors.size() == 1,
"IOCTL_ES_GETTITLEID no out buffer"); "IOCTL_ES_GETTITLEID no out buffer");
Memory::Write_U64(m_TitleID, Buffer.PayloadBuffer[0].m_Address); Memory::Write_U64(m_TitleID, request.io_vectors[0].address);
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLEID: %08x/%08x", (u32)(m_TitleID >> 32), (u32)m_TitleID); INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLEID: %08x/%08x", (u32)(m_TitleID >> 32), (u32)m_TitleID);
} }
break; break;
case IOCTL_ES_SETUID: case IOCTL_ES_SETUID:
{ {
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 1, "IOCTL_ES_SETUID no in buffer"); _dbg_assert_msg_(WII_IPC_ES, request.in_vectors.size() == 1, "IOCTL_ES_SETUID no in buffer");
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 0, _dbg_assert_msg_(WII_IPC_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(Buffer.InBuffer[0].m_Address); u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
INFO_LOG(WII_IPC_ES, "IOCTL_ES_SETUID titleID: %08x/%08x", (u32)(TitleID >> 32), (u32)TitleID); INFO_LOG(WII_IPC_ES, "IOCTL_ES_SETUID titleID: %08x/%08x", (u32)(TitleID >> 32), (u32)TitleID);
} }
break; break;
case IOCTL_ES_GETTITLECNT: case IOCTL_ES_GETTITLECNT:
{ {
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 0, _dbg_assert_msg_(WII_IPC_ES, request.in_vectors.size() == 0,
"IOCTL_ES_GETTITLECNT has an in buffer"); "IOCTL_ES_GETTITLECNT has an in buffer");
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1, _dbg_assert_msg_(WII_IPC_ES, request.io_vectors.size() == 1,
"IOCTL_ES_GETTITLECNT has no out buffer"); "IOCTL_ES_GETTITLECNT has no out buffer");
_dbg_assert_msg_(WII_IPC_ES, Buffer.PayloadBuffer[0].m_Size == 4, _dbg_assert_msg_(WII_IPC_ES, request.io_vectors[0].size == 4,
"IOCTL_ES_GETTITLECNT payload[0].size != 4"); "IOCTL_ES_GETTITLECNT payload[0].size != 4");
Memory::Write_U32((u32)m_TitleIDs.size(), Buffer.PayloadBuffer[0].m_Address); Memory::Write_U32((u32)m_TitleIDs.size(), request.io_vectors[0].address);
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLECNT: Number of Titles %zu", m_TitleIDs.size()); INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLECNT: Number of Titles %zu", m_TitleIDs.size());
Memory::Write_U32(0, _CommandAddress + 0x4); request.SetReturnValue(IPC_SUCCESS);
return GetDefaultReply(); return GetDefaultReply();
} }
break; break;
case IOCTL_ES_GETTITLES: case IOCTL_ES_GETTITLES:
{ {
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 1, "IOCTL_ES_GETTITLES has an in buffer"); _dbg_assert_msg_(WII_IPC_ES, request.in_vectors.size() == 1,
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1, "IOCTL_ES_GETTITLES has an in buffer");
_dbg_assert_msg_(WII_IPC_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(Buffer.InBuffer[0].m_Address); u32 MaxCount = Memory::Read_U32(request.in_vectors[0].address);
u32 Count = 0; u32 Count = 0;
for (int i = 0; i < (int)m_TitleIDs.size(); i++) for (int i = 0; i < (int)m_TitleIDs.size(); i++)
{ {
Memory::Write_U64(m_TitleIDs[i], Buffer.PayloadBuffer[0].m_Address + i * 8); Memory::Write_U64(m_TitleIDs[i], request.io_vectors[0].address + i * 8);
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLES: %08x/%08x", (u32)(m_TitleIDs[i] >> 32), INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLES: %08x/%08x", (u32)(m_TitleIDs[i] >> 32),
(u32)m_TitleIDs[i]); (u32)m_TitleIDs[i]);
Count++; Count++;
@ -723,18 +708,19 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
} }
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLES: Number of titles returned %i", Count); INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLES: Number of titles returned %i", Count);
Memory::Write_U32(0, _CommandAddress + 0x4); request.SetReturnValue(IPC_SUCCESS);
return GetDefaultReply(); return GetDefaultReply();
} }
break; break;
case IOCTL_ES_GETVIEWCNT: case IOCTL_ES_GETVIEWCNT:
{ {
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 1, "IOCTL_ES_GETVIEWCNT no in buffer"); _dbg_assert_msg_(WII_IPC_ES, request.in_vectors.size() == 1,
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1, "IOCTL_ES_GETVIEWCNT no in buffer");
_dbg_assert_msg_(WII_IPC_ES, request.io_vectors.size() == 1,
"IOCTL_ES_GETVIEWCNT no out buffer"); "IOCTL_ES_GETVIEWCNT no out buffer");
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
u32 retVal = 0; u32 retVal = 0;
const DiscIO::CNANDContentLoader& Loader = AccessContentDevice(TitleID); const DiscIO::CNANDContentLoader& Loader = AccessContentDevice(TitleID);
@ -774,20 +760,19 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETVIEWCNT for titleID: %08x/%08x (View Count = %i)", INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETVIEWCNT for titleID: %08x/%08x (View Count = %i)",
(u32)(TitleID >> 32), (u32)TitleID, ViewCount); (u32)(TitleID >> 32), (u32)TitleID, ViewCount);
Memory::Write_U32(ViewCount, Buffer.PayloadBuffer[0].m_Address); Memory::Write_U32(ViewCount, request.io_vectors[0].address);
Memory::Write_U32(retVal, _CommandAddress + 0x4); request.SetReturnValue(retVal);
return GetDefaultReply(); return GetDefaultReply();
} }
break; break;
case IOCTL_ES_GETVIEWS: case IOCTL_ES_GETVIEWS:
{ {
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 2, "IOCTL_ES_GETVIEWS no in buffer"); _dbg_assert_msg_(WII_IPC_ES, request.in_vectors.size() == 2, "IOCTL_ES_GETVIEWS no in buffer");
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1, _dbg_assert_msg_(WII_IPC_ES, request.io_vectors.size() == 1, "IOCTL_ES_GETVIEWS no out buffer");
"IOCTL_ES_GETVIEWS no out buffer");
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
u32 maxViews = Memory::Read_U32(Buffer.InBuffer[1].m_Address); u32 maxViews = Memory::Read_U32(request.in_vectors[1].address);
u32 retVal = 0; u32 retVal = 0;
const DiscIO::CNANDContentLoader& Loader = AccessContentDevice(TitleID); const DiscIO::CNANDContentLoader& Loader = AccessContentDevice(TitleID);
@ -808,9 +793,9 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
pFile.ReadBytes(FileTicket, DiscIO::CNANDContentLoader::TICKET_SIZE); pFile.ReadBytes(FileTicket, DiscIO::CNANDContentLoader::TICKET_SIZE);
++View) ++View)
{ {
Memory::Write_U32(View, Buffer.PayloadBuffer[0].m_Address + View * 0xD8); Memory::Write_U32(View, request.io_vectors[0].address + View * 0xD8);
Memory::CopyToEmu(Buffer.PayloadBuffer[0].m_Address + 4 + View * 0xD8, Memory::CopyToEmu(request.io_vectors[0].address + 4 + View * 0xD8, FileTicket + 0x1D0,
FileTicket + 0x1D0, 212); 212);
} }
} }
} }
@ -820,7 +805,7 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
// SDK or libogc, just passed to LaunchTitle, so this // SDK or libogc, just passed to LaunchTitle, so this
// shouldn't matter at all. Just fill out some fields just // shouldn't matter at all. Just fill out some fields just
// to be on the safe side. // to be on the safe side.
u32 Address = Buffer.PayloadBuffer[0].m_Address; u32 Address = request.io_vectors[0].address;
Memory::Memset(Address, 0, 0xD8); Memory::Memset(Address, 0, 0xD8);
Memory::Write_U64(TitleID, Address + 4 + (0x1dc - 0x1d0)); // title ID Memory::Write_U64(TitleID, Address + 4 + (0x1dc - 0x1d0)); // title ID
Memory::Write_U16(0xffff, Address + 4 + (0x1e4 - 0x1d0)); // unnnown Memory::Write_U16(0xffff, Address + 4 + (0x1e4 - 0x1d0)); // unnnown
@ -840,8 +825,8 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
static_cast<u32>(Loader.GetTicket().size()) / DiscIO::CNANDContentLoader::TICKET_SIZE; static_cast<u32>(Loader.GetTicket().size()) / DiscIO::CNANDContentLoader::TICKET_SIZE;
for (unsigned int view = 0; view != maxViews && view < view_count; ++view) for (unsigned int view = 0; view != maxViews && view < view_count; ++view)
{ {
Memory::Write_U32(view, Buffer.PayloadBuffer[0].m_Address + view * 0xD8); Memory::Write_U32(view, request.io_vectors[0].address + view * 0xD8);
Memory::CopyToEmu(Buffer.PayloadBuffer[0].m_Address + 4 + view * 0xD8, Memory::CopyToEmu(request.io_vectors[0].address + 4 + view * 0xD8,
&ticket[0x1D0 + (view * DiscIO::CNANDContentLoader::TICKET_SIZE)], 212); &ticket[0x1D0 + (view * DiscIO::CNANDContentLoader::TICKET_SIZE)], 212);
} }
} }
@ -849,18 +834,19 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETVIEWS for titleID: %08x/%08x (MaxViews = %i)", INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETVIEWS for titleID: %08x/%08x (MaxViews = %i)",
(u32)(TitleID >> 32), (u32)TitleID, maxViews); (u32)(TitleID >> 32), (u32)TitleID, maxViews);
Memory::Write_U32(retVal, _CommandAddress + 0x4); request.SetReturnValue(retVal);
return GetDefaultReply(); return GetDefaultReply();
} }
break; break;
case IOCTL_ES_GETTMDVIEWCNT: case IOCTL_ES_GETTMDVIEWCNT:
{ {
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 1, "IOCTL_ES_GETTMDVIEWCNT no in buffer"); _dbg_assert_msg_(WII_IPC_ES, request.in_vectors.size() == 1,
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1, "IOCTL_ES_GETTMDVIEWCNT no in buffer");
_dbg_assert_msg_(WII_IPC_ES, request.io_vectors.size() == 1,
"IOCTL_ES_GETTMDVIEWCNT no out buffer"); "IOCTL_ES_GETTMDVIEWCNT no out buffer");
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
const DiscIO::CNANDContentLoader& Loader = AccessContentDevice(TitleID); const DiscIO::CNANDContentLoader& Loader = AccessContentDevice(TitleID);
@ -873,9 +859,9 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
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, Buffer.PayloadBuffer[0].m_Address); Memory::Write_U32(TMDViewCnt, request.io_vectors[0].address);
Memory::Write_U32(0, _CommandAddress + 0x4); request.SetReturnValue(IPC_SUCCESS);
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTMDVIEWCNT: title: %08x/%08x (view size %i)", INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTMDVIEWCNT: title: %08x/%08x (view size %i)",
(u32)(TitleID >> 32), (u32)TitleID, TMDViewCnt); (u32)(TitleID >> 32), (u32)TitleID, TMDViewCnt);
@ -885,12 +871,13 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
case IOCTL_ES_GETTMDVIEWS: case IOCTL_ES_GETTMDVIEWS:
{ {
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 2, "IOCTL_ES_GETTMDVIEWCNT no in buffer"); _dbg_assert_msg_(WII_IPC_ES, request.in_vectors.size() == 2,
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1, "IOCTL_ES_GETTMDVIEWCNT no in buffer");
_dbg_assert_msg_(WII_IPC_ES, request.io_vectors.size() == 1,
"IOCTL_ES_GETTMDVIEWCNT no out buffer"); "IOCTL_ES_GETTMDVIEWCNT no out buffer");
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
u32 MaxCount = Memory::Read_U32(Buffer.InBuffer[1].m_Address); u32 MaxCount = Memory::Read_U32(request.in_vectors[1].address);
const DiscIO::CNANDContentLoader& Loader = AccessContentDevice(TitleID); const DiscIO::CNANDContentLoader& Loader = AccessContentDevice(TitleID);
@ -899,7 +886,7 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
if (Loader.IsValid()) if (Loader.IsValid())
{ {
u32 Address = Buffer.PayloadBuffer[0].m_Address; u32 Address = request.io_vectors[0].address;
Memory::CopyToEmu(Address, Loader.GetTMDView(), DiscIO::CNANDContentLoader::TMD_VIEW_SIZE); Memory::CopyToEmu(Address, Loader.GetTMDView(), DiscIO::CNANDContentLoader::TMD_VIEW_SIZE);
Address += DiscIO::CNANDContentLoader::TMD_VIEW_SIZE; Address += DiscIO::CNANDContentLoader::TMD_VIEW_SIZE;
@ -923,9 +910,9 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
} }
_dbg_assert_(WII_IPC_ES, _dbg_assert_(WII_IPC_ES,
(Address - Buffer.PayloadBuffer[0].m_Address) == Buffer.PayloadBuffer[0].m_Size); (Address - request.io_vectors[0].address) == request.io_vectors[0].size);
} }
Memory::Write_U32(0, _CommandAddress + 0x4); request.SetReturnValue(IPC_SUCCESS);
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTMDVIEWS: title: %08x/%08x (buffer size: %i)", INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTMDVIEWS: title: %08x/%08x (buffer size: %i)",
(u32)(TitleID >> 32), (u32)TitleID, MaxCount); (u32)(TitleID >> 32), (u32)TitleID, MaxCount);
@ -934,51 +921,51 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
break; break;
case IOCTL_ES_GETCONSUMPTION: // This is at least what crediar's ES module does case IOCTL_ES_GETCONSUMPTION: // This is at least what crediar's ES module does
Memory::Write_U32(0, Buffer.PayloadBuffer[1].m_Address); Memory::Write_U32(0, request.io_vectors[1].address);
Memory::Write_U32(0, _CommandAddress + 0x4); request.SetReturnValue(IPC_SUCCESS);
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETCONSUMPTION:%d", Memory::Read_U32(_CommandAddress + 4)); INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETCONSUMPTION");
return GetDefaultReply(); return GetDefaultReply();
case IOCTL_ES_DELETETICKET: case IOCTL_ES_DELETETICKET:
{ {
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
INFO_LOG(WII_IPC_ES, "IOCTL_ES_DELETETICKET: title: %08x/%08x", (u32)(TitleID >> 32), INFO_LOG(WII_IPC_ES, "IOCTL_ES_DELETETICKET: title: %08x/%08x", (u32)(TitleID >> 32),
(u32)TitleID); (u32)TitleID);
if (File::Delete(Common::GetTicketFileName(TitleID, Common::FROM_SESSION_ROOT))) if (File::Delete(Common::GetTicketFileName(TitleID, Common::FROM_SESSION_ROOT)))
{ {
Memory::Write_U32(0, _CommandAddress + 0x4); request.SetReturnValue(IPC_SUCCESS);
} }
else else
{ {
// Presumably return -1017 when delete fails // Presumably return -1017 when delete fails
Memory::Write_U32(ES_PARAMTER_SIZE_OR_ALIGNMENT, _CommandAddress + 0x4); request.SetReturnValue(ES_PARAMETER_SIZE_OR_ALIGNMENT);
} }
} }
break; break;
case IOCTL_ES_DELETETITLECONTENT: case IOCTL_ES_DELETETITLECONTENT:
{ {
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
INFO_LOG(WII_IPC_ES, "IOCTL_ES_DELETETITLECONTENT: title: %08x/%08x", (u32)(TitleID >> 32), INFO_LOG(WII_IPC_ES, "IOCTL_ES_DELETETITLECONTENT: title: %08x/%08x", (u32)(TitleID >> 32),
(u32)TitleID); (u32)TitleID);
if (DiscIO::CNANDContentManager::Access().RemoveTitle(TitleID, Common::FROM_SESSION_ROOT)) if (DiscIO::CNANDContentManager::Access().RemoveTitle(TitleID, Common::FROM_SESSION_ROOT))
{ {
Memory::Write_U32(0, _CommandAddress + 0x4); request.SetReturnValue(IPC_SUCCESS);
} }
else else
{ {
// Presumably return -1017 when title not installed TODO verify // Presumably return -1017 when title not installed TODO verify
Memory::Write_U32(ES_PARAMTER_SIZE_OR_ALIGNMENT, _CommandAddress + 0x4); request.SetReturnValue(ES_PARAMETER_SIZE_OR_ALIGNMENT);
} }
} }
break; break;
case IOCTL_ES_GETSTOREDTMDSIZE: case IOCTL_ES_GETSTOREDTMDSIZE:
{ {
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 1, _dbg_assert_msg_(WII_IPC_ES, request.in_vectors.size() == 1,
"IOCTL_ES_GETSTOREDTMDSIZE no in buffer"); "IOCTL_ES_GETSTOREDTMDSIZE no in buffer");
// _dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1, "IOCTL_ES_ES_GETSTOREDTMDSIZE // _dbg_assert_msg_(WII_IPC_ES, request.io_vectors.size() == 1, "IOCTL_ES_ES_GETSTOREDTMDSIZE
// no out buffer"); // no out buffer");
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
const DiscIO::CNANDContentLoader& Loader = AccessContentDevice(TitleID); const DiscIO::CNANDContentLoader& Loader = AccessContentDevice(TitleID);
_dbg_assert_(WII_IPC_ES, Loader.IsValid()); _dbg_assert_(WII_IPC_ES, Loader.IsValid());
@ -988,10 +975,10 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
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 (Buffer.NumberPayloadBuffer) if (request.io_vectors.size())
Memory::Write_U32(TMDCnt, Buffer.PayloadBuffer[0].m_Address); Memory::Write_U32(TMDCnt, request.io_vectors[0].address);
Memory::Write_U32(0, _CommandAddress + 0x4); request.SetReturnValue(IPC_SUCCESS);
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETSTOREDTMDSIZE: title: %08x/%08x (view size %i)", INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETSTOREDTMDSIZE: title: %08x/%08x (view size %i)",
(u32)(TitleID >> 32), (u32)TitleID, TMDCnt); (u32)(TitleID >> 32), (u32)TitleID, TMDCnt);
@ -1000,28 +987,29 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
break; break;
case IOCTL_ES_GETSTOREDTMD: case IOCTL_ES_GETSTOREDTMD:
{ {
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer > 0, "IOCTL_ES_GETSTOREDTMD no in buffer"); _dbg_assert_msg_(WII_IPC_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_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1, "IOCTL_ES_GETSTOREDTMD no out //_dbg_assert_msg_(WII_IPC_ES, request.io_vectors.size() == 1, "IOCTL_ES_GETSTOREDTMD no out
// buffer"); // buffer");
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
u32 MaxCount = 0; u32 MaxCount = 0;
if (Buffer.NumberInBuffer > 1) if (request.in_vectors.size() > 1)
{ {
// TODO: actually use this param in when writing to the outbuffer :/ // TODO: actually use this param in when writing to the outbuffer :/
MaxCount = Memory::Read_U32(Buffer.InBuffer[1].m_Address); MaxCount = Memory::Read_U32(request.in_vectors[1].address);
} }
const DiscIO::CNANDContentLoader& Loader = AccessContentDevice(TitleID); const DiscIO::CNANDContentLoader& Loader = AccessContentDevice(TitleID);
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETSTOREDTMD: title: %08x/%08x buffer size: %i", INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETSTOREDTMD: title: %08x/%08x buffer size: %i",
(u32)(TitleID >> 32), (u32)TitleID, MaxCount); (u32)(TitleID >> 32), (u32)TitleID, MaxCount);
if (Loader.IsValid() && Buffer.NumberPayloadBuffer) if (Loader.IsValid() && request.io_vectors.size())
{ {
u32 Address = Buffer.PayloadBuffer[0].m_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);
@ -1036,9 +1024,9 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
} }
_dbg_assert_(WII_IPC_ES, _dbg_assert_(WII_IPC_ES,
(Address - Buffer.PayloadBuffer[0].m_Address) == Buffer.PayloadBuffer[0].m_Size); (Address - request.io_vectors[0].address) == request.io_vectors[0].size);
} }
Memory::Write_U32(0, _CommandAddress + 0x4); request.SetReturnValue(IPC_SUCCESS);
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETSTOREDTMD: title: %08x/%08x (buffer size: %i)", INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETSTOREDTMD: title: %08x/%08x (buffer size: %i)",
(u32)(TitleID >> 32), (u32)TitleID, MaxCount); (u32)(TitleID >> 32), (u32)TitleID, MaxCount);
@ -1048,12 +1036,12 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
case IOCTL_ES_ENCRYPT: case IOCTL_ES_ENCRYPT:
{ {
u32 keyIndex = Memory::Read_U32(Buffer.InBuffer[0].m_Address); u32 keyIndex = Memory::Read_U32(request.in_vectors[0].address);
u8* IV = Memory::GetPointer(Buffer.InBuffer[1].m_Address); u8* IV = Memory::GetPointer(request.in_vectors[1].address);
u8* source = Memory::GetPointer(Buffer.InBuffer[2].m_Address); u8* source = Memory::GetPointer(request.in_vectors[2].address);
u32 size = Buffer.InBuffer[2].m_Size; u32 size = request.in_vectors[2].size;
u8* newIV = Memory::GetPointer(Buffer.PayloadBuffer[0].m_Address); u8* newIV = Memory::GetPointer(request.io_vectors[0].address);
u8* destination = Memory::GetPointer(Buffer.PayloadBuffer[1].m_Address); u8* destination = Memory::GetPointer(request.io_vectors[1].address);
mbedtls_aes_context AES_ctx; mbedtls_aes_context AES_ctx;
mbedtls_aes_setkey_enc(&AES_ctx, keyTable[keyIndex], 128); mbedtls_aes_setkey_enc(&AES_ctx, keyTable[keyIndex], 128);
@ -1067,12 +1055,12 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
case IOCTL_ES_DECRYPT: case IOCTL_ES_DECRYPT:
{ {
u32 keyIndex = Memory::Read_U32(Buffer.InBuffer[0].m_Address); u32 keyIndex = Memory::Read_U32(request.in_vectors[0].address);
u8* IV = Memory::GetPointer(Buffer.InBuffer[1].m_Address); u8* IV = Memory::GetPointer(request.in_vectors[1].address);
u8* source = Memory::GetPointer(Buffer.InBuffer[2].m_Address); u8* source = Memory::GetPointer(request.in_vectors[2].address);
u32 size = Buffer.InBuffer[2].m_Size; u32 size = request.in_vectors[2].size;
u8* newIV = Memory::GetPointer(Buffer.PayloadBuffer[0].m_Address); u8* newIV = Memory::GetPointer(request.io_vectors[0].address);
u8* destination = Memory::GetPointer(Buffer.PayloadBuffer[1].m_Address); u8* destination = Memory::GetPointer(request.io_vectors[1].address);
DecryptContent(keyIndex, IV, source, size, newIV, destination); DecryptContent(keyIndex, IV, source, size, newIV, destination);
@ -1083,17 +1071,17 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
case IOCTL_ES_LAUNCH: case IOCTL_ES_LAUNCH:
{ {
_dbg_assert_(WII_IPC_ES, Buffer.NumberInBuffer == 2); _dbg_assert_(WII_IPC_ES, request.in_vectors.size() == 2);
bool bSuccess = false; bool bSuccess = false;
bool bReset = false; bool bReset = false;
u16 IOSv = 0xffff; u16 IOSv = 0xffff;
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
u32 view = Memory::Read_U32(Buffer.InBuffer[1].m_Address); u32 view = Memory::Read_U32(request.in_vectors[1].address);
u64 ticketid = Memory::Read_U64(Buffer.InBuffer[1].m_Address + 4); u64 ticketid = Memory::Read_U64(request.in_vectors[1].address + 4);
u32 devicetype = Memory::Read_U32(Buffer.InBuffer[1].m_Address + 12); u32 devicetype = Memory::Read_U32(request.in_vectors[1].address + 12);
u64 titleid = Memory::Read_U64(Buffer.InBuffer[1].m_Address + 16); u64 titleid = Memory::Read_U64(request.in_vectors[1].address + 16);
u16 access = Memory::Read_U16(Buffer.InBuffer[1].m_Address + 24); u16 access = Memory::Read_U16(request.in_vectors[1].address + 24);
// ES_LAUNCH should probably reset thw whole state, which at least means closing all open files. // ES_LAUNCH should probably reset thw whole state, which at least means closing all open files.
// leaving them open through ES_LAUNCH may cause hangs and other funky behavior // leaving them open through ES_LAUNCH may cause hangs and other funky behavior
@ -1199,7 +1187,7 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
// could clobber the DOL we just loaded. // could clobber the DOL we just loaded.
if (!bReset) if (!bReset)
{ {
Memory::Write_U32(0, _CommandAddress + 0x4); request.SetReturnValue(IPC_SUCCESS);
} }
ERROR_LOG(WII_IPC_ES, ERROR_LOG(WII_IPC_ES,
@ -1213,14 +1201,14 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
if (!bReset) if (!bReset)
{ {
// The command type is overwritten with the reply type. // The command type is overwritten with the reply type.
Memory::Write_U32(IPC_REPLY, _CommandAddress); Memory::Write_U32(IPC_REPLY, request.address);
// IOS also writes back the command that was responded to in the FD field. // IOS also writes back the command that was responded to in the FD field.
Memory::Write_U32(IPC_CMD_IOCTLV, _CommandAddress + 8); Memory::Write_U32(IPC_CMD_IOCTLV, request.address + 8);
} }
// Generate a "reply" to the IPC command. ES_LAUNCH is unique because it // Generate a "reply" to the IPC command. ES_LAUNCH is unique because it
// involves restarting IOS; IOS generates two acknowledgements in a row. // involves restarting IOS; IOS generates two acknowledgements in a row.
WII_IPC_HLE_Interface::EnqueueCommandAcknowledgement(_CommandAddress, 0); WII_IPC_HLE_Interface::EnqueueCommandAcknowledgement(request.address, 0);
return GetNoReply(); return GetNoReply();
} }
break; break;
@ -1231,14 +1219,14 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
// -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(WII_IPC_ES, "IOCTL_ES_CHECKKOREAREGION: Title checked for Korean keys."); INFO_LOG(WII_IPC_ES, "IOCTL_ES_CHECKKOREAREGION: Title checked for Korean keys.");
Memory::Write_U32(ES_PARAMTER_SIZE_OR_ALIGNMENT, _CommandAddress + 0x4); request.SetReturnValue(ES_PARAMETER_SIZE_OR_ALIGNMENT);
return GetDefaultReply(); return GetDefaultReply();
case IOCTL_ES_GETDEVICECERT: // (Input: none, Output: 384 bytes) case IOCTL_ES_GETDEVICECERT: // (Input: none, Output: 384 bytes)
{ {
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETDEVICECERT"); INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETDEVICECERT");
_dbg_assert_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1); _dbg_assert_(WII_IPC_ES, request.io_vectors.size() == 1);
u8* destination = Memory::GetPointer(Buffer.PayloadBuffer[0].m_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());
@ -1248,10 +1236,10 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
case IOCTL_ES_SIGN: case IOCTL_ES_SIGN:
{ {
INFO_LOG(WII_IPC_ES, "IOCTL_ES_SIGN"); INFO_LOG(WII_IPC_ES, "IOCTL_ES_SIGN");
u8* ap_cert_out = Memory::GetPointer(Buffer.PayloadBuffer[1].m_Address); u8* ap_cert_out = Memory::GetPointer(request.io_vectors[1].address);
u8* data = Memory::GetPointer(Buffer.InBuffer[0].m_Address); u8* data = Memory::GetPointer(request.in_vectors[0].address);
u32 data_size = Buffer.InBuffer[0].m_Size; u32 data_size = request.in_vectors[0].size;
u8* sig_out = Memory::GetPointer(Buffer.PayloadBuffer[0].m_Address); u8* sig_out = Memory::GetPointer(request.io_vectors[0].address);
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(),
@ -1264,7 +1252,7 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETBOOT2VERSION"); INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETBOOT2VERSION");
Memory::Write_U32( Memory::Write_U32(
4, Buffer.PayloadBuffer[0].m_Address); // 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
} }
break; break;
@ -1277,18 +1265,14 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
case IOCTL_ES_GETOWNEDTITLECNT: case IOCTL_ES_GETOWNEDTITLECNT:
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETOWNEDTITLECNT"); INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETOWNEDTITLECNT");
Memory::Write_U32(0, Buffer.PayloadBuffer[0].m_Address); Memory::Write_U32(0, request.io_vectors[0].address);
break; break;
default: default:
INFO_LOG(WII_IPC_ES, "CWII_IPC_HLE_Device_es: 0x%x", Buffer.Parameter); request.DumpUnknown(GetDeviceName(), LogTypes::WII_IPC_HLE);
INFO_LOG(WII_IPC_ES, "command.Parameter: 0x%08x", Buffer.Parameter);
break;
} }
// Write return value (0 means OK) request.SetReturnValue(IPC_SUCCESS);
Memory::Write_U32(0, _CommandAddress + 0x4);
return GetDefaultReply(); return GetDefaultReply();
} }

View file

@ -27,8 +27,6 @@ class CWII_IPC_HLE_Device_es : public IWII_IPC_HLE_Device
public: public:
CWII_IPC_HLE_Device_es(u32 _DeviceID, const std::string& _rDeviceName); CWII_IPC_HLE_Device_es(u32 _DeviceID, const std::string& _rDeviceName);
virtual ~CWII_IPC_HLE_Device_es();
void LoadWAD(const std::string& _rContentFile); void LoadWAD(const std::string& _rContentFile);
// Internal implementation of the ES_DECRYPT ioctlv. // Internal implementation of the ES_DECRYPT ioctlv.
@ -38,10 +36,9 @@ public:
void DoState(PointerWrap& p) override; void DoState(PointerWrap& p) override;
IPCCommandResult Open(u32 _CommandAddress, u32 _Mode) override; IOSReturnCode Open(const IOSOpenRequest& request) override;
IPCCommandResult Close(u32 _CommandAddress, bool _bForce) override; void Close() override;
IPCCommandResult IOCtlV(const IOSIOCtlVRequest& request) override;
IPCCommandResult IOCtlV(u32 _CommandAddress) override;
static u32 ES_DIVerify(const std::vector<u8>& tmd); static u32 ES_DIVerify(const std::vector<u8>& tmd);
@ -116,7 +113,7 @@ private:
ES_INVALID_TMD = -106, // or access denied ES_INVALID_TMD = -106, // or access denied
ES_READ_LESS_DATA_THAN_EXPECTED = -1009, ES_READ_LESS_DATA_THAN_EXPECTED = -1009,
ES_WRITE_FAILURE = -1010, ES_WRITE_FAILURE = -1010,
ES_PARAMTER_SIZE_OR_ALIGNMENT = -1017, ES_PARAMETER_SIZE_OR_ALIGNMENT = -1017,
ES_HASH_DOESNT_MATCH = -1022, ES_HASH_DOESNT_MATCH = -1022,
ES_MEM_ALLOC_FAILED = -1024, ES_MEM_ALLOC_FAILED = -1024,
ES_INCORRECT_ACCESS_RIGHT = -1026, ES_INCORRECT_ACCESS_RIGHT = -1026,