sf: implement mitm forwarding + domains.

This commit is contained in:
Michael Scire
2019-10-21 02:45:52 -07:00
committed by SciresM
parent 0b22af1206
commit 4f455dacf4
14 changed files with 509 additions and 68 deletions

View File

@@ -19,18 +19,20 @@
static constexpr u32 Module_ServiceFramework = 10;
static constexpr Result ResultServiceFrameworkNotSupported = MAKERESULT(Module_ServiceFramework, 1);
static constexpr Result ResultServiceFrameworkPreconditionViolation = MAKERESULT(Module_ServiceFramework, 3);
static constexpr Result ResultServiceFrameworkNotSupported = MAKERESULT(Module_ServiceFramework, 1);
static constexpr Result ResultServiceFrameworkPreconditionViolation = MAKERESULT(Module_ServiceFramework, 3);
static constexpr Result ResultServiceFrameworkInvalidCmifHeaderSize = MAKERESULT(Module_ServiceFramework, 202);
static constexpr Result ResultServiceFrameworkInvalidCmifInHeader = MAKERESULT(Module_ServiceFramework, 211);
static constexpr Result ResultServiceFrameworkUnknownCmifCommandId = MAKERESULT(Module_ServiceFramework, 221);
static constexpr Result ResultServiceFrameworkInvalidCmifOutRawSize = MAKERESULT(Module_ServiceFramework, 232);
static constexpr Result ResultServiceFrameworkInvalidCmifHeaderSize = MAKERESULT(Module_ServiceFramework, 202);
static constexpr Result ResultServiceFrameworkInvalidCmifInHeader = MAKERESULT(Module_ServiceFramework, 211);
static constexpr Result ResultServiceFrameworkUnknownCmifCommandId = MAKERESULT(Module_ServiceFramework, 221);
static constexpr Result ResultServiceFrameworkInvalidCmifOutRawSize = MAKERESULT(Module_ServiceFramework, 232);
static constexpr Result ResultServiceFrameworkInvalidCmifNumInObjects = MAKERESULT(Module_ServiceFramework, 235);
static constexpr Result ResultServiceFrameworkInvalidCmifNumOutObjects = MAKERESULT(Module_ServiceFramework, 236);
static constexpr Result ResultServiceFrameworkTargetNotFound = MAKERESULT(Module_ServiceFramework, 261);
static constexpr Result ResultServiceFrameworkTargetNotFound = MAKERESULT(Module_ServiceFramework, 261);
static constexpr Result ResultServiceFrameworkOutOfDomainEntries = MAKERESULT(Module_ServiceFramework, 301);
static constexpr Result ResultServiceFrameworkOutOfDomainEntries = MAKERESULT(Module_ServiceFramework, 301);
static constexpr Result ResultServiceFrameworkRequestDeferred = MAKERESULT(Module_ServiceFramework, 811);
static constexpr Result ResultServiceFrameworkRequestDeferredByUser = MAKERESULT(Module_ServiceFramework, 812);
static constexpr Result ResultServiceFrameworkRequestDeferred = MAKERESULT(Module_ServiceFramework, 811);
static constexpr Result ResultServiceFrameworkRequestDeferredByUser = MAKERESULT(Module_ServiceFramework, 812);

View File

