From 38716989aeef06e51faf9f119b387bc0be85950c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=97=B1=20PixelyIon?= Date: Sun, 24 Nov 2019 00:18:22 +0530 Subject: [PATCH] Improve IPC interface This commit changes how IPC is interacted with in two ways: * Simplify all buffers into just InputBuffer and OutputBuffer * Use pushing/popping for data payload --- app/src/main/cpp/skyline/gpu.cpp | 33 +++---- .../main/cpp/skyline/gpu/devices/nvdevice.h | 70 +++----------- .../skyline/gpu/devices/nvhost_channel.cpp | 14 +-- .../cpp/skyline/gpu/devices/nvhost_channel.h | 14 +-- .../skyline/gpu/devices/nvhost_ctrl_gpu.cpp | 10 +- .../cpp/skyline/gpu/devices/nvhost_ctrl_gpu.h | 10 +- .../main/cpp/skyline/gpu/devices/nvmap.cpp | 12 +-- app/src/main/cpp/skyline/gpu/devices/nvmap.h | 12 +-- app/src/main/cpp/skyline/gpu/display.cpp | 10 +- app/src/main/cpp/skyline/gpu/display.h | 13 +-- app/src/main/cpp/skyline/gpu/parcel.cpp | 12 +-- app/src/main/cpp/skyline/gpu/parcel.h | 21 +---- app/src/main/cpp/skyline/kernel/ipc.cpp | 33 +++++-- app/src/main/cpp/skyline/kernel/ipc.h | 91 +++++++++++++++++-- app/src/main/cpp/skyline/kernel/svc.cpp | 2 + .../skyline/kernel/types/KTransferMemory.cpp | 3 - .../skyline/services/am/appletController.cpp | 14 +-- app/src/main/cpp/skyline/services/apm/apm.cpp | 14 ++- app/src/main/cpp/skyline/services/hid/hid.cpp | 47 +++------- .../main/cpp/skyline/services/nvdrv/nvdrv.cpp | 32 +++---- .../skyline/services/nvnflinger/dispdrv.cpp | 58 +++++------- .../cpp/skyline/services/nvnflinger/dispdrv.h | 10 +- .../main/cpp/skyline/services/serviceman.cpp | 10 +- app/src/main/cpp/skyline/services/set/sys.cpp | 2 +- .../main/cpp/skyline/services/time/time.cpp | 6 +- app/src/main/cpp/skyline/services/vi/vi_m.cpp | 43 ++++----- 26 files changed, 284 insertions(+), 312 deletions(-) diff --git a/app/src/main/cpp/skyline/gpu.cpp b/app/src/main/cpp/skyline/gpu.cpp index 16dc7409..69a2e04d 100644 --- a/app/src/main/cpp/skyline/gpu.cpp +++ b/app/src/main/cpp/skyline/gpu.cpp @@ -122,24 +122,21 @@ namespace skyline::gpu { void GPU::Ioctl(u32 fd, u32 cmd, kernel::ipc::IpcRequest &request, kernel::ipc::IpcResponse &response) { state.logger->Debug("IOCTL on device: 0x{:X}, cmd: 0x{:X}", fd, cmd); try { - if (!request.vecBufA.empty() && !request.vecBufB.empty()) { - device::IoctlBuffers input(device::InputBuffer(request.vecBufA[0]), device::OutputBuffer(request.vecBufB[0])); - fdMap.at(fd)->HandleIoctl(cmd, input); - response.WriteValue(input.status); - } else if (!request.vecBufX.empty() && !request.vecBufC.empty()) { - device::IoctlBuffers input(device::InputBuffer(request.vecBufX[0]), device::OutputBuffer(request.vecBufC[0])); - fdMap.at(fd)->HandleIoctl(cmd, input); - response.WriteValue(input.status); - } else if (!request.vecBufX.empty()) { - device::IoctlBuffers input(device::InputBuffer(request.vecBufX[0])); - fdMap.at(fd)->HandleIoctl(cmd, input); - response.WriteValue(input.status); - } else if (!request.vecBufC.empty()) { - device::IoctlBuffers input(device::OutputBuffer(request.vecBufC[0])); - fdMap.at(fd)->HandleIoctl(cmd, input); - response.WriteValue(input.status); - } else - throw exception("Unknown IOCTL buffer configuration"); + if(request.inputBuf.empty() || request.outputBuf.empty()) { + if(request.inputBuf.empty()) { + device::IoctlData data(request.outputBuf.at(0)); + fdMap.at(fd)->HandleIoctl(cmd, data); + response.Push(data.status); + } else { + device::IoctlData data(request.inputBuf.at(0)); + fdMap.at(fd)->HandleIoctl(cmd, data); + response.Push(data.status); + } + } else { + device::IoctlData data(request.inputBuf.at(0), request.outputBuf.at(0)); + fdMap.at(fd)->HandleIoctl(cmd, data); + response.Push(data.status); + } } catch (const std::out_of_range &) { throw exception("IOCTL was requested on an invalid file descriptor"); } diff --git a/app/src/main/cpp/skyline/gpu/devices/nvdevice.h b/app/src/main/cpp/skyline/gpu/devices/nvdevice.h index 0644ad13..0a6428ac 100644 --- a/app/src/main/cpp/skyline/gpu/devices/nvdevice.h +++ b/app/src/main/cpp/skyline/gpu/devices/nvdevice.h @@ -54,50 +54,6 @@ namespace skyline::gpu::device { {"/dev/nvhost-ctrl-gpu", NvDeviceType::nvhost_ctrl_gpu} }; - /** - * @brief Describes a buffer by holding the address and size - */ - struct IoctlBuffer { - u64 address; //!< The address of the buffer - size_t size; //!< The size of the buffer - - /** - * @param address The address of the buffer - * @param size The size of the buffer - */ - IoctlBuffer(u64 address, size_t size) : address(address), size(size) {} - }; - - /** - * @brief Wrapper around IoctlBuffer that loads in the address from a A Buffer Descriptor - */ - struct InputBuffer : public IoctlBuffer { - /** - * @param aBuf The A Buffer Descriptor that has contains the input data - */ - InputBuffer(kernel::ipc::BufferDescriptorABW *aBuf) : IoctlBuffer(aBuf->Address(), aBuf->Size()) {} - - /** - * @param aBuf The X Buffer Descriptor that has contains the input data - */ - InputBuffer(kernel::ipc::BufferDescriptorX *xBuf) : IoctlBuffer(xBuf->Address(), xBuf->size) {} - }; - - /** - * @brief Wrapper around IoctlBuffer that loads in the address from a B Buffer Descriptor - */ - struct OutputBuffer : public IoctlBuffer { - /** - * @param aBuf The B Buffer Descriptor that has to be outputted to - */ - OutputBuffer(kernel::ipc::BufferDescriptorABW *bBuf) : IoctlBuffer(bBuf->Address(), bBuf->Size()) {} - - /** - * @param xBuf The C Buffer Descriptor that has to be outputted to - */ - OutputBuffer(kernel::ipc::BufferDescriptorC *cBuf) : IoctlBuffer(cBuf->address, cBuf->size) {} - }; - /** * @brief This enumerates all the possible error codes returned by the Nvidia driver (https://switchbrew.org/wiki/NV_services#Errors) */ @@ -128,11 +84,11 @@ namespace skyline::gpu::device { }; /** - * @brief This holds all the IoctlBuffer objects in a coherent container + * @brief This holds all the input and output data for an IOCTL function */ - struct IoctlBuffers { - std::vector input; //!< A vector of all input IOCTL buffers - std::vector output; //!< A vector of all output IOCTL buffers + struct IoctlData { + std::vector input; //!< A vector of all input IOCTL buffers + std::vector output; //!< A vector of all output IOCTL buffers NvStatus status{NvStatus::Success}; //!< The error code that is returned to the application /** @@ -140,19 +96,19 @@ namespace skyline::gpu::device { * @param input An input buffer * @param output An output buffer */ - IoctlBuffers(InputBuffer input, OutputBuffer output) : input({input}), output({output}) {} + IoctlData(kernel::ipc::InputBuffer input, kernel::ipc::OutputBuffer output) : input({input}), output({output}) {} /** * @brief This constructor takes 1 input buffer, it's used for Ioctl sometimes * @param output An output buffer */ - IoctlBuffers(InputBuffer input) : input({input}) {} + IoctlData(kernel::ipc::InputBuffer input) : input({input}) {} /** * @brief This constructor takes 1 output buffer, it's used for Ioctl sometimes * @param output An output buffer */ - IoctlBuffers(OutputBuffer output) : output({output}) {} + IoctlData(kernel::ipc::OutputBuffer output) : output({output}) {} /** * @brief This constructor takes 2 input buffers and 1 output buffer, it's used for Ioctl1 @@ -160,7 +116,7 @@ namespace skyline::gpu::device { * @param input2 The second input buffer * @param output An output buffer */ - IoctlBuffers(InputBuffer input1, InputBuffer input2, OutputBuffer output) : input({input1, input2}), output({output}) {} + IoctlData(kernel::ipc::InputBuffer input1, kernel::ipc::InputBuffer input2, kernel::ipc::OutputBuffer output) : input({input1, input2}), output({output}) {} /** * @brief This constructor takes 1 input buffer and 2 output buffers, it's used for Ioctl2 @@ -168,7 +124,7 @@ namespace skyline::gpu::device { * @param output1 The first output buffer * @param output2 The second output buffer */ - IoctlBuffers(InputBuffer input, OutputBuffer output1, OutputBuffer output2) : input({input}), output({output1, output2}) {} + IoctlData(kernel::ipc::InputBuffer input, kernel::ipc::OutputBuffer output1, kernel::ipc::OutputBuffer output2) : input({input}), output({output1, output2}) {} }; /** @@ -177,7 +133,7 @@ namespace skyline::gpu::device { class NvDevice { protected: const DeviceState &state; //!< The state of the device - std::unordered_map> vTable; //!< This holds the mapping from an Ioctl to the actual function + std::unordered_map> vTable; //!< This holds the mapping from an Ioctl to the actual function public: u16 refCount{1}; //!< The amount of handles to the device @@ -188,7 +144,7 @@ namespace skyline::gpu::device { * @param deviceType The type of the device * @param vTable The functions in this device */ - NvDevice(const DeviceState &state, NvDeviceType deviceType, std::unordered_map> vTable) : state(state), deviceType(deviceType), vTable(vTable) {} + NvDevice(const DeviceState &state, NvDeviceType deviceType, std::unordered_map> vTable) : state(state), deviceType(deviceType), vTable(vTable) {} /** * @brief This returns the name of the current service @@ -208,8 +164,8 @@ namespace skyline::gpu::device { * @param cmd The IOCTL command that was called * @param input The input to the IOCTL call */ - void HandleIoctl(u32 cmd, IoctlBuffers &input) { - std::function function; + void HandleIoctl(u32 cmd, IoctlData &input) { + std::function function; try { function = vTable.at(cmd); } catch (std::out_of_range &) { diff --git a/app/src/main/cpp/skyline/gpu/devices/nvhost_channel.cpp b/app/src/main/cpp/skyline/gpu/devices/nvhost_channel.cpp index 66120478..75426419 100644 --- a/app/src/main/cpp/skyline/gpu/devices/nvhost_channel.cpp +++ b/app/src/main/cpp/skyline/gpu/devices/nvhost_channel.cpp @@ -12,15 +12,15 @@ namespace skyline::gpu::device { {0x40084714, NFUNC(NvHostChannel::SetUserData)} }) {} - void NvHostChannel::SetNvmapFd(skyline::gpu::device::IoctlBuffers &buffer) {} + void NvHostChannel::SetNvmapFd(skyline::gpu::device::IoctlData &buffer) {} - void NvHostChannel::AllocObjCtx(skyline::gpu::device::IoctlBuffers &buffer) {} + void NvHostChannel::AllocObjCtx(skyline::gpu::device::IoctlData &buffer) {} - void NvHostChannel::ZcullBind(IoctlBuffers &buffer) {} + void NvHostChannel::ZcullBind(IoctlData &buffer) {} - void NvHostChannel::SetErrorNotifier(skyline::gpu::device::IoctlBuffers &buffer) {} + void NvHostChannel::SetErrorNotifier(skyline::gpu::device::IoctlData &buffer) {} - void NvHostChannel::SetPriority(skyline::gpu::device::IoctlBuffers &buffer) { + void NvHostChannel::SetPriority(skyline::gpu::device::IoctlData &buffer) { auto priority = state.thisProcess->ReadMemory(buffer.input[0].address); switch (priority) { case NvChannelPriority::Low: @@ -35,8 +35,8 @@ namespace skyline::gpu::device { } } - void NvHostChannel::AllocGpfifoEx2(skyline::gpu::device::IoctlBuffers &buffer) {} + void NvHostChannel::AllocGpfifoEx2(skyline::gpu::device::IoctlData &buffer) {} - void NvHostChannel::SetUserData(skyline::gpu::device::IoctlBuffers &buffer) {} + void NvHostChannel::SetUserData(skyline::gpu::device::IoctlData &buffer) {} } diff --git a/app/src/main/cpp/skyline/gpu/devices/nvhost_channel.h b/app/src/main/cpp/skyline/gpu/devices/nvhost_channel.h index a9511076..f9939264 100644 --- a/app/src/main/cpp/skyline/gpu/devices/nvhost_channel.h +++ b/app/src/main/cpp/skyline/gpu/devices/nvhost_channel.h @@ -22,36 +22,36 @@ namespace skyline::gpu::device { /** * @brief This sets the nvmap file descriptor (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_SET_NVMAP_FD) */ - void SetNvmapFd(IoctlBuffers &buffer); + void SetNvmapFd(IoctlData &buffer); /** * @brief This allocates a graphic context object (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_ALLOC_OBJ_CTX) */ - void AllocObjCtx(IoctlBuffers &buffer); + void AllocObjCtx(IoctlData &buffer); /** * @brief This initializes the error notifier for this channel (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_ZCULL_BIND) */ - void ZcullBind(IoctlBuffers &buffer); + void ZcullBind(IoctlData &buffer); /** * @brief This initializes the error notifier for this channel (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_SET_ERROR_NOTIFIER) */ - void SetErrorNotifier(IoctlBuffers &buffer); + void SetErrorNotifier(IoctlData &buffer); /** * @brief This sets the priority of the channel (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_SET_PRIORITY) */ - void SetPriority(IoctlBuffers &buffer); + void SetPriority(IoctlData &buffer); /** * @brief This allocates a GPFIFO entry (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_ALLOC_GPFIFO_EX2) */ - void AllocGpfifoEx2(IoctlBuffers &buffer); + void AllocGpfifoEx2(IoctlData &buffer); /** * @brief This sets the user specific data (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_SET_USER_DATA) */ - void SetUserData(IoctlBuffers &buffer); + void SetUserData(IoctlData &buffer); }; } diff --git a/app/src/main/cpp/skyline/gpu/devices/nvhost_ctrl_gpu.cpp b/app/src/main/cpp/skyline/gpu/devices/nvhost_ctrl_gpu.cpp index 0740ae14..8d5a59a3 100644 --- a/app/src/main/cpp/skyline/gpu/devices/nvhost_ctrl_gpu.cpp +++ b/app/src/main/cpp/skyline/gpu/devices/nvhost_ctrl_gpu.cpp @@ -10,12 +10,12 @@ namespace skyline::gpu::device { {0x80084714, NFUNC(NvHostCtrlGpu::GetActiveSlotMask)} }) {} - void NvHostCtrlGpu::ZCullGetCtxSize(IoctlBuffers &buffer) { + void NvHostCtrlGpu::ZCullGetCtxSize(IoctlData &buffer) { u32 size = 0x1; state.thisProcess->WriteMemory(size, buffer.output[0].address); } - void NvHostCtrlGpu::ZCullGetInfo(skyline::gpu::device::IoctlBuffers &buffer) { + void NvHostCtrlGpu::ZCullGetInfo(skyline::gpu::device::IoctlData &buffer) { struct { u32 widthAlignPixels{0x20}; u32 heightAlignPixels{0x20}; @@ -31,7 +31,7 @@ namespace skyline::gpu::device { state.thisProcess->WriteMemory(zCullInfo, buffer.output[0].address); } - void NvHostCtrlGpu::GetCharacteristics(IoctlBuffers &buffer) { + void NvHostCtrlGpu::GetCharacteristics(IoctlData &buffer) { struct GpuCharacteristics { u32 arch; // 0x120 (NVGPU_GPU_ARCH_GM200) u32 impl; // 0xB (NVGPU_GPU_IMPL_GM20B) or 0xE (NVGPU_GPU_IMPL_GM20B_B) @@ -114,7 +114,7 @@ namespace skyline::gpu::device { state.thisProcess->WriteMemory(data, buffer.output[0].address); } - void NvHostCtrlGpu::GetTpcMasks(IoctlBuffers &buffer) { + void NvHostCtrlGpu::GetTpcMasks(IoctlData &buffer) { struct Data { u32 maskBufSize; // In u32 reserved[3]; // In @@ -125,7 +125,7 @@ namespace skyline::gpu::device { state.thisProcess->WriteMemory(data, buffer.output[0].address); } - void NvHostCtrlGpu::GetActiveSlotMask(IoctlBuffers &buffer) { + void NvHostCtrlGpu::GetActiveSlotMask(IoctlData &buffer) { struct Data { u32 slot; // Out u32 mask; // Out diff --git a/app/src/main/cpp/skyline/gpu/devices/nvhost_ctrl_gpu.h b/app/src/main/cpp/skyline/gpu/devices/nvhost_ctrl_gpu.h index f3dcb9db..c5fafe61 100644 --- a/app/src/main/cpp/skyline/gpu/devices/nvhost_ctrl_gpu.h +++ b/app/src/main/cpp/skyline/gpu/devices/nvhost_ctrl_gpu.h @@ -13,26 +13,26 @@ namespace skyline::gpu::device { /** * @brief This returns a u32 GPU ZCULL Context Size (https://switchbrew.org/wiki/NV_services#NVGPU_GPU_IOCTL_ZCULL_GET_CTX_SIZE) */ - void ZCullGetCtxSize(IoctlBuffers &buffer); + void ZCullGetCtxSize(IoctlData &buffer); /** * @brief This returns a the GPU ZCULL Information (https://switchbrew.org/wiki/NV_services#NVGPU_GPU_IOCTL_ZCULL_GET_INFO) */ - void ZCullGetInfo(IoctlBuffers &buffer); + void ZCullGetInfo(IoctlData &buffer); /** * @brief This returns a struct with certain GPU characteristics (https://switchbrew.org/wiki/NV_services#NVGPU_GPU_IOCTL_GET_CHARACTERISTICS) */ - void GetCharacteristics(IoctlBuffers &buffer); + void GetCharacteristics(IoctlData &buffer); /** * @brief This returns the TPC mask value for each GPC (https://switchbrew.org/wiki/NV_services#NVGPU_GPU_IOCTL_GET_TPC_MASKS) */ - void GetTpcMasks(IoctlBuffers &buffer); + void GetTpcMasks(IoctlData &buffer); /** * @brief This returns the mask value for a ZBC slot (https://switchbrew.org/wiki/NV_services#NVGPU_GPU_IOCTL_ZBC_GET_ACTIVE_SLOT_MASK) */ - void GetActiveSlotMask(IoctlBuffers &buffer); + void GetActiveSlotMask(IoctlData &buffer); }; } diff --git a/app/src/main/cpp/skyline/gpu/devices/nvmap.cpp b/app/src/main/cpp/skyline/gpu/devices/nvmap.cpp index 68404bde..b6396f7c 100644 --- a/app/src/main/cpp/skyline/gpu/devices/nvmap.cpp +++ b/app/src/main/cpp/skyline/gpu/devices/nvmap.cpp @@ -13,7 +13,7 @@ namespace skyline::gpu::device { {0xC008010E, NFUNC(NvMap::GetId)} }) {} - void NvMap::Create(IoctlBuffers &buffer) { + void NvMap::Create(IoctlData &buffer) { struct Data { u32 size; // In u32 handle; // Out @@ -24,7 +24,7 @@ namespace skyline::gpu::device { state.logger->Debug("Create: Input: Size: 0x{:X}, Output: Handle: 0x{:X}, Status: {}", data.size, data.handle, buffer.status); } - void NvMap::FromId(skyline::gpu::device::IoctlBuffers &buffer) { + void NvMap::FromId(skyline::gpu::device::IoctlData &buffer) { struct Data { u32 id; // In u32 handle; // Out @@ -44,7 +44,7 @@ namespace skyline::gpu::device { state.logger->Debug("FromId: Input: Handle: 0x{:X}, Output: ID: 0x{:X}, Status: {}", data.handle, data.id, buffer.status); } - void NvMap::Alloc(IoctlBuffers &buffer) { + void NvMap::Alloc(IoctlData &buffer) { struct Data { u32 handle; // In u32 heapMask; // In @@ -64,7 +64,7 @@ namespace skyline::gpu::device { state.logger->Debug("Alloc: Input: Handle: 0x{:X}, HeapMask: 0x{:X}, Flags: {}, Align: 0x{:X}, Kind: {}, Address: 0x{:X}, Output: Status: {}", data.handle, data.heapMask, data.flags, data.align, data.kind, data.address, buffer.status); } - void NvMap::Free(skyline::gpu::device::IoctlBuffers &buffer) { + void NvMap::Free(skyline::gpu::device::IoctlData &buffer) { struct Data { u32 handle; // In u32 _pad0_; @@ -85,7 +85,7 @@ namespace skyline::gpu::device { state.thisProcess->WriteMemory(data, buffer.output[0].address); } - void NvMap::Param(IoctlBuffers &buffer) { + void NvMap::Param(IoctlData &buffer) { enum class Parameter : u32 { Size = 1, Alignment = 2, Base = 3, HeapMask = 4, Kind = 5, Compr = 6 }; // https://android.googlesource.com/kernel/tegra/+/refs/heads/android-tegra-flounder-3.10-marshmallow/include/linux/nvmap.h#102 struct Data { u32 handle; // In @@ -128,7 +128,7 @@ namespace skyline::gpu::device { state.logger->Debug("Param: Input: Handle: 0x{:X}, Parameter: {}, Output: Result: 0x{:X}, Status: {}", data.handle, data.parameter, data.result, buffer.status); } - void NvMap::GetId(skyline::gpu::device::IoctlBuffers &buffer) { + void NvMap::GetId(skyline::gpu::device::IoctlData &buffer) { struct Data { u32 id; // Out u32 handle; // In diff --git a/app/src/main/cpp/skyline/gpu/devices/nvmap.h b/app/src/main/cpp/skyline/gpu/devices/nvmap.h index 349119a3..9e104d64 100644 --- a/app/src/main/cpp/skyline/gpu/devices/nvmap.h +++ b/app/src/main/cpp/skyline/gpu/devices/nvmap.h @@ -41,31 +41,31 @@ namespace skyline::gpu::device { /** * @brief This creates an NvMapObject and returns an handle to it (https://switchbrew.org/wiki/NV_services#NVMAP_IOC_CREATE) */ - void Create(IoctlBuffers &buffer); + void Create(IoctlData &buffer); /** * @brief This returns the handle of an NvMapObject from it's ID (https://switchbrew.org/wiki/NV_services#NVMAP_IOC_FROM_ID) */ - void FromId(IoctlBuffers &buffer); + void FromId(IoctlData &buffer); /** * @brief This allocates memory for an NvMapObject (https://switchbrew.org/wiki/NV_services#NVMAP_IOC_ALLOC) */ - void Alloc(IoctlBuffers &buffer); + void Alloc(IoctlData &buffer); /** * @brief This frees previously allocated memory (https://switchbrew.org/wiki/NV_services#NVMAP_IOC_FREE) */ - void Free(IoctlBuffers &buffer); + void Free(IoctlData &buffer); /** * @brief This returns a particular parameter from an NvMapObject (https://switchbrew.org/wiki/NV_services#NVMAP_IOC_PARAM) */ - void Param(IoctlBuffers &buffer); + void Param(IoctlData &buffer); /** * @brief This returns the ID of an NvMapObject from it's handle (https://switchbrew.org/wiki/NV_services#NVMAP_IOC_GET_ID) */ - void GetId(IoctlBuffers &buffer); + void GetId(IoctlData &buffer); }; } diff --git a/app/src/main/cpp/skyline/gpu/display.cpp b/app/src/main/cpp/skyline/gpu/display.cpp index 6fbe3fe3..05fcf65c 100644 --- a/app/src/main/cpp/skyline/gpu/display.cpp +++ b/app/src/main/cpp/skyline/gpu/display.cpp @@ -34,7 +34,7 @@ namespace skyline::gpu { state.thisProcess->ReadMemory(dataBuffer.data(), nvBuffer->address + gbpBuffer.offset, gbpBuffer.size); } - BufferQueue::WaitContext::WaitContext(std::shared_ptr thread, DequeueIn input, u64 address, u64 size) : thread(std::move(thread)), input(input), address(address), size(size) {} + BufferQueue::WaitContext::WaitContext(std::shared_ptr thread, DequeueIn input, kernel::ipc::OutputBuffer& buffer) : thread(std::move(thread)), input(input), buffer(buffer) {} BufferQueue::DequeueOut::DequeueOut(u32 slot) : slot(slot), _unk0_(0x1), _unk1_(0x24) {} @@ -49,7 +49,7 @@ namespace skyline::gpu { state.logger->Debug("RequestBuffer: Slot: {}", slot, sizeof(GbpBuffer)); } - bool BufferQueue::DequeueBuffer(Parcel &in, Parcel &out, u64 address, u64 size) { + bool BufferQueue::DequeueBuffer(Parcel &in, Parcel &out, kernel::ipc::OutputBuffer& buffer) { auto *data = reinterpret_cast(in.data.data() + constant::TokenLength); i64 slot{-1}; for (auto &buffer : queue) { @@ -60,7 +60,7 @@ namespace skyline::gpu { } if (slot == -1) { state.thisThread->Sleep(); - waitVec.emplace_back(state.thisThread, *data, address, size); + waitVec.emplace_back(state.thisThread, *data, buffer); state.logger->Debug("DequeueBuffer: Width: {}, Height: {}, Format: {}, Usage: {}, Timestamps: {}, No Free Buffers", data->width, data->height, data->format, data->usage, data->timestamps); return true; } @@ -130,12 +130,12 @@ namespace skyline::gpu { else { auto context = waitVec.begin(); while (context != waitVec.end()) { - if (slot->resolution.width == context->input.width && slot->resolution.height == context->input.height && slot->gbpBuffer.format == context->input.format && slot->gbpBuffer.usage == context->input.usage) { + if (slot->resolution.width == context->input.width && slot->resolution.height == context->input.height && slot->gbpBuffer.usage == context->input.usage) { context->thread->WakeUp(); gpu::Parcel out(state); DequeueOut output(slotNo); out.WriteData(output); - out.WriteParcel(context->address, context->size, context->thread->pid); + out.WriteParcel(context->buffer, context->thread->pid); slot->status = BufferStatus::Dequeued; waitVec.erase(context); break; diff --git a/app/src/main/cpp/skyline/gpu/display.h b/app/src/main/cpp/skyline/gpu/display.h index da87c479..d91abd20 100644 --- a/app/src/main/cpp/skyline/gpu/display.h +++ b/app/src/main/cpp/skyline/gpu/display.h @@ -160,16 +160,14 @@ namespace skyline::gpu { struct WaitContext { std::shared_ptr thread; //!< The thread that is waiting on a buffer DequeueIn input; //!< The input of DequeueBuffer - u64 address; //!< The address of the parcel buffer - u64 size; //!< The size of the parcel buffer + kernel::ipc::OutputBuffer buffer; //!< The output buffer to write the parcel into /** * @param thread The thread that is waiting on a buffer * @param input The input of DequeueBuffer - * @param address The address of the parcel buffer - * @param size The size of the parcel buffer + * @param buffer The output buffer to write the parcel into */ - WaitContext(std::shared_ptr thread, DequeueIn input, u64 address, u64 size); + WaitContext(std::shared_ptr thread, DequeueIn input, kernel::ipc::OutputBuffer& buffer); }; std::vector waitVec; //!< A vector of shared pointers to threads waiting on a buffer @@ -189,11 +187,10 @@ namespace skyline::gpu { /** * @brief This returns the slot of a free buffer - * @param address The address of the parcel buffer - * @param size The size of the parcel buffer + * @param buffer The output parcel buffer * @return If the process is waiting for a buffer or not */ - bool DequeueBuffer(Parcel &in, Parcel &out, u64 address, u64 size); + bool DequeueBuffer(Parcel &in, Parcel &out, kernel::ipc::OutputBuffer& buffer); /** * @brief This queues a buffer to be displayed diff --git a/app/src/main/cpp/skyline/gpu/parcel.cpp b/app/src/main/cpp/skyline/gpu/parcel.cpp index 8a3e31e1..f0d71ba3 100644 --- a/app/src/main/cpp/skyline/gpu/parcel.cpp +++ b/app/src/main/cpp/skyline/gpu/parcel.cpp @@ -3,9 +3,7 @@ #include namespace skyline::gpu { - Parcel::Parcel(kernel::ipc::BufferDescriptorABW *buffer, const DeviceState &state) : Parcel(buffer->Address(), buffer->Size(), state) {} - - Parcel::Parcel(kernel::ipc::BufferDescriptorX *buffer, const DeviceState &state) : Parcel(buffer->Address(), buffer->size, state) {} + Parcel::Parcel(kernel::ipc::InputBuffer &buffer, const DeviceState &state) : Parcel(buffer.address, buffer.size, state) {} Parcel::Parcel(u64 address, u64 size, const DeviceState &state) : state(state) { state.thisProcess->ReadMemory(&header, address, sizeof(ParcelHeader)); @@ -19,12 +17,8 @@ namespace skyline::gpu { Parcel::Parcel(const DeviceState &state) : state(state) {} - u64 Parcel::WriteParcel(kernel::ipc::BufferDescriptorABW *buffer, pid_t process) { - return WriteParcel(buffer->Address(), buffer->Size(), process); - } - - u64 Parcel::WriteParcel(kernel::ipc::BufferDescriptorC *buffer, pid_t process) { - return WriteParcel(buffer->address, buffer->size, process); + u64 Parcel::WriteParcel(kernel::ipc::OutputBuffer& buffer, pid_t process) { + return WriteParcel(buffer.address, buffer.size, process); } u64 Parcel::WriteParcel(u64 address, u64 maxSize, pid_t process) { diff --git a/app/src/main/cpp/skyline/gpu/parcel.h b/app/src/main/cpp/skyline/gpu/parcel.h index 687315b5..b282e5c1 100644 --- a/app/src/main/cpp/skyline/gpu/parcel.h +++ b/app/src/main/cpp/skyline/gpu/parcel.h @@ -31,14 +31,7 @@ namespace skyline::gpu { * @param buffer The buffer that contains the parcel * @param state The state of the device */ - Parcel(kernel::ipc::BufferDescriptorABW *buffer, const DeviceState &state); - - /** - * @brief This constructor fills in the Parcel object with data from a IPC buffer - * @param buffer The buffer that contains the parcel - * @param state The state of the device - */ - Parcel(kernel::ipc::BufferDescriptorX *buffer, const DeviceState &state); + Parcel(kernel::ipc::InputBuffer &buffer, const DeviceState &state); /** * @brief This constructor fills in the Parcel object with data from a Parcel on a remote process @@ -85,20 +78,12 @@ namespace skyline::gpu { } /** - * @brief Writes the Parcel object into a particular B buffer on a process + * @brief Writes the Parcel object into a particular output buffer on a process * @param buffer The buffer to write into * @param process The process to write the Parcel to * @return The total size of the message */ - u64 WriteParcel(kernel::ipc::BufferDescriptorABW *buffer, pid_t process = 0); - - /** - * @brief Writes the Parcel object into a particular C buffer on a process - * @param buffer The buffer to write into - * @param process The process to write the Parcel to - * @return The total size of the message - */ - u64 WriteParcel(kernel::ipc::BufferDescriptorC *buffer, pid_t process = 0); + u64 WriteParcel(kernel::ipc::OutputBuffer& buffer, pid_t process = 0); /** * @brief Writes the Parcel object into the process's memory diff --git a/app/src/main/cpp/skyline/kernel/ipc.cpp b/app/src/main/cpp/skyline/kernel/ipc.cpp index 4d83ff48..a030f688 100644 --- a/app/src/main/cpp/skyline/kernel/ipc.cpp +++ b/app/src/main/cpp/skyline/kernel/ipc.cpp @@ -2,6 +2,16 @@ #include "types/KProcess.h" namespace skyline::kernel::ipc { + IpcBuffer::IpcBuffer(u64 address, size_t size, IpcBufferType type) : address(address), size(size), type(type) {} + + InputBuffer::InputBuffer(kernel::ipc::BufferDescriptorX *xBuf) : IpcBuffer(xBuf->Address(), xBuf->size, IpcBufferType::X) {} + + InputBuffer::InputBuffer(kernel::ipc::BufferDescriptorABW *aBuf, IpcBufferType type) : IpcBuffer(aBuf->Address(), aBuf->Size(), type) {} + + OutputBuffer::OutputBuffer(kernel::ipc::BufferDescriptorABW *bBuf, IpcBufferType type) : IpcBuffer(bBuf->Address(), bBuf->Size(), type) {} + + OutputBuffer::OutputBuffer(kernel::ipc::BufferDescriptorC *cBuf) : IpcBuffer(cBuf->address, cBuf->size, IpcBufferType::C) {} + IpcRequest::IpcRequest(bool isDomain, const DeviceState &state) : isDomain(isDomain), state(state), tls() { u8 *currPtr = tls.data(); state.thisProcess->ReadMemory(currPtr, state.thisThread->tls, constant::TlsIpcSize); @@ -25,7 +35,7 @@ namespace skyline::kernel::ipc { for (uint index = 0; header->Xno > index; index++) { auto bufX = reinterpret_cast(currPtr); if (bufX->Address()) { - vecBufX.push_back(bufX); + inputBuf.emplace_back(bufX); state.logger->Debug("Buf X #{} AD: 0x{:X} SZ: 0x{:X} CTR: {}", index, u64(bufX->Address()), u16(bufX->size), u16(bufX->Counter())); } currPtr += sizeof(BufferDescriptorX); @@ -34,7 +44,7 @@ namespace skyline::kernel::ipc { for (uint index = 0; header->Ano > index; index++) { auto bufA = reinterpret_cast(currPtr); if (bufA->Address()) { - vecBufA.push_back(bufA); + inputBuf.emplace_back(bufA); state.logger->Debug("Buf A #{} AD: 0x{:X} SZ: 0x{:X}", index, u64(bufA->Address()), u64(bufA->Size())); } currPtr += sizeof(BufferDescriptorABW); @@ -43,7 +53,7 @@ namespace skyline::kernel::ipc { for (uint index = 0; header->Bno > index; index++) { auto bufB = reinterpret_cast(currPtr); if (bufB->Address()) { - vecBufB.push_back(bufB); + outputBuf.emplace_back(bufB); state.logger->Debug("Buf B #{} AD: 0x{:X} SZ: 0x{:X}", index, u64(bufB->Address()), u64(bufB->Size())); } currPtr += sizeof(BufferDescriptorABW); @@ -52,7 +62,8 @@ namespace skyline::kernel::ipc { for (uint index = 0; header->Wno > index; index++) { auto bufW = reinterpret_cast(currPtr); if (bufW->Address()) { - vecBufW.push_back(bufW); + inputBuf.emplace_back(bufW, IpcBufferType::W); + outputBuf.emplace_back(bufW, IpcBufferType::W); state.logger->Debug("Buf W #{} AD: 0x{:X} SZ: 0x{:X}", index, u64(bufW->Address()), u16(bufW->Size())); } currPtr += sizeof(BufferDescriptorABW); @@ -85,6 +96,8 @@ namespace skyline::kernel::ipc { currPtr += cmdArgSz; } + payloadOffset = cmdArg; + if (payload->magic != constant::SfciMagic && header->type != CommandType::Control) state.logger->Debug("Unexpected Magic in PayloadHeader: 0x{:X}", u32(payload->magic)); @@ -92,13 +105,15 @@ namespace skyline::kernel::ipc { if (header->cFlag == BufferCFlag::SingleDescriptor) { auto bufC = reinterpret_cast(currPtr); - vecBufC.push_back(bufC); - state.logger->Debug("Buf C: AD: 0x{:X} SZ: 0x{:X}", u64(bufC->address), u16(bufC->size)); + if (bufC->address) { + outputBuf.emplace_back(bufC); + state.logger->Debug("Buf C: AD: 0x{:X} SZ: 0x{:X}", u64(bufC->address), u16(bufC->size)); + } } else if (header->cFlag > BufferCFlag::SingleDescriptor) { for (uint index = 0; (static_cast(header->cFlag) - 2) > index; index++) { // (cFlag - 2) C descriptors are present auto bufC = reinterpret_cast(currPtr); if (bufC->address) { - vecBufC.push_back(bufC); + outputBuf.emplace_back(bufC); state.logger->Debug("Buf C #{} AD: 0x{:X} SZ: 0x{:X}", index, u64(bufC->address), u16(bufC->size)); } currPtr += sizeof(BufferDescriptorC); @@ -106,7 +121,7 @@ namespace skyline::kernel::ipc { } if (header->type == CommandType::Request) { - state.logger->Debug("Header: X No: {}, A No: {}, B No: {}, W No: {}, C No: {}, Raw Size: {}", u8(header->Xno), u8(header->Ano), u8(header->Bno), u8(header->Wno), u8(vecBufC.size()), u64(cmdArgSz)); + state.logger->Debug("Header: Input No: {}, Output No: {}, Raw Size: {}", inputBuf.size(), outputBuf.size(), u64(cmdArgSz)); if (header->handleDesc) state.logger->Debug("Handle Descriptor: Send PID: {}, Copy Count: {}, Move Count: {}", bool(handleDesc->sendPid), u32(handleDesc->copyCount), u32(handleDesc->moveCount)); if (isDomain) @@ -117,7 +132,7 @@ namespace skyline::kernel::ipc { IpcResponse::IpcResponse(bool isDomain, const DeviceState &state) : isDomain(isDomain), state(state) {} - void IpcResponse::WriteTls() { + void IpcResponse::WriteResponse() { std::array tls{}; u8 *currPtr = tls.data(); auto header = reinterpret_cast(currPtr); diff --git a/app/src/main/cpp/skyline/kernel/ipc.h b/app/src/main/cpp/skyline/kernel/ipc.h index db04bcb5..cbcb6081 100644 --- a/app/src/main/cpp/skyline/kernel/ipc.h +++ b/app/src/main/cpp/skyline/kernel/ipc.h @@ -168,12 +168,70 @@ namespace skyline::kernel::ipc { }; static_assert(sizeof(BufferDescriptorC) == 8); + /** + * @brief This enumerates the types of IPC buffers + */ + enum class IpcBufferType { + X, //!< This is a type-X buffer + A, //!< This is a type-A buffer + B, //!< This is a type-B buffer + W, //!< This is a type-W buffer + C //!< This is a type-C buffer + }; + + /** + * @brief Describes a buffer by holding the address and size + */ + struct IpcBuffer { + u64 address; //!< The address of the buffer + size_t size; //!< The size of the buffer + IpcBufferType type; //!< The type of the buffer + + /** + * @param address The address of the buffer + * @param size The size of the buffer + * @param type The type of the buffer + */ + IpcBuffer(u64 address, size_t size, IpcBufferType type); + }; + + /** + * @brief This holds an input IPC buffer + */ + struct InputBuffer : public IpcBuffer { + /** + * @param aBuf The X Buffer Descriptor that has contains the input data + */ + InputBuffer(kernel::ipc::BufferDescriptorX *xBuf); + + /** + * @param aBuf The A or W Buffer Descriptor that has contains the input data + */ + InputBuffer(kernel::ipc::BufferDescriptorABW *aBuf, IpcBufferType type = IpcBufferType::A); + }; + + /** + * @brief This holds an output IPC buffer + */ + struct OutputBuffer : public IpcBuffer { + /** + * @param bBuf The B or W Buffer Descriptor that has to be outputted to + */ + OutputBuffer(kernel::ipc::BufferDescriptorABW *bBuf, IpcBufferType type = IpcBufferType::B); + + /** + * @param cBuf The C Buffer Descriptor that has to be outputted to + */ + OutputBuffer(kernel::ipc::BufferDescriptorC *cBuf); + }; + /** * @brief This class encapsulates an IPC Request (https://switchbrew.org/wiki/IPC_Marshalling) */ class IpcRequest { private: const DeviceState &state; //!< The state of the device + u8 *payloadOffset; //!< This is the offset of the data read from the payload public: std::array tls; //!< A static-sized array where TLS data is actually copied to @@ -187,17 +245,34 @@ namespace skyline::kernel::ipc { std::vector copyHandles; //!< A vector of handles that should be copied from the server to the client process (The difference is just to match application expectations, there is no real difference b/w copying and moving handles) std::vector moveHandles; //!< A vector of handles that should be moved from the server to the client process rather than copied std::vector domainObjects; //!< A vector of all input domain objects - std::vector vecBufX; //!< This is a vector of pointers to X Buffer Descriptors - std::vector vecBufA; //!< This is a vector of pointers to A Buffer Descriptors - std::vector vecBufB; //!< This is a vector of pointers to B Buffer Descriptors - std::vector vecBufW; //!< This is a vector of pointers to W Buffer Descriptors - std::vector vecBufC; //!< This is a vector of pointers to C Buffer Descriptors + std::vector inputBuf; //!< This is a vector of input buffers + std::vector outputBuf; //!< This is a vector of output buffers /** * @param isDomain If the following request is a domain request * @param state The state of the device */ IpcRequest(bool isDomain, const DeviceState &state); + + /** + * @brief This returns a reference to an item from the top of the payload + * @tparam ValueType The type of the object to read + */ + template + inline ValueType& Pop() { + ValueType& value = *reinterpret_cast(payloadOffset); + payloadOffset += sizeof(ValueType); + return value; + } + + /** + * @brief This skips an object to pop off the top + * @tparam ValueType The type of the object to skip + */ + template + inline void Skip() { + payloadOffset += sizeof(ValueType); + } }; /** @@ -225,10 +300,10 @@ namespace skyline::kernel::ipc { /** * @brief Writes an object to the payload * @tparam ValueType The type of the object to write - * @param value The object to be written + * @param value A reference to the object to be written */ template - void WriteValue(const ValueType &value) { + inline void Push(const ValueType &value) { argVec.reserve(argVec.size() + sizeof(ValueType)); auto item = reinterpret_cast(&value); for (uint index = 0; sizeof(ValueType) > index; index++) { @@ -240,6 +315,6 @@ namespace skyline::kernel::ipc { /** * @brief Writes this IpcResponse object's contents into TLS */ - void WriteTls(); + void WriteResponse(); }; } diff --git a/app/src/main/cpp/skyline/kernel/svc.cpp b/app/src/main/cpp/skyline/kernel/svc.cpp index a66510ba..16072814 100644 --- a/app/src/main/cpp/skyline/kernel/svc.cpp +++ b/app/src/main/cpp/skyline/kernel/svc.cpp @@ -460,6 +460,8 @@ namespace skyline::kernel::svc { void OutputDebugString(DeviceState &state) { std::string debug(state.nce->GetRegister(Xreg::X1), '\0'); state.os->thisProcess->ReadMemory(debug.data(), state.nce->GetRegister(Xreg::X0), state.nce->GetRegister(Xreg::X1)); + if(debug.back() == '\n') + debug.pop_back(); state.logger->Info("Debug Output: {}", debug); state.nce->SetRegister(Wreg::W0, constant::status::Success); } diff --git a/app/src/main/cpp/skyline/kernel/types/KTransferMemory.cpp b/app/src/main/cpp/skyline/kernel/types/KTransferMemory.cpp index c284217d..d2437c4c 100644 --- a/app/src/main/cpp/skyline/kernel/types/KTransferMemory.cpp +++ b/app/src/main/cpp/skyline/kernel/types/KTransferMemory.cpp @@ -2,9 +2,6 @@ #include #include -constexpr const char *ASHMEM_NAME_DEF = "dev/ashmem"; -constexpr int ASHMEM_SET_SIZE = 0x40087703; - namespace skyline::kernel::type { u64 MapTransferFunc(u64 address, size_t size, u64 perms) { return reinterpret_cast(mmap(reinterpret_cast(address), size, static_cast(perms), MAP_ANONYMOUS | MAP_PRIVATE | ((address) ? MAP_FIXED : 0), -1, 0)); // NOLINT(hicpp-signed-bitwise) diff --git a/app/src/main/cpp/skyline/services/am/appletController.cpp b/app/src/main/cpp/skyline/services/am/appletController.cpp index 8817f7ff..8a5862d8 100644 --- a/app/src/main/cpp/skyline/services/am/appletController.cpp +++ b/app/src/main/cpp/skyline/services/am/appletController.cpp @@ -30,20 +30,20 @@ namespace skyline::service::am { response.errorCode = constant::status::NoMessages; return; } - response.WriteValue(static_cast(messageQueue.front())); + response.Push(static_cast(messageQueue.front())); messageQueue.pop(); } void ICommonStateGetter::GetCurrentFocusState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { - response.WriteValue(static_cast(focusState)); + response.Push(static_cast(focusState)); } void ICommonStateGetter::GetOperationMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { - response.WriteValue(static_cast(operationMode)); + response.Push(static_cast(operationMode)); } void ICommonStateGetter::GetPerformanceMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { - response.WriteValue(static_cast(operationMode)); + response.Push(static_cast(operationMode)); } void ICommonStateGetter::GetDefaultDisplayResolution(type::KSession& session, ipc::IpcRequest& request, ipc::IpcResponse& response) { @@ -77,7 +77,7 @@ namespace skyline::service::am { if (state.gpu->layerStatus == gpu::LayerStatus::Initialized) throw exception("The application is creating more than one layer"); state.gpu->layerStatus = gpu::LayerStatus::Initialized; - response.WriteValue(0); + response.Push(0); } IWindowController::IWindowController(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager, false, Service::am_IWindowController, { @@ -86,7 +86,7 @@ namespace skyline::service::am { }) {} void IWindowController::GetAppletResourceUserId(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { - response.WriteValue(static_cast(state.thisProcess->mainThread)); + response.Push(static_cast(state.thisProcess->mainThread)); } void IWindowController::AcquireForegroundRights(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {} @@ -105,7 +105,7 @@ namespace skyline::service::am { }) {} void IApplicationFunctions::NotifyRunning(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { - response.WriteValue(1); + response.Push(1); } IDebugFunctions::IDebugFunctions(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager, false, Service::am_IDebugFunctions, { diff --git a/app/src/main/cpp/skyline/services/apm/apm.cpp b/app/src/main/cpp/skyline/services/apm/apm.cpp index ee15f6ef..6ea481ac 100644 --- a/app/src/main/cpp/skyline/services/apm/apm.cpp +++ b/app/src/main/cpp/skyline/services/apm/apm.cpp @@ -15,16 +15,14 @@ namespace skyline::service::apm { }) {} void ISession::SetPerformanceConfiguration(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { - struct InputStruct { - u32 mode; - u32 config; - } *performance = reinterpret_cast(request.cmdArg); - performanceConfig[performance->mode] = performance->config; - state.logger->Info("SetPerformanceConfiguration called with 0x{:X} ({})", performance->config, performance->mode ? "Docked" : "Handheld"); + auto mode = request.Pop(); + auto config = request.Pop(); + performanceConfig[mode] = config; + state.logger->Info("SetPerformanceConfiguration called with 0x{:X} ({})", config, mode ? "Docked" : "Handheld"); } void ISession::GetPerformanceConfiguration(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { - u32 performanceMode = *reinterpret_cast(request.cmdArg); - response.WriteValue(performanceConfig[performanceMode]); + u32 performanceMode = request.Pop(); + response.Push(performanceConfig[performanceMode]); } } diff --git a/app/src/main/cpp/skyline/services/hid/hid.cpp b/app/src/main/cpp/skyline/services/hid/hid.cpp index 0553aecd..065aa45d 100644 --- a/app/src/main/cpp/skyline/services/hid/hid.cpp +++ b/app/src/main/cpp/skyline/services/hid/hid.cpp @@ -30,20 +30,16 @@ namespace skyline::service::hid { } void hid::SetSupportedNpadStyleSet(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { - struct InputStruct { - u32 styleSet; - u64 appletUserId; - } *input = reinterpret_cast(request.cmdArg); - styleSet = *reinterpret_cast(&input->styleSet); - state.logger->Debug("Controller Support:\nPro-Controller: {}\nJoy-Con: Handheld: {}, Dual: {}, L: {}, R: {}\nGameCube: {}\nPokeBall: {}\nNES: {}, NES Handheld: {}, SNES: {}", static_cast(styleSet->proController), static_cast(styleSet->joyconHandheld), static_cast(styleSet->joyconDual), static_cast(styleSet->joyconLeft), static_cast - (styleSet->joyconRight), static_cast(styleSet->gamecube), static_cast(styleSet->pokeball), static_cast(styleSet->nes), static_cast(styleSet->nesHandheld), static_cast(styleSet->snes)); + auto styleSet = request.Pop(); + state.logger->Debug("Controller Support:\nPro-Controller: {}\nJoy-Con: Handheld: {}, Dual: {}, L: {}, R: {}\nGameCube: {}\nPokeBall: {}\nNES: {}, NES Handheld: {}, SNES: {}", static_cast(styleSet.proController), static_cast(styleSet.joyconHandheld), static_cast(styleSet.joyconDual), static_cast(styleSet.joyconLeft), static_cast + (styleSet.joyconRight), static_cast(styleSet.gamecube), static_cast(styleSet.pokeball), static_cast(styleSet.nes), static_cast(styleSet.nesHandheld), static_cast(styleSet.snes)); } void hid::SetSupportedNpadIdType(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { - const auto &buffer = request.vecBufX[0]; - uint numId = buffer->size / sizeof(NpadId); - u64 address = buffer->Address(); - for (uint i = 0; i < numId; i++) { + const auto &buffer = request.inputBuf.at(0); + size_t numId = buffer.size / sizeof(NpadId); + u64 address = buffer.address; + for (size_t i = 0; i < numId; i++) { auto id = state.thisProcess->ReadMemory(address); deviceMap[id] = JoyConDevice(id); address += sizeof(NpadId); @@ -53,36 +49,21 @@ namespace skyline::service::hid { void hid::ActivateNpad(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {} void hid::SetNpadJoyHoldType(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { - struct InputStruct { - NpadId controllerId; - u64 appletUserId; - } *input = reinterpret_cast(request.cmdArg); - deviceMap[input->controllerId].assignment = JoyConAssignment::Single; + deviceMap[request.Pop()].assignment = JoyConAssignment::Single; } void hid::SetNpadJoyAssignmentModeSingleByDefault(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { - struct InputStruct { - u64 appletUserId; - JoyConOrientation orientation; - } *input = reinterpret_cast(request.cmdArg); - orientation = input->orientation; + orientation = request.Pop(); } void hid::SetNpadJoyAssignmentModeSingle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { - struct InputStruct { - NpadId controllerId; - u64 appletUserId; - JoyConSide joyDeviceType; - } *input = reinterpret_cast(request.cmdArg); - deviceMap[input->controllerId].assignment = JoyConAssignment::Single; - deviceMap[input->controllerId].side = input->joyDeviceType; + auto controllerId = request.Pop(); + auto appletUserId = request.Pop(); + deviceMap[controllerId].assignment = JoyConAssignment::Single; + deviceMap[controllerId].side = request.Pop(); } void hid::SetNpadJoyAssignmentModeDual(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { - struct InputStruct { - NpadId controllerType; - u64 appletUserId; - } *input = reinterpret_cast(request.cmdArg); - deviceMap[input->controllerType].assignment = JoyConAssignment::Dual; + deviceMap[request.Pop()].assignment = JoyConAssignment::Dual; } } diff --git a/app/src/main/cpp/skyline/services/nvdrv/nvdrv.cpp b/app/src/main/cpp/skyline/services/nvdrv/nvdrv.cpp index 07f31ffb..176734ee 100644 --- a/app/src/main/cpp/skyline/services/nvdrv/nvdrv.cpp +++ b/app/src/main/cpp/skyline/services/nvdrv/nvdrv.cpp @@ -12,43 +12,39 @@ namespace skyline::service::nvdrv { }) {} void nvdrv::Open(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { - auto aBuf = request.vecBufA[0]; - std::string path(aBuf->Size(), '\0'); - state.thisProcess->ReadMemory(path.data(), aBuf->Address(), aBuf->Size()); - response.WriteValue(state.gpu->OpenDevice(path)); - response.WriteValue(constant::status::Success); + auto buffer = request.inputBuf.at(0); + std::string path(buffer.size, '\0'); + state.thisProcess->ReadMemory(path.data(), buffer.address, buffer.size); + response.Push(state.gpu->OpenDevice(path)); + response.Push(constant::status::Success); } void nvdrv::Ioctl(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { - struct InputStruct { - u32 fd; - u32 cmd; - } *input = reinterpret_cast(request.cmdArg); - state.gpu->Ioctl(input->fd, input->cmd, request, response); + auto fd = request.Pop(); + auto cmd = request.Pop(); + state.gpu->Ioctl(fd, cmd, request, response); } void nvdrv::Close(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { u32 fd = *reinterpret_cast(request.cmdArg); state.gpu->CloseDevice(fd); - response.WriteValue(constant::status::Success); + response.Push(constant::status::Success); } void nvdrv::Initialize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { - response.WriteValue(constant::status::Success); + response.Push(constant::status::Success); } void nvdrv::QueryEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { - struct InputStruct { - u32 fd; - u32 eventId; - } *input = reinterpret_cast(request.cmdArg); + auto fd = request.Pop(); + auto eventId = request.Pop(); auto event = std::make_shared(state); auto handle = state.thisProcess->InsertItem(event); - state.logger->Debug("QueryEvent: FD: {}, Event ID: {}, Handle: {}", input->fd, input->eventId, handle); + state.logger->Debug("QueryEvent: FD: {}, Event ID: {}, Handle: {}", fd, eventId, handle); response.copyHandles.push_back(handle); } void nvdrv::SetAruidByPID(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { - response.WriteValue(constant::status::Success); + response.Push(constant::status::Success); } } diff --git a/app/src/main/cpp/skyline/services/nvnflinger/dispdrv.cpp b/app/src/main/cpp/skyline/services/nvnflinger/dispdrv.cpp index ec5c75dc..b7a98fd8 100644 --- a/app/src/main/cpp/skyline/services/nvnflinger/dispdrv.cpp +++ b/app/src/main/cpp/skyline/services/nvnflinger/dispdrv.cpp @@ -11,36 +11,25 @@ namespace skyline::service::nvnflinger { }) {} void dispdrv::TransactParcel(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { - struct InputStruct { - u32 layerId; - TransactionCode code; - } *input = reinterpret_cast(request.cmdArg); - std::shared_ptr in{}; - if (request.vecBufA.empty()) - in = std::make_shared(request.vecBufX[0], state); - else - in = std::make_shared(request.vecBufA[0], state); + auto layerId = request.Pop(); + auto code = request.Pop(); + gpu::Parcel in(request.inputBuf.at(0), state); gpu::Parcel out(state); - state.logger->Debug("TransactParcel: Layer ID: {}, Code: {}", input->layerId, input->code); - switch (input->code) { + state.logger->Debug("TransactParcel: Layer ID: {}, Code: {}", layerId, code); + switch (code) { case TransactionCode::RequestBuffer: - state.gpu->bufferQueue.RequestBuffer(*in, out); + state.gpu->bufferQueue.RequestBuffer(in, out); break; case TransactionCode::DequeueBuffer: { - if (request.vecBufA.empty()) { - if (state.gpu->bufferQueue.DequeueBuffer(*in, out, request.vecBufC[0]->address, request.vecBufC[0]->size)) - return; - } else { - if (state.gpu->bufferQueue.DequeueBuffer(*in, out, request.vecBufB[0]->Address(), request.vecBufB[0]->Size())) - return; - } + if (state.gpu->bufferQueue.DequeueBuffer(in, out, request.outputBuf.at(0))) + return; break; } case TransactionCode::QueueBuffer: - state.gpu->bufferQueue.QueueBuffer(*in, out); + state.gpu->bufferQueue.QueueBuffer(in, out); break; case TransactionCode::CancelBuffer: - state.gpu->bufferQueue.CancelBuffer(*in); + state.gpu->bufferQueue.CancelBuffer(in); break; case TransactionCode::Query: out.WriteData(0); @@ -59,30 +48,25 @@ namespace skyline::service::nvnflinger { case TransactionCode::Disconnect: break; case TransactionCode::SetPreallocatedBuffer: - state.gpu->bufferQueue.SetPreallocatedBuffer(*in); + state.gpu->bufferQueue.SetPreallocatedBuffer(in); break; default: - throw exception("An unimplemented transaction was called: {}", static_cast(input->code)); + throw exception("An unimplemented transaction was called: {}", static_cast(code)); } - if (request.vecBufA.empty()) - out.WriteParcel(request.vecBufC[0]); - else - out.WriteParcel(request.vecBufB[0]); + out.WriteParcel(request.outputBuf.at(0)); + } + + void dispdrv::AdjustRefcount(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { + request.Skip(); + auto addVal = request.Pop(); + auto type = request.Pop(); + state.logger->Debug("Reference Change: {} {} reference", addVal, type ? "strong" : "weak"); } void dispdrv::GetNativeHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { handle_t handle = state.thisProcess->InsertItem(state.gpu->bufferEvent); state.logger->Debug("BufferEvent Handle: 0x{:X}", handle); response.copyHandles.push_back(handle); - response.WriteValue(constant::status::Success); - } - - void dispdrv::AdjustRefcount(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { - struct InputStruct { - u32 layerId; - i32 addVal; - i32 type; - } *input = reinterpret_cast(request.cmdArg); - state.logger->Debug("Reference Change: {} {} reference", input->addVal, input->type ? "strong" : "weak"); + response.Push(constant::status::Success); } } diff --git a/app/src/main/cpp/skyline/services/nvnflinger/dispdrv.h b/app/src/main/cpp/skyline/services/nvnflinger/dispdrv.h index 081843a8..098f0c1e 100644 --- a/app/src/main/cpp/skyline/services/nvnflinger/dispdrv.h +++ b/app/src/main/cpp/skyline/services/nvnflinger/dispdrv.h @@ -50,14 +50,14 @@ namespace skyline::service::nvnflinger { */ void TransactParcel(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); - /** - * @brief This adjusts the reference counts to the underlying binder, it is stubbed as we aren't using the real symbols (https://switchbrew.org/wiki/Nvnflinger_services#GetNativeHandle) - */ - void GetNativeHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); - /** * @brief This adjusts the reference counts to the underlying binder, it is stubbed as we aren't using the real symbols (https://switchbrew.org/wiki/Nvnflinger_services#AdjustRefcount) */ void AdjustRefcount(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); + + /** + * @brief This adjusts the reference counts to the underlying binder, it is stubbed as we aren't using the real symbols (https://switchbrew.org/wiki/Nvnflinger_services#GetNativeHandle) + */ + void GetNativeHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); }; } diff --git a/app/src/main/cpp/skyline/services/serviceman.cpp b/app/src/main/cpp/skyline/services/serviceman.cpp index c3a28ee4..dc864f7f 100644 --- a/app/src/main/cpp/skyline/services/serviceman.cpp +++ b/app/src/main/cpp/skyline/services/serviceman.cpp @@ -199,7 +199,7 @@ namespace skyline::service { } else session->serviceObject->HandleRequest(*session, request, response); if (!response.nWrite) - response.WriteTls(); + response.WriteResponse(); break; case ipc::CommandType::Control: @@ -207,19 +207,19 @@ namespace skyline::service { state.logger->Debug("Control IPC Message: 0x{:X}", request.payload->value); switch (static_cast(request.payload->value)) { case ipc::ControlCommand::ConvertCurrentObjectToDomain: - response.WriteValue(session->ConvertDomain()); + response.Push(session->ConvertDomain()); break; case ipc::ControlCommand::CloneCurrentObject: case ipc::ControlCommand::CloneCurrentObjectEx: - response.WriteValue(state.thisProcess->InsertItem(session)); + response.Push(state.thisProcess->InsertItem(session)); break; case ipc::ControlCommand::QueryPointerBufferSize: - response.WriteValue(0x1000); + response.Push(0x1000); break; default: throw exception("Unknown Control Command: {}", request.payload->value); } - response.WriteTls(); + response.WriteResponse(); break; case ipc::CommandType::Close: diff --git a/app/src/main/cpp/skyline/services/set/sys.cpp b/app/src/main/cpp/skyline/services/set/sys.cpp index 6e3c0020..84aea751 100644 --- a/app/src/main/cpp/skyline/services/set/sys.cpp +++ b/app/src/main/cpp/skyline/services/set/sys.cpp @@ -6,6 +6,6 @@ namespace skyline::service::set { void sys::GetFirmwareVersion(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { SysVerTitle title{.minor=9, .major=0, .micro=0, .revMajor=4, .platform="NX", .verHash="4de65c071fd0869695b7629f75eb97b2551dbf2f", .dispVer="9.0.0", .dispTitle="NintendoSDK Firmware for NX 9.0.0-4.0"}; - state.thisProcess->WriteMemory(title, request.vecBufC[0]->address); + state.thisProcess->WriteMemory(title, request.outputBuf.at(0).address); } } diff --git a/app/src/main/cpp/skyline/services/time/time.cpp b/app/src/main/cpp/skyline/services/time/time.cpp index 2e77ace0..37b15e39 100644 --- a/app/src/main/cpp/skyline/services/time/time.cpp +++ b/app/src/main/cpp/skyline/services/time/time.cpp @@ -29,7 +29,7 @@ namespace skyline::service::time { }) {} void ISystemClock::GetCurrentTime(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { - response.WriteValue(static_cast(std::time(nullptr))); + response.Push(static_cast(std::time(nullptr))); } ITimeZoneService::ITimeZoneService(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager, false, Service::time_ITimeZoneService, { @@ -46,7 +46,7 @@ namespace skyline::service::time { .minute = static_cast(calender.tm_min), .second = static_cast(calender.tm_sec) }; - response.WriteValue(calendarTime); + response.Push(calendarTime); CalendarAdditionalInfo calendarInfo{ .day_week = static_cast(calender.tm_wday), .day_month = static_cast(calender.tm_mday), @@ -54,6 +54,6 @@ namespace skyline::service::time { .dst = static_cast(calender.tm_isdst), .utc_rel = static_cast(calender.tm_gmtoff) }; - response.WriteValue(calendarInfo); + response.Push(calendarInfo); } } diff --git a/app/src/main/cpp/skyline/services/vi/vi_m.cpp b/app/src/main/cpp/skyline/services/vi/vi_m.cpp index 574dbc43..3a55945d 100644 --- a/app/src/main/cpp/skyline/services/vi/vi_m.cpp +++ b/app/src/main/cpp/skyline/services/vi/vi_m.cpp @@ -16,7 +16,7 @@ namespace skyline::service::vi { void IDisplayService::CreateStrayLayer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { state.logger->Debug("Creating Stray Layer"); - response.WriteValue(0); // There's only one layer + response.Push(0); // There's only one layer gpu::Parcel parcel(state); LayerParcel data{ .type = 0x20, @@ -25,7 +25,7 @@ namespace skyline::service::vi { .string = "dispdrv" }; parcel.WriteData(data); - response.WriteValue(parcel.WriteParcel(request.vecBufB[0])); + response.Push(parcel.WriteParcel(request.outputBuf.at(0))); } IApplicationDisplayService::IApplicationDisplayService(const DeviceState &state, ServiceManager &manager) : IDisplayService(state, manager, Service::vi_IApplicationDisplayService, { @@ -61,7 +61,7 @@ namespace skyline::service::vi { std::string displayName(reinterpret_cast(request.cmdArg)); state.logger->Debug("Setting display as: {}", displayName); state.gpu->SetDisplay(displayName); - response.WriteValue(0); // There's only one display + response.Push(0); // There's only one display } void IApplicationDisplayService::CloseDisplay(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { @@ -74,9 +74,9 @@ namespace skyline::service::vi { char displayName[0x40]; u64 layerId; u64 userId; - } *input = reinterpret_cast(request.cmdArg); - state.logger->Debug("Opening Layer: Display Name: {}, Layer ID: {}, User ID: {}", input->displayName, input->layerId, input->userId); - std::string name(input->displayName); + } input = request.Pop(); + state.logger->Debug("Opening Layer: Display Name: {}, Layer ID: {}, User ID: {}", input.displayName, input.layerId, input.userId); + std::string name(input.displayName); gpu::Parcel parcel(state); LayerParcel data{ .type = 0x20, @@ -86,24 +86,22 @@ namespace skyline::service::vi { }; parcel.WriteData(data); parcel.objects.resize(4); - response.WriteValue(parcel.WriteParcel(request.vecBufB[0])); + response.Push(parcel.WriteParcel(request.outputBuf.at(0))); } void IApplicationDisplayService::CloseLayer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { - u64 layerId = *reinterpret_cast(request.cmdArg); + u64 layerId = request.Pop(); state.logger->Debug("Closing Layer: {}", layerId); if (state.gpu->layerStatus == gpu::LayerStatus::Uninitialized) state.logger->Warn("The application is destroying an uninitialized layer"); state.gpu->layerStatus = gpu::LayerStatus::Uninitialized; - response.WriteValue(constant::status::Success); + response.Push(constant::status::Success); } void IApplicationDisplayService::SetLayerScalingMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { - struct InputStruct { - u64 scalingMode; - u64 layerId; - } *input = reinterpret_cast(request.cmdArg); - state.logger->Debug("Setting Layer Scaling mode to '{}' for layer {}", input->scalingMode, input->layerId); + auto scalingMode = request.Pop(); + auto layerId = request.Pop(); + state.logger->Debug("Setting Layer Scaling mode to '{}' for layer {}", scalingMode, layerId); } void IApplicationDisplayService::GetDisplayVsyncEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { @@ -118,7 +116,7 @@ namespace skyline::service::vi { }) {} void ISystemDisplayService::SetLayerZ(skyline::kernel::type::KSession &session, skyline::kernel::ipc::IpcRequest &request, skyline::kernel::ipc::IpcResponse &response) { - response.WriteValue(constant::status::Success); + response.Push(constant::status::Success); } IManagerDisplayService::IManagerDisplayService(const DeviceState &state, ServiceManager &manager) : IDisplayService(state, manager, Service::vi_IManagerDisplayService, { @@ -129,16 +127,13 @@ namespace skyline::service::vi { }) {} void IManagerDisplayService::CreateManagedLayer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { - struct InputStruct { - u32 _unk0_; - u64 displayId; - u64 userId; - } *input = reinterpret_cast(request.cmdArg); - state.logger->Debug("Creating Managed Layer: {}", input->displayId); + request.Skip(); + u64 displayId = request.Pop(); + state.logger->Debug("Creating Managed Layer: {}", displayId); if (state.gpu->layerStatus == gpu::LayerStatus::Initialized) throw exception("The application is creating more than one layer"); state.gpu->layerStatus = gpu::LayerStatus::Initialized; - response.WriteValue(0); // There's only one layer + response.Push(0); // There's only one layer } void IManagerDisplayService::DestroyManagedLayer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { @@ -146,10 +141,10 @@ namespace skyline::service::vi { if (state.gpu->layerStatus == gpu::LayerStatus::Uninitialized) state.logger->Warn("The application is destroying an uninitialized layer"); state.gpu->layerStatus = gpu::LayerStatus::Uninitialized; - response.WriteValue(constant::status::Success); + response.Push(constant::status::Success); } void IManagerDisplayService::AddToLayerStack(skyline::kernel::type::KSession &session, skyline::kernel::ipc::IpcRequest &request, skyline::kernel::ipc::IpcResponse &response) { - response.WriteValue(constant::status::Success); + response.Push(constant::status::Success); } }