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/kernel/hle_ipc.cpp | 152 ++++++++++++++++++++++------------------ 1 file changed, 84 insertions(+), 68 deletions(-) (limited to 'src/core/hle/kernel/hle_ipc.cpp') diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index 6020e9764..b7070af03 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp @@ -5,6 +5,7 @@ #include #include "common/assert.h" #include "common/common_types.h" +#include "core/hle/ipc_helpers.h" #include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/hle_ipc.h" #include "core/hle/kernel/kernel.h" @@ -44,88 +45,103 @@ void HLERequestContext::ClearIncomingObjects() { request_handles.clear(); } -ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const u32_le* src_cmdbuf, - Process& src_process, - HandleTable& src_table) { - IPC::Header header{src_cmdbuf[0]}; +void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf) { + IPC::RequestParser rp(src_cmdbuf); + command_header = std::make_unique(rp.PopRaw()); - size_t untranslated_size = 1u + header.normal_params_size; - size_t command_size = untranslated_size + header.translate_params_size; - ASSERT(command_size <= IPC::COMMAND_BUFFER_LENGTH); // TODO(yuriks): Return error + // If handle descriptor is present, add size of it + if (command_header->enable_handle_descriptor) { + handle_descriptor_header = + std::make_unique(rp.PopRaw()); + if (handle_descriptor_header->send_current_pid) { + rp.Skip(2, false); + } + rp.Skip(handle_descriptor_header->num_handles_to_copy, false); + rp.Skip(handle_descriptor_header->num_handles_to_move, false); + } - std::copy_n(src_cmdbuf, untranslated_size, cmd_buf.begin()); + // Padding to align to 16 bytes + rp.AlignWithPadding(); - size_t i = untranslated_size; - while (i < command_size) { - u32 descriptor = cmd_buf[i] = src_cmdbuf[i]; - i += 1; - - switch (IPC::GetDescriptorType(descriptor)) { - case IPC::DescriptorType::CopyHandle: - case IPC::DescriptorType::MoveHandle: { - u32 num_handles = IPC::HandleNumberFromDesc(descriptor); - ASSERT(i + num_handles <= command_size); // TODO(yuriks): Return error - for (u32 j = 0; j < num_handles; ++j) { - Handle handle = src_cmdbuf[i]; - SharedPtr object = nullptr; - if (handle != 0) { - object = src_table.GetGeneric(handle); - ASSERT(object != nullptr); // TODO(yuriks): Return error - if (descriptor == IPC::DescriptorType::MoveHandle) { - src_table.Close(handle); - } - } + if (command_header->num_buf_x_descriptors) { + UNIMPLEMENTED(); + } + if (command_header->num_buf_a_descriptors) { + UNIMPLEMENTED(); + } + if (command_header->num_buf_b_descriptors) { + UNIMPLEMENTED(); + } + if (command_header->num_buf_w_descriptors) { + UNIMPLEMENTED(); + } + if (command_header->buf_c_descriptor_flags != + IPC::CommandHeader::BufferDescriptorCFlag::Disabled) { + UNIMPLEMENTED(); + } - cmd_buf[i++] = AddOutgoingHandle(std::move(object)); - } - break; - } - case IPC::DescriptorType::CallingPid: { - cmd_buf[i++] = src_process.process_id; - break; - } - default: - UNIMPLEMENTED_MSG("Unsupported handle translation: 0x%08X", descriptor); + data_payload_header = + std::make_unique(rp.PopRaw()); + ASSERT(data_payload_header->magic == 0x49434653 || data_payload_header->magic == 0x4F434653); + + data_payload_offset = rp.GetCurrentOffset(); + command = rp.Pop(); +} + +ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(u32_le* src_cmdbuf, + Process& src_process, + HandleTable& src_table) { + ParseCommandBuffer(src_cmdbuf); + size_t untranslated_size = data_payload_offset + command_header->data_size; + std::copy_n(src_cmdbuf, untranslated_size, cmd_buf.begin()); + + if (command_header->enable_handle_descriptor) { + if (handle_descriptor_header->num_handles_to_copy || + handle_descriptor_header->num_handles_to_move) { + UNIMPLEMENTED(); } } - return RESULT_SUCCESS; } ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf, Process& dst_process, - HandleTable& dst_table) const { - IPC::Header header{cmd_buf[0]}; - - size_t untranslated_size = 1u + header.normal_params_size; - size_t command_size = untranslated_size + header.translate_params_size; - ASSERT(command_size <= IPC::COMMAND_BUFFER_LENGTH); - + HandleTable& dst_table) { + ParseCommandBuffer(&cmd_buf[0]); + size_t untranslated_size = data_payload_offset + command_header->data_size; std::copy_n(cmd_buf.begin(), untranslated_size, dst_cmdbuf); - size_t i = untranslated_size; - while (i < command_size) { - u32 descriptor = dst_cmdbuf[i] = cmd_buf[i]; - i += 1; - - switch (IPC::GetDescriptorType(descriptor)) { - case IPC::DescriptorType::CopyHandle: - case IPC::DescriptorType::MoveHandle: { - // HLE services don't use handles, so we treat both CopyHandle and MoveHandle equally - u32 num_handles = IPC::HandleNumberFromDesc(descriptor); - ASSERT(i + num_handles <= command_size); - for (u32 j = 0; j < num_handles; ++j) { - SharedPtr object = GetIncomingHandle(cmd_buf[i]); - Handle handle = 0; - if (object != nullptr) { - // TODO(yuriks): Figure out the proper error handling for if this fails - handle = dst_table.Create(object).Unwrap(); + if (command_header->enable_handle_descriptor) { + size_t command_size = untranslated_size + handle_descriptor_header->num_handles_to_copy + + handle_descriptor_header->num_handles_to_move; + ASSERT(command_size <= IPC::COMMAND_BUFFER_LENGTH); + + size_t untranslated_index = untranslated_size; + size_t handle_write_offset = 3; + while (untranslated_index < command_size) { + u32 descriptor = cmd_buf[untranslated_index]; + untranslated_index += 1; + + switch (IPC::GetDescriptorType(descriptor)) { + case IPC::DescriptorType::CopyHandle: + case IPC::DescriptorType::MoveHandle: { + // HLE services don't use handles, so we treat both CopyHandle and MoveHandle + // equally + u32 num_handles = IPC::HandleNumberFromDesc(descriptor); + for (u32 j = 0; j < num_handles; ++j) { + SharedPtr object = GetIncomingHandle(cmd_buf[untranslated_index]); + Handle handle = 0; + if (object != nullptr) { + // TODO(yuriks): Figure out the proper error handling for if this fails + handle = dst_table.Create(object).Unwrap(); + } + dst_cmdbuf[handle_write_offset++] = handle; + untranslated_index++; } - dst_cmdbuf[i++] = handle; + break; + } + default: + UNIMPLEMENTED_MSG("Unsupported handle translation: 0x%08X", descriptor); } - break; - } - default: - UNIMPLEMENTED_MSG("Unsupported handle translation: 0x%08X", descriptor); } } -- cgit v1.2.3