mirror of
https://git.suyu.dev/suyu/suyu.git
synced 2024-11-15 22:54:00 +00:00
Merge pull request #12798 from liamwhite/cmif-fixes
cmif_serialization: fixes
This commit is contained in:
commit
bc22b4e782
4 changed files with 129 additions and 71 deletions
|
@ -97,20 +97,20 @@ constexpr RequestLayout GetDomainReplyOutLayout() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool Domain, typename MethodArguments>
|
template <typename MethodArguments>
|
||||||
constexpr RequestLayout GetReplyInLayout() {
|
constexpr RequestLayout GetReplyInLayout(bool is_domain) {
|
||||||
return Domain ? GetDomainReplyInLayout<MethodArguments>() : GetNonDomainReplyInLayout<MethodArguments>();
|
return is_domain ? GetDomainReplyInLayout<MethodArguments>() : GetNonDomainReplyInLayout<MethodArguments>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool Domain, typename MethodArguments>
|
template <typename MethodArguments>
|
||||||
constexpr RequestLayout GetReplyOutLayout() {
|
constexpr RequestLayout GetReplyOutLayout(bool is_domain) {
|
||||||
return Domain ? GetDomainReplyOutLayout<MethodArguments>() : GetNonDomainReplyOutLayout<MethodArguments>();
|
return is_domain ? GetDomainReplyOutLayout<MethodArguments>() : GetNonDomainReplyOutLayout<MethodArguments>();
|
||||||
}
|
}
|
||||||
|
|
||||||
using OutTemporaryBuffers = std::array<Common::ScratchBuffer<u8>, 3>;
|
using OutTemporaryBuffers = std::array<Common::ScratchBuffer<u8>, 3>;
|
||||||
|
|
||||||
template <bool Domain, typename MethodArguments, typename CallArguments, size_t PrevAlign = 1, size_t DataOffset = 0, size_t HandleIndex = 0, size_t InBufferIndex = 0, size_t OutBufferIndex = 0, bool RawDataFinished = false, size_t ArgIndex = 0>
|
template <typename MethodArguments, typename CallArguments, size_t PrevAlign = 1, size_t DataOffset = 0, size_t HandleIndex = 0, size_t InBufferIndex = 0, size_t OutBufferIndex = 0, bool RawDataFinished = false, size_t ArgIndex = 0>
|
||||||
void ReadInArgument(CallArguments& args, const u8* raw_data, HLERequestContext& ctx, OutTemporaryBuffers& temp) {
|
void ReadInArgument(bool is_domain, CallArguments& args, const u8* raw_data, HLERequestContext& ctx, OutTemporaryBuffers& temp) {
|
||||||
if constexpr (ArgIndex >= std::tuple_size_v<CallArguments>) {
|
if constexpr (ArgIndex >= std::tuple_size_v<CallArguments>) {
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
@ -134,25 +134,25 @@ void ReadInArgument(CallArguments& args, const u8* raw_data, HLERequestContext&
|
||||||
std::memcpy(&std::get<ArgIndex>(args), raw_data + ArgOffset, ArgSize);
|
std::memcpy(&std::get<ArgIndex>(args), raw_data + ArgOffset, ArgSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ReadInArgument<Domain, MethodArguments, CallArguments, ArgAlign, ArgEnd, HandleIndex, InBufferIndex, OutBufferIndex, false, ArgIndex + 1>(args, raw_data, ctx, temp);
|
return ReadInArgument<MethodArguments, CallArguments, ArgAlign, ArgEnd, HandleIndex, InBufferIndex, OutBufferIndex, false, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
||||||
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::InInterface) {
|
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::InInterface) {
|
||||||
constexpr size_t ArgAlign = alignof(u32);
|
constexpr size_t ArgAlign = alignof(u32);
|
||||||
constexpr size_t ArgSize = sizeof(u32);
|
constexpr size_t ArgSize = sizeof(u32);
|
||||||
constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign);
|
constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign);
|
||||||
constexpr size_t ArgEnd = ArgOffset + ArgSize;
|
constexpr size_t ArgEnd = ArgOffset + ArgSize;
|
||||||
|
|
||||||
static_assert(Domain);
|
ASSERT(is_domain);
|
||||||
ASSERT(ctx.GetDomainMessageHeader().input_object_count > 0);
|
ASSERT(ctx.GetDomainMessageHeader().input_object_count > 0);
|
||||||
|
|
||||||
u32 value{};
|
u32 value{};
|
||||||
std::memcpy(&value, raw_data + ArgOffset, ArgSize);
|
std::memcpy(&value, raw_data + ArgOffset, ArgSize);
|
||||||
std::get<ArgIndex>(args) = ctx.GetDomainHandler<ArgType::Type>(value - 1);
|
std::get<ArgIndex>(args) = ctx.GetDomainHandler<ArgType::Type>(value - 1);
|
||||||
|
|
||||||
return ReadInArgument<Domain, MethodArguments, CallArguments, ArgAlign, ArgEnd, HandleIndex, InBufferIndex, OutBufferIndex, true, ArgIndex + 1>(args, raw_data, ctx, temp);
|
return ReadInArgument<MethodArguments, CallArguments, ArgAlign, ArgEnd, HandleIndex, InBufferIndex, OutBufferIndex, true, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
||||||
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::InCopyHandle) {
|
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::InCopyHandle) {
|
||||||
std::get<ArgIndex>(args) = std::move(ctx.GetObjectFromHandle<typename ArgType::Type>(ctx.GetCopyHandle(HandleIndex)));
|
std::get<ArgIndex>(args) = ctx.GetObjectFromHandle<typename ArgType::Type>(ctx.GetCopyHandle(HandleIndex)).GetPointerUnsafe();
|
||||||
|
|
||||||
return ReadInArgument<Domain, MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex + 1, InBufferIndex, OutBufferIndex, RawDataFinished, ArgIndex + 1>(args, raw_data, ctx, temp);
|
return ReadInArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex + 1, InBufferIndex, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
||||||
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::InLargeData) {
|
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::InLargeData) {
|
||||||
constexpr size_t BufferSize = sizeof(ArgType);
|
constexpr size_t BufferSize = sizeof(ArgType);
|
||||||
|
|
||||||
|
@ -172,7 +172,7 @@ void ReadInArgument(CallArguments& args, const u8* raw_data, HLERequestContext&
|
||||||
|
|
||||||
std::memcpy(&std::get<ArgIndex>(args), buffer.data(), std::min(BufferSize, buffer.size()));
|
std::memcpy(&std::get<ArgIndex>(args), buffer.data(), std::min(BufferSize, buffer.size()));
|
||||||
|
|
||||||
return ReadInArgument<Domain, MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex, InBufferIndex + 1, OutBufferIndex, RawDataFinished, ArgIndex + 1>(args, raw_data, ctx, temp);
|
return ReadInArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex, InBufferIndex + 1, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
||||||
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::InBuffer) {
|
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::InBuffer) {
|
||||||
using ElementType = typename ArgType::Type;
|
using ElementType = typename ArgType::Type;
|
||||||
|
|
||||||
|
@ -193,14 +193,14 @@ void ReadInArgument(CallArguments& args, const u8* raw_data, HLERequestContext&
|
||||||
|
|
||||||
std::get<ArgIndex>(args) = std::span(ptr, size);
|
std::get<ArgIndex>(args) = std::span(ptr, size);
|
||||||
|
|
||||||
return ReadInArgument<Domain, MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex, InBufferIndex + 1, OutBufferIndex, RawDataFinished, ArgIndex + 1>(args, raw_data, ctx, temp);
|
return ReadInArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex, InBufferIndex + 1, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
||||||
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutLargeData) {
|
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutLargeData) {
|
||||||
constexpr size_t BufferSize = sizeof(ArgType);
|
constexpr size_t BufferSize = sizeof(ArgType);
|
||||||
|
|
||||||
// Clear the existing data.
|
// Clear the existing data.
|
||||||
std::memset(&std::get<ArgIndex>(args), 0, BufferSize);
|
std::memset(&std::get<ArgIndex>(args), 0, BufferSize);
|
||||||
|
|
||||||
return ReadInArgument<Domain, MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex, InBufferIndex, OutBufferIndex + 1, RawDataFinished, ArgIndex + 1>(args, raw_data, ctx, temp);
|
return ReadInArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex, InBufferIndex, OutBufferIndex + 1, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
||||||
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutBuffer) {
|
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutBuffer) {
|
||||||
using ElementType = typename ArgType::Type;
|
using ElementType = typename ArgType::Type;
|
||||||
|
|
||||||
|
@ -217,15 +217,15 @@ void ReadInArgument(CallArguments& args, const u8* raw_data, HLERequestContext&
|
||||||
|
|
||||||
std::get<ArgIndex>(args) = std::span(ptr, size);
|
std::get<ArgIndex>(args) = std::span(ptr, size);
|
||||||
|
|
||||||
return ReadInArgument<Domain, MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex, InBufferIndex, OutBufferIndex + 1, RawDataFinished, ArgIndex + 1>(args, raw_data, ctx, temp);
|
return ReadInArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex, InBufferIndex, OutBufferIndex + 1, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
||||||
} else {
|
} else {
|
||||||
return ReadInArgument<Domain, MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex, InBufferIndex, OutBufferIndex, RawDataFinished, ArgIndex + 1>(args, raw_data, ctx, temp);
|
return ReadInArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex, InBufferIndex, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool Domain, typename MethodArguments, typename CallArguments, size_t PrevAlign = 1, size_t DataOffset = 0, size_t OutBufferIndex = 0, bool RawDataFinished = false, size_t ArgIndex = 0>
|
template <typename MethodArguments, typename CallArguments, size_t PrevAlign = 1, size_t DataOffset = 0, size_t OutBufferIndex = 0, bool RawDataFinished = false, size_t ArgIndex = 0>
|
||||||
void WriteOutArgument(CallArguments& args, u8* raw_data, HLERequestContext& ctx, OutTemporaryBuffers& temp) {
|
void WriteOutArgument(bool is_domain, CallArguments& args, u8* raw_data, HLERequestContext& ctx, OutTemporaryBuffers& temp) {
|
||||||
if constexpr (ArgIndex >= std::tuple_size_v<CallArguments>) {
|
if constexpr (ArgIndex >= std::tuple_size_v<CallArguments>) {
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
@ -243,23 +243,23 @@ void WriteOutArgument(CallArguments& args, u8* raw_data, HLERequestContext& ctx,
|
||||||
|
|
||||||
std::memcpy(raw_data + ArgOffset, &std::get<ArgIndex>(args), ArgSize);
|
std::memcpy(raw_data + ArgOffset, &std::get<ArgIndex>(args), ArgSize);
|
||||||
|
|
||||||
return WriteOutArgument<Domain, MethodArguments, CallArguments, ArgAlign, ArgEnd, OutBufferIndex, false, ArgIndex + 1>(args, raw_data, ctx, temp);
|
return WriteOutArgument<MethodArguments, CallArguments, ArgAlign, ArgEnd, OutBufferIndex, false, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
||||||
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutInterface) {
|
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutInterface) {
|
||||||
if constexpr (Domain) {
|
if (is_domain) {
|
||||||
ctx.AddDomainObject(std::get<ArgIndex>(args));
|
ctx.AddDomainObject(std::get<ArgIndex>(args));
|
||||||
} else {
|
} else {
|
||||||
ctx.AddMoveInterface(std::get<ArgIndex>(args));
|
ctx.AddMoveInterface(std::get<ArgIndex>(args));
|
||||||
}
|
}
|
||||||
|
|
||||||
return WriteOutArgument<Domain, MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, true, ArgIndex + 1>(args, raw_data, ctx, temp);
|
return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, true, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
||||||
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutCopyHandle) {
|
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutCopyHandle) {
|
||||||
ctx.AddCopyObject(std::get<ArgIndex>(args).GetPointerUnsafe());
|
ctx.AddCopyObject(std::get<ArgIndex>(args));
|
||||||
|
|
||||||
return WriteOutArgument<Domain, MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, RawDataFinished, ArgIndex + 1>(args, raw_data, ctx, temp);
|
return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
||||||
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutMoveHandle) {
|
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutMoveHandle) {
|
||||||
ctx.AddMoveObject(std::get<ArgIndex>(args).GetPointerUnsafe());
|
ctx.AddMoveObject(std::get<ArgIndex>(args));
|
||||||
|
|
||||||
return WriteOutArgument<Domain, MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, RawDataFinished, ArgIndex + 1>(args, raw_data, ctx, temp);
|
return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
||||||
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutLargeData) {
|
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutLargeData) {
|
||||||
constexpr size_t BufferSize = sizeof(ArgType);
|
constexpr size_t BufferSize = sizeof(ArgType);
|
||||||
|
|
||||||
|
@ -272,7 +272,7 @@ void WriteOutArgument(CallArguments& args, u8* raw_data, HLERequestContext& ctx,
|
||||||
ctx.WriteBufferC(&std::get<ArgIndex>(args), BufferSize, OutBufferIndex);
|
ctx.WriteBufferC(&std::get<ArgIndex>(args), BufferSize, OutBufferIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return WriteOutArgument<Domain, MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex + 1, RawDataFinished, ArgIndex + 1>(args, raw_data, ctx, temp);
|
return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex + 1, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
||||||
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutBuffer) {
|
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutBuffer) {
|
||||||
auto& buffer = temp[OutBufferIndex];
|
auto& buffer = temp[OutBufferIndex];
|
||||||
const size_t size = buffer.size();
|
const size_t size = buffer.size();
|
||||||
|
@ -287,9 +287,9 @@ void WriteOutArgument(CallArguments& args, u8* raw_data, HLERequestContext& ctx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return WriteOutArgument<Domain, MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex + 1, RawDataFinished, ArgIndex + 1>( args, raw_data, ctx, temp);
|
return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex + 1, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
||||||
} else {
|
} else {
|
||||||
return WriteOutArgument<Domain, MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, RawDataFinished, ArgIndex + 1>(args, raw_data, ctx, temp);
|
return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -297,11 +297,10 @@ void WriteOutArgument(CallArguments& args, u8* raw_data, HLERequestContext& ctx,
|
||||||
template <bool Domain, typename T, typename... A>
|
template <bool Domain, typename T, typename... A>
|
||||||
void CmifReplyWrapImpl(HLERequestContext& ctx, T& t, Result (T::*f)(A...)) {
|
void CmifReplyWrapImpl(HLERequestContext& ctx, T& t, Result (T::*f)(A...)) {
|
||||||
// Verify domain state.
|
// Verify domain state.
|
||||||
if constexpr (Domain) {
|
if constexpr (!Domain) {
|
||||||
ASSERT_MSG(ctx.GetManager()->IsDomain(), "Domain reply used on non-domain session");
|
|
||||||
} else {
|
|
||||||
ASSERT_MSG(!ctx.GetManager()->IsDomain(), "Non-domain reply used on domain session");
|
ASSERT_MSG(!ctx.GetManager()->IsDomain(), "Non-domain reply used on domain session");
|
||||||
}
|
}
|
||||||
|
const bool is_domain = Domain ? ctx.GetManager()->IsDomain() : false;
|
||||||
|
|
||||||
using MethodArguments = std::tuple<std::remove_reference_t<A>...>;
|
using MethodArguments = std::tuple<std::remove_reference_t<A>...>;
|
||||||
|
|
||||||
|
@ -310,7 +309,7 @@ void CmifReplyWrapImpl(HLERequestContext& ctx, T& t, Result (T::*f)(A...)) {
|
||||||
|
|
||||||
// Read inputs.
|
// Read inputs.
|
||||||
const size_t offset_plus_command_id = ctx.GetDataPayloadOffset() + 2;
|
const size_t offset_plus_command_id = ctx.GetDataPayloadOffset() + 2;
|
||||||
ReadInArgument<Domain, MethodArguments>(call_arguments, reinterpret_cast<u8*>(ctx.CommandBuffer() + offset_plus_command_id), ctx, buffers);
|
ReadInArgument<MethodArguments>(is_domain, call_arguments, reinterpret_cast<u8*>(ctx.CommandBuffer() + offset_plus_command_id), ctx, buffers);
|
||||||
|
|
||||||
// Call.
|
// Call.
|
||||||
const auto Callable = [&]<typename... CallArgs>(CallArgs&... args) {
|
const auto Callable = [&]<typename... CallArgs>(CallArgs&... args) {
|
||||||
|
@ -319,12 +318,12 @@ void CmifReplyWrapImpl(HLERequestContext& ctx, T& t, Result (T::*f)(A...)) {
|
||||||
const Result res = std::apply(Callable, call_arguments);
|
const Result res = std::apply(Callable, call_arguments);
|
||||||
|
|
||||||
// Write result.
|
// Write result.
|
||||||
constexpr RequestLayout layout = GetReplyOutLayout<Domain, MethodArguments>();
|
const RequestLayout layout = GetReplyOutLayout<MethodArguments>(is_domain);
|
||||||
IPC::ResponseBuilder rb{ctx, 2 + Common::DivCeil(layout.cmif_raw_data_size, sizeof(u32)), layout.copy_handle_count, layout.move_handle_count + layout.domain_interface_count};
|
IPC::ResponseBuilder rb{ctx, 2 + Common::DivCeil(layout.cmif_raw_data_size, sizeof(u32)), layout.copy_handle_count, layout.move_handle_count + layout.domain_interface_count};
|
||||||
rb.Push(res);
|
rb.Push(res);
|
||||||
|
|
||||||
// Write out arguments.
|
// Write out arguments.
|
||||||
WriteOutArgument<Domain, MethodArguments>(call_arguments, reinterpret_cast<u8*>(ctx.CommandBuffer() + rb.GetCurrentOffset()), ctx, buffers);
|
WriteOutArgument<MethodArguments>(is_domain, call_arguments, reinterpret_cast<u8*>(ctx.CommandBuffer() + rb.GetCurrentOffset()), ctx, buffers);
|
||||||
}
|
}
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
|
|
|
@ -15,19 +15,21 @@ namespace Service {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class Out {
|
class Out {
|
||||||
public:
|
public:
|
||||||
/* implicit */ Out(T& t) : raw(&t) {}
|
using Type = T;
|
||||||
|
|
||||||
|
/* implicit */ Out(Type& t) : raw(&t) {}
|
||||||
~Out() = default;
|
~Out() = default;
|
||||||
|
|
||||||
T* Get() const {
|
Type* Get() const {
|
||||||
return raw;
|
return raw;
|
||||||
}
|
}
|
||||||
|
|
||||||
T& operator*() {
|
Type& operator*() {
|
||||||
return *raw;
|
return *raw;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T* raw;
|
Type* raw;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -45,51 +47,93 @@ struct ClientProcessId {
|
||||||
u64 pid;
|
u64 pid;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ProcessId {
|
||||||
|
explicit operator bool() const {
|
||||||
|
return pid != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const u64& operator*() const {
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 pid;
|
||||||
|
};
|
||||||
|
|
||||||
using ClientAppletResourceUserId = ClientProcessId;
|
using ClientAppletResourceUserId = ClientProcessId;
|
||||||
|
using AppletResourceUserId = ProcessId;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class InCopyHandle : public Kernel::KScopedAutoObject<T> {
|
class InCopyHandle {
|
||||||
public:
|
public:
|
||||||
using Type = T;
|
using Type = T;
|
||||||
|
|
||||||
template <typename... Args>
|
/* implicit */ InCopyHandle(Type* t) : raw(t) {}
|
||||||
/* implicit */ InCopyHandle(Args&&... args) : Kernel::KScopedAutoObject<T>(std::forward<Args...>(args)...) {}
|
/* implicit */ InCopyHandle() : raw() {}
|
||||||
~InCopyHandle() = default;
|
~InCopyHandle() = default;
|
||||||
|
|
||||||
InCopyHandle& operator=(InCopyHandle&& rhs) {
|
InCopyHandle& operator=(Type* rhs) {
|
||||||
Kernel::KScopedAutoObject<T>::operator=(std::move(rhs));
|
raw = rhs;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Type* Get() const {
|
||||||
|
return raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
Type& operator*() const {
|
||||||
|
return *raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
Type* operator->() const {
|
||||||
|
return raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit operator bool() const {
|
||||||
|
return raw != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Type* raw;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class OutCopyHandle : public Kernel::KScopedAutoObject<T> {
|
class OutCopyHandle {
|
||||||
public:
|
public:
|
||||||
using Type = T;
|
using Type = T*;
|
||||||
|
|
||||||
template <typename... Args>
|
/* implicit */ OutCopyHandle(Type& t) : raw(&t) {}
|
||||||
/* implicit */ OutCopyHandle(Args&&... args) : Kernel::KScopedAutoObject<T>(std::forward<Args...>(args)...) {}
|
|
||||||
~OutCopyHandle() = default;
|
~OutCopyHandle() = default;
|
||||||
|
|
||||||
OutCopyHandle& operator=(OutCopyHandle&& rhs) {
|
Type* Get() const {
|
||||||
Kernel::KScopedAutoObject<T>::operator=(std::move(rhs));
|
return raw;
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Type& operator*() {
|
||||||
|
return *raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Type* raw;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class OutMoveHandle : public Kernel::KScopedAutoObject<T> {
|
class OutMoveHandle {
|
||||||
public:
|
public:
|
||||||
using Type = T;
|
using Type = T*;
|
||||||
|
|
||||||
template <typename... Args>
|
/* implicit */ OutMoveHandle(Type& t) : raw(&t) {}
|
||||||
/* implicit */ OutMoveHandle(Args&&... args) : Kernel::KScopedAutoObject<T>(std::forward<Args...>(args)...) {}
|
|
||||||
~OutMoveHandle() = default;
|
~OutMoveHandle() = default;
|
||||||
|
|
||||||
OutMoveHandle& operator=(OutMoveHandle&& rhs) {
|
Type* Get() const {
|
||||||
Kernel::KScopedAutoObject<T>::operator=(std::move(rhs));
|
return raw;
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Type& operator*() {
|
||||||
|
return *raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Type* raw;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum BufferAttr : int {
|
enum BufferAttr : int {
|
||||||
|
@ -105,12 +149,15 @@ enum BufferAttr : int {
|
||||||
|
|
||||||
template <typename T, int A>
|
template <typename T, int A>
|
||||||
struct Buffer : public std::span<T> {
|
struct Buffer : public std::span<T> {
|
||||||
static_assert(std::is_trivial_v<T>, "Buffer type must be trivial");
|
static_assert(std::is_trivially_copyable_v<T>, "Buffer type must be trivially copyable");
|
||||||
static_assert((A & BufferAttr_FixedSize) == 0, "Buffer attr must not contain FixedSize");
|
static_assert((A & BufferAttr_FixedSize) == 0, "Buffer attr must not contain FixedSize");
|
||||||
static_assert(((A & BufferAttr_In) == 0) ^ ((A & BufferAttr_Out) == 0), "Buffer attr must be In or Out");
|
static_assert(((A & BufferAttr_In) == 0) ^ ((A & BufferAttr_Out) == 0), "Buffer attr must be In or Out");
|
||||||
static constexpr BufferAttr Attr = static_cast<BufferAttr>(A);
|
static constexpr BufferAttr Attr = static_cast<BufferAttr>(A);
|
||||||
using Type = T;
|
using Type = T;
|
||||||
|
|
||||||
|
/* implicit */ Buffer(const std::span<T>& rhs) : std::span<T>(rhs) {}
|
||||||
|
/* implicit */ Buffer() = default;
|
||||||
|
|
||||||
Buffer& operator=(const std::span<T>& rhs) {
|
Buffer& operator=(const std::span<T>& rhs) {
|
||||||
std::span<T>::operator=(rhs);
|
std::span<T>::operator=(rhs);
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -139,11 +186,14 @@ using OutArray = Buffer<T, BufferAttr_Out | A>;
|
||||||
|
|
||||||
template <typename T, int A>
|
template <typename T, int A>
|
||||||
struct LargeData : public T {
|
struct LargeData : public T {
|
||||||
static_assert(std::is_trivial_v<T>, "LargeData type must be trivial");
|
static_assert(std::is_trivially_copyable_v<T>, "LargeData type must be trivially copyable");
|
||||||
static_assert((A & BufferAttr_FixedSize) != 0, "LargeData attr must contain FixedSize");
|
static_assert((A & BufferAttr_FixedSize) != 0, "LargeData attr must contain FixedSize");
|
||||||
static_assert(((A & BufferAttr_In) == 0) ^ ((A & BufferAttr_Out) == 0), "LargeData attr must be In or Out");
|
static_assert(((A & BufferAttr_In) == 0) ^ ((A & BufferAttr_Out) == 0), "LargeData attr must be In or Out");
|
||||||
static constexpr BufferAttr Attr = static_cast<BufferAttr>(A);
|
static constexpr BufferAttr Attr = static_cast<BufferAttr>(A);
|
||||||
using Type = T;
|
using Type = T;
|
||||||
|
|
||||||
|
/* implicit */ LargeData(const T& rhs) : T(rhs) {}
|
||||||
|
/* implicit */ LargeData() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, BufferAttr A>
|
template <typename T, BufferAttr A>
|
||||||
|
@ -159,7 +209,17 @@ struct RemoveOut {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct RemoveOut<Out<T>> {
|
struct RemoveOut<Out<T>> {
|
||||||
using Type = T;
|
using Type = typename Out<T>::Type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct RemoveOut<OutCopyHandle<T>> {
|
||||||
|
using Type = typename OutCopyHandle<T>::Type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct RemoveOut<OutMoveHandle<T>> {
|
||||||
|
using Type = typename OutMoveHandle<T>::Type;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ArgumentType {
|
enum class ArgumentType {
|
||||||
|
|
|
@ -27,7 +27,7 @@ static_assert(sizeof(Struct32) == 32, "Struct32 has wrong size");
|
||||||
class IJitEnvironment final : public ServiceFramework<IJitEnvironment> {
|
class IJitEnvironment final : public ServiceFramework<IJitEnvironment> {
|
||||||
public:
|
public:
|
||||||
explicit IJitEnvironment(Core::System& system_,
|
explicit IJitEnvironment(Core::System& system_,
|
||||||
Kernel::KScopedAutoObject<Kernel::KProcess>&& process_,
|
Kernel::KScopedAutoObject<Kernel::KProcess> process_,
|
||||||
CodeMemory&& user_rx_, CodeMemory&& user_ro_)
|
CodeMemory&& user_rx_, CodeMemory&& user_ro_)
|
||||||
: ServiceFramework{system_, "IJitEnvironment"}, process{std::move(process_)},
|
: ServiceFramework{system_, "IJitEnvironment"}, process{std::move(process_)},
|
||||||
user_rx{std::move(user_rx_)}, user_ro{std::move(user_ro_)},
|
user_rx{std::move(user_rx_)}, user_ro{std::move(user_ro_)},
|
||||||
|
@ -129,7 +129,7 @@ public:
|
||||||
Result LoadPlugin(u64 tmem_size, InCopyHandle<Kernel::KTransferMemory>& tmem,
|
Result LoadPlugin(u64 tmem_size, InCopyHandle<Kernel::KTransferMemory>& tmem,
|
||||||
InBuffer<BufferAttr_HipcMapAlias> nrr,
|
InBuffer<BufferAttr_HipcMapAlias> nrr,
|
||||||
InBuffer<BufferAttr_HipcMapAlias> nro) {
|
InBuffer<BufferAttr_HipcMapAlias> nro) {
|
||||||
if (tmem.IsNull()) {
|
if (!tmem) {
|
||||||
LOG_ERROR(Service_JIT, "Invalid transfer memory handle!");
|
LOG_ERROR(Service_JIT, "Invalid transfer memory handle!");
|
||||||
R_THROW(ResultUnknown);
|
R_THROW(ResultUnknown);
|
||||||
}
|
}
|
||||||
|
@ -271,15 +271,15 @@ private:
|
||||||
u64 rx_size, u64 ro_size, InCopyHandle<Kernel::KProcess>& process,
|
u64 rx_size, u64 ro_size, InCopyHandle<Kernel::KProcess>& process,
|
||||||
InCopyHandle<Kernel::KCodeMemory>& rx_mem,
|
InCopyHandle<Kernel::KCodeMemory>& rx_mem,
|
||||||
InCopyHandle<Kernel::KCodeMemory>& ro_mem) {
|
InCopyHandle<Kernel::KCodeMemory>& ro_mem) {
|
||||||
if (process.IsNull()) {
|
if (!process) {
|
||||||
LOG_ERROR(Service_JIT, "process is null");
|
LOG_ERROR(Service_JIT, "process is null");
|
||||||
R_THROW(ResultUnknown);
|
R_THROW(ResultUnknown);
|
||||||
}
|
}
|
||||||
if (rx_mem.IsNull()) {
|
if (!rx_mem) {
|
||||||
LOG_ERROR(Service_JIT, "rx_mem is null");
|
LOG_ERROR(Service_JIT, "rx_mem is null");
|
||||||
R_THROW(ResultUnknown);
|
R_THROW(ResultUnknown);
|
||||||
}
|
}
|
||||||
if (rx_mem.IsNull()) {
|
if (!ro_mem) {
|
||||||
LOG_ERROR(Service_JIT, "ro_mem is null");
|
LOG_ERROR(Service_JIT, "ro_mem is null");
|
||||||
R_THROW(ResultUnknown);
|
R_THROW(ResultUnknown);
|
||||||
}
|
}
|
||||||
|
@ -291,8 +291,8 @@ private:
|
||||||
R_TRY(ro.Initialize(*process, *ro_mem, ro_size, Kernel::Svc::MemoryPermission::Read,
|
R_TRY(ro.Initialize(*process, *ro_mem, ro_size, Kernel::Svc::MemoryPermission::Read,
|
||||||
generate_random));
|
generate_random));
|
||||||
|
|
||||||
*out_jit_environment = std::make_shared<IJitEnvironment>(system, std::move(process),
|
*out_jit_environment =
|
||||||
std::move(rx), std::move(ro));
|
std::make_shared<IJitEnvironment>(system, process.Get(), std::move(rx), std::move(ro));
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -551,8 +551,7 @@ public:
|
||||||
Result RegisterProcessHandle(ClientProcessId client_pid,
|
Result RegisterProcessHandle(ClientProcessId client_pid,
|
||||||
InCopyHandle<Kernel::KProcess>& process) {
|
InCopyHandle<Kernel::KProcess>& process) {
|
||||||
// Register the process.
|
// Register the process.
|
||||||
R_RETURN(m_ro->RegisterProcess(std::addressof(m_context_id), process.GetPointerUnsafe(),
|
R_RETURN(m_ro->RegisterProcess(std::addressof(m_context_id), process.Get(), *client_pid));
|
||||||
*client_pid));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result RegisterProcessModuleInfo(ClientProcessId client_pid, u64 nrr_address, u64 nrr_size,
|
Result RegisterProcessModuleInfo(ClientProcessId client_pid, u64 nrr_address, u64 nrr_size,
|
||||||
|
|
Loading…
Reference in a new issue