From f0035420d729afec924390dc58760082581c380b Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 23 Jan 2018 18:58:25 -0500 Subject: ipc_helpers: Make interface domain agnostic and add header validation. --- src/core/hle/ipc_helpers.h | 70 ++++++++++++++++++++++++++++--------------- src/core/hle/kernel/hle_ipc.h | 13 +++++++- 2 files changed, 58 insertions(+), 25 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h index d62731678..aa7ffd036 100644 --- a/src/core/hle/ipc_helpers.h +++ b/src/core/hle/ipc_helpers.h @@ -30,11 +30,6 @@ public: 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); - } - void Skip(unsigned size_in_words, bool set_to_null) { if (set_to_null) memset(cmdbuf + index, 0, size_in_words * sizeof(u32)); @@ -63,10 +58,18 @@ class RequestBuilder : public RequestHelperBase { public: RequestBuilder(u32* command_buffer) : RequestHelperBase(command_buffer) {} - RequestBuilder(Kernel::HLERequestContext& context, unsigned normal_params_size, - u32 num_handles_to_copy = 0, u32 num_handles_to_move = 0, - u32 num_domain_objects = 0) - : RequestHelperBase(context) { + u32 normal_params_size; + u32 num_handles_to_copy; + u32 num_objects_to_move; ///< Domain objects or move handles, context dependent + std::ptrdiff_t datapayload_index; + + RequestBuilder(Kernel::HLERequestContext& context, u32 normal_params_size, + u32 num_handles_to_copy = 0, u32 num_objects_to_move = 0, + bool always_move_handle = false) + + : RequestHelperBase(context), normal_params_size(normal_params_size), + num_handles_to_copy(num_handles_to_copy), num_objects_to_move(num_objects_to_move) { + memset(cmdbuf, 0, sizeof(u32) * IPC::COMMAND_BUFFER_LENGTH); context.ClearIncomingObjects(); @@ -76,12 +79,18 @@ public: // The entire size of the raw data section in u32 units, including the 16 bytes of mandatory // padding. u32 raw_data_size = sizeof(IPC::DataPayloadHeader) / 4 + 4 + normal_params_size; + + u32 num_handles_to_move{}; + u32 num_domain_objects{}; + + if (!context.Session()->IsDomain() || always_move_handle) { + num_handles_to_move = num_objects_to_move; + } else { + num_domain_objects = num_objects_to_move; + } + if (context.Session()->IsDomain()) { raw_data_size += sizeof(DomainMessageHeader) / 4 + num_domain_objects; - } else { - // If we're not in a domain, turn the domain object parameters into move handles. - num_handles_to_move += num_domain_objects; - num_domain_objects = 0; } header.data_size.Assign(raw_data_size); @@ -109,11 +118,12 @@ public: IPC::DataPayloadHeader data_payload_header{}; data_payload_header.magic = Common::MakeMagic('S', 'F', 'C', 'O'); PushRaw(data_payload_header); + + datapayload_index = index; } - template - void PushIpcInterface(Args&&... args) { - auto iface = std::make_shared(std::forward(args)...); + template + void PushIpcInterface(std::shared_ptr iface) { if (context->Session()->IsDomain()) { context->AddDomainObject(std::move(iface)); } else { @@ -125,6 +135,24 @@ public: } } + template + void PushIpcInterface(Args&&... args) { + PushIpcInterface(std::make_shared(std::forward(args)...)); + } + + void ValidateHeader() { + const size_t num_domain_objects = context->NumDomainObjects(); + const size_t num_move_objects = context->NumMoveObjects(); + ASSERT_MSG(!num_domain_objects || !num_move_objects, + "cannot move normal handles and domain objects"); + ASSERT_MSG((index - datapayload_index) == normal_params_size, + "normal_params_size value is incorrect"); + ASSERT_MSG((num_domain_objects + num_move_objects) == num_objects_to_move, + "num_objects_to_move value is incorrect"); + ASSERT_MSG(context->NumCopyObjects() == num_handles_to_copy, + "num_handles_to_copy value is incorrect"); + } + // Validate on destruction, as there shouldn't be any case where we don't want it ~RequestBuilder() { ValidateHeader(); @@ -227,14 +255,8 @@ public: } RequestBuilder MakeBuilder(u32 normal_params_size, u32 num_handles_to_copy, - u32 num_handles_to_move, u32 num_domain_objects, - bool validate_header = true) { - if (validate_header) { - ValidateHeader(); - } - - return {*context, normal_params_size, num_handles_to_copy, num_handles_to_move, - num_domain_objects}; + u32 num_handles_to_move, bool validate_header = true) { + return {*context, normal_params_size, num_handles_to_copy, num_handles_to_move}; } template diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index 71e5609b8..da8335b35 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h @@ -175,6 +175,18 @@ public: domain_objects.clear(); } + size_t NumMoveObjects() const { + return move_objects.size(); + } + + size_t NumCopyObjects() const { + return copy_objects.size(); + } + + size_t NumDomainObjects() const { + return domain_objects.size(); + } + private: std::array cmd_buf; SharedPtr server_session; @@ -196,7 +208,6 @@ private: unsigned data_payload_offset{}; unsigned buffer_c_offset{}; u32_le command{}; - bool is_domain{}; }; } // namespace Kernel -- cgit v1.2.3