#include "ipc.hpp" #include "os.hpp" namespace HLE { namespace IPC { TLSReader::TLSReader(OS::Thread& thread) : thread(thread) { } OS::Handle TLSReader::ParseHandle() { // TODO: Read the number of handles from the descriptor at "offset" rather // than assuming we should only read a single one! auto ret = thread.ReadTLS(offset); offset += 4; return {ret}; } OS::Result TLSReader::operator()(const IPC::CommandTags::result_tag& /* unused */) { uint32_t data = thread.ReadTLS(offset); offset += 4; return data; } uint32_t TLSReader::operator()(const IPC::CommandTags::uint32_tag& /* unused */) { uint32_t data = thread.ReadTLS(offset); offset += 4; return data; } uint64_t TLSReader::operator()(const IPC::CommandTags::uint64_tag& /* unused */) { uint64_t data = (static_cast(thread.ReadTLS(offset + 4)) << 32) | thread.ReadTLS(offset); offset += 8; return data; } IPC::StaticBuffer TLSReader::operator()(const IPC::CommandTags::static_buffer_tag& /* unused */) { // TLS@offset stores the translation descriptor, which is only relevant for the kernel IPC::TranslationDescriptor descriptor = { thread.ReadTLS(offset) }; uint32_t buffer_addr = thread.ReadTLS(offset + 4); offset += 8; return { buffer_addr, descriptor.static_buffer.size.Value(), descriptor.static_buffer.id.Value() }; } IPC::StaticBuffer TLSReader::operator()(const IPC::CommandTags::pxi_buffer_tag& /* unused */) { // TLS@offset stores the translation descriptor, which is only relevant for the kernel IPC::TranslationDescriptor descriptor = { thread.ReadTLS(offset) }; uint32_t buffer_addr = thread.ReadTLS(offset + 4); offset += 8; // TODO: DONT DO THIS. Instead use the commented-out version. return { buffer_addr, descriptor.static_buffer.size.Value(), descriptor.static_buffer.id.Value() }; // return { buffer_addr, descriptor.pxi_buffer.size.Value(), descriptor.pxi_buffer.id.Value() }; } IPC::StaticBuffer TLSReader::operator()(const IPC::CommandTags::pxi_buffer_tag& /* unused */) { // TLS@offset stores the translation descriptor, which is only relevant for the kernel IPC::TranslationDescriptor descriptor = { thread.ReadTLS(offset) }; uint32_t buffer_addr = thread.ReadTLS(offset + 4); offset += 8; // TODO: DONT DO THIS. Instead use the commented-out version. return { buffer_addr, descriptor.static_buffer.size.Value(), descriptor.static_buffer.id.Value() }; // return { buffer_addr, descriptor.pxi_buffer.size.Value(), descriptor.pxi_buffer.id.Value() }; } OS::ProcessId TLSReader::operator()(const IPC::CommandTags::process_id_tag& /* unused */) { uint32_t process_id = thread.ReadTLS(offset + 4); offset += 8; return process_id; } MappedBuffer TLSReader::operator()(const IPC::CommandTags::map_buffer_r_tag& /* unused */) { MappedBuffer ret; ret.size = TranslationDescriptor{thread.ReadTLS(offset)}.map_buffer.size; ret.addr = thread.ReadTLS(offset + 4); offset += 8; return ret; } MappedBuffer TLSReader::operator()(const IPC::CommandTags::map_buffer_w_tag& /* unused */) { MappedBuffer ret; ret.size = TranslationDescriptor{thread.ReadTLS(offset)}.map_buffer.size; ret.addr = thread.ReadTLS(offset + 4); offset += 8; return ret; } TLSWriter::TLSWriter(OS::Thread& thread) : thread(thread) { } void TLSWriter::WriteHandleDescriptor(const OS::Handle* data, size_t num, bool close) { thread.WriteTLS(offset, IPC::TranslationDescriptor::MakeHandles(num, close).raw); offset += 4; for (auto data_ptr = data; data_ptr != data + num; ++data_ptr) { thread.WriteTLS(offset, data_ptr->value); offset += 4; } } void TLSWriter::operator()(IPC::CommandTags::result_tag, OS::Result data) { thread.WriteTLS(offset, data); offset += 4; } void TLSWriter::operator()(IPC::CommandTags::uint32_tag, uint32_t data) { thread.WriteTLS(offset, data); offset += 4; } void TLSWriter::operator()(IPC::CommandTags::uint64_tag, uint64_t data) { thread.WriteTLS(offset , data & 0xFFFFFFFF); thread.WriteTLS(offset + 4, data >> 32); offset += 8; } void TLSWriter::operator()(IPC::CommandTags::map_buffer_r_tag, const MappedBuffer& buffer) { thread.WriteTLS(offset, IPC::TranslationDescriptor::MapBuffer(buffer.size, TranslationDescriptor::Read).raw); thread.WriteTLS(offset + 4, buffer.addr); offset += 8; } void TLSWriter::operator()(IPC::CommandTags::map_buffer_w_tag, const MappedBuffer& buffer) { thread.WriteTLS(offset, IPC::TranslationDescriptor::MapBuffer(buffer.size, TranslationDescriptor::Write).raw); thread.WriteTLS(offset + 4, buffer.addr); offset += 8; } void TLSWriter::operator()(IPC::CommandTags::static_buffer_tag, const StaticBuffer& buffer) { thread.WriteTLS(offset, IPC::TranslationDescriptor::MakeStaticBuffer(buffer.id, buffer.size).raw); thread.WriteTLS(offset + 4, buffer.addr); offset += 8; } void TLSWriter::operator()(IPC::CommandTags::process_id_tag, const EmptyValue&) { thread.WriteTLS(offset, IPC::TranslationDescriptor::MakeProcessHandle().raw); thread.WriteTLS(offset + 4, 0); offset += 8; } void TLSWriter::operator()(IPC::CommandTags::pxi_buffer_tag, const StaticBuffer& buffer) { thread.WriteTLS(offset, IPC::TranslationDescriptor::MakePXIBuffer(buffer.id, buffer.size).raw); thread.WriteTLS(offset + 4, buffer.addr); offset += 8; } void TLSWriter::operator()(IPC::CommandTags::pxi_buffer_tag, const StaticBuffer& buffer) { thread.WriteTLS(offset, IPC::TranslationDescriptor::MakePXIConstBuffer(buffer.id, buffer.size).raw); thread.WriteTLS(offset + 4, buffer.addr); offset += 8; } } // namespace IPC } // namespace HLE