@@ -57,7 +57,7 @@ namespace sts::sf::cmif {
class ServerDomainBase {
public:
virtual Result ReserveIds(DomainObjectId *out_ids, size_t count) = 0;
virtual Result AlterReservedIds(const DomainObjectId *old_reserved_ids, const DomainObjectId *new_reserved_ids, size_t count) = 0;
virtual void ReserveSpecificIds(const DomainObjectId *ids, size_t count) = 0;
virtual void UnreserveIds(const DomainObjectId *ids, size_t count) = 0;
virtual void RegisterObject(DomainObjectId id, ServiceObjectHolder &&obj) = 0;

View File

@@ -56,7 +56,7 @@ namespace sts::sf::cmif {
}
virtual Result ReserveIds(DomainObjectId *out_ids, size_t count) override final;
virtual Result AlterReservedIds(const DomainObjectId *old_reserved_ids, const DomainObjectId *new_reserved_ids, size_t count) override final;
virtual void ReserveSpecificIds(const DomainObjectId *ids, size_t count) override final;
virtual void UnreserveIds(const DomainObjectId *ids, size_t count) override final;
virtual void RegisterObject(DomainObjectId id, ServiceObjectHolder &&obj) override final;
@@ -81,7 +81,7 @@ namespace sts::sf::cmif {
Entry *AllocateEntry();
void FreeEntry(Entry *);
void ReallocateEntries(const DomainObjectId *old_reserved_ids, const DomainObjectId *new_reserved_ids, size_t count);
void AllocateSpecificEntries(const DomainObjectId *ids, size_t count);
inline DomainObjectId GetId(Entry *e) {
const size_t index = e - this->entries;
@@ -116,6 +116,11 @@ namespace sts::sf::cmif {
}
return new (storage) Domain(this);
}
inline void FreeDomainServiceObject(DomainServiceObject *object) {
static_cast<Domain *>(object)->~Domain();
this->FreeDomain(object);
}
};

View File

@@ -24,8 +24,10 @@ namespace sts::sf::cmif {
class DomainServiceObjectDispatchTable : public impl::ServiceDispatchTableBase {
private:
Result ProcessMessageImpl(ServiceDispatchContext &ctx, ServerDomainBase *domain, const cmif::PointerAndSize &in_raw_data) const;
Result ProcessMessageForMitmImpl(ServiceDispatchContext &ctx, ServerDomainBase *domain, const cmif::PointerAndSize &in_raw_data) const;
public:
Result ProcessMessage(ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data) const;
Result ProcessMessageForMitm(ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data) const;
};
@@ -33,6 +35,30 @@ namespace sts::sf::cmif {
private:
ServerMessageProcessor *impl_processor;
ServerDomainBase *domain;
DomainObjectId *in_object_ids;
DomainObjectId *out_object_ids;
size_t num_in_objects;
ServerMessageRuntimeMetadata impl_metadata;
public:
DomainServiceObjectProcessor(ServerDomainBase *d, DomainObjectId *in_obj_ids, size_t num_in_objs) : domain(d), in_object_ids(in_obj_ids), num_in_objects(num_in_objs) {
STS_ASSERT(this->domain != nullptr);
STS_ASSERT(this->in_object_ids != nullptr);
this->impl_processor = nullptr;
this->out_object_ids = nullptr;
this->impl_metadata = {};
}
constexpr size_t GetInObjectCount() const {
return this->num_in_objects;
}
constexpr size_t GetOutObjectCount() const {
return this->impl_metadata.GetOutObjectCount();
}
constexpr size_t GetImplOutDataTotalSize() const {
return this->impl_metadata.GetOutDataSize() + this->impl_metadata.GetOutHeadersSize();
}
public:
/* Used to enabled templated message processors. */
virtual void SetImplementationProcessor(ServerMessageProcessor *impl) override final {
@@ -41,16 +67,32 @@ namespace sts::sf::cmif {
} else {
this->impl_processor->SetImplementationProcessor(impl);
}
this->impl_metadata = this->impl_processor->GetRuntimeMetadata();
}
virtual Result PrepareForProcess(const ServiceDispatchContext &ctx, size_t &headers_size) const override final;
virtual const ServerMessageRuntimeMetadata GetRuntimeMetadata() const override final {
const auto runtime_metadata = this->impl_processor->GetRuntimeMetadata();
return ServerMessageRuntimeMetadata {
.in_data_size = static_cast<u16>(runtime_metadata.GetInDataSize() + runtime_metadata.GetInObjectCount() * sizeof(DomainObjectId)),
.out_data_size = static_cast<u16>(runtime_metadata.GetOutDataSize() + runtime_metadata.GetOutObjectCount() * sizeof(DomainObjectId)),
.in_headers_size = static_cast<u8>(runtime_metadata.GetInHeadersSize() + sizeof(CmifDomainInHeader)),
.out_headers_size = static_cast<u8>(runtime_metadata.GetOutHeadersSize() + sizeof(CmifDomainOutHeader)),
.in_object_count = 0,
.out_object_count = 0,
};
}
virtual Result PrepareForProcess(const ServiceDispatchContext &ctx, const ServerMessageRuntimeMetadata runtime_metadata) const override final;
virtual Result GetInObjects(ServiceObjectHolder *in_objects) const override final;
virtual HipcRequest PrepareForReply(const cmif::ServiceDispatchContext &ctx, PointerAndSize &out_raw_data, const size_t headers_size, size_t &num_out_object_handles) override final;
virtual void PrepareForErrorReply(const cmif::ServiceDispatchContext &ctx, PointerAndSize &out_raw_data, const size_t headers_size) override final;
virtual HipcRequest PrepareForReply(const cmif::ServiceDispatchContext &ctx, PointerAndSize &out_raw_data, const ServerMessageRuntimeMetadata runtime_metadata) override final;
virtual void PrepareForErrorReply(const cmif::ServiceDispatchContext &ctx, PointerAndSize &out_raw_data, const ServerMessageRuntimeMetadata runtime_metadata) override final;
virtual void SetOutObjects(const cmif::ServiceDispatchContext &ctx, const HipcRequest &response, ServiceObjectHolder *out_objects, DomainObjectId *ids) override final;
};
class DomainServiceObject : public IServiceObject, public ServerDomainBase {
friend class DomainServiceObjectDispatchTable;
public:
static constexpr inline DomainServiceObjectDispatchTable s_CmifServiceDispatchTable{};
private:
@@ -59,6 +101,8 @@ namespace sts::sf::cmif {
/* TODO: Implement to use domain object processor. */
};
class MitmDomainServiceObject : public DomainServiceObject{};
template<>
struct ServiceDispatchTraits<DomainServiceObject> {
static_assert(std::is_base_of<sf::IServiceObject, DomainServiceObject>::value, "DomainServiceObject must derive from sf::IServiceObject");
@@ -71,4 +115,16 @@ namespace sts::sf::cmif {
static constexpr inline ServiceDispatchMeta Meta{&DomainServiceObject::s_CmifServiceDispatchTable, ProcessHandlerImpl};
};
template<>
struct ServiceDispatchTraits<MitmDomainServiceObject> {
static_assert(std::is_base_of<DomainServiceObject, MitmDomainServiceObject>::value, "MitmDomainServiceObject must derive from DomainServiceObject");
using ProcessHandlerType = decltype(ServiceDispatchMeta::ProcessHandler);
using DispatchTableType = DomainServiceObjectDispatchTable;
static constexpr ProcessHandlerType ProcessHandlerImpl = &impl::ServiceDispatchTableBase::ProcessMessageForMitm<DispatchTableType>;
static constexpr inline ServiceDispatchMeta Meta{&DomainServiceObject::s_CmifServiceDispatchTable, ProcessHandlerImpl};
};
}

View File

@@ -25,15 +25,57 @@ namespace sts::sf::cmif {
class ServiceObjectHolder;
struct DomainObjectId;
/* This is needed for non-templated domain message processing. */
struct ServerMessageRuntimeMetadata {
u16 in_data_size;
u16 out_data_size;
u8 in_headers_size;
u8 out_headers_size;
u8 in_object_count;
u8 out_object_count;
constexpr size_t GetInDataSize() const {
return size_t(this->in_data_size);
}
constexpr size_t GetOutDataSize() const {
return size_t(this->out_data_size);
}
constexpr size_t GetInHeadersSize() const {
return size_t(this->in_headers_size);
}
constexpr size_t GetOutHeadersSize() const {
return size_t(this->out_headers_size);
}
constexpr size_t GetInObjectCount() const {
return size_t(this->in_object_count);
}
constexpr size_t GetOutObjectCount() const {
return size_t(this->out_object_count);
}
constexpr size_t GetUnfixedOutPointerSizeOffset() const {
return this->GetInDataSize() + this->GetInHeadersSize() + 0x10 /* padding. */;
}
};
static_assert(std::is_pod<ServerMessageRuntimeMetadata>::value, "std::is_pod<ServerMessageRuntimeMetadata>::value");
static_assert(sizeof(ServerMessageRuntimeMetadata) == sizeof(u64), "sizeof(ServerMessageRuntimeMetadata)");
class ServerMessageProcessor {
public:
/* Used to enabled templated message processors. */
virtual void SetImplementationProcessor(ServerMessageProcessor *impl) { /* ... */ }
virtual const ServerMessageRuntimeMetadata GetRuntimeMetadata() const = 0;
virtual Result PrepareForProcess(const ServiceDispatchContext &ctx, size_t &headers_size) const = 0;
virtual Result PrepareForProcess(const ServiceDispatchContext &ctx, const ServerMessageRuntimeMetadata runtime_metadata) const = 0;
virtual Result GetInObjects(ServiceObjectHolder *in_objects) const = 0;
virtual HipcRequest PrepareForReply(const cmif::ServiceDispatchContext &ctx, PointerAndSize &out_raw_data, const size_t headers_size, size_t &num_out_object_handles) = 0;
virtual void PrepareForErrorReply(const cmif::ServiceDispatchContext &ctx, PointerAndSize &out_raw_data, const size_t headers_size) = 0;
virtual HipcRequest PrepareForReply(const cmif::ServiceDispatchContext &ctx, PointerAndSize &out_raw_data, const ServerMessageRuntimeMetadata runtime_metadata) = 0;
virtual void PrepareForErrorReply(const cmif::ServiceDispatchContext &ctx, PointerAndSize &out_raw_data, const ServerMessageRuntimeMetadata runtime_metadata) = 0;
virtual void SetOutObjects(const cmif::ServiceDispatchContext &ctx, const HipcRequest &response, ServiceObjectHolder *out_objects, DomainObjectId *ids) = 0;
};
}

View File

@@ -22,6 +22,7 @@
namespace sts::sf::hipc {
class ServerSessionManager;
class ServerSession;
}
@@ -37,6 +38,7 @@ namespace sts::sf::cmif {
struct ServiceDispatchContext {
sf::IServiceObject *srv_obj;
hipc::ServerSessionManager *manager;
hipc::ServerSession *session;
ServerMessageProcessor *processor;
HandlesToClose *handles_to_close;
const PointerAndSize pointer_buffer;

View File

@@ -28,6 +28,14 @@ namespace sts::sf::hipc {
virtual Result DispatchManagerRequest(ServerSession *session, const cmif::PointerAndSize &in_message, const cmif::PointerAndSize &out_message) override final;
public:
ServerDomainSessionManager(DomainEntryStorage *entry_storage, size_t entry_count) : ServerDomainManager(entry_storage, entry_count) { /* ... */ }
inline cmif::DomainServiceObject *AllocateDomainServiceObject() {
return cmif::ServerDomainManager::AllocateDomainServiceObject();
}
inline void FreeDomainServiceObject(cmif::DomainServiceObject *object) {
cmif::ServerDomainManager::FreeDomainServiceObject(object);
}
};
}

View File

@@ -21,6 +21,12 @@
#include "../cmif/sf_cmif_service_object_holder.hpp"
#include "sf_hipc_api.hpp"
namespace sts::sf::cmif {
struct ServiceDispatchContext;
}
namespace sts::sf::hipc {
class ServerSessionManager;
@@ -65,6 +71,8 @@ namespace sts::sf::hipc {
bool IsMitmSession() const {
return this->forward_service != nullptr;
}
Result ForwardRequest(const cmif::ServiceDispatchContext &ctx) const;
};
class ServerSessionManager {

View File

@@ -442,8 +442,7 @@ namespace sts::sf::impl {
/* In/Out data marshalling. */
static constexpr std::array<size_t, NumInDatas+1> InDataOffsets = RawDataOffsetCalculator<InDatas>::Offsets;
static constexpr size_t InDataRawUnfixedOutPointerSizeOffset = util::AlignUp(InDataOffsets[NumInDatas] + 0x10, alignof(u16));
static constexpr size_t InDataSize = util::AlignUp(util::AlignUp(InDataOffsets[NumInDatas], alignof(u16)) + sizeof(u16) * NumUnfixedSizeOutHipcPointerBuffers, alignof(u32));
static constexpr size_t InDataSize = util::AlignUp(InDataOffsets[NumInDatas], alignof(u16));
static constexpr std::array<size_t, NumOutDatas+1> OutDataOffsets = RawDataOffsetCalculator<OutDatas>::Offsets;
static constexpr size_t OutDataSize = util::AlignUp(OutDataOffsets[NumOutDatas], alignof(u32));
@@ -464,6 +463,16 @@ namespace sts::sf::impl {
static_assert(NumInMoveHandles + NumInCopyHandles == NumInHandles, "NumInMoveHandles + NumInCopyHandles == NumInHandles");
static_assert(NumOutMoveHandles + NumOutCopyHandles == NumOutHandles, "NumOutMoveHandles + NumOutCopyHandles == NumOutHandles");
/* Used by server message processor at runtime. */
static constexpr inline const cmif::ServerMessageRuntimeMetadata RuntimeMetadata = cmif::ServerMessageRuntimeMetadata{
.in_data_size = InDataSize,
.out_data_size = OutDataSize,
.in_headers_size = sizeof(CmifInHeader),
.out_headers_size = sizeof(CmifOutHeader),
.in_object_count = NumInObjects,
.out_object_count = NumOutObjects,
};
/* Construction of argument serialization structs. */
private:
template<typename>
@@ -686,7 +695,11 @@ namespace sts::sf::impl {
template<typename CommandMeta>
struct HipcCommandProcessor : public sf::cmif::ServerMessageProcessor {
public:
virtual Result PrepareForProcess(const cmif::ServiceDispatchContext &ctx, size_t &headers_size) const override final {
virtual const cmif::ServerMessageRuntimeMetadata GetRuntimeMetadata() const override final {
return CommandMeta::RuntimeMetadata;
}
virtual Result PrepareForProcess(const cmif::ServiceDispatchContext &ctx, const cmif::ServerMessageRuntimeMetadata runtime_metadata) const override final {
const auto &meta = ctx.request.meta;
bool is_request_valid = true;
is_request_valid &= meta.send_pid == CommandMeta::HasInProcessIdHolder;
@@ -699,30 +712,33 @@ namespace sts::sf::impl {
is_request_valid &= meta.num_move_handles == CommandMeta::NumInMoveHandles;
const size_t meta_raw_size = meta.num_data_words * sizeof(u32);
is_request_valid &= meta_raw_size >= CommandMeta::InDataSize + 0x10 /* padding */ + headers_size /* headers */;
const size_t command_raw_size = util::AlignUp(runtime_metadata.GetUnfixedOutPointerSizeOffset() + (CommandMeta::NumUnfixedSizeOutHipcPointerBuffers * sizeof(u16)), alignof(u32));
is_request_valid &= meta_raw_size >= command_raw_size;
R_UNLESS(is_request_valid, ResultHipcInvalidRequest);
return ResultSuccess;
}
virtual HipcRequest PrepareForReply(const cmif::ServiceDispatchContext &ctx, cmif::PointerAndSize &out_raw_data, const size_t headers_size, size_t &num_out_object_handles) override final {
virtual HipcRequest PrepareForReply(const cmif::ServiceDispatchContext &ctx, cmif::PointerAndSize &out_raw_data, const cmif::ServerMessageRuntimeMetadata runtime_metadata) override final {
const size_t raw_size = runtime_metadata.GetOutDataSize() + runtime_metadata.GetOutHeadersSize();
const auto response = hipcMakeRequestInline(ctx.out_message_buffer.GetPointer(),
.type = CmifCommandType_Invalid, /* Really response */
.num_send_statics = CommandMeta::NumOutHipcPointerBuffers,
.num_data_words = static_cast<u32>((util::AlignUp(CommandMeta::OutDataSize + headers_size, 0x4) + 0x10 /* padding */) / sizeof(u32)),
.num_data_words = static_cast<u32>((util::AlignUp(raw_size, 0x4) + 0x10 /* padding */) / sizeof(u32)),
.num_copy_handles = CommandMeta::NumOutCopyHandles,
.num_move_handles = static_cast<u32>(CommandMeta::NumOutMoveHandles + num_out_object_handles),
.num_move_handles = static_cast<u32>(CommandMeta::NumOutMoveHandles + runtime_metadata.GetOutObjectCount()),
);
out_raw_data = cmif::PointerAndSize(util::AlignUp(reinterpret_cast<uintptr_t>(response.data_words), 0x10), CommandMeta::OutDataSize + headers_size);
out_raw_data = cmif::PointerAndSize(util::AlignUp(reinterpret_cast<uintptr_t>(response.data_words), 0x10), raw_size);
return response;
}
virtual void PrepareForErrorReply(const cmif::ServiceDispatchContext &ctx, cmif::PointerAndSize &out_raw_data, const size_t headers_size) override final {
virtual void PrepareForErrorReply(const cmif::ServiceDispatchContext &ctx, cmif::PointerAndSize &out_raw_data, const cmif::ServerMessageRuntimeMetadata runtime_metadata) override final {
const size_t raw_size = runtime_metadata.GetOutHeadersSize();
const auto response = hipcMakeRequestInline(ctx.out_message_buffer.GetPointer(),
.type = CmifCommandType_Invalid, /* Really response */
.num_data_words = static_cast<u32>((util::AlignUp(headers_size, 0x4) + 0x10 /* padding */) / sizeof(u32)),
.num_data_words = static_cast<u32>((util::AlignUp(raw_size, 0x4) + 0x10 /* padding */) / sizeof(u32)),
);
out_raw_data = cmif::PointerAndSize(util::AlignUp(reinterpret_cast<uintptr_t>(response.data_words), 0x10), headers_size);
out_raw_data = cmif::PointerAndSize(util::AlignUp(reinterpret_cast<uintptr_t>(response.data_words), 0x10), raw_size);
}
virtual Result GetInObjects(cmif::ServiceObjectHolder *in_objects) const override final {
@@ -789,7 +805,7 @@ namespace sts::sf::impl {
}();
template<size_t BufferIndex, size_t Index = GetIndexFromBufferIndex<BufferIndex>>
NX_CONSTEXPR void ProcessBufferImpl(const cmif::ServiceDispatchContext &ctx, cmif::PointerAndSize &buffer, bool &is_buffer_map_alias, bool &map_alias_buffers_valid, size_t &pointer_buffer_head, size_t &pointer_buffer_tail, size_t in_headers_size) {
NX_CONSTEXPR void ProcessBufferImpl(const cmif::ServiceDispatchContext &ctx, cmif::PointerAndSize &buffer, bool &is_buffer_map_alias, bool &map_alias_buffers_valid, size_t &pointer_buffer_head, size_t &pointer_buffer_tail, const cmif::ServerMessageRuntimeMetadata runtime_metadata) {
static_assert(Index != std::numeric_limits<size_t>::max(), "Invalid Index From Buffer Index");
constexpr auto Info = CommandMeta::ArgumentSerializationInfos[Index];
constexpr auto Attributes = CommandMeta::BufferAttributes[BufferIndex];
@@ -824,7 +840,7 @@ namespace sts::sf::impl {
pointer_buffer_head = util::AlignDown(pointer_buffer_head - size, 0x10);
buffer = cmif::PointerAndSize(pointer_buffer_head, size);
} else {
const u16 *recv_pointer_sizes = reinterpret_cast<const u16 *>(reinterpret_cast<uintptr_t>(ctx.request.data.data_words) + in_headers_size + CommandMeta::InDataRawUnfixedOutPointerSizeOffset);
const u16 *recv_pointer_sizes = reinterpret_cast<const u16 *>(reinterpret_cast<uintptr_t>(ctx.request.data.data_words) + runtime_metadata.GetUnfixedOutPointerSizeOffset());
const size_t size = size_t(recv_pointer_sizes[Info.unfixed_recv_pointer_index]);
pointer_buffer_head = util::AlignDown(pointer_buffer_head - size, 0x10);
buffer = cmif::PointerAndSize(pointer_buffer_head, size);
@@ -860,7 +876,7 @@ namespace sts::sf::impl {
pointer_buffer_head = util::AlignDown(pointer_buffer_head - size, 0x10);
buffer = cmif::PointerAndSize(pointer_buffer_head, size);
} else {
const u16 *recv_pointer_sizes = reinterpret_cast<const u16 *>(reinterpret_cast<uintptr_t>(ctx.request.data.data_words) + CommandMeta::InDataRawUnfixedOutPointerSizeOffset);
const u16 *recv_pointer_sizes = reinterpret_cast<const u16 *>(reinterpret_cast<uintptr_t>(ctx.request.data.data_words) + runtime_metadata.GetUnfixedOutPointerSizeOffset());
const size_t size = size_t(recv_pointer_sizes[Info.unfixed_recv_pointer_index]);
pointer_buffer_head = util::AlignDown(pointer_buffer_head - size, 0x10);
buffer = cmif::PointerAndSize(pointer_buffer_head, size);
@@ -894,11 +910,11 @@ namespace sts::sf::impl {
}
}
public:
NX_CONSTEXPR Result ProcessBuffers(const cmif::ServiceDispatchContext &ctx, BufferArrayType &buffers, std::array<bool, CommandMeta::NumBuffers> &is_buffer_map_alias, size_t in_headers_size) {
NX_CONSTEXPR Result ProcessBuffers(const cmif::ServiceDispatchContext &ctx, BufferArrayType &buffers, std::array<bool, CommandMeta::NumBuffers> &is_buffer_map_alias, const cmif::ServerMessageRuntimeMetadata runtime_metadata) {
bool map_alias_buffers_valid = true;
size_t pointer_buffer_tail = ctx.pointer_buffer.GetAddress();
size_t pointer_buffer_head = pointer_buffer_tail + ctx.pointer_buffer.GetSize();
#define _SF_IMPL_PROCESSOR_PROCESS_BUFFER_IMPL(n) do { if constexpr (CommandMeta::NumBuffers > n) { ProcessBufferImpl<n>(ctx, buffers[n], is_buffer_map_alias[n], map_alias_buffers_valid, pointer_buffer_head, pointer_buffer_tail, in_headers_size); } } while (0)
#define _SF_IMPL_PROCESSOR_PROCESS_BUFFER_IMPL(n) do { if constexpr (CommandMeta::NumBuffers > n) { ProcessBufferImpl<n>(ctx, buffers[n], is_buffer_map_alias[n], map_alias_buffers_valid, pointer_buffer_head, pointer_buffer_tail, runtime_metadata); } } while (0)
_SF_IMPL_PROCESSOR_PROCESS_BUFFER_IMPL(0);
_SF_IMPL_PROCESSOR_PROCESS_BUFFER_IMPL(1);
_SF_IMPL_PROCESSOR_PROCESS_BUFFER_IMPL(2);
@@ -1032,8 +1048,8 @@ namespace sts::sf::impl {
}
/* Validate the metadata has the expected counts. */
size_t in_headers_size = sizeof(CmifInHeader);
R_TRY(ctx.processor->PrepareForProcess(ctx, in_headers_size));
const auto runtime_metadata = ctx.processor->GetRuntimeMetadata();
R_TRY(ctx.processor->PrepareForProcess(ctx, runtime_metadata));
/* Storage for output. */
BufferArrayType buffers;
@@ -1043,7 +1059,7 @@ namespace sts::sf::impl {
InOutObjectHolderType in_out_objects_holder;
/* Process buffers. */
R_TRY(ImplProcessorType::ProcessBuffers(ctx, buffers, is_buffer_map_alias, in_headers_size));
R_TRY(ImplProcessorType::ProcessBuffers(ctx, buffers, is_buffer_map_alias, runtime_metadata));
/* Process input/output objects. */
R_TRY(in_out_objects_holder.GetInObjects(ctx.processor));
@@ -1062,7 +1078,7 @@ namespace sts::sf::impl {
if constexpr (CommandMeta::ReturnsResult) {
R_TRY_CLEANUP(std::apply([=](auto&&... args) { return (this_ptr->*ServiceCommandImpl)(args...); }, args_tuple), {
cmif::PointerAndSize out_raw_data;
ctx.processor->PrepareForErrorReply(ctx, out_raw_data, sizeof(CmifOutHeader));
ctx.processor->PrepareForErrorReply(ctx, out_raw_data, runtime_metadata);
R_TRY(GetCmifOutHeaderPointer(out_header_ptr, out_raw_data));
});
} else {
@@ -1072,8 +1088,7 @@ namespace sts::sf::impl {
/* Encode. */
cmif::PointerAndSize out_raw_data;
size_t num_out_object_handles = CommandMeta::NumOutObjects;
const auto response = ctx.processor->PrepareForReply(ctx, out_raw_data, sizeof(CmifOutHeader), num_out_object_handles);
const auto response = ctx.processor->PrepareForReply(ctx, out_raw_data, runtime_metadata);
R_TRY(GetCmifOutHeaderPointer(out_header_ptr, out_raw_data));
/* Copy raw data output struct. */
@@ -1084,7 +1099,7 @@ namespace sts::sf::impl {
ImplProcessorType::SetOutBuffers(response, buffers, is_buffer_map_alias);
/* Set out handles. */
out_handles_holder.CopyTo(response, num_out_object_handles);
out_handles_holder.CopyTo(response, runtime_metadata.GetOutObjectCount());
/* Set output objects. */
in_out_objects_holder.SetOutObjects(ctx, response);