From 812000281689cff87e95458734b917365a20074a Mon Sep 17 00:00:00 2001 From: DH Date: Thu, 26 Sep 2024 23:56:49 +0300 Subject: [PATCH] ipmi: allow pass more than single buffer to fake client invoke --- rpcsx-os/main.cpp | 110 ++++++++++++++++++++++++++++++---------------- 1 file changed, 73 insertions(+), 37 deletions(-) diff --git a/rpcsx-os/main.cpp b/rpcsx-os/main.cpp index e3269b08a..4ea0461dd 100644 --- a/rpcsx-os/main.cpp +++ b/rpcsx-os/main.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -1613,9 +1614,13 @@ template struct GuestAlloc { orbis::ptr guestAddress; GuestAlloc(std::size_t size) { - guestAddress = orbis::ptr(rx::vm::map( - nullptr, size, rx::vm::kMapProtCpuRead | rx::vm::kMapProtCpuWrite, - rx::vm::kMapFlagPrivate | rx::vm::kMapFlagAnonymous)); + if (size == 0) { + guestAddress = nullptr; + } else { + guestAddress = orbis::ptr(rx::vm::map( + nullptr, size, rx::vm::kMapProtCpuRead | rx::vm::kMapProtCpuWrite, + rx::vm::kMapFlagPrivate | rx::vm::kMapFlagAnonymous)); + } } GuestAlloc() : GuestAlloc(sizeof(T)) {} @@ -1632,7 +1637,20 @@ template struct GuestAlloc { } } - ~GuestAlloc() { rx::vm::unmap(guestAddress, sizeof(T)); } + GuestAlloc(const GuestAlloc &) = delete; + + GuestAlloc(GuestAlloc &&other) : guestAddress(other.guestAddress) { + other.guestAddress = 0; + } + GuestAlloc &operator=(GuestAlloc &&other) { + std::swap(guestAddress, other.guestAddress); + } + + ~GuestAlloc() { + if (guestAddress != 0) { + rx::vm::unmap(guestAddress, sizeof(T)); + } + } operator orbis::ptr() { return guestAddress; } T *operator->() { return guestAddress; } @@ -1644,28 +1662,41 @@ struct IpmiClient { orbis::uint kid; orbis::Thread *thread; - orbis::sint sendSyncMessage(std::uint32_t method, const void *data, - std::size_t size, - std::vector &outData) { + orbis::sint + sendSyncMessageRaw(std::uint32_t method, + const std::vector> &inData, + std::vector> &outBuf) { GuestAlloc serverResult; - GuestAlloc outBufferInfo = orbis::IpmiBufferInfo{ - .data = outData.data(), - .capacity = outData.size(), - }; + GuestAlloc guestInDataArray{ + sizeof(orbis::IpmiDataInfo) * inData.size()}; + GuestAlloc guestOutBufArray{ + sizeof(orbis::IpmiBufferInfo) * outBuf.size()}; - auto guestData = GuestAlloc{data, size}; + std::vector> guestAllocs; + guestAllocs.reserve(inData.size() + outBuf.size()); - GuestAlloc inDataInfo = orbis::IpmiDataInfo{ - .data = guestData, - .size = size, - }; + for (auto &data : inData) { + auto pointer = + guestAllocs.emplace_back(data.data(), data.size()).guestAddress; + + guestInDataArray.guestAddress[&data - inData.data()] = { + .data = pointer, .size = data.size()}; + } + + for (auto &buf : outBuf) { + auto pointer = + guestAllocs.emplace_back(buf.data(), buf.size()).guestAddress; + + guestOutBufArray.guestAddress[&buf - outBuf.data()] = { + .data = pointer, .capacity = buf.size()}; + } GuestAlloc params = orbis::IpmiSyncCallParams{ .method = method, - .numInData = 1, - .numOutData = 1, - .pInData = inDataInfo, - .pOutData = outBufferInfo, + .numInData = static_cast(inData.size()), + .numOutData = static_cast(outBuf.size()), + .pInData = guestInDataArray, + .pOutData = guestOutBufArray, .pResult = serverResult, }; @@ -1673,29 +1704,34 @@ struct IpmiClient { orbis::sysIpmiClientInvokeSyncMethod(thread, errorCode, kid, params, sizeof(orbis::IpmiSyncCallParams)); - outData.resize(outBufferInfo->size); + for (auto &buf : outBuf) { + auto size = guestOutBufArray.guestAddress[inData.data() - &buf].size; + buf.resize(size); + } return serverResult; } - template - orbis::sint sendSyncMessage(std::uint32_t method, const T &data, - std::vector &outData) { - return sendSyncMessage(method, &data, sizeof(data), outData); + template + orbis::sint sendSyncMessage(std::uint32_t method, + const InputTypes &...input) { + std::vector> outBuf; + return sendSyncMessageRaw(method, {toBytes(input)...}, outBuf); } - template - orbis::sint sendSyncMessage(std::uint32_t method, const T &data) { - std::vector outData; - return sendSyncMessage(method, &data, sizeof(data), outData); - } + template + requires((sizeof...(OutputTypes) > 0) || sizeof...(InputTypes) == 0) + std::tuple sendSyncMessage(std::uint32_t method, + InputTypes... input) { + std::vector> outBuf{sizeof(OutputTypes)...}; + sendSyncMessageRaw(method, {toBytes(input)...}, outBuf); + std::tuple output; - template - std::vector sendSyncMessage(std::uint32_t method, const T &data, - std::size_t outputCapacity) { - std::vector outData; - outData.resize(outputCapacity); - sendSyncMessage(method, &data, sizeof(data), outData); - return outData; + auto unpack = [&](std::index_sequence) { + ((std::get(output) = *reinterpret_cast(outBuf.data())), + ...); + }; + unpack(std::make_index_sequence{}); + return output; } };