mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-09 22:56:35 +00:00
tipc: fix compilation issues with core serialization routines
This commit is contained in:
parent
e93d71d932
commit
21b883a75c
10 changed files with 662 additions and 68 deletions
|
@ -23,7 +23,7 @@ PRECOMPILED_HEADERS := $(CURRENT_DIRECTORY)/include/stratosphere.hpp
|
||||||
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_STRATOSPHERE -D_GNU_SOURCE
|
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_STRATOSPHERE -D_GNU_SOURCE
|
||||||
SETTINGS := $(ATMOSPHERE_SETTINGS) -O2
|
SETTINGS := $(ATMOSPHERE_SETTINGS) -O2
|
||||||
CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
||||||
CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -flto
|
CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS)
|
||||||
ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS)
|
ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS)
|
||||||
|
|
||||||
LDFLAGS := -specs=$(DEVKITPRO)/libnx/switch.specs $(SETTINGS) -Wl,-Map,$(notdir $*.map)
|
LDFLAGS := -specs=$(DEVKITPRO)/libnx/switch.specs $(SETTINGS) -Wl,-Map,$(notdir $*.map)
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stratosphere/tipc/impl/tipc_impl_command_serialization.hpp>
|
#include <stratosphere/tipc/impl/tipc_impl_command_serialization.hpp>
|
||||||
|
|
|
@ -15,6 +15,10 @@
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <vapours.hpp>
|
#include <vapours.hpp>
|
||||||
|
#include <stratosphere/tipc/tipc_common.hpp>
|
||||||
|
#include <stratosphere/tipc/tipc_out.hpp>
|
||||||
|
#include <stratosphere/tipc/tipc_buffers.hpp>
|
||||||
|
#include <stratosphere/tipc/tipc_handles.hpp>
|
||||||
|
|
||||||
namespace ams::tipc {
|
namespace ams::tipc {
|
||||||
|
|
||||||
|
@ -72,13 +76,13 @@ namespace ams::tipc::impl {
|
||||||
constexpr inline ArgumentType GetArgumentType = [] {
|
constexpr inline ArgumentType GetArgumentType = [] {
|
||||||
if constexpr (tipc::IsBuffer<T>) {
|
if constexpr (tipc::IsBuffer<T>) {
|
||||||
return ArgumentType::Buffer;
|
return ArgumentType::Buffer;
|
||||||
} else if constexpr (std::is_base_of<sf::impl::InHandleTag, T>::value) {
|
} else if constexpr (std::is_base_of<tipc::impl::InHandleTag, T>::value) {
|
||||||
return ArgumentType::InHandle;
|
return ArgumentType::InHandle;
|
||||||
} else if constexpr (std::is_base_of<sf::impl::OutHandleTag, T>::value) {
|
} else if constexpr (std::is_base_of<tipc::impl::OutHandleTag, T>::value) {
|
||||||
return ArgumentType::OutHandle;
|
return ArgumentType::OutHandle;
|
||||||
} else if constexpr (std::is_base_of<sf::impl::OutBaseTag, T>::value) {
|
} else if constexpr (std::is_base_of<tipc::impl::OutBaseTag, T>::value) {
|
||||||
return ArgumentType::OutData;
|
return ArgumentType::OutData;
|
||||||
} else if constexpr (std::same_as<tipc::ClientProcessId>) {
|
} else if constexpr (std::same_as<T, tipc::ClientProcessId>) {
|
||||||
return ArgumentType::ProcessId;
|
return ArgumentType::ProcessId;
|
||||||
} else if constexpr (std::is_trivial<T>::value && !std::is_pointer<T>::value) {
|
} else if constexpr (std::is_trivial<T>::value && !std::is_pointer<T>::value) {
|
||||||
return ArgumentType::InData;
|
return ArgumentType::InData;
|
||||||
|
@ -111,21 +115,21 @@ namespace ams::tipc::impl {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using OutHandleFilter = ArgumentTypeFilter<T, ArgumentType::OutHandle>;
|
using OutHandleFilter = ArgumentTypeFilter<T, ArgumentType::OutHandle>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using ProcessIdFilter = ArgumentTypeFilter<T, ArgumentType::ProcessId>;
|
||||||
|
|
||||||
/* Handle kind filters. */
|
/* Handle kind filters. */
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using InMoveHandleFilter = TypeEqualityFilter<T, sf::MoveHandle>;
|
using InMoveHandleFilter = TypeEqualityFilter<T, tipc::MoveHandle>;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using InCopyHandleFilter = TypeEqualityFilter<T, sf::CopyHandle>;
|
using InCopyHandleFilter = TypeEqualityFilter<T, tipc::CopyHandle>;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using OutMoveHandleFilter = TypeEqualityFilter<T, sf::Out<sf::MoveHandle>>;
|
using OutMoveHandleFilter = TypeEqualityFilter<T, tipc::Out<tipc::MoveHandle>>;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using OutCopyHandleFilter = TypeEqualityFilter<T, sf::Out<sf::CopyHandle>>;
|
using OutCopyHandleFilter = TypeEqualityFilter<T, tipc::Out<tipc::CopyHandle>>;
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct ProcessIdFilter = ArgumentTypeFilter<T, ArgumentType::ProcessId>;
|
|
||||||
|
|
||||||
template<typename>
|
template<typename>
|
||||||
struct BufferAttributeArrayGetter;
|
struct BufferAttributeArrayGetter;
|
||||||
|
@ -236,7 +240,8 @@ namespace ams::tipc::impl {
|
||||||
template<u16 _CommandId, typename... Arguments>
|
template<u16 _CommandId, typename... Arguments>
|
||||||
struct CommandMetaInfo {
|
struct CommandMetaInfo {
|
||||||
public:
|
public:
|
||||||
using CommandId = _CommandId;
|
static constexpr u16 CommandId = _CommandId;
|
||||||
|
|
||||||
using ArgsType = std::tuple<typename std::decay<Arguments>::type...>;
|
using ArgsType = std::tuple<typename std::decay<Arguments>::type...>;
|
||||||
|
|
||||||
using InDatas = TupleFilter<InDataFilter>::FilteredType<ArgsType>;
|
using InDatas = TupleFilter<InDataFilter>::FilteredType<ArgsType>;
|
||||||
|
@ -257,7 +262,7 @@ namespace ams::tipc::impl {
|
||||||
|
|
||||||
static_assert(NumBuffers <= 8, "Methods must take in <= 8 Buffers");
|
static_assert(NumBuffers <= 8, "Methods must take in <= 8 Buffers");
|
||||||
static_assert(NumInHandles <= 8, "Methods must take in <= 8 Handles");
|
static_assert(NumInHandles <= 8, "Methods must take in <= 8 Handles");
|
||||||
static_assert(NumOutHandles + NumOutObjects <= 8, "Methods must output <= 8 Handles");
|
static_assert(NumOutHandles <= 8, "Methods must output <= 8 Handles");
|
||||||
|
|
||||||
/* Buffer marshalling. */
|
/* Buffer marshalling. */
|
||||||
static constexpr std::array<u32, NumBuffers> BufferAttributes = BufferAttributeArrayGetter<Buffers>::value;
|
static constexpr std::array<u32, NumBuffers> BufferAttributes = BufferAttributeArrayGetter<Buffers>::value;
|
||||||
|
@ -292,8 +297,8 @@ namespace ams::tipc::impl {
|
||||||
/* tipc-specific accessors. */
|
/* tipc-specific accessors. */
|
||||||
static constexpr bool HasInSpecialHeader = HasProcessId || NumInHandles > 0;
|
static constexpr bool HasInSpecialHeader = HasProcessId || NumInHandles > 0;
|
||||||
|
|
||||||
static constexpr svc::ipc::MessageBuffer::MessageHeader InMessageHeader(CommandId, HasInSpecialHeader, 0, NumInBuffers, NumOutBuffers, 0, InDataSize / sizeof(u32), 0);
|
static constexpr svc::ipc::MessageBuffer::MessageHeader InMessageHeader{CommandId, HasInSpecialHeader, 0, NumInBuffers, NumOutBuffers, 0, InDataSize / sizeof(u32), 0};
|
||||||
static constexpr svc::ipc::MessageBuffer::SpecialHeader InSpecialHeader(HasProcessId, NumInMoveHandles, NumInCopyHandles);
|
static constexpr svc::ipc::MessageBuffer::SpecialHeader InSpecialHeader{HasProcessId, NumInCopyHandles, NumInMoveHandles, HasInSpecialHeader};
|
||||||
|
|
||||||
static constexpr auto InMessageProcessIdIndex = svc::ipc::MessageBuffer::GetSpecialDataIndex(InMessageHeader, InSpecialHeader);
|
static constexpr auto InMessageProcessIdIndex = svc::ipc::MessageBuffer::GetSpecialDataIndex(InMessageHeader, InSpecialHeader);
|
||||||
static constexpr auto InMessageHandleIndex = svc::ipc::MessageBuffer::GetSpecialDataIndex(InMessageHeader, InSpecialHeader) + (HasProcessId ? sizeof(u64) / sizeof(u32) : 0);
|
static constexpr auto InMessageHandleIndex = svc::ipc::MessageBuffer::GetSpecialDataIndex(InMessageHeader, InSpecialHeader) + (HasProcessId ? sizeof(u64) / sizeof(u32) : 0);
|
||||||
|
@ -302,8 +307,8 @@ namespace ams::tipc::impl {
|
||||||
|
|
||||||
static constexpr bool HasOutSpecialHeader = NumOutHandles > 0;
|
static constexpr bool HasOutSpecialHeader = NumOutHandles > 0;
|
||||||
|
|
||||||
static constexpr svc::ipc::MessageBuffer::MessageHeader OutMessageHeader(CommandId, HasOutSpecialHeader, 0, 0, 0, 0, (OutDataSize / sizeof(u32)) + 1, 0);
|
static constexpr svc::ipc::MessageBuffer::MessageHeader OutMessageHeader{CommandId, HasOutSpecialHeader, 0, 0, 0, 0, (OutDataSize / sizeof(u32)) + 1, 0};
|
||||||
static constexpr svc::ipc::MessageBuffer::SpecialHeader OutSpecialHeader(false, NumOutMoveHandles, NumOutCopyHandles);
|
static constexpr svc::ipc::MessageBuffer::SpecialHeader OutSpecialHeader{false, NumOutCopyHandles, NumOutMoveHandles, HasOutSpecialHeader};
|
||||||
|
|
||||||
static constexpr auto OutMessageHandleIndex = svc::ipc::MessageBuffer::GetSpecialDataIndex(OutMessageHeader, OutSpecialHeader);
|
static constexpr auto OutMessageHandleIndex = svc::ipc::MessageBuffer::GetSpecialDataIndex(OutMessageHeader, OutSpecialHeader);
|
||||||
static constexpr auto OutMessageRawDataIndex = svc::ipc::MessageBuffer::GetRawDataIndex(OutMessageHeader, OutSpecialHeader);
|
static constexpr auto OutMessageRawDataIndex = svc::ipc::MessageBuffer::GetRawDataIndex(OutMessageHeader, OutSpecialHeader);
|
||||||
|
@ -322,10 +327,6 @@ namespace ams::tipc::impl {
|
||||||
/* Save a copy of the current state to return. */
|
/* Save a copy of the current state to return. */
|
||||||
ArgumentSerializationInfo returned_info = current_info;
|
ArgumentSerializationInfo returned_info = current_info;
|
||||||
|
|
||||||
/* Clear previous iteration's fixed size. */
|
|
||||||
returned_info.fixed_size = 0;
|
|
||||||
current_info.fixed_size = 0;
|
|
||||||
|
|
||||||
constexpr auto arg_type = GetArgumentType<T>;
|
constexpr auto arg_type = GetArgumentType<T>;
|
||||||
returned_info.arg_type = arg_type;
|
returned_info.arg_type = arg_type;
|
||||||
if constexpr (arg_type == ArgumentType::InData) {
|
if constexpr (arg_type == ArgumentType::InData) {
|
||||||
|
@ -336,18 +337,18 @@ namespace ams::tipc::impl {
|
||||||
current_info.out_raw_data_index++;
|
current_info.out_raw_data_index++;
|
||||||
} else if constexpr (arg_type == ArgumentType::InHandle) {
|
} else if constexpr (arg_type == ArgumentType::InHandle) {
|
||||||
/* New InHandle, increment the appropriate index. */
|
/* New InHandle, increment the appropriate index. */
|
||||||
if constexpr (std::is_same<T, sf::MoveHandle>::value) {
|
if constexpr (std::is_same<T, tipc::MoveHandle>::value) {
|
||||||
current_info.in_move_handle_index++;
|
current_info.in_move_handle_index++;
|
||||||
} else if constexpr (std::is_same<T, sf::CopyHandle>::value) {
|
} else if constexpr (std::is_same<T, tipc::CopyHandle>::value) {
|
||||||
current_info.in_copy_handle_index++;
|
current_info.in_copy_handle_index++;
|
||||||
} else {
|
} else {
|
||||||
static_assert(!std::is_same<T, T>::value, "Invalid InHandle kind");
|
static_assert(!std::is_same<T, T>::value, "Invalid InHandle kind");
|
||||||
}
|
}
|
||||||
} else if constexpr (arg_type == ArgumentType::OutHandle) {
|
} else if constexpr (arg_type == ArgumentType::OutHandle) {
|
||||||
/* New OutHandle, increment the appropriate index. */
|
/* New OutHandle, increment the appropriate index. */
|
||||||
if constexpr (std::is_same<T, sf::Out<sf::MoveHandle>>::value) {
|
if constexpr (std::is_same<T, tipc::Out<tipc::MoveHandle>>::value) {
|
||||||
current_info.out_move_handle_index++;
|
current_info.out_move_handle_index++;
|
||||||
} else if constexpr (std::is_same<T, sf::Out<sf::CopyHandle>>::value) {
|
} else if constexpr (std::is_same<T, tipc::Out<tipc::CopyHandle>>::value) {
|
||||||
current_info.out_copy_handle_index++;
|
current_info.out_copy_handle_index++;
|
||||||
} else {
|
} else {
|
||||||
static_assert(!std::is_same<T, T>::value, "Invalid OutHandle kind");
|
static_assert(!std::is_same<T, T>::value, "Invalid OutHandle kind");
|
||||||
|
@ -477,12 +478,12 @@ namespace ams::tipc::impl {
|
||||||
static consteval u32 GetSpecialHeaderForCheck(const svc::ipc::MessageBuffer::SpecialHeader &header) {
|
static consteval u32 GetSpecialHeaderForCheck(const svc::ipc::MessageBuffer::SpecialHeader &header) {
|
||||||
using Value = util::BitPack32::Field<0, BITSIZEOF(util::BitPack32)>;
|
using Value = util::BitPack32::Field<0, BITSIZEOF(util::BitPack32)>;
|
||||||
|
|
||||||
return header->GetHeader()->Get<Value>();
|
return header.GetHeader()->Get<Value>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Argument deserialization. */
|
/* Argument deserialization. */
|
||||||
template<size_t Index, typename T = typename std::tuple_element<Index, ArgsType>::type>
|
template<size_t Index, typename T = typename std::tuple_element<Index, ArgsType>::type>
|
||||||
static ALWAYS_INLINE typename std::tuple_element<Index, ArgsTypeForInvoke>::type DeserializeArgumentImpl(const svc::ipc::MessageBuffer &message_buffer, const OutRawHolderType &out_raw_holder, OutHandleHolderType &out_handles_holder) {
|
static ALWAYS_INLINE typename std::tuple_element<Index, ArgsType>::type DeserializeArgumentImpl(const svc::ipc::MessageBuffer &message_buffer, const OutRawHolderType &out_raw_holder, OutHandleHolderType &out_handles_holder) {
|
||||||
constexpr auto Info = CommandMeta::ArgumentSerializationInfos[Index];
|
constexpr auto Info = CommandMeta::ArgumentSerializationInfos[Index];
|
||||||
if constexpr (Info.arg_type == ArgumentType::InData) {
|
if constexpr (Info.arg_type == ArgumentType::InData) {
|
||||||
/* New in rawdata. */
|
/* New in rawdata. */
|
||||||
|
@ -490,17 +491,21 @@ namespace ams::tipc::impl {
|
||||||
constexpr size_t RawIndex = Offset / sizeof(u32);
|
constexpr size_t RawIndex = Offset / sizeof(u32);
|
||||||
static_assert(Offset == RawIndex * sizeof(u32)); /* TODO: Do unaligned data exist? */
|
static_assert(Offset == RawIndex * sizeof(u32)); /* TODO: Do unaligned data exist? */
|
||||||
|
|
||||||
return message_buffer.GetRaw(InMessageRawDataIndex + RawIndex);
|
if constexpr (!std::same_as<T, bool>) {
|
||||||
|
return message_buffer.GetRaw<T>(CommandMeta::InMessageRawDataIndex + RawIndex);
|
||||||
|
} else {
|
||||||
|
return message_buffer.GetRaw<u8>(CommandMeta::InMessageRawDataIndex + RawIndex) & 1;
|
||||||
|
}
|
||||||
} else if constexpr (Info.arg_type == ArgumentType::OutData) {
|
} else if constexpr (Info.arg_type == ArgumentType::OutData) {
|
||||||
/* New out rawdata. */
|
/* New out rawdata. */
|
||||||
constexpr size_t Offset = CommandMeta::OutDataOffsets[Info.out_raw_data_index];
|
constexpr size_t Offset = CommandMeta::OutDataOffsets[Info.out_raw_data_index];
|
||||||
return T(out_raw_holder.template GetAddress<Offset, T::TypeSize>());
|
return T(out_raw_holder.template GetAddress<Offset, T::TypeSize>());
|
||||||
} else if constexpr (Info.arg_type == ArgumentType::InHandle) {
|
} else if constexpr (Info.arg_type == ArgumentType::InHandle) {
|
||||||
/* New InHandle. */
|
/* New InHandle. */
|
||||||
if constexpr (std::is_same<T, sf::MoveHandle>::value) {
|
if constexpr (std::is_same<T, tipc::MoveHandle>::value) {
|
||||||
constexpr auto HandleIndex = CommandMeta::InMessageHandleIndex + CommandMeta::NumInCopyHandles + Info.in_move_handle_index;
|
constexpr auto HandleIndex = CommandMeta::InMessageHandleIndex + CommandMeta::NumInCopyHandles + Info.in_move_handle_index;
|
||||||
return T(message_buffer.GetHandle(HandleIndex));
|
return T(message_buffer.GetHandle(HandleIndex));
|
||||||
} else if constexpr (std::is_same<T, sf::CopyHandle>::value) {
|
} else if constexpr (std::is_same<T, tipc::CopyHandle>::value) {
|
||||||
constexpr auto HandleIndex = CommandMeta::InMessageHandleIndex + Info.in_copy_handle_index;
|
constexpr auto HandleIndex = CommandMeta::InMessageHandleIndex + Info.in_copy_handle_index;
|
||||||
return T(message_buffer.GetHandle(HandleIndex));
|
return T(message_buffer.GetHandle(HandleIndex));
|
||||||
} else {
|
} else {
|
||||||
|
@ -508,9 +513,9 @@ namespace ams::tipc::impl {
|
||||||
}
|
}
|
||||||
} else if constexpr (Info.arg_type == ArgumentType::OutHandle) {
|
} else if constexpr (Info.arg_type == ArgumentType::OutHandle) {
|
||||||
/* New OutHandle. */
|
/* New OutHandle. */
|
||||||
if constexpr (std::is_same<T, sf::Out<sf::MoveHandle>>::value) {
|
if constexpr (std::is_same<T, tipc::Out<tipc::MoveHandle>>::value) {
|
||||||
return T(out_handles_holder.template GetMoveHandlePointer<Info.out_move_handle_index>());
|
return T(out_handles_holder.template GetMoveHandlePointer<Info.out_move_handle_index>());
|
||||||
} else if constexpr (std::is_same<T, sf::Out<sf::CopyHandle>>::value) {
|
} else if constexpr (std::is_same<T, tipc::Out<tipc::CopyHandle>>::value) {
|
||||||
return T(out_handles_holder.template GetCopyHandlePointer<Info.out_copy_handle_index>());
|
return T(out_handles_holder.template GetCopyHandlePointer<Info.out_copy_handle_index>());
|
||||||
} else {
|
} else {
|
||||||
static_assert(!std::is_same<T, T>::value, "Invalid OutHandle kind");
|
static_assert(!std::is_same<T, T>::value, "Invalid OutHandle kind");
|
||||||
|
@ -518,16 +523,17 @@ namespace ams::tipc::impl {
|
||||||
} else if constexpr (Info.arg_type == ArgumentType::Buffer) {
|
} else if constexpr (Info.arg_type == ArgumentType::Buffer) {
|
||||||
/* NOTE: There are currently no tipc commands which use buffers-with-attributes */
|
/* NOTE: There are currently no tipc commands which use buffers-with-attributes */
|
||||||
/* If these are added (e.g., NonSecure buffers), implement checking here? */
|
/* If these are added (e.g., NonSecure buffers), implement checking here? */
|
||||||
|
constexpr size_t MapAliasDescriptorSize = svc::ipc::MessageBuffer::MapAliasDescriptor::GetDataSize();
|
||||||
|
|
||||||
if constexpr (Info.is_send_buffer) {
|
if constexpr (Info.is_send_buffer) {
|
||||||
/* Input send buffer. */
|
/* Input send buffer. */
|
||||||
constexpr auto BufferIndex = CommandMeta::InMessageBufferIndex + (Info.send_map_alias_index * MapAliasDescriptor::GetDataSize() / sizeof(util::BitPack32));
|
constexpr auto BufferIndex = CommandMeta::InMessageBufferIndex + (Info.send_map_alias_index * MapAliasDescriptorSize / sizeof(util::BitPack32));
|
||||||
|
|
||||||
const svc::ipc::MessageBuffer::MapAliasDescriptor descriptor(message_buffer, BufferIndex);
|
const svc::ipc::MessageBuffer::MapAliasDescriptor descriptor(message_buffer, BufferIndex);
|
||||||
return T(tipc::PointerAndSize(descriptor.GetAddress(), descriptor.GetSize()));
|
return T(tipc::PointerAndSize(descriptor.GetAddress(), descriptor.GetSize()));
|
||||||
} else {
|
} else {
|
||||||
/* Input receive buffer. */
|
/* Input receive buffer. */
|
||||||
constexpr auto BufferIndex = CommandMeta::InMessageBufferIndex + ((CommandMeta::NumInBuffers + Info.recv_map_alias_index) * MapAliasDescriptor::GetDataSize() / sizeof(util::BitPack32));
|
constexpr auto BufferIndex = CommandMeta::InMessageBufferIndex + ((CommandMeta::NumInBuffers + Info.recv_map_alias_index) * MapAliasDescriptorSize / sizeof(util::BitPack32));
|
||||||
|
|
||||||
const svc::ipc::MessageBuffer::MapAliasDescriptor descriptor(message_buffer, BufferIndex);
|
const svc::ipc::MessageBuffer::MapAliasDescriptor descriptor(message_buffer, BufferIndex);
|
||||||
return T(tipc::PointerAndSize(descriptor.GetAddress(), descriptor.GetSize()));
|
return T(tipc::PointerAndSize(descriptor.GetAddress(), descriptor.GetSize()));
|
||||||
|
@ -540,8 +546,8 @@ namespace ams::tipc::impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<size_t... Is>
|
template<size_t... Is>
|
||||||
static ALWAYS_INLINE ArgsTypeForInvoke DeserializeArgumentsImpl(const svc::ipc::MessageBuffer &message_buffer, const OutRawHolderType &out_raw_holder, OutHandleHolderType &out_handles_holder, std::index_sequence<Is...>) {
|
static ALWAYS_INLINE ArgsType DeserializeArgumentsImpl(const svc::ipc::MessageBuffer &message_buffer, const OutRawHolderType &out_raw_holder, OutHandleHolderType &out_handles_holder, std::index_sequence<Is...>) {
|
||||||
return ArgsTypeForInvoke { DeserializeArgumentImpl<Is>(message_buffer, out_raw_holder, out_handles_holder, in_out_objects_holder)..., };
|
return ArgsType { DeserializeArgumentImpl<Is>(message_buffer, out_raw_holder, out_handles_holder)..., };
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
static ALWAYS_INLINE Result ValidateCommandFormat(const svc::ipc::MessageBuffer &message_buffer) {
|
static ALWAYS_INLINE Result ValidateCommandFormat(const svc::ipc::MessageBuffer &message_buffer) {
|
||||||
|
@ -555,16 +561,35 @@ namespace ams::tipc::impl {
|
||||||
constexpr auto SpecialHeaderIndex = svc::ipc::MessageBuffer::MessageHeader::GetDataSize() / sizeof(util::BitPack32);
|
constexpr auto SpecialHeaderIndex = svc::ipc::MessageBuffer::MessageHeader::GetDataSize() / sizeof(util::BitPack32);
|
||||||
R_UNLESS(message_buffer.Get32(SpecialHeaderIndex) == ExpectedSpecialHeader, tipc::ResultInvalidMessageFormat());
|
R_UNLESS(message_buffer.Get32(SpecialHeaderIndex) == ExpectedSpecialHeader, tipc::ResultInvalidMessageFormat());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
static ALWAYS_INLINE ArgsType DeserializeArguments(const svc::ipc::MessageBuffer &message_buffer, const OutRawHolderType &out_raw_holder, OutHandleHolderType &out_handles_holder) {
|
static ALWAYS_INLINE ArgsType DeserializeArguments(const svc::ipc::MessageBuffer &message_buffer, const OutRawHolderType &out_raw_holder, OutHandleHolderType &out_handles_holder) {
|
||||||
return DeserializeArgumentsImpl(message_buffer, out_raw_holder, out_handles_holder, std::make_index_sequence<std::tuple_size<ArgsType>::value>{});
|
return DeserializeArgumentsImpl(message_buffer, out_raw_holder, out_handles_holder, std::make_index_sequence<std::tuple_size<ArgsType>::value>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ALWAYS_INLINE void SerializeResults(const svc::ipc::MessageBuffer &message_buffer, const Result &result, const OutRawHolderType &out_raw_holder, const OutHandleHolderType &out_handles_holder) {
|
||||||
|
/* Set output headers. */
|
||||||
|
message_buffer.Set(CommandMeta::OutMessageHeader);
|
||||||
|
if constexpr (CommandMeta::HasOutSpecialHeader) {
|
||||||
|
message_buffer.Set(CommandMeta::OutSpecialHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set output handles. */
|
||||||
|
out_handles_holder.CopyTo(message_buffer);
|
||||||
|
|
||||||
|
/* Set output data. */
|
||||||
|
out_raw_holder.CopyTo(message_buffer);
|
||||||
|
|
||||||
|
/* Set output result. */
|
||||||
|
message_buffer.Set(CommandMeta::OutMessageResultIndex, result.GetValue());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<auto ServiceCommandImpl, typename Return, typename ClassType, typename... Arguments>
|
template<auto ServiceCommandImpl, u16 _CommmandId, typename Return, typename ClassType, typename... Arguments>
|
||||||
constexpr ALWAYS_INLINE Result InvokeServiceCommandImpl(ClassType *object) {
|
constexpr ALWAYS_INLINE Result InvokeServiceCommandImpl(ClassType *object, const svc::ipc::MessageBuffer &message_buffer) {
|
||||||
using CommandMeta = CommandMetaInfo<Arguments...>;
|
using CommandMeta = CommandMetaInfo<_CommmandId, Arguments...>;
|
||||||
using Processor = CommandProcessor<CommandMeta>;
|
using Processor = CommandProcessor<CommandMeta>;
|
||||||
/* TODO: ValidateClassType is valid? */
|
/* TODO: ValidateClassType is valid? */
|
||||||
|
|
||||||
|
@ -572,16 +597,13 @@ namespace ams::tipc::impl {
|
||||||
constexpr bool ReturnsVoid = std::is_same<Return, void>::value;
|
constexpr bool ReturnsVoid = std::is_same<Return, void>::value;
|
||||||
static_assert(ReturnsResult || ReturnsVoid, "Service Commands must return Result or void.");
|
static_assert(ReturnsResult || ReturnsVoid, "Service Commands must return Result or void.");
|
||||||
|
|
||||||
/* Create accessor to the message buffer. */
|
|
||||||
svc::ipc::MessageBuffer message_buffer(svc::ipc::GetMessageBuffer());
|
|
||||||
|
|
||||||
/* Validate that the command is valid. */
|
/* Validate that the command is valid. */
|
||||||
R_TRY(Processor::ValidateCommandFormat(message_buffer));
|
R_TRY(Processor::ValidateCommandFormat(message_buffer));
|
||||||
|
|
||||||
/* Deserialize arguments. */
|
/* Deserialize arguments. */
|
||||||
Processor::OutRawHolderType out_raw_holder;
|
typename Processor::OutRawHolderType out_raw_holder;
|
||||||
Processor::OutHandleHolderType out_handles_holder;
|
typename Processor::OutHandleHolderType out_handles_holder;
|
||||||
const Result command_result = [object]<size_t... Ix>(std::index_sequence<Ix...>) ALWAYS_INLINE_LAMBDA {
|
const Result command_result = [&]<size_t... Ix>(std::index_sequence<Ix...>) ALWAYS_INLINE_LAMBDA {
|
||||||
auto args_tuple = Processor::DeserializeArguments(message_buffer, out_raw_holder, out_handles_holder);
|
auto args_tuple = Processor::DeserializeArguments(message_buffer, out_raw_holder, out_handles_holder);
|
||||||
|
|
||||||
using TrueArgumentsTuple = std::tuple<Arguments...>;
|
using TrueArgumentsTuple = std::tuple<Arguments...>;
|
||||||
|
@ -595,22 +617,7 @@ namespace ams::tipc::impl {
|
||||||
}(std::make_index_sequence<std::tuple_size<typename CommandMeta::ArgsType>::value>());
|
}(std::make_index_sequence<std::tuple_size<typename CommandMeta::ArgsType>::value>());
|
||||||
|
|
||||||
/* Serialize output. */
|
/* Serialize output. */
|
||||||
{
|
Processor::SerializeResults(message_buffer, command_result, out_raw_holder, out_handles_holder);
|
||||||
/* Set output headers. */
|
|
||||||
message_buffer.Set(CommandMeta::OutMessageHeader);
|
|
||||||
if constexpr (CommandMeta::HasOutSpecialHeader) {
|
|
||||||
message_buffer.Set(CommandMeta::OutSpecialHeader);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set output handles. */
|
|
||||||
out_handles_holder.CopyTo(message_buffer);
|
|
||||||
|
|
||||||
/* Set output data. */
|
|
||||||
out_raw_holder.CopyTo(message_buffer);
|
|
||||||
|
|
||||||
/* Set output result. */
|
|
||||||
message_buffer.Set(CommandMeta::OutMessageResultIndex, command_result.GetValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,213 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <stratosphere/tipc/tipc_common.hpp>
|
||||||
|
#include <stratosphere/tipc/tipc_out.hpp>
|
||||||
|
#include <stratosphere/tipc/tipc_pointer_and_size.hpp>
|
||||||
|
|
||||||
|
namespace ams::tipc {
|
||||||
|
|
||||||
|
namespace impl {
|
||||||
|
|
||||||
|
/* Buffer utilities. */
|
||||||
|
struct BufferBaseTag{};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace impl {
|
||||||
|
|
||||||
|
class BufferBase : public BufferBaseTag {
|
||||||
|
public:
|
||||||
|
static constexpr u32 AdditionalAttributes = 0;
|
||||||
|
private:
|
||||||
|
const tipc::PointerAndSize pas;
|
||||||
|
protected:
|
||||||
|
constexpr ALWAYS_INLINE uintptr_t GetAddressImpl() const {
|
||||||
|
return this->pas.GetAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Entry>
|
||||||
|
constexpr ALWAYS_INLINE size_t GetSizeImpl() const {
|
||||||
|
return this->pas.GetSize() / sizeof(Entry);
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
constexpr ALWAYS_INLINE BufferBase() : pas() { /* ... */ }
|
||||||
|
constexpr ALWAYS_INLINE BufferBase(const tipc::PointerAndSize &_pas) : pas(_pas) { /* ... */ }
|
||||||
|
constexpr ALWAYS_INLINE BufferBase(uintptr_t ptr, size_t sz) : pas(ptr, sz) { /* ... */ }
|
||||||
|
};
|
||||||
|
|
||||||
|
class InBufferBase : public BufferBase {
|
||||||
|
public:
|
||||||
|
using BaseType = BufferBase;
|
||||||
|
static constexpr u32 AdditionalAttributes = BaseType::AdditionalAttributes |
|
||||||
|
SfBufferAttr_In;
|
||||||
|
public:
|
||||||
|
constexpr ALWAYS_INLINE InBufferBase() : BaseType() { /* ... */ }
|
||||||
|
constexpr ALWAYS_INLINE InBufferBase(const tipc::PointerAndSize &_pas) : BaseType(_pas) { /* ... */ }
|
||||||
|
constexpr ALWAYS_INLINE InBufferBase(uintptr_t ptr, size_t sz) : BaseType(ptr, sz) { /* ... */ }
|
||||||
|
|
||||||
|
constexpr ALWAYS_INLINE InBufferBase(const void *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
|
||||||
|
constexpr ALWAYS_INLINE InBufferBase(const u8 *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
|
||||||
|
};
|
||||||
|
|
||||||
|
class OutBufferBase : public BufferBase {
|
||||||
|
public:
|
||||||
|
using BaseType = BufferBase;
|
||||||
|
static constexpr u32 AdditionalAttributes = BaseType::AdditionalAttributes |
|
||||||
|
SfBufferAttr_Out;
|
||||||
|
public:
|
||||||
|
constexpr ALWAYS_INLINE OutBufferBase() : BaseType() { /* ... */ }
|
||||||
|
constexpr ALWAYS_INLINE OutBufferBase(const tipc::PointerAndSize &_pas) : BaseType(_pas) { /* ... */ }
|
||||||
|
constexpr ALWAYS_INLINE OutBufferBase(uintptr_t ptr, size_t sz) : BaseType(ptr, sz) { /* ... */ }
|
||||||
|
|
||||||
|
constexpr ALWAYS_INLINE OutBufferBase(void *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
|
||||||
|
constexpr ALWAYS_INLINE OutBufferBase(u8 *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<u32 ExtraAttributes = 0>
|
||||||
|
class InBufferImpl : public InBufferBase {
|
||||||
|
public:
|
||||||
|
using BaseType = InBufferBase;
|
||||||
|
static constexpr u32 AdditionalAttributes = BaseType::AdditionalAttributes |
|
||||||
|
ExtraAttributes;
|
||||||
|
public:
|
||||||
|
constexpr ALWAYS_INLINE InBufferImpl() : BaseType() { /* ... */ }
|
||||||
|
constexpr ALWAYS_INLINE InBufferImpl(const tipc::PointerAndSize &_pas) : BaseType(_pas) { /* ... */ }
|
||||||
|
constexpr ALWAYS_INLINE InBufferImpl(uintptr_t ptr, size_t sz) : BaseType(ptr, sz) { /* ... */ }
|
||||||
|
|
||||||
|
constexpr ALWAYS_INLINE InBufferImpl(const void *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
|
||||||
|
constexpr ALWAYS_INLINE InBufferImpl(const u8 *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
|
||||||
|
|
||||||
|
constexpr ALWAYS_INLINE const u8 *GetPointer() const {
|
||||||
|
return reinterpret_cast<const u8 *>(this->GetAddressImpl());
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr ALWAYS_INLINE size_t GetSize() const {
|
||||||
|
return this->GetSizeImpl<u8>();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<u32 ExtraAttributes = 0>
|
||||||
|
class OutBufferImpl : public OutBufferBase {
|
||||||
|
public:
|
||||||
|
using BaseType = OutBufferBase;
|
||||||
|
static constexpr u32 AdditionalAttributes = BaseType::AdditionalAttributes |
|
||||||
|
ExtraAttributes;
|
||||||
|
public:
|
||||||
|
constexpr ALWAYS_INLINE OutBufferImpl() : BaseType() { /* ... */ }
|
||||||
|
constexpr ALWAYS_INLINE OutBufferImpl(const tipc::PointerAndSize &_pas) : BaseType(_pas) { /* ... */ }
|
||||||
|
constexpr ALWAYS_INLINE OutBufferImpl(uintptr_t ptr, size_t sz) : BaseType(ptr, sz) { /* ... */ }
|
||||||
|
|
||||||
|
constexpr ALWAYS_INLINE OutBufferImpl(void *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
|
||||||
|
constexpr ALWAYS_INLINE OutBufferImpl(u8 *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
|
||||||
|
|
||||||
|
constexpr ALWAYS_INLINE u8 *GetPointer() const {
|
||||||
|
return reinterpret_cast<u8 *>(this->GetAddressImpl());
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr ALWAYS_INLINE size_t GetSize() const {
|
||||||
|
return this->GetSizeImpl<u8>();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct InArrayImpl : public InBufferBase {
|
||||||
|
public:
|
||||||
|
using BaseType = InBufferBase;
|
||||||
|
static constexpr u32 AdditionalAttributes = BaseType::AdditionalAttributes;
|
||||||
|
public:
|
||||||
|
constexpr ALWAYS_INLINE InArrayImpl() : BaseType() { /* ... */ }
|
||||||
|
constexpr ALWAYS_INLINE InArrayImpl(const tipc::PointerAndSize &_pas) : BaseType(_pas) { /* ... */ }
|
||||||
|
constexpr ALWAYS_INLINE InArrayImpl(const T *ptr, size_t num_elements) : BaseType(reinterpret_cast<uintptr_t>(ptr), num_elements * sizeof(T)) { /* ... */ }
|
||||||
|
|
||||||
|
constexpr ALWAYS_INLINE const T *GetPointer() const {
|
||||||
|
return reinterpret_cast<const T *>(this->GetAddressImpl());
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr ALWAYS_INLINE size_t GetSize() const {
|
||||||
|
return this->GetSizeImpl<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr ALWAYS_INLINE const T &operator[](size_t i) const {
|
||||||
|
return this->GetPointer()[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr explicit ALWAYS_INLINE operator Span<const T>() const {
|
||||||
|
return {this->GetPointer(), this->GetSize()};
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr ALWAYS_INLINE Span<const T> ToSpan() const {
|
||||||
|
return {this->GetPointer(), this->GetSize()};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct OutArrayImpl : public OutBufferBase {
|
||||||
|
public:
|
||||||
|
using BaseType = OutBufferBase;
|
||||||
|
static constexpr u32 AdditionalAttributes = BaseType::AdditionalAttributes;
|
||||||
|
public:
|
||||||
|
constexpr ALWAYS_INLINE OutArrayImpl() : BaseType() { /* ... */ }
|
||||||
|
constexpr ALWAYS_INLINE OutArrayImpl(const tipc::PointerAndSize &_pas) : BaseType(_pas) { /* ... */ }
|
||||||
|
constexpr ALWAYS_INLINE OutArrayImpl(T *ptr, size_t num_elements) : BaseType(reinterpret_cast<uintptr_t>(ptr), num_elements * sizeof(T)) { /* ... */ }
|
||||||
|
|
||||||
|
constexpr ALWAYS_INLINE T *GetPointer() const {
|
||||||
|
return reinterpret_cast<T *>(this->GetAddressImpl());
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr ALWAYS_INLINE size_t GetSize() const {
|
||||||
|
return this->GetSizeImpl<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr ALWAYS_INLINE T &operator[](size_t i) const {
|
||||||
|
return this->GetPointer()[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr explicit ALWAYS_INLINE operator Span<T>() const {
|
||||||
|
return {this->GetPointer(), this->GetSize()};
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr ALWAYS_INLINE Span<T> ToSpan() const {
|
||||||
|
return {this->GetPointer(), this->GetSize()};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Buffer Types. */
|
||||||
|
using InBuffer = typename impl::InBufferImpl<>;
|
||||||
|
// using InNonSecureBuffer = typename impl::InBufferImpl<SfBufferAttr_HipcMapTransferAllowsNonSecure>;
|
||||||
|
// using InNonDeviceBuffer = typename impl::InBufferImpl<SfBufferAttr_HipcMapTransferAllowsNonDevice>;
|
||||||
|
|
||||||
|
using OutBuffer = typename impl::OutBufferImpl<>;
|
||||||
|
//using OutNonSecureBuffer = typename impl::OutBufferImpl<SfBufferAttr_HipcMapTransferAllowsNonSecure>;
|
||||||
|
//using OutNonDeviceBuffer = typename impl::OutBufferImpl<SfBufferAttr_HipcMapTransferAllowsNonDevice>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using InArray = typename impl::InArrayImpl<T>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using OutArray = typename impl::OutArrayImpl<T>;
|
||||||
|
|
||||||
|
/* Attribute serialization structs. */
|
||||||
|
template<typename T>
|
||||||
|
concept IsBuffer = std::derived_from<T, impl::BufferBaseTag>;
|
||||||
|
|
||||||
|
template<typename T> requires IsBuffer<T>
|
||||||
|
constexpr inline u32 BufferAttributes = SfBufferAttr_HipcMapAlias | T::AdditionalAttributes;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <vapours.hpp>
|
||||||
|
#include <stratosphere/ams.hpp>
|
||||||
|
#include <stratosphere/os.hpp>
|
||||||
|
#include <stratosphere/sm/sm_types.hpp>
|
|
@ -0,0 +1,170 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <stratosphere/tipc/tipc_common.hpp>
|
||||||
|
#include <stratosphere/tipc/tipc_out.hpp>
|
||||||
|
#include <stratosphere/tipc/tipc_pointer_and_size.hpp>
|
||||||
|
|
||||||
|
namespace ams::tipc {
|
||||||
|
|
||||||
|
namespace impl {
|
||||||
|
|
||||||
|
struct InHandleTag{};
|
||||||
|
struct OutHandleTag{};
|
||||||
|
|
||||||
|
template<u32 Attribute>
|
||||||
|
struct InHandle : public InHandleTag {
|
||||||
|
::Handle handle;
|
||||||
|
|
||||||
|
constexpr InHandle() : handle(INVALID_HANDLE) { /* ... */ }
|
||||||
|
constexpr InHandle(::Handle h) : handle(h) { /* ... */ }
|
||||||
|
constexpr InHandle(const InHandle &o) : handle(o.handle) { /* ... */ }
|
||||||
|
|
||||||
|
constexpr void operator=(const ::Handle &h) { this->handle = h; }
|
||||||
|
constexpr void operator=(const InHandle &o) { this->handle = o.handle; }
|
||||||
|
|
||||||
|
constexpr /* TODO: explicit? */ operator ::Handle() const { return this->handle; }
|
||||||
|
constexpr ::Handle GetValue() const { return this->handle; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class OutHandleImpl : public OutHandleTag {
|
||||||
|
static_assert(std::is_base_of<InHandleTag, T>::value, "OutHandleImpl requires InHandle base");
|
||||||
|
private:
|
||||||
|
T *ptr;
|
||||||
|
public:
|
||||||
|
constexpr OutHandleImpl(T *p) : ptr(p) { /* ... */ }
|
||||||
|
|
||||||
|
constexpr void SetValue(const Handle &value) {
|
||||||
|
*this->ptr = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void SetValue(const T &value) {
|
||||||
|
*this->ptr = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const T &GetValue() const {
|
||||||
|
return *this->ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr T *GetPointer() const {
|
||||||
|
return this->ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Handle *GetHandlePointer() const {
|
||||||
|
return &this->ptr->handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr T &operator *() const {
|
||||||
|
return *this->ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr T *operator ->() const {
|
||||||
|
return this->ptr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
using MoveHandle = typename impl::InHandle<SfOutHandleAttr_HipcMove>;
|
||||||
|
using CopyHandle = typename impl::InHandle<SfOutHandleAttr_HipcCopy>;
|
||||||
|
|
||||||
|
static_assert(sizeof(MoveHandle) == sizeof(::Handle), "sizeof(MoveHandle)");
|
||||||
|
static_assert(sizeof(CopyHandle) == sizeof(::Handle), "sizeof(CopyHandle)");
|
||||||
|
|
||||||
|
template<>
|
||||||
|
class IsOutForceEnabled<MoveHandle> : public std::true_type{};
|
||||||
|
template<>
|
||||||
|
class IsOutForceEnabled<CopyHandle> : public std::true_type{};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
class Out<MoveHandle> : public impl::OutHandleImpl<MoveHandle> {
|
||||||
|
private:
|
||||||
|
using T = MoveHandle;
|
||||||
|
using Base = impl::OutHandleImpl<T>;
|
||||||
|
public:
|
||||||
|
constexpr Out<T>(T *p) : Base(p) { /* ... */ }
|
||||||
|
|
||||||
|
constexpr void SetValue(const Handle &value) {
|
||||||
|
Base::SetValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void SetValue(const T &value) {
|
||||||
|
Base::SetValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const T &GetValue() const {
|
||||||
|
return Base::GetValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr T *GetPointer() const {
|
||||||
|
return Base::GetPointer();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Handle *GetHandlePointer() const {
|
||||||
|
return Base::GetHandlePointer();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr T &operator *() const {
|
||||||
|
return Base::operator*();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr T *operator ->() const {
|
||||||
|
return Base::operator->();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
class Out<CopyHandle> : public impl::OutHandleImpl<CopyHandle> {
|
||||||
|
private:
|
||||||
|
using T = CopyHandle;
|
||||||
|
using Base = impl::OutHandleImpl<T>;
|
||||||
|
public:
|
||||||
|
constexpr Out<T>(T *p) : Base(p) { /* ... */ }
|
||||||
|
|
||||||
|
constexpr void SetValue(const Handle &value) {
|
||||||
|
Base::SetValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void SetValue(const T &value) {
|
||||||
|
Base::SetValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const T &GetValue() const {
|
||||||
|
return Base::GetValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr T *GetPointer() const {
|
||||||
|
return Base::GetPointer();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Handle *GetHandlePointer() const {
|
||||||
|
return Base::GetHandlePointer();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr T &operator *() const {
|
||||||
|
return Base::operator*();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr T *operator ->() const {
|
||||||
|
return Base::operator->();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using OutMoveHandle = tipc::Out<tipc::MoveHandle>;
|
||||||
|
using OutCopyHandle = tipc::Out<tipc::CopyHandle>;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <stratosphere/tipc/tipc_common.hpp>
|
||||||
|
#include <stratosphere/tipc/tipc_pointer_and_size.hpp>
|
||||||
|
|
||||||
|
namespace ams::tipc {
|
||||||
|
|
||||||
|
namespace impl {
|
||||||
|
|
||||||
|
struct OutBaseTag{};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename>
|
||||||
|
struct IsOutForceEnabled : public std::false_type{};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct IsOutForceEnabled<::ams::Result> : public std::true_type{};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept OutEnabled = (std::is_trivial<T>::value || IsOutForceEnabled<T>::value) && !std::is_pointer<T>::value;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class Out : public impl::OutBaseTag {
|
||||||
|
static_assert(OutEnabled<T>);
|
||||||
|
public:
|
||||||
|
static constexpr size_t TypeSize = sizeof(T);
|
||||||
|
private:
|
||||||
|
T *ptr;
|
||||||
|
public:
|
||||||
|
constexpr Out(uintptr_t p) : ptr(reinterpret_cast<T *>(p)) { /* ... */ }
|
||||||
|
constexpr Out(T *p) : ptr(p) { /* ... */ }
|
||||||
|
constexpr Out(const tipc::PointerAndSize &pas) : ptr(reinterpret_cast<T *>(pas.GetAddress())) { /* TODO: Is AMS_ABORT_UNLESS(pas.GetSize() >= sizeof(T)); necessary? */ }
|
||||||
|
|
||||||
|
ALWAYS_INLINE void SetValue(const T& value) const {
|
||||||
|
*this->ptr = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE const T &GetValue() const {
|
||||||
|
return *this->ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE T *GetPointer() const {
|
||||||
|
return this->ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convenience operators. */
|
||||||
|
ALWAYS_INLINE T &operator*() const {
|
||||||
|
return *this->ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE T *operator->() const {
|
||||||
|
return this->ptr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class Out<T *> {
|
||||||
|
static_assert(!std::is_same<T, T>::value, "Invalid tipc::Out<T> (Raw Pointer)");
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <stratosphere/tipc/tipc_pointer_and_size.hpp>
|
||||||
|
|
||||||
|
namespace ams::tipc {
|
||||||
|
|
||||||
|
class PointerAndSize {
|
||||||
|
private:
|
||||||
|
uintptr_t pointer;
|
||||||
|
size_t size;
|
||||||
|
public:
|
||||||
|
constexpr PointerAndSize() : pointer(0), size(0) { /* ... */ }
|
||||||
|
constexpr PointerAndSize(uintptr_t ptr, size_t sz) : pointer(ptr), size(sz) { /* ... */ }
|
||||||
|
constexpr PointerAndSize(void *ptr, size_t sz) : PointerAndSize(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
|
||||||
|
|
||||||
|
constexpr ALWAYS_INLINE void *GetPointer() const {
|
||||||
|
return reinterpret_cast<void *>(this->pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr ALWAYS_INLINE uintptr_t GetAddress() const {
|
||||||
|
return this->pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr ALWAYS_INLINE size_t GetSize() const {
|
||||||
|
return this->size;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include <stratosphere.hpp>
|
||||||
|
|
||||||
|
namespace ams::_test {
|
||||||
|
|
||||||
|
class UserInterfaceFacade {
|
||||||
|
public:
|
||||||
|
Result RegisterClient(const tipc::ClientProcessId &process_id);
|
||||||
|
Result GetServiceHandle(tipc::OutMoveHandle out_h, sm::ServiceName service);
|
||||||
|
Result RegisterService(tipc::OutMoveHandle out_h, sm::ServiceName service, u32 max_sessions, bool is_light);
|
||||||
|
Result UnregisterService(sm::ServiceName service);
|
||||||
|
};
|
||||||
|
|
||||||
|
Result TestRegisterClient(UserInterfaceFacade *facade, const svc::ipc::MessageBuffer &message_buffer) {
|
||||||
|
return tipc::impl::InvokeServiceCommandImpl<&UserInterfaceFacade::RegisterClient, 16, Result, UserInterfaceFacade, const tipc::ClientProcessId &>(facade, message_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result TestGetServiceHandle(UserInterfaceFacade *facade, const svc::ipc::MessageBuffer &message_buffer) {
|
||||||
|
return tipc::impl::InvokeServiceCommandImpl<&UserInterfaceFacade::GetServiceHandle, 17, Result, UserInterfaceFacade, tipc::OutMoveHandle, sm::ServiceName>(facade, message_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result TestRegisterService(UserInterfaceFacade *facade, const svc::ipc::MessageBuffer &message_buffer) {
|
||||||
|
return tipc::impl::InvokeServiceCommandImpl<&UserInterfaceFacade::RegisterService, 18, Result, UserInterfaceFacade, tipc::OutMoveHandle, sm::ServiceName, u32, bool>(facade, message_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result TestUnregisterService(UserInterfaceFacade *facade, const svc::ipc::MessageBuffer &message_buffer) {
|
||||||
|
return tipc::impl::InvokeServiceCommandImpl<&UserInterfaceFacade::UnregisterService, 19, Result, UserInterfaceFacade, sm::ServiceName>(facade, message_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result TestManualDispatch(UserInterfaceFacade *facade) {
|
||||||
|
svc::ipc::MessageBuffer message_buffer(svc::ipc::GetMessageBuffer());
|
||||||
|
|
||||||
|
switch (svc::ipc::MessageBuffer::MessageHeader(message_buffer).GetTag()) {
|
||||||
|
case 16:
|
||||||
|
return tipc::impl::InvokeServiceCommandImpl<&UserInterfaceFacade::RegisterClient, 16, Result, UserInterfaceFacade, const tipc::ClientProcessId &>(facade, message_buffer);
|
||||||
|
case 17:
|
||||||
|
return tipc::impl::InvokeServiceCommandImpl<&UserInterfaceFacade::GetServiceHandle, 17, Result, UserInterfaceFacade, tipc::OutMoveHandle, sm::ServiceName>(facade, message_buffer);
|
||||||
|
case 18:
|
||||||
|
return tipc::impl::InvokeServiceCommandImpl<&UserInterfaceFacade::RegisterService, 18, Result, UserInterfaceFacade, tipc::OutMoveHandle, sm::ServiceName, u32, bool>(facade, message_buffer);
|
||||||
|
case 19:
|
||||||
|
return tipc::impl::InvokeServiceCommandImpl<&UserInterfaceFacade::UnregisterService, 19, Result, UserInterfaceFacade, sm::ServiceName>(facade, message_buffer);
|
||||||
|
default:
|
||||||
|
return tipc::ResultInvalidMethod();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -152,6 +152,14 @@ namespace ams::svc::ipc {
|
||||||
this->header.Set<MoveHandleCount>(move);
|
this->header.Set<MoveHandleCount>(move);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
consteval explicit SpecialHeader(bool pid, s32 copy, s32 move, bool _has_header) : header{0}, has_header(_has_header) {
|
||||||
|
this->header.Set<HasProcessId>(pid);
|
||||||
|
this->header.Set<CopyHandleCount>(copy);
|
||||||
|
this->header.Set<MoveHandleCount>(move);
|
||||||
|
|
||||||
|
AMS_ASSUME(this->has_header == (this->GetHasProcessId() || this->GetCopyHandleCount() > 0 || this->GetMoveHandleCount() > 0));
|
||||||
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE explicit SpecialHeader(const MessageBuffer &buf, const MessageHeader &hdr) : header{0}, has_header(hdr.GetHasSpecialHeader()) {
|
ALWAYS_INLINE explicit SpecialHeader(const MessageBuffer &buf, const MessageHeader &hdr) : header{0}, has_header(hdr.GetHasSpecialHeader()) {
|
||||||
if (this->has_header) {
|
if (this->has_header) {
|
||||||
buf.Get(MessageHeader::GetDataSize() / sizeof(util::BitPack32), std::addressof(this->header), sizeof(this->header) / sizeof(util::BitPack32));
|
buf.Get(MessageHeader::GetDataSize() / sizeof(util::BitPack32), std::addressof(this->header), sizeof(this->header) / sizeof(util::BitPack32));
|
||||||
|
@ -410,11 +418,7 @@ namespace ams::svc::ipc {
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ALWAYS_INLINE const T &GetRaw(s32 index) const {
|
ALWAYS_INLINE const T &GetRaw(s32 index) const {
|
||||||
if constexpr (!std::same_as<T, bool>) {
|
return *reinterpret_cast<const T *>(this->buffer + index);
|
||||||
return *reinterpret_cast<const T *>(this->buffer + index);
|
|
||||||
} else {
|
|
||||||
return *reinterpret_cast<const u8 *>(this->buffer + index) & 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
Loading…
Reference in a new issue