mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-25 15:19:42 -06:00
IOS/ES: Separate title content functions from IPC handlers
Allows them to be reused easily. Still a bit too much duplicated code in my opinion (OpenContent/SeekContent/ReadContent should just call FS code), but this is a start.
This commit is contained in:
@ -113,6 +113,12 @@ public:
|
|||||||
u32 GetSharedContentsCount() const;
|
u32 GetSharedContentsCount() const;
|
||||||
std::vector<std::array<u8, 20>> GetSharedContents() const;
|
std::vector<std::array<u8, 20>> GetSharedContents() const;
|
||||||
|
|
||||||
|
// Title contents
|
||||||
|
s32 OpenContent(const IOS::ES::TMDReader& tmd, u16 content_index, u32 uid);
|
||||||
|
ReturnCode CloseContent(u32 cfd, u32 uid);
|
||||||
|
s32 ReadContent(u32 cfd, u8* buffer, u32 size, u32 uid);
|
||||||
|
s32 SeekContent(u32 cfd, u32 offset, SeekMode mode, u32 uid);
|
||||||
|
|
||||||
// Title management
|
// Title management
|
||||||
ReturnCode ImportTicket(const std::vector<u8>& ticket_bytes, const std::vector<u8>& cert_chain);
|
ReturnCode ImportTicket(const std::vector<u8>& ticket_bytes, const std::vector<u8>& cert_chain);
|
||||||
ReturnCode ImportTmd(Context& context, const std::vector<u8>& tmd_bytes);
|
ReturnCode ImportTmd(Context& context, const std::vector<u8>& tmd_bytes);
|
||||||
@ -342,8 +348,6 @@ private:
|
|||||||
|
|
||||||
static const DiscIO::NANDContentLoader& AccessContentDevice(u64 title_id);
|
static const DiscIO::NANDContentLoader& AccessContentDevice(u64 title_id);
|
||||||
|
|
||||||
s32 OpenContent(const IOS::ES::TMDReader& tmd, u16 content_index, u32 uid);
|
|
||||||
|
|
||||||
using ContentTable = std::array<OpenedContent, 16>;
|
using ContentTable = std::array<OpenedContent, 16>;
|
||||||
ContentTable m_content_table;
|
ContentTable m_content_table;
|
||||||
|
|
||||||
|
@ -88,23 +88,16 @@ IPCCommandResult ES::OpenActiveTitleContent(u32 caller_uid, const IOCtlVRequest&
|
|||||||
return GetDefaultReply(OpenContent(GetTitleContext().tmd, content_index, caller_uid));
|
return GetDefaultReply(OpenContent(GetTitleContext().tmd, content_index, caller_uid));
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult ES::ReadContent(u32 uid, const IOCtlVRequest& request)
|
s32 ES::ReadContent(u32 cfd, u8* buffer, u32 size, u32 uid)
|
||||||
{
|
{
|
||||||
if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != sizeof(u32))
|
|
||||||
return GetDefaultReply(ES_EINVAL);
|
|
||||||
|
|
||||||
const u32 cfd = Memory::Read_U32(request.in_vectors[0].address);
|
|
||||||
u32 size = request.io_vectors[0].size;
|
|
||||||
const u32 addr = request.io_vectors[0].address;
|
|
||||||
|
|
||||||
if (cfd >= m_content_table.size())
|
if (cfd >= m_content_table.size())
|
||||||
return GetDefaultReply(ES_EINVAL);
|
return ES_EINVAL;
|
||||||
OpenedContent& entry = m_content_table[cfd];
|
OpenedContent& entry = m_content_table[cfd];
|
||||||
|
|
||||||
if (entry.m_uid != uid)
|
if (entry.m_uid != uid)
|
||||||
return GetDefaultReply(ES_EACCES);
|
return ES_EACCES;
|
||||||
if (!entry.m_opened)
|
if (!entry.m_opened)
|
||||||
return GetDefaultReply(IPC_EINVAL);
|
return IPC_EINVAL;
|
||||||
|
|
||||||
// XXX: make this reuse the FS code... ES just does a simple "IOS_Read" call here
|
// XXX: make this reuse the FS code... ES just does a simple "IOS_Read" call here
|
||||||
// instead of all this duplicated filesystem logic.
|
// instead of all this duplicated filesystem logic.
|
||||||
@ -112,46 +105,45 @@ IPCCommandResult ES::ReadContent(u32 uid, const IOCtlVRequest& request)
|
|||||||
if (entry.m_position + size > entry.m_content.size)
|
if (entry.m_position + size > entry.m_content.size)
|
||||||
size = static_cast<u32>(entry.m_content.size) - entry.m_position;
|
size = static_cast<u32>(entry.m_content.size) - entry.m_position;
|
||||||
|
|
||||||
if (size > 0)
|
|
||||||
{
|
|
||||||
if (addr)
|
|
||||||
{
|
|
||||||
const DiscIO::NANDContentLoader& ContentLoader = AccessContentDevice(entry.m_title_id);
|
const DiscIO::NANDContentLoader& ContentLoader = AccessContentDevice(entry.m_title_id);
|
||||||
// ContentLoader should never be invalid; rContent has been created by it.
|
// ContentLoader should never be invalid; rContent has been created by it.
|
||||||
if (ContentLoader.IsValid() && ContentLoader.GetTicket().IsValid())
|
if (ContentLoader.IsValid() && ContentLoader.GetTicket().IsValid())
|
||||||
{
|
{
|
||||||
const DiscIO::NANDContent* pContent =
|
const DiscIO::NANDContent* pContent = ContentLoader.GetContentByIndex(entry.m_content.index);
|
||||||
ContentLoader.GetContentByIndex(entry.m_content.index);
|
|
||||||
pContent->m_Data->Open();
|
pContent->m_Data->Open();
|
||||||
if (!pContent->m_Data->GetRange(entry.m_position, size, Memory::GetPointer(addr)))
|
if (!pContent->m_Data->GetRange(entry.m_position, size, buffer))
|
||||||
|
{
|
||||||
ERROR_LOG(IOS_ES, "ES: failed to read %u bytes from %u!", size, entry.m_position);
|
ERROR_LOG(IOS_ES, "ES: failed to read %u bytes from %u!", size, entry.m_position);
|
||||||
|
return ES_SHORT_READ;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
entry.m_position += size;
|
entry.m_position += size;
|
||||||
}
|
return size;
|
||||||
else
|
|
||||||
{
|
|
||||||
PanicAlert("IOCTL_ES_READCONTENT - bad destination");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return GetDefaultReply(size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult ES::CloseContent(u32 uid, const IOCtlVRequest& request)
|
IPCCommandResult ES::ReadContent(u32 uid, const IOCtlVRequest& request)
|
||||||
{
|
{
|
||||||
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sizeof(u32))
|
if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != sizeof(u32))
|
||||||
return GetDefaultReply(ES_EINVAL);
|
return GetDefaultReply(ES_EINVAL);
|
||||||
|
|
||||||
const u32 cfd = Memory::Read_U32(request.in_vectors[0].address);
|
const u32 cfd = Memory::Read_U32(request.in_vectors[0].address);
|
||||||
|
const u32 size = request.io_vectors[0].size;
|
||||||
|
const u32 addr = request.io_vectors[0].address;
|
||||||
|
|
||||||
|
return GetDefaultReply(ReadContent(cfd, Memory::GetPointer(addr), size, uid));
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnCode ES::CloseContent(u32 cfd, u32 uid)
|
||||||
|
{
|
||||||
if (cfd >= m_content_table.size())
|
if (cfd >= m_content_table.size())
|
||||||
return GetDefaultReply(ES_EINVAL);
|
return ES_EINVAL;
|
||||||
|
|
||||||
OpenedContent& entry = m_content_table[cfd];
|
OpenedContent& entry = m_content_table[cfd];
|
||||||
if (entry.m_uid != uid)
|
if (entry.m_uid != uid)
|
||||||
return GetDefaultReply(ES_EACCES);
|
return ES_EACCES;
|
||||||
if (!entry.m_opened)
|
if (!entry.m_opened)
|
||||||
return GetDefaultReply(IPC_EINVAL);
|
return IPC_EINVAL;
|
||||||
|
|
||||||
// XXX: again, this should be a simple IOS_Close.
|
// XXX: again, this should be a simple IOS_Close.
|
||||||
const DiscIO::NANDContentLoader& ContentLoader = AccessContentDevice(entry.m_title_id);
|
const DiscIO::NANDContentLoader& ContentLoader = AccessContentDevice(entry.m_title_id);
|
||||||
@ -164,7 +156,49 @@ IPCCommandResult ES::CloseContent(u32 uid, const IOCtlVRequest& request)
|
|||||||
|
|
||||||
entry = {};
|
entry = {};
|
||||||
INFO_LOG(IOS_ES, "CloseContent: CFD %u", cfd);
|
INFO_LOG(IOS_ES, "CloseContent: CFD %u", cfd);
|
||||||
return GetDefaultReply(IPC_SUCCESS);
|
return IPC_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPCCommandResult ES::CloseContent(u32 uid, const IOCtlVRequest& request)
|
||||||
|
{
|
||||||
|
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sizeof(u32))
|
||||||
|
return GetDefaultReply(ES_EINVAL);
|
||||||
|
|
||||||
|
const u32 cfd = Memory::Read_U32(request.in_vectors[0].address);
|
||||||
|
return GetDefaultReply(CloseContent(cfd, uid));
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 ES::SeekContent(u32 cfd, u32 offset, SeekMode mode, u32 uid)
|
||||||
|
{
|
||||||
|
if (cfd >= m_content_table.size())
|
||||||
|
return ES_EINVAL;
|
||||||
|
|
||||||
|
OpenedContent& entry = m_content_table[cfd];
|
||||||
|
if (entry.m_uid != uid)
|
||||||
|
return ES_EACCES;
|
||||||
|
if (!entry.m_opened)
|
||||||
|
return IPC_EINVAL;
|
||||||
|
|
||||||
|
// XXX: This should be a simple IOS_Seek.
|
||||||
|
switch (mode)
|
||||||
|
{
|
||||||
|
case SeekMode::IOS_SEEK_SET:
|
||||||
|
entry.m_position = offset;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SeekMode::IOS_SEEK_CUR:
|
||||||
|
entry.m_position += offset;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SeekMode::IOS_SEEK_END:
|
||||||
|
entry.m_position = static_cast<u32>(entry.m_content.size) + offset;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return FS_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return entry.m_position;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult ES::SeekContent(u32 uid, const IOCtlVRequest& request)
|
IPCCommandResult ES::SeekContent(u32 uid, const IOCtlVRequest& request)
|
||||||
@ -173,35 +207,10 @@ IPCCommandResult ES::SeekContent(u32 uid, const IOCtlVRequest& request)
|
|||||||
return GetDefaultReply(ES_EINVAL);
|
return GetDefaultReply(ES_EINVAL);
|
||||||
|
|
||||||
const u32 cfd = Memory::Read_U32(request.in_vectors[0].address);
|
const u32 cfd = Memory::Read_U32(request.in_vectors[0].address);
|
||||||
if (cfd >= m_content_table.size())
|
const u32 offset = Memory::Read_U32(request.in_vectors[1].address);
|
||||||
return GetDefaultReply(ES_EINVAL);
|
const SeekMode mode = static_cast<SeekMode>(Memory::Read_U32(request.in_vectors[2].address));
|
||||||
|
|
||||||
OpenedContent& entry = m_content_table[cfd];
|
return GetDefaultReply(SeekContent(cfd, offset, mode, uid));
|
||||||
if (entry.m_uid != uid)
|
|
||||||
return GetDefaultReply(ES_EACCES);
|
|
||||||
if (!entry.m_opened)
|
|
||||||
return GetDefaultReply(IPC_EINVAL);
|
|
||||||
|
|
||||||
u32 Addr = Memory::Read_U32(request.in_vectors[1].address);
|
|
||||||
u32 Mode = Memory::Read_U32(request.in_vectors[2].address);
|
|
||||||
|
|
||||||
// XXX: This should be a simple IOS_Seek.
|
|
||||||
switch (Mode)
|
|
||||||
{
|
|
||||||
case 0: // SET
|
|
||||||
entry.m_position = Addr;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1: // CUR
|
|
||||||
entry.m_position += Addr;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2: // END
|
|
||||||
entry.m_position = static_cast<u32>(entry.m_content.size) + Addr;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return GetDefaultReply(entry.m_position);
|
|
||||||
}
|
}
|
||||||
} // namespace Device
|
} // namespace Device
|
||||||
} // namespace HLE
|
} // namespace HLE
|
||||||
|
Reference in New Issue
Block a user