From 960a1416de3780e91855d9389c4534acf8c061df Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 14 Oct 2017 22:18:42 -0400 Subject: hle: Initial implementation of NX service framework and IPC. --- src/core/hle/ipc_helpers.h | 122 +++++++++++++++++++-------------------------- 1 file changed, 51 insertions(+), 71 deletions(-) (limited to 'src/core/hle/ipc_helpers.h') diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h index 7cb95cbac..083d3a0d0 100644 --- a/src/core/hle/ipc_helpers.h +++ b/src/core/hle/ipc_helpers.h @@ -19,24 +19,17 @@ class RequestHelperBase { protected: Kernel::HLERequestContext* context = nullptr; u32* cmdbuf; - ptrdiff_t index = 1; - Header header; + ptrdiff_t index = 0; public: - RequestHelperBase(Kernel::HLERequestContext& context, Header desired_header) - : context(&context), cmdbuf(context.CommandBuffer()), header(desired_header) {} + RequestHelperBase(u32* command_buffer) : cmdbuf(command_buffer) {} - RequestHelperBase(u32* command_buffer, Header command_header) - : cmdbuf(command_buffer), header(command_header) {} - - /// Returns the total size of the request in words - size_t TotalSize() const { - return 1 /* command header */ + header.normal_params_size + header.translate_params_size; - } + RequestHelperBase(Kernel::HLERequestContext& context) + : context(&context), cmdbuf(context.CommandBuffer()) {} void ValidateHeader() { - DEBUG_ASSERT_MSG(index == TotalSize(), "Operations do not match the header (cmd 0x%x)", - header.raw); + // DEBUG_ASSERT_MSG(index == TotalSize(), "Operations do not match the header (cmd 0x%x)", + // header.raw); } void Skip(unsigned size_in_words, bool set_to_null) { @@ -46,45 +39,50 @@ public: } /** - * @brief Retrieves the address of a static buffer, used when a buffer is needed for output - * @param buffer_id The index of the static buffer - * @param data_size If non-null, will store the size of the buffer + * Aligns the current position forward to a 16-byte boundary, padding with zeros. Jumps forward + * by 16-bytes at a minimum. */ - VAddr PeekStaticBuffer(u8 buffer_id, size_t* data_size = nullptr) const { - u32* static_buffer = cmdbuf + Kernel::kStaticBuffersOffset / sizeof(u32) + buffer_id * 2; - if (data_size) - *data_size = StaticBufferDescInfo{static_buffer[0]}.size; - return static_buffer[1]; + void AlignWithPadding() { + Skip(4 - (index & 3), true); + } + + unsigned GetCurrentOffset() const { + return static_cast(index); } }; class RequestBuilder : public RequestHelperBase { public: - RequestBuilder(Kernel::HLERequestContext& context, Header command_header) - : RequestHelperBase(context, command_header) { - // From this point we will start overwriting the existing command buffer, so it's safe to - // release all previous incoming Object pointers since they won't be usable anymore. - context.ClearIncomingObjects(); - cmdbuf[0] = header.raw; - } - - RequestBuilder(Kernel::HLERequestContext& context, u16 command_id, unsigned normal_params_size, - unsigned translate_params_size) - : RequestBuilder( - context, Header{MakeHeader(command_id, normal_params_size, translate_params_size)}) {} + RequestBuilder(u32* command_buffer) : RequestHelperBase(command_buffer) {} - RequestBuilder(u32* command_buffer, Header command_header) - : RequestHelperBase(command_buffer, command_header) { - cmdbuf[0] = header.raw; - } + RequestBuilder(Kernel::HLERequestContext& context, unsigned normal_params_size, + u32 num_handles_to_copy = 0, u32 num_handles_to_move = 0) + : RequestHelperBase(context) { + memset(cmdbuf, 0, 64); - explicit RequestBuilder(u32* command_buffer, u32 command_header) - : RequestBuilder(command_buffer, Header{command_header}) {} + context.ClearIncomingObjects(); - RequestBuilder(u32* command_buffer, u16 command_id, unsigned normal_params_size, - unsigned translate_params_size) - : RequestBuilder(command_buffer, - MakeHeader(command_id, normal_params_size, translate_params_size)) {} + IPC::CommandHeader header{}; + header.data_size.Assign(normal_params_size * sizeof(u32)); + if (num_handles_to_copy || num_handles_to_move) { + header.enable_handle_descriptor.Assign(1); + } + PushRaw(header); + + if (header.enable_handle_descriptor) { + IPC::HandleDescriptorHeader handle_descriptor_header{}; + handle_descriptor_header.num_handles_to_copy.Assign(num_handles_to_copy); + handle_descriptor_header.num_handles_to_move.Assign(num_handles_to_move); + PushRaw(handle_descriptor_header); + Skip(num_handles_to_copy + num_handles_to_move, true); + } + + AlignWithPadding(); + + IPC::DataPayloadHeader data_payload_header{}; + data_payload_header.magic = 0x4f434653; + PushRaw(data_payload_header); + } // Validate on destruction, as there shouldn't be any case where we don't want it ~RequestBuilder() { @@ -131,7 +129,6 @@ inline void RequestBuilder::Push(u32 value) { template void RequestBuilder::PushRaw(const T& value) { - static_assert(std::is_trivially_copyable(), "Raw types should be trivially copyable"); std::memcpy(cmdbuf + index, &value, sizeof(T)); index += (sizeof(T) + 3) / 4; // round up to word length } @@ -203,36 +200,20 @@ inline void RequestBuilder::PushMappedBuffer(VAddr buffer_vaddr, size_t size, class RequestParser : public RequestHelperBase { public: - RequestParser(Kernel::HLERequestContext& context, Header desired_header) - : RequestHelperBase(context, desired_header) {} + RequestParser(u32* command_buffer) : RequestHelperBase(command_buffer) {} - RequestParser(Kernel::HLERequestContext& context, u16 command_id, unsigned normal_params_size, - unsigned translate_params_size) - : RequestParser(context, - Header{MakeHeader(command_id, normal_params_size, translate_params_size)}) { + RequestParser(Kernel::HLERequestContext& context) : RequestHelperBase(context) { + ASSERT_MSG(context.GetDataPayloadOffset(), "context is incomplete"); + Skip(context.GetDataPayloadOffset(), false); } - RequestParser(u32* command_buffer, Header command_header) - : RequestHelperBase(command_buffer, command_header) {} - - explicit RequestParser(u32* command_buffer, u32 command_header) - : RequestParser(command_buffer, Header{command_header}) {} - - RequestParser(u32* command_buffer, u16 command_id, unsigned normal_params_size, - unsigned translate_params_size) - : RequestParser(command_buffer, - MakeHeader(command_id, normal_params_size, translate_params_size)) {} - - RequestBuilder MakeBuilder(u32 normal_params_size, u32 translate_params_size, - bool validateHeader = true) { - if (validateHeader) + RequestBuilder MakeBuilder(u32 normal_params_size, u32 num_handles_to_copy, + u32 num_handles_to_move, bool validate_header = true) { + if (validate_header) { ValidateHeader(); - Header builderHeader{MakeHeader(static_cast(header.command_id), normal_params_size, - translate_params_size)}; - if (context != nullptr) - return {*context, builderHeader}; - else - return {cmdbuf, builderHeader}; + } + + return {*context, normal_params_size, num_handles_to_copy, num_handles_to_move}; } template @@ -342,7 +323,6 @@ inline u32 RequestParser::Pop() { template void RequestParser::PopRaw(T& value) { - static_assert(std::is_trivially_copyable(), "Raw types should be trivially copyable"); std::memcpy(&value, cmdbuf + index, sizeof(T)); index += (sizeof(T) + 3) / 4; // round up to word length } -- cgit v1.2.3