From 4f8ee5e4562da3aa8678a42dd3b8d94f6c1a1f5c Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 13 Feb 2018 21:39:58 -0500 Subject: [PATCH 01/10] vi: Fix TransactParcelAuto to support both buffer formats. --- src/core/hle/service/vi/vi.cpp | 41 +++++++++++++--------------------- 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 8b4ed30d2d..55f196ab02 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -429,7 +429,7 @@ public: {0, &IHOSBinderDriver::TransactParcel, "TransactParcel"}, {1, &IHOSBinderDriver::AdjustRefcount, "AdjustRefcount"}, {2, &IHOSBinderDriver::GetNativeHandle, "GetNativeHandle"}, - {3, &IHOSBinderDriver::TransactParcelAuto, "TransactParcelAuto"}, + {3, &IHOSBinderDriver::TransactParcel, "TransactParcelAuto"}, }; RegisterHandlers(functions); } @@ -518,30 +518,21 @@ private: u32 flags = rp.Pop(); LOG_DEBUG(Service_VI, "called, transaction=%x", transaction); - auto& input_buffer = ctx.BufferDescriptorA()[0]; - auto& output_buffer = ctx.BufferDescriptorB()[0]; - std::vector input_data(input_buffer.Size()); - Memory::ReadBlock(input_buffer.Address(), input_data.data(), input_buffer.Size()); - - TransactParcel(id, transaction, input_data, output_buffer.Address(), output_buffer.Size()); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); - } - - void TransactParcelAuto(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - u32 id = rp.Pop(); - auto transaction = static_cast(rp.Pop()); - u32 flags = rp.Pop(); - LOG_DEBUG(Service_VI, "called, transaction=%x", transaction); - - auto& input_buffer = ctx.BufferDescriptorX()[0]; - auto& output_buffer = ctx.BufferDescriptorC()[0]; - std::vector input_data(input_buffer.size); - Memory::ReadBlock(input_buffer.Address(), input_data.data(), input_buffer.size); - - TransactParcel(id, transaction, input_data, output_buffer.Address(), output_buffer.Size()); + if (ctx.BufferDescriptorA()[0].Size() != 0) { + auto& input_buffer = ctx.BufferDescriptorA()[0]; + auto& output_buffer = ctx.BufferDescriptorB()[0]; + std::vector input_data(input_buffer.Size()); + Memory::ReadBlock(input_buffer.Address(), input_data.data(), input_buffer.Size()); + TransactParcel(id, transaction, input_data, output_buffer.Address(), + output_buffer.Size()); + } else { + auto& input_buffer = ctx.BufferDescriptorX()[0]; + auto& output_buffer = ctx.BufferDescriptorC()[0]; + std::vector input_data(input_buffer.size); + Memory::ReadBlock(input_buffer.Address(), input_data.data(), input_buffer.size); + TransactParcel(id, transaction, input_data, output_buffer.Address(), + output_buffer.Size()); + } IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); From 1ce6fff0648008b7510e9feb3cf6696a2c25dd5c Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 13 Feb 2018 21:41:20 -0500 Subject: [PATCH 02/10] hle_ipc: Add helper functions for reading and writing buffers. --- src/core/hle/ipc.h | 4 ++++ src/core/hle/kernel/hle_ipc.cpp | 39 +++++++++++++++++++++++++++++++++ src/core/hle/kernel/hle_ipc.h | 12 ++++++++++ 3 files changed, 55 insertions(+) diff --git a/src/core/hle/ipc.h b/src/core/hle/ipc.h index 0dcaede678..a6602e12cb 100644 --- a/src/core/hle/ipc.h +++ b/src/core/hle/ipc.h @@ -91,6 +91,10 @@ struct BufferDescriptorX { address |= static_cast(address_bits_36_38) << 36; return address; } + + u64 Size() const { + return static_cast(size); + } }; static_assert(sizeof(BufferDescriptorX) == 8, "BufferDescriptorX size is incorrect"); diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index db104e8a26..a5a3d4fe49 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp @@ -12,6 +12,7 @@ #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/server_session.h" +#include "core/memory.h" namespace Kernel { @@ -210,4 +211,42 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf, P return RESULT_SUCCESS; } +std::vector HLERequestContext::ReadBuffer() const { + std::vector buffer; + const bool is_buffer_a{BufferDescriptorA().size() && BufferDescriptorA()[0].Size()}; + + if (is_buffer_a) { + buffer.resize(BufferDescriptorA()[0].Size()); + Memory::ReadBlock(BufferDescriptorA()[0].Address(), buffer.data(), buffer.size()); + } else { + buffer.resize(BufferDescriptorX()[0].Size()); + Memory::ReadBlock(BufferDescriptorX()[0].Address(), buffer.data(), buffer.size()); + } + + return buffer; +} + +size_t HLERequestContext::WriteBuffer(const void* buffer, const size_t size) const { + const bool is_buffer_b{BufferDescriptorB().size() && BufferDescriptorB()[0].Size()}; + + if (is_buffer_b) { + const size_t size{std::min(BufferDescriptorB()[0].Size(), size)}; + Memory::WriteBlock(BufferDescriptorB()[0].Address(), buffer, size); + return size; + } else { + const size_t size{std::min(BufferDescriptorC()[0].Size(), size)}; + Memory::WriteBlock(BufferDescriptorC()[0].Address(), buffer, size); + return size; + } +} + +size_t HLERequestContext::WriteBuffer(const std::vector& buffer) const { + return WriteBuffer(buffer.data(), buffer.size()); +} + +size_t HLERequestContext::GetWriteBufferSize() const { + const bool is_buffer_b{BufferDescriptorB().size() && BufferDescriptorB()[0].Size()}; + return is_buffer_b ? BufferDescriptorB()[0].Size() : BufferDescriptorC()[0].Size(); +} + } // namespace Kernel diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index da8335b35b..0cc2709095 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h @@ -143,6 +143,18 @@ public: return domain_message_header; } + /// Helper function to read a buffer using the appropriate buffer descriptor + std::vector ReadBuffer() const; + + /// Helper function to write a buffer using the appropriate buffer descriptor + size_t WriteBuffer(const void* buffer, const size_t size) const; + + /// Helper function to write a buffer using the appropriate buffer descriptor + size_t WriteBuffer(const std::vector& buffer) const; + + /// Helper function to get the size of the output buffer + size_t GetWriteBufferSize() const; + template SharedPtr GetCopyObject(size_t index) { ASSERT(index < copy_objects.size()); From fc1b425520d750335131f6ddc20f1d964ab384c5 Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 13 Feb 2018 23:53:18 -0500 Subject: [PATCH 03/10] hle_ipc: Add helper functions for reading and writing buffers. --- src/core/hle/kernel/hle_ipc.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index a5a3d4fe49..0a9986c180 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp @@ -230,14 +230,12 @@ size_t HLERequestContext::WriteBuffer(const void* buffer, const size_t size) con const bool is_buffer_b{BufferDescriptorB().size() && BufferDescriptorB()[0].Size()}; if (is_buffer_b) { - const size_t size{std::min(BufferDescriptorB()[0].Size(), size)}; Memory::WriteBlock(BufferDescriptorB()[0].Address(), buffer, size); - return size; } else { - const size_t size{std::min(BufferDescriptorC()[0].Size(), size)}; Memory::WriteBlock(BufferDescriptorC()[0].Address(), buffer, size); - return size; } + + return size; } size_t HLERequestContext::WriteBuffer(const std::vector& buffer) const { From 8f84665775ca7732b20505f5472d640f3eaa8c1e Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 13 Feb 2018 21:54:12 -0500 Subject: [PATCH 04/10] vi: Use ReadBuffer/WriteBuffer functions for TransactParcel. --- src/core/hle/service/vi/vi.cpp | 117 +++++++++++++-------------------- 1 file changed, 46 insertions(+), 71 deletions(-) diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 55f196ab02..1f00a6cca5 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -453,85 +453,60 @@ private: SetPreallocatedBuffer = 14 }; - void TransactParcel(u32 id, TransactionId transaction, const std::vector& input_data, - VAddr output_addr, u64 output_size) { - auto buffer_queue = nv_flinger->GetBufferQueue(id); - - if (transaction == TransactionId::Connect) { - IGBPConnectRequestParcel request{input_data}; - IGBPConnectResponseParcel response{1280, 720}; - std::vector response_buffer = response.Serialize(); - Memory::WriteBlock(output_addr, response_buffer.data(), response_buffer.size()); - } else if (transaction == TransactionId::SetPreallocatedBuffer) { - IGBPSetPreallocatedBufferRequestParcel request{input_data}; - - buffer_queue->SetPreallocatedBuffer(request.data.slot, request.buffer); - - IGBPSetPreallocatedBufferResponseParcel response{}; - std::vector response_buffer = response.Serialize(); - Memory::WriteBlock(output_addr, response_buffer.data(), response_buffer.size()); - } else if (transaction == TransactionId::DequeueBuffer) { - IGBPDequeueBufferRequestParcel request{input_data}; - - u32 slot = buffer_queue->DequeueBuffer(request.data.pixel_format, request.data.width, - request.data.height); - - IGBPDequeueBufferResponseParcel response{slot}; - std::vector response_buffer = response.Serialize(); - Memory::WriteBlock(output_addr, response_buffer.data(), response_buffer.size()); - } else if (transaction == TransactionId::RequestBuffer) { - IGBPRequestBufferRequestParcel request{input_data}; - - auto& buffer = buffer_queue->RequestBuffer(request.slot); - - IGBPRequestBufferResponseParcel response{buffer}; - std::vector response_buffer = response.Serialize(); - Memory::WriteBlock(output_addr, response_buffer.data(), response_buffer.size()); - } else if (transaction == TransactionId::QueueBuffer) { - IGBPQueueBufferRequestParcel request{input_data}; - - buffer_queue->QueueBuffer(request.data.slot, request.data.transform); - - IGBPQueueBufferResponseParcel response{1280, 720}; - std::vector response_buffer = response.Serialize(); - Memory::WriteBlock(output_addr, response_buffer.data(), response_buffer.size()); - } else if (transaction == TransactionId::Query) { - IGBPQueryRequestParcel request{input_data}; - - u32 value = - buffer_queue->Query(static_cast(request.type)); - - IGBPQueryResponseParcel response{value}; - std::vector response_buffer = response.Serialize(); - Memory::WriteBlock(output_addr, response_buffer.data(), response_buffer.size()); - } else if (transaction == TransactionId::CancelBuffer) { - LOG_WARNING(Service_VI, "(STUBBED) called, transaction=CancelBuffer"); - } else { - ASSERT_MSG(false, "Unimplemented"); - } - } - void TransactParcel(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; u32 id = rp.Pop(); auto transaction = static_cast(rp.Pop()); u32 flags = rp.Pop(); + auto buffer_queue = nv_flinger->GetBufferQueue(id); + LOG_DEBUG(Service_VI, "called, transaction=%x", transaction); - if (ctx.BufferDescriptorA()[0].Size() != 0) { - auto& input_buffer = ctx.BufferDescriptorA()[0]; - auto& output_buffer = ctx.BufferDescriptorB()[0]; - std::vector input_data(input_buffer.Size()); - Memory::ReadBlock(input_buffer.Address(), input_data.data(), input_buffer.Size()); - TransactParcel(id, transaction, input_data, output_buffer.Address(), - output_buffer.Size()); + if (transaction == TransactionId::Connect) { + IGBPConnectRequestParcel request{ctx.ReadBuffer()}; + IGBPConnectResponseParcel response{1280, 720}; + ctx.WriteBuffer(response.Serialize()); + } else if (transaction == TransactionId::SetPreallocatedBuffer) { + IGBPSetPreallocatedBufferRequestParcel request{ctx.ReadBuffer()}; + + buffer_queue->SetPreallocatedBuffer(request.data.slot, request.buffer); + + IGBPSetPreallocatedBufferResponseParcel response{}; + ctx.WriteBuffer(response.Serialize()); + } else if (transaction == TransactionId::DequeueBuffer) { + IGBPDequeueBufferRequestParcel request{ctx.ReadBuffer()}; + + u32 slot = buffer_queue->DequeueBuffer(request.data.pixel_format, request.data.width, + request.data.height); + + IGBPDequeueBufferResponseParcel response{slot}; + ctx.WriteBuffer(response.Serialize()); + } else if (transaction == TransactionId::RequestBuffer) { + IGBPRequestBufferRequestParcel request{ctx.ReadBuffer()}; + + auto& buffer = buffer_queue->RequestBuffer(request.slot); + + IGBPRequestBufferResponseParcel response{buffer}; + ctx.WriteBuffer(response.Serialize()); + } else if (transaction == TransactionId::QueueBuffer) { + IGBPQueueBufferRequestParcel request{ctx.ReadBuffer()}; + + buffer_queue->QueueBuffer(request.data.slot, request.data.transform); + + IGBPQueueBufferResponseParcel response{1280, 720}; + ctx.WriteBuffer(response.Serialize()); + } else if (transaction == TransactionId::Query) { + IGBPQueryRequestParcel request{ctx.ReadBuffer()}; + + u32 value = + buffer_queue->Query(static_cast(request.type)); + + IGBPQueryResponseParcel response{value}; + ctx.WriteBuffer(response.Serialize()); + } else if (transaction == TransactionId::CancelBuffer) { + LOG_WARNING(Service_VI, "(STUBBED) called, transaction=CancelBuffer"); } else { - auto& input_buffer = ctx.BufferDescriptorX()[0]; - auto& output_buffer = ctx.BufferDescriptorC()[0]; - std::vector input_data(input_buffer.size); - Memory::ReadBlock(input_buffer.Address(), input_data.data(), input_buffer.size); - TransactParcel(id, transaction, input_data, output_buffer.Address(), - output_buffer.Size()); + ASSERT_MSG(false, "Unimplemented"); } IPC::ResponseBuilder rb{ctx, 2}; From d42e77797e83a6c1ed7291e532041c781881e853 Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 13 Feb 2018 22:21:17 -0500 Subject: [PATCH 05/10] nvdrv: Use ReadBuffer/WriteBuffer functions for Ioctl. --- src/core/hle/service/nvdrv/interface.cpp | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/src/core/hle/service/nvdrv/interface.cpp b/src/core/hle/service/nvdrv/interface.cpp index 367791da66..13d23291eb 100644 --- a/src/core/hle/service/nvdrv/interface.cpp +++ b/src/core/hle/service/nvdrv/interface.cpp @@ -32,25 +32,13 @@ void NVDRV::Ioctl(Kernel::HLERequestContext& ctx) { u32 fd = rp.Pop(); u32 command = rp.Pop(); + std::vector output(ctx.GetWriteBufferSize()); + IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); - if (ctx.BufferDescriptorA()[0].Size() != 0) { - auto input_buffer = ctx.BufferDescriptorA()[0]; - auto output_buffer = ctx.BufferDescriptorB()[0]; - std::vector input(input_buffer.Size()); - std::vector output(output_buffer.Size()); - Memory::ReadBlock(input_buffer.Address(), input.data(), input_buffer.Size()); - rb.Push(nvdrv->Ioctl(fd, command, input, output)); - Memory::WriteBlock(output_buffer.Address(), output.data(), output_buffer.Size()); - } else { - auto input_buffer = ctx.BufferDescriptorX()[0]; - auto output_buffer = ctx.BufferDescriptorC()[0]; - std::vector input(input_buffer.size); - std::vector output(output_buffer.size); - Memory::ReadBlock(input_buffer.Address(), input.data(), input_buffer.size); - rb.Push(nvdrv->Ioctl(fd, command, input, output)); - Memory::WriteBlock(output_buffer.Address(), output.data(), output_buffer.size); - } + rb.Push(nvdrv->Ioctl(fd, command, ctx.ReadBuffer(), output)); + + ctx.WriteBuffer(output); } void NVDRV::Close(Kernel::HLERequestContext& ctx) { From f16bb1dfcfa8f62818c1baba0e7ab9b8c65c30cd Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 13 Feb 2018 22:42:52 -0500 Subject: [PATCH 06/10] vi: Eliminate direct usage of BufferDescriptorB. --- src/core/hle/service/vi/vi.cpp | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 1f00a6cca5..ff5005f71f 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -685,18 +685,13 @@ void IApplicationDisplayService::OpenLayer(Kernel::HLERequestContext& ctx) { u64 layer_id = rp.Pop(); u64 aruid = rp.Pop(); - auto& buffer = ctx.BufferDescriptorB()[0]; - u64 display_id = nv_flinger->OpenDisplay(display_name); u32 buffer_queue_id = nv_flinger->GetBufferQueueId(display_id, layer_id); NativeWindow native_window{buffer_queue_id}; - auto data = native_window.Serialize(); - Memory::WriteBlock(buffer.Address(), data.data(), data.size()); - IPC::ResponseBuilder rb = rp.MakeBuilder(4, 0, 0); rb.Push(RESULT_SUCCESS); - rb.Push(data.size()); + rb.Push(ctx.WriteBuffer(native_window.Serialize())); } void IApplicationDisplayService::CreateStrayLayer(Kernel::HLERequestContext& ctx) { @@ -707,21 +702,16 @@ void IApplicationDisplayService::CreateStrayLayer(Kernel::HLERequestContext& ctx rp.Pop(); // padding u64 display_id = rp.Pop(); - auto& buffer = ctx.BufferDescriptorB()[0]; - // TODO(Subv): What's the difference between a Stray and a Managed layer? u64 layer_id = nv_flinger->CreateLayer(display_id); u32 buffer_queue_id = nv_flinger->GetBufferQueueId(display_id, layer_id); NativeWindow native_window{buffer_queue_id}; - auto data = native_window.Serialize(); - Memory::WriteBlock(buffer.Address(), data.data(), data.size()); - IPC::ResponseBuilder rb = rp.MakeBuilder(6, 0, 0); rb.Push(RESULT_SUCCESS); rb.Push(layer_id); - rb.Push(data.size()); + rb.Push(ctx.WriteBuffer(native_window.Serialize())); } void IApplicationDisplayService::DestroyStrayLayer(Kernel::HLERequestContext& ctx) { @@ -747,8 +737,7 @@ void IApplicationDisplayService::SetLayerScalingMode(Kernel::HLERequestContext& void IApplicationDisplayService::ListDisplays(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; DisplayInfo display_info; - auto& buffer = ctx.BufferDescriptorB()[0]; - Memory::WriteBlock(buffer.Address(), &display_info, sizeof(DisplayInfo)); + ctx.WriteBuffer(&display_info, sizeof(DisplayInfo)); IPC::ResponseBuilder rb = rp.MakeBuilder(4, 0, 0); rb.Push(RESULT_SUCCESS); rb.Push(1); From d6e52581acb9b124df57055c12088bb08e530ffc Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 13 Feb 2018 22:48:31 -0500 Subject: [PATCH 07/10] audio: Use WriteBuffer instead of BufferDescriptorB. --- src/core/hle/service/audio/audout_u.cpp | 8 ++------ src/core/hle/service/audio/audren_u.cpp | 4 +--- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp index f56ba2ea10..780a4e6e5f 100644 --- a/src/core/hle/service/audio/audout_u.cpp +++ b/src/core/hle/service/audio/audout_u.cpp @@ -99,8 +99,6 @@ private: void GetReleasedAudioOutBuffer_1(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_Audio, "(STUBBED) called"); - const auto& buffer = ctx.BufferDescriptorB()[0]; - // TODO(st4rk): This is how libtransistor currently implements the // GetReleasedAudioOutBuffer, it should return the key (a VAddr) to the app and this address // is used to know which buffer should be filled with data and send again to the service @@ -112,7 +110,7 @@ private: queue_keys.pop_back(); } - Memory::WriteBlock(buffer.Address(), &key, sizeof(u64)); + ctx.WriteBuffer(&key, sizeof(u64)); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); @@ -158,10 +156,8 @@ void AudOutU::ListAudioOuts(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_Audio, "(STUBBED) called"); IPC::RequestParser rp{ctx}; - auto& buffer = ctx.BufferDescriptorB()[0]; const std::string audio_interface = "AudioInterface"; - - Memory::WriteBlock(buffer.Address(), &audio_interface[0], audio_interface.size()); + ctx.WriteBuffer(audio_interface.c_str(), audio_interface.size()); IPC::ResponseBuilder rb = rp.MakeBuilder(3, 0, 0); diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index c8d8ba748a..20306c6cfd 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp @@ -69,9 +69,7 @@ private: response_data.state_entries[i].state = 5; } - auto& buffer = ctx.BufferDescriptorB()[0]; - - Memory::WriteBlock(buffer.Address(), &response_data, response_data.total_size); + ctx.WriteBuffer(&response_data, response_data.total_size); IPC::ResponseBuilder rb{ctx, 2}; From 516a95721c5ec7ae2f09cb1e7c9757903523d09e Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 13 Feb 2018 23:16:19 -0500 Subject: [PATCH 08/10] service: Remove remaining uses of BufferDescriptor*. --- src/core/hle/service/acc/acc_u0.cpp | 3 +-- src/core/hle/service/am/am.cpp | 6 +++--- src/core/hle/service/filesystem/fsp_srv.cpp | 4 +--- src/core/hle/service/nvdrv/interface.cpp | 5 ++--- src/core/hle/service/set/set.cpp | 4 +--- 5 files changed, 8 insertions(+), 14 deletions(-) diff --git a/src/core/hle/service/acc/acc_u0.cpp b/src/core/hle/service/acc/acc_u0.cpp index ee7d07aa7a..7955f726be 100644 --- a/src/core/hle/service/acc/acc_u0.cpp +++ b/src/core/hle/service/acc/acc_u0.cpp @@ -66,8 +66,7 @@ void ACC_U0::GetUserExistence(Kernel::HLERequestContext& ctx) { void ACC_U0::ListAllUsers(Kernel::HLERequestContext& ctx) { constexpr std::array user_ids{DEFAULT_USER_ID}; - const auto& output_buffer = ctx.BufferDescriptorC()[0]; - Memory::WriteBlock(output_buffer.Address(), user_ids.data(), user_ids.size()); + ctx.WriteBuffer(user_ids.data(), user_ids.size()); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); LOG_DEBUG(Service_ACC, "called"); diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 07cea87173..402105ea07 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -306,11 +306,11 @@ private: u64 offset = rp.Pop(); - const auto& output_buffer = ctx.BufferDescriptorC()[0]; + const size_t size{ctx.GetWriteBufferSize()}; - ASSERT(offset + output_buffer.Size() <= buffer.size()); + ASSERT(offset + size <= buffer.size()); - Memory::WriteBlock(output_buffer.Address(), buffer.data() + offset, output_buffer.Size()); + ctx.WriteBuffer(buffer.data() + offset, size); IPC::ResponseBuilder rb{ctx, 2}; diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index 34d4fd035d..87a07e457a 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp @@ -33,12 +33,10 @@ private: IPC::RequestParser rp{ctx}; const s64 offset = rp.Pop(); const s64 length = rp.Pop(); - const auto& descriptor = ctx.BufferDescriptorB()[0]; LOG_DEBUG(Service_FS, "called, offset=0x%llx, length=0x%llx", offset, length); // Error checking - ASSERT_MSG(length == descriptor.Size(), "unexpected size difference"); if (length < 0) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultCode(ErrorModule::FS, ErrorDescription::InvalidLength)); @@ -60,7 +58,7 @@ private: } // Write the data to memory - Memory::WriteBlock(descriptor.Address(), output.data(), descriptor.Size()); + ctx.WriteBuffer(output); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); diff --git a/src/core/hle/service/nvdrv/interface.cpp b/src/core/hle/service/nvdrv/interface.cpp index 13d23291eb..1e50d218a8 100644 --- a/src/core/hle/service/nvdrv/interface.cpp +++ b/src/core/hle/service/nvdrv/interface.cpp @@ -14,9 +14,8 @@ namespace Nvidia { void NVDRV::Open(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_NVDRV, "called"); - auto buffer = ctx.BufferDescriptorA()[0]; - - std::string device_name = Memory::ReadCString(buffer.Address(), buffer.Size()); + const auto& buffer = ctx.ReadBuffer(); + std::string device_name(buffer.begin(), buffer.end()); u32 fd = nvdrv->Open(device_name); IPC::ResponseBuilder rb{ctx, 4}; diff --git a/src/core/hle/service/set/set.cpp b/src/core/hle/service/set/set.cpp index 1062ba8b38..3001ee411c 100644 --- a/src/core/hle/service/set/set.cpp +++ b/src/core/hle/service/set/set.cpp @@ -17,9 +17,7 @@ void SET::GetAvailableLanguageCodes(Kernel::HLERequestContext& ctx) { u32 id = rp.Pop(); constexpr std::array lang_codes{}; - const auto& output_buffer = ctx.BufferDescriptorC()[0]; - - Memory::WriteBlock(output_buffer.Address(), lang_codes.data(), lang_codes.size()); + ctx.WriteBuffer(lang_codes.data(), lang_codes.size()); IPC::ResponseBuilder rb{ctx, 2}; From 6fd19f05f1eba884a20e79ee43fce1af388204d4 Mon Sep 17 00:00:00 2001 From: bunnei Date: Wed, 14 Feb 2018 00:14:17 -0500 Subject: [PATCH 09/10] hle_ipc: Add GetReadBufferSize and check write buffer size. --- src/core/hle/kernel/hle_ipc.cpp | 7 +++++++ src/core/hle/kernel/hle_ipc.h | 3 +++ 2 files changed, 10 insertions(+) diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index 0a9986c180..d592f502de 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp @@ -229,6 +229,8 @@ std::vector HLERequestContext::ReadBuffer() const { size_t HLERequestContext::WriteBuffer(const void* buffer, const size_t size) const { const bool is_buffer_b{BufferDescriptorB().size() && BufferDescriptorB()[0].Size()}; + ASSERT_MSG(size <= GetWriteBufferSize(), "Size %d is too big", size); + if (is_buffer_b) { Memory::WriteBlock(BufferDescriptorB()[0].Address(), buffer, size); } else { @@ -242,6 +244,11 @@ size_t HLERequestContext::WriteBuffer(const std::vector& buffer) const { return WriteBuffer(buffer.data(), buffer.size()); } +size_t HLERequestContext::GetReadBufferSize() const { + const bool is_buffer_a{BufferDescriptorA().size() && BufferDescriptorA()[0].Size()}; + return is_buffer_a ? BufferDescriptorA()[0].Size() : BufferDescriptorX()[0].Size(); +} + size_t HLERequestContext::GetWriteBufferSize() const { const bool is_buffer_b{BufferDescriptorB().size() && BufferDescriptorB()[0].Size()}; return is_buffer_b ? BufferDescriptorB()[0].Size() : BufferDescriptorC()[0].Size(); diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index 0cc2709095..5b1eae74ab 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h @@ -152,6 +152,9 @@ public: /// Helper function to write a buffer using the appropriate buffer descriptor size_t WriteBuffer(const std::vector& buffer) const; + /// Helper function to get the size of the input buffer + size_t GetReadBufferSize() const; + /// Helper function to get the size of the output buffer size_t GetWriteBufferSize() const; From 88bfec37ce445db30fe36bb2d00b115df6a24838 Mon Sep 17 00:00:00 2001 From: bunnei Date: Wed, 14 Feb 2018 14:21:10 -0500 Subject: [PATCH 10/10] hle_ipc: Remove const from WriteBuffer size. --- src/core/hle/kernel/hle_ipc.cpp | 2 +- src/core/hle/kernel/hle_ipc.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index d592f502de..6d16f71a7c 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp @@ -226,7 +226,7 @@ std::vector HLERequestContext::ReadBuffer() const { return buffer; } -size_t HLERequestContext::WriteBuffer(const void* buffer, const size_t size) const { +size_t HLERequestContext::WriteBuffer(const void* buffer, size_t size) const { const bool is_buffer_b{BufferDescriptorB().size() && BufferDescriptorB()[0].Size()}; ASSERT_MSG(size <= GetWriteBufferSize(), "Size %d is too big", size); diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index 5b1eae74ab..81e3489c8d 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h @@ -147,7 +147,7 @@ public: std::vector ReadBuffer() const; /// Helper function to write a buffer using the appropriate buffer descriptor - size_t WriteBuffer(const void* buffer, const size_t size) const; + size_t WriteBuffer(const void* buffer, size_t size) const; /// Helper function to write a buffer using the appropriate buffer descriptor size_t WriteBuffer(const std::vector& buffer) const;