ams: support building unit test programs on windows/linux/macos
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <stratosphere/sf/sf_mitm_config.hpp>
|
||||
#include <stratosphere/sf/cmif/sf_cmif_service_dispatch.hpp>
|
||||
#include <stratosphere/sf/cmif/sf_cmif_domain_api.hpp>
|
||||
#include <stratosphere/sf/cmif/sf_cmif_server_message_processor.hpp>
|
||||
@@ -110,7 +111,9 @@ namespace ams::sf::cmif {
|
||||
template<>
|
||||
struct ServiceDispatchTraits<DomainServiceObject> {
|
||||
static_assert(std::is_base_of<sf::IServiceObject, DomainServiceObject>::value, "DomainServiceObject must derive from sf::IServiceObject");
|
||||
#if AMS_SF_MITM_SUPPORTED
|
||||
static_assert(!std::is_base_of<sf::IMitmServiceObject, DomainServiceObject>::value, "DomainServiceObject must not derive from sf::IMitmServiceObject");
|
||||
#endif
|
||||
using ProcessHandlerType = decltype(ServiceDispatchMeta::ProcessHandler);
|
||||
|
||||
using DispatchTableType = DomainServiceObjectDispatchTable;
|
||||
|
||||
@@ -26,9 +26,9 @@ namespace ams::sf::cmif {
|
||||
public:
|
||||
constexpr PointerAndSize() : m_pointer(0), m_size(0) { /* ... */ }
|
||||
constexpr PointerAndSize(uintptr_t ptr, size_t sz) : m_pointer(ptr), m_size(sz) { /* ... */ }
|
||||
constexpr PointerAndSize(void *ptr, size_t sz) : PointerAndSize(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
|
||||
PointerAndSize(void *ptr, size_t sz) : PointerAndSize(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
|
||||
|
||||
constexpr void *GetPointer() const {
|
||||
void *GetPointer() const {
|
||||
return reinterpret_cast<void *>(m_pointer);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <stratosphere/sf/sf_mitm_config.hpp>
|
||||
#include <stratosphere/sf/sf_service_object.hpp>
|
||||
#include <stratosphere/sf/cmif/sf_cmif_pointer_and_size.hpp>
|
||||
#include <stratosphere/sf/cmif/sf_cmif_server_message_processor.hpp>
|
||||
@@ -137,7 +138,7 @@ namespace ams::sf::cmif {
|
||||
const impl::ServiceDispatchTableBase *DispatchTable;
|
||||
Result (impl::ServiceDispatchTableBase::*ProcessHandler)(ServiceDispatchContext &, const cmif::PointerAndSize &) const;
|
||||
|
||||
constexpr uintptr_t GetServiceId() const {
|
||||
uintptr_t GetServiceId() const {
|
||||
return reinterpret_cast<uintptr_t>(this->DispatchTable);
|
||||
}
|
||||
};
|
||||
@@ -160,10 +161,12 @@ namespace ams::sf::cmif {
|
||||
static constexpr inline auto DispatchTable = ServiceDispatchTable<0>(std::array<ServiceCommandMeta, 0>{});
|
||||
};
|
||||
|
||||
#if AMS_SF_MITM_SUPPORTED
|
||||
template<>
|
||||
struct ServiceDispatchTraits<sf::IMitmServiceObject> {
|
||||
static constexpr inline auto DispatchTable = ServiceDispatchTable<0>(std::array<ServiceCommandMeta, 0>{});
|
||||
};
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
constexpr ALWAYS_INLINE const ServiceDispatchMeta *GetServiceDispatchMeta() {
|
||||
|
||||
@@ -20,8 +20,16 @@
|
||||
|
||||
namespace ams::sf::hipc {
|
||||
|
||||
void *GetMessageBufferOnTls();
|
||||
|
||||
constexpr size_t TlsMessageBufferSize = 0x100;
|
||||
|
||||
#if defined(ATMOSPHERE_OS_HORIZON)
|
||||
ALWAYS_INLINE void *GetMessageBufferOnTls() {
|
||||
return svc::GetThreadLocalRegion()->message_buffer;
|
||||
}
|
||||
#endif
|
||||
|
||||
enum class ReceiveResult {
|
||||
Success,
|
||||
Closed,
|
||||
@@ -37,4 +45,5 @@ namespace ams::sf::hipc {
|
||||
|
||||
Result CreateSession(os::NativeHandle *out_server_handle, os::NativeHandle *out_client_handle);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <stratosphere/sf/sf_mitm_config.hpp>
|
||||
#include <stratosphere/sf/hipc/sf_hipc_server_domain_session_manager.hpp>
|
||||
#include <stratosphere/sm.hpp>
|
||||
|
||||
@@ -38,12 +39,16 @@ namespace ams::sf::hipc {
|
||||
NON_COPYABLE(ServerManagerBase);
|
||||
NON_MOVEABLE(ServerManagerBase);
|
||||
public:
|
||||
#if AMS_SF_MITM_SUPPORTED
|
||||
using MitmQueryFunction = bool (*)(const sm::MitmProcessInfo &);
|
||||
#endif
|
||||
private:
|
||||
enum class UserDataTag : uintptr_t {
|
||||
Server = 1,
|
||||
Session = 2,
|
||||
#if AMS_SF_MITM_SUPPORTED
|
||||
MitmServer = 3,
|
||||
#endif
|
||||
};
|
||||
protected:
|
||||
using ServerDomainSessionManager::DomainEntryStorage;
|
||||
@@ -61,8 +66,11 @@ namespace ams::sf::hipc {
|
||||
sm::ServiceName m_service_name;
|
||||
int m_index;
|
||||
bool m_service_managed;
|
||||
#if AMS_SF_MITM_SUPPORTED
|
||||
bool m_is_mitm_server;
|
||||
#endif
|
||||
public:
|
||||
#if AMS_SF_MITM_SUPPORTED
|
||||
void AcknowledgeMitmSession(std::shared_ptr<::Service> *out_fsrv, sm::MitmProcessInfo *out_client_info) {
|
||||
/* Check mitm server. */
|
||||
AMS_ABORT_UNLESS(m_is_mitm_server);
|
||||
@@ -73,10 +81,13 @@ namespace ams::sf::hipc {
|
||||
/* Get client info. */
|
||||
R_ABORT_UNLESS(sm::mitm::AcknowledgeSession(out_fsrv->get(), out_client_info, m_service_name));
|
||||
}
|
||||
#endif
|
||||
};
|
||||
protected:
|
||||
static constinit inline bool g_is_any_deferred_supported = false;
|
||||
#if AMS_SF_MITM_SUPPORTED
|
||||
static constinit inline bool g_is_any_mitm_supported = false;
|
||||
#endif
|
||||
private:
|
||||
/* Multiple wait management. */
|
||||
os::MultiWaitType m_multi_wait;
|
||||
@@ -101,13 +112,17 @@ namespace ams::sf::hipc {
|
||||
bool WaitAndProcessImpl();
|
||||
|
||||
Result ProcessForServer(os::MultiWaitHolderType *holder);
|
||||
Result ProcessForMitmServer(os::MultiWaitHolderType *holder);
|
||||
Result ProcessForSession(os::MultiWaitHolderType *holder);
|
||||
|
||||
#if AMS_SF_MITM_SUPPORTED
|
||||
Result ProcessForMitmServer(os::MultiWaitHolderType *holder);
|
||||
#endif
|
||||
|
||||
void RegisterServerImpl(Server *server, os::NativeHandle port_handle, bool is_mitm_server) {
|
||||
server->m_port_handle = port_handle;
|
||||
hipc::AttachMultiWaitHolderForAccept(server, port_handle);
|
||||
|
||||
#if AMS_SF_MITM_SUPPORTED
|
||||
server->m_is_mitm_server = is_mitm_server;
|
||||
if (is_mitm_server) {
|
||||
/* Mitm server. */
|
||||
@@ -117,6 +132,10 @@ namespace ams::sf::hipc {
|
||||
/* Non-mitm server. */
|
||||
os::SetMultiWaitHolderUserData(server, static_cast<uintptr_t>(UserDataTag::Server));
|
||||
}
|
||||
#else
|
||||
AMS_UNUSED(is_mitm_server);
|
||||
os::SetMultiWaitHolderUserData(server, static_cast<uintptr_t>(UserDataTag::Server));
|
||||
#endif
|
||||
|
||||
os::LinkMultiWaitHolder(std::addressof(m_multi_wait), server);
|
||||
}
|
||||
@@ -158,7 +177,9 @@ namespace ams::sf::hipc {
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
#if AMS_SF_MITM_SUPPORTED
|
||||
Result InstallMitmServerImpl(os::NativeHandle *out_port_handle, sm::ServiceName service_name, MitmQueryFunction query_func);
|
||||
#endif
|
||||
protected:
|
||||
virtual Server *AllocateServer() = 0;
|
||||
virtual void DestroyServer(Server *server) = 0;
|
||||
@@ -172,6 +193,7 @@ namespace ams::sf::hipc {
|
||||
return ServerSessionManager::AcceptSession(server->m_port_handle, std::move(p));
|
||||
}
|
||||
|
||||
#if AMS_SF_MITM_SUPPORTED
|
||||
template<typename Interface>
|
||||
Result AcceptMitmImpl(Server *server, SharedPointer<Interface> p, std::shared_ptr<::Service> forward_service) {
|
||||
AMS_ABORT_UNLESS(this->CanManageMitmServers());
|
||||
@@ -200,6 +222,7 @@ namespace ams::sf::hipc {
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
#endif
|
||||
public:
|
||||
ServerManagerBase(DomainEntryStorage *entry_storage, size_t entry_count, bool defer_supported, bool mitm_supported) :
|
||||
ServerDomainSessionManager(entry_storage, entry_count),
|
||||
@@ -216,21 +239,28 @@ namespace ams::sf::hipc {
|
||||
os::InitializeMultiWait(std::addressof(m_deferred_list));
|
||||
}
|
||||
|
||||
virtual ~ServerManagerBase() = default;
|
||||
|
||||
static ALWAYS_INLINE bool CanAnyDeferInvokeRequest() {
|
||||
return g_is_any_deferred_supported;
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE bool CanAnyManageMitmServers() {
|
||||
return g_is_any_mitm_supported;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE bool CanDeferInvokeRequest() const {
|
||||
return CanAnyDeferInvokeRequest() && m_is_defer_supported;
|
||||
}
|
||||
|
||||
#if AMS_SF_MITM_SUPPORTED
|
||||
static ALWAYS_INLINE bool CanAnyManageMitmServers() {
|
||||
return g_is_any_mitm_supported;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE bool CanManageMitmServers() const {
|
||||
return CanAnyManageMitmServers() && m_is_mitm_supported;
|
||||
}
|
||||
#else
|
||||
static consteval bool CanAnyManageMitmServers() { return false; }
|
||||
static consteval bool CanManageMitmServers() { return false; }
|
||||
#endif
|
||||
|
||||
template<typename Interface>
|
||||
void RegisterObjectForServer(SharedPointer<Interface> static_object, os::NativeHandle port_handle) {
|
||||
@@ -278,6 +308,10 @@ namespace ams::sf::hipc {
|
||||
}
|
||||
}();
|
||||
static_assert(DomainCountsValid, "Invalid Domain Counts");
|
||||
|
||||
#if !(AMS_SF_MITM_SUPPORTED)
|
||||
static_assert(!ManagerOptions::CanManageMitmServers);
|
||||
#endif
|
||||
protected:
|
||||
using ServerManagerBase::DomainEntryStorage;
|
||||
using ServerManagerBase::DomainStorage;
|
||||
@@ -289,7 +323,11 @@ namespace ams::sf::hipc {
|
||||
util::TypedStorage<ServerSession> m_session_storages[MaxSessions];
|
||||
bool m_session_allocated[MaxSessions];
|
||||
u8 m_pointer_buffer_storage[0x10 + (MaxSessions * ManagerOptions::PointerBufferSize)];
|
||||
#if AMS_SF_MITM_SUPPORTED
|
||||
u8 m_saved_message_storage[0x10 + (MaxSessions * ((ManagerOptions::CanDeferInvokeRequest || ManagerOptions::CanManageMitmServers) ? hipc::TlsMessageBufferSize : 0))];
|
||||
#else
|
||||
u8 m_saved_message_storage[0x10 + (MaxSessions * ((ManagerOptions::CanDeferInvokeRequest) ? hipc::TlsMessageBufferSize : 0))];
|
||||
#endif
|
||||
uintptr_t m_pointer_buffers_start;
|
||||
uintptr_t m_saved_messages_start;
|
||||
|
||||
@@ -359,6 +397,7 @@ namespace ams::sf::hipc {
|
||||
os::UnlinkMultiWaitHolder(server);
|
||||
os::FinalizeMultiWaitHolder(server);
|
||||
if (server->m_service_managed) {
|
||||
#if AMS_SF_MITM_SUPPORTED
|
||||
if constexpr (ManagerOptions::CanManageMitmServers) {
|
||||
if (server->m_is_mitm_server) {
|
||||
R_ABORT_UNLESS(sm::mitm::UninstallMitm(server->m_service_name));
|
||||
@@ -368,6 +407,9 @@ namespace ams::sf::hipc {
|
||||
} else {
|
||||
R_ABORT_UNLESS(sm::UnregisterService(server->m_service_name));
|
||||
}
|
||||
#else
|
||||
R_ABORT_UNLESS(sm::UnregisterService(server->m_service_name));
|
||||
#endif
|
||||
os::CloseNativeHandle(server->m_port_handle);
|
||||
}
|
||||
}
|
||||
@@ -430,9 +472,11 @@ namespace ams::sf::hipc {
|
||||
if constexpr (ManagerOptions::CanDeferInvokeRequest) {
|
||||
ServerManagerBase::g_is_any_deferred_supported = true;
|
||||
}
|
||||
#if AMS_SF_MITM_SUPPORTED
|
||||
if constexpr (ManagerOptions::CanManageMitmServers) {
|
||||
ServerManagerBase::g_is_any_mitm_supported = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
~ServerManager() {
|
||||
@@ -455,11 +499,13 @@ namespace ams::sf::hipc {
|
||||
}
|
||||
}
|
||||
public:
|
||||
#if AMS_SF_MITM_SUPPORTED
|
||||
template<typename Interface, bool Enable = ManagerOptions::CanManageMitmServers, typename = typename std::enable_if<Enable>::type>
|
||||
Result RegisterMitmServer(int port_index, sm::ServiceName service_name) {
|
||||
AMS_ABORT_UNLESS(this->CanManageMitmServers());
|
||||
return this->template RegisterMitmServerImpl<Interface>(port_index, cmif::ServiceObjectHolder(), service_name);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#pragma once
|
||||
#include <stratosphere/sf/sf_common.hpp>
|
||||
#include <stratosphere/sf/sf_mitm_config.hpp>
|
||||
#include <stratosphere/sf/sf_service_object.hpp>
|
||||
#include <stratosphere/sf/cmif/sf_cmif_pointer_and_size.hpp>
|
||||
#include <stratosphere/sf/cmif/sf_cmif_service_object_holder.hpp>
|
||||
@@ -48,7 +49,9 @@ namespace ams::sf::hipc {
|
||||
cmif::ServiceObjectHolder m_srv_obj_holder;
|
||||
cmif::PointerAndSize m_pointer_buffer;
|
||||
cmif::PointerAndSize m_saved_message;
|
||||
#if AMS_SF_MITM_SUPPORTED
|
||||
util::TypedStorage<std::shared_ptr<::Service>> m_forward_service;
|
||||
#endif
|
||||
os::NativeHandle m_session_handle;
|
||||
bool m_is_closed;
|
||||
bool m_has_received;
|
||||
@@ -58,9 +61,20 @@ namespace ams::sf::hipc {
|
||||
hipc::AttachMultiWaitHolderForReply(this, h);
|
||||
m_is_closed = false;
|
||||
m_has_received = false;
|
||||
#if AMS_SF_MITM_SUPPORTED
|
||||
AMS_ABORT_UNLESS(!this->IsMitmSession());
|
||||
#endif
|
||||
}
|
||||
|
||||
~ServerSession() {
|
||||
#if AMS_SF_MITM_SUPPORTED
|
||||
if (m_has_forward_service) {
|
||||
util::DestroyAt(m_forward_service);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if AMS_SF_MITM_SUPPORTED
|
||||
ServerSession(os::NativeHandle h, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv) : m_srv_obj_holder(std::move(obj)), m_session_handle(h), m_has_forward_service(true) {
|
||||
hipc::AttachMultiWaitHolderForReply(this, h);
|
||||
m_is_closed = false;
|
||||
@@ -69,12 +83,6 @@ namespace ams::sf::hipc {
|
||||
AMS_ABORT_UNLESS(util::GetReference(m_forward_service) != nullptr);
|
||||
}
|
||||
|
||||
~ServerSession() {
|
||||
if (m_has_forward_service) {
|
||||
util::DestroyAt(m_forward_service);
|
||||
}
|
||||
}
|
||||
|
||||
ALWAYS_INLINE bool IsMitmSession() const {
|
||||
return m_has_forward_service;
|
||||
}
|
||||
@@ -89,6 +97,7 @@ namespace ams::sf::hipc {
|
||||
static inline std::shared_ptr<::Service> CreateForwardService() {
|
||||
return std::shared_ptr<::Service>(new ::Service(), ForwardServiceDeleter);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
class ServerSessionManager {
|
||||
@@ -124,8 +133,11 @@ namespace ams::sf::hipc {
|
||||
void CloseSessionImpl(ServerSession *session);
|
||||
Result RegisterSessionImpl(ServerSession *session_memory, os::NativeHandle session_handle, cmif::ServiceObjectHolder &&obj);
|
||||
Result AcceptSessionImpl(ServerSession *session_memory, os::NativeHandle port_handle, cmif::ServiceObjectHolder &&obj);
|
||||
|
||||
#if AMS_SF_MITM_SUPPORTED
|
||||
Result RegisterMitmSessionImpl(ServerSession *session_memory, os::NativeHandle mitm_session_handle, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv);
|
||||
Result AcceptMitmSessionImpl(ServerSession *session_memory, os::NativeHandle mitm_port_handle, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv);
|
||||
#endif
|
||||
|
||||
Result ReceiveRequest(ServerSession *session, const cmif::PointerAndSize &message) {
|
||||
return this->ReceiveRequestImpl(session, message);
|
||||
@@ -145,6 +157,7 @@ namespace ams::sf::hipc {
|
||||
return this->CreateSessionImpl(out, ctor);
|
||||
}
|
||||
|
||||
#if AMS_SF_MITM_SUPPORTED
|
||||
Result RegisterMitmSession(ServerSession **out, os::NativeHandle mitm_session_handle, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv) {
|
||||
auto ctor = [&](ServerSession *session_memory) -> Result {
|
||||
return this->RegisterMitmSessionImpl(session_memory, mitm_session_handle, std::forward<cmif::ServiceObjectHolder>(obj), std::forward<std::shared_ptr<::Service>>(fsrv));
|
||||
@@ -158,21 +171,27 @@ namespace ams::sf::hipc {
|
||||
};
|
||||
return this->CreateSessionImpl(out, ctor);
|
||||
}
|
||||
#endif
|
||||
public:
|
||||
Result RegisterSession(os::NativeHandle session_handle, cmif::ServiceObjectHolder &&obj);
|
||||
Result AcceptSession(os::NativeHandle port_handle, cmif::ServiceObjectHolder &&obj);
|
||||
|
||||
#if AMS_SF_MITM_SUPPORTED
|
||||
Result RegisterMitmSession(os::NativeHandle session_handle, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv);
|
||||
Result AcceptMitmSession(os::NativeHandle mitm_port_handle, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv);
|
||||
#endif
|
||||
|
||||
template<typename Interface>
|
||||
Result AcceptSession(os::NativeHandle port_handle, SharedPointer<Interface> obj) {
|
||||
return this->AcceptSession(port_handle, cmif::ServiceObjectHolder(std::move(obj)));
|
||||
}
|
||||
|
||||
#if AMS_SF_MITM_SUPPORTED
|
||||
template<typename Interface>
|
||||
Result AcceptMitmSession(os::NativeHandle mitm_port_handle, SharedPointer<Interface> obj, std::shared_ptr<::Service> &&fsrv) {
|
||||
return this->AcceptMitmSession(mitm_port_handle, cmif::ServiceObjectHolder(std::move(obj)), std::forward<std::shared_ptr<::Service>>(fsrv));
|
||||
}
|
||||
#endif
|
||||
|
||||
Result ProcessRequest(ServerSession *session, const cmif::PointerAndSize &message);
|
||||
|
||||
|
||||
@@ -145,6 +145,7 @@ namespace ams::sf {
|
||||
}
|
||||
|
||||
|
||||
#if defined(ATMOSPHERE_OS_HORIZON)
|
||||
namespace ams::sf::impl {
|
||||
|
||||
/* Machinery for filtering type lists. */
|
||||
@@ -1116,7 +1117,7 @@ namespace ams::sf::impl {
|
||||
}
|
||||
};
|
||||
|
||||
constexpr Result GetCmifOutHeaderPointer(CmifOutHeader **out_header_ptr, cmif::PointerAndSize &out_raw_data) {
|
||||
inline Result GetCmifOutHeaderPointer(CmifOutHeader **out_header_ptr, cmif::PointerAndSize &out_raw_data) {
|
||||
CmifOutHeader *header = static_cast<CmifOutHeader *>(out_raw_data.GetPointer());
|
||||
R_UNLESS(out_raw_data.GetSize() >= sizeof(*header), sf::cmif::ResultInvalidHeaderSize());
|
||||
out_raw_data = cmif::PointerAndSize(out_raw_data.GetAddress() + sizeof(*header), out_raw_data.GetSize() - sizeof(*header));
|
||||
@@ -1265,6 +1266,45 @@ namespace ams::sf::impl {
|
||||
}
|
||||
|
||||
}
|
||||
#elif defined(ATMOSPHERE_OS_WINDOWS)
|
||||
namespace ams::sf::impl {
|
||||
|
||||
template<auto ServiceCommandImpl, typename Return, typename ClassType, typename... Arguments>
|
||||
inline Result InvokeServiceCommandImpl(CmifOutHeader **out_header_ptr, cmif::ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data) {
|
||||
/* TODO: Is some kind of emulated serialization interesting/desirable? */
|
||||
AMS_UNUSED(out_header_ptr, ctx, in_raw_data);
|
||||
AMS_ABORT("HIPC serialization not currently supported on Windows.");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
#elif defined(ATMOSPHERE_OS_LINUX)
|
||||
namespace ams::sf::impl {
|
||||
|
||||
template<auto ServiceCommandImpl, typename Return, typename ClassType, typename... Arguments>
|
||||
inline Result InvokeServiceCommandImpl(CmifOutHeader **out_header_ptr, cmif::ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data) {
|
||||
/* TODO: Is some kind of emulated serialization interesting/desirable? */
|
||||
AMS_UNUSED(out_header_ptr, ctx, in_raw_data);
|
||||
AMS_ABORT("HIPC serialization not currently supported on Linux.");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
#elif defined(ATMOSPHERE_OS_MACOS)
|
||||
namespace ams::sf::impl {
|
||||
|
||||
template<auto ServiceCommandImpl, typename Return, typename ClassType, typename... Arguments>
|
||||
inline Result InvokeServiceCommandImpl(CmifOutHeader **out_header_ptr, cmif::ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data) {
|
||||
/* TODO: Is some kind of emulated serialization interesting/desirable? */
|
||||
AMS_UNUSED(out_header_ptr, ctx, in_raw_data);
|
||||
AMS_ABORT("HIPC serialization not currently supported on macOS.");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
#else
|
||||
#error "Unknown OS for sf Command serialization."
|
||||
#endif
|
||||
|
||||
namespace ams::sf::impl {
|
||||
|
||||
|
||||
@@ -116,8 +116,8 @@ namespace ams::sf {
|
||||
constexpr InBufferBase(const cmif::PointerAndSize &pas) : BaseType(pas) { /* ... */ }
|
||||
constexpr InBufferBase(uintptr_t ptr, size_t sz) : BaseType(ptr, sz) { /* ... */ }
|
||||
|
||||
constexpr InBufferBase(const void *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
|
||||
constexpr InBufferBase(const u8 *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
|
||||
InBufferBase(const void *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
|
||||
InBufferBase(const u8 *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
|
||||
};
|
||||
|
||||
class OutBufferBase : public BufferBase {
|
||||
@@ -130,8 +130,8 @@ namespace ams::sf {
|
||||
constexpr OutBufferBase(const cmif::PointerAndSize &pas) : BaseType(pas) { /* ... */ }
|
||||
constexpr OutBufferBase(uintptr_t ptr, size_t sz) : BaseType(ptr, sz) { /* ... */ }
|
||||
|
||||
constexpr OutBufferBase(void *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
|
||||
constexpr OutBufferBase(u8 *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
|
||||
OutBufferBase(void *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
|
||||
OutBufferBase(u8 *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
|
||||
};
|
||||
|
||||
template<BufferTransferMode TMode, u32 ExtraAttributes = 0>
|
||||
@@ -146,8 +146,8 @@ namespace ams::sf {
|
||||
constexpr InBufferImpl(const cmif::PointerAndSize &pas) : BaseType(pas) { /* ... */ }
|
||||
constexpr InBufferImpl(uintptr_t ptr, size_t sz) : BaseType(ptr, sz) { /* ... */ }
|
||||
|
||||
constexpr InBufferImpl(const void *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
|
||||
constexpr InBufferImpl(const u8 *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
|
||||
InBufferImpl(const void *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
|
||||
InBufferImpl(const u8 *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
|
||||
|
||||
constexpr const u8 *GetPointer() const {
|
||||
return reinterpret_cast<const u8 *>(this->GetAddressImpl());
|
||||
@@ -170,8 +170,8 @@ namespace ams::sf {
|
||||
constexpr OutBufferImpl(const cmif::PointerAndSize &pas) : BaseType(pas) { /* ... */ }
|
||||
constexpr OutBufferImpl(uintptr_t ptr, size_t sz) : BaseType(ptr, sz) { /* ... */ }
|
||||
|
||||
constexpr OutBufferImpl(void *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
|
||||
constexpr OutBufferImpl(u8 *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
|
||||
OutBufferImpl(void *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
|
||||
OutBufferImpl(u8 *ptr, size_t sz) : BaseType(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
|
||||
|
||||
constexpr u8 *GetPointer() const {
|
||||
return reinterpret_cast<u8 *>(this->GetAddressImpl());
|
||||
@@ -191,7 +191,7 @@ namespace ams::sf {
|
||||
public:
|
||||
constexpr InArrayImpl() : BaseType() { /* ... */ }
|
||||
constexpr InArrayImpl(const cmif::PointerAndSize &pas) : BaseType(pas) { /* ... */ }
|
||||
constexpr InArrayImpl(const T *ptr, size_t num_elements) : BaseType(reinterpret_cast<uintptr_t>(ptr), num_elements * sizeof(T)) { /* ... */ }
|
||||
InArrayImpl(const T *ptr, size_t num_elements) : BaseType(reinterpret_cast<uintptr_t>(ptr), num_elements * sizeof(T)) { /* ... */ }
|
||||
|
||||
constexpr const T *GetPointer() const {
|
||||
return reinterpret_cast<const T *>(this->GetAddressImpl());
|
||||
@@ -223,7 +223,7 @@ namespace ams::sf {
|
||||
public:
|
||||
constexpr OutArrayImpl() : BaseType() { /* ... */ }
|
||||
constexpr OutArrayImpl(const cmif::PointerAndSize &pas) : BaseType(pas) { /* ... */ }
|
||||
constexpr OutArrayImpl(T *ptr, size_t num_elements) : BaseType(reinterpret_cast<uintptr_t>(ptr), num_elements * sizeof(T)) { /* ... */ }
|
||||
OutArrayImpl(T *ptr, size_t num_elements) : BaseType(reinterpret_cast<uintptr_t>(ptr), num_elements * sizeof(T)) { /* ... */ }
|
||||
|
||||
constexpr T *GetPointer() const {
|
||||
return reinterpret_cast<T *>(this->GetAddressImpl());
|
||||
|
||||
@@ -18,4 +18,6 @@
|
||||
#include <vapours.hpp>
|
||||
#include <stratosphere/ams.hpp>
|
||||
#include <stratosphere/os.hpp>
|
||||
#include <stratosphere/sm/sm_types.hpp>
|
||||
#include <stratosphere/sm/sm_types.hpp>
|
||||
#include <stratosphere/sf/sf_types.hpp>
|
||||
#include <stratosphere/sf/sf_mitm_config.hpp>
|
||||
@@ -60,7 +60,7 @@ namespace ams::sf {
|
||||
typename std::aligned_storage<Size == 0 ? 1 : Size>::type buffer;
|
||||
};
|
||||
|
||||
static constinit inline Globals _globals;
|
||||
static constinit inline Globals _globals = {};
|
||||
|
||||
|
||||
static void Initialize(int option) {
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) 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
|
||||
|
||||
#if defined(ATMOSPHERE_OS_HORIZON)
|
||||
#define AMS_SF_MITM_SUPPORTED 1
|
||||
#else
|
||||
#define AMS_SF_MITM_SUPPORTED 0
|
||||
#endif
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <stratosphere/sf/sf_mitm_config.hpp>
|
||||
|
||||
#if AMS_SF_MITM_SUPPORTED
|
||||
#include <switch.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -98,3 +101,5 @@ NX_INLINE Result serviceMitmDispatchImpl(
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -297,16 +297,19 @@ namespace ams::sf {
|
||||
|
||||
template<typename Interface, typename Smart>
|
||||
constexpr SharedPointer<Interface> CreateShared(Allocator *a, Smart &&sp) {
|
||||
AMS_UNUSED(a);
|
||||
return StaticObjectFactory::template CreateShared<Interface>(m_allocator, std::forward<Smart>(sp));
|
||||
}
|
||||
|
||||
template<typename Interface, typename T>
|
||||
constexpr SharedPointer<Interface> CreateShared(Allocator *a, T *p) {
|
||||
AMS_UNUSED(a);
|
||||
return StaticObjectFactory::template CreateShared<Interface>(m_allocator, p);
|
||||
}
|
||||
|
||||
template<typename Interface, typename T>
|
||||
constexpr SharedPointer<Interface> CreateSharedWithoutManagement(Allocator *a, T *p) {
|
||||
AMS_UNUSED(a);
|
||||
return StaticObjectFactory::template CreateSharedWithoutManagement<Interface>(m_allocator, p);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -46,6 +46,9 @@ namespace ams::sf {
|
||||
constexpr Out(T *p) : m_ptr(p) { /* ... */ }
|
||||
constexpr Out(const cmif::PointerAndSize &pas) : m_ptr(reinterpret_cast<T *>(pas.GetAddress())) { /* TODO: Is AMS_ABORT_UNLESS(pas.GetSize() >= sizeof(T)); necessary? */ }
|
||||
|
||||
template<typename U> requires (std::integral<T> && std::is_enum<U>::value && std::same_as<typename std::underlying_type<U>::type, T>)
|
||||
constexpr Out(U *p) : m_ptr(reinterpret_cast<T *>(p)) { static_assert(sizeof(U) == sizeof(T)); static_assert(alignof(U) == alignof(T)); }
|
||||
|
||||
void SetValue(const T& value) const {
|
||||
*m_ptr = value;
|
||||
}
|
||||
|
||||
@@ -29,26 +29,31 @@ namespace ams::sf {
|
||||
template<typename T>
|
||||
concept IsServiceObject = std::derived_from<T, IServiceObject>;
|
||||
|
||||
class IMitmServiceObject : public IServiceObject {
|
||||
public:
|
||||
virtual ~IMitmServiceObject() { /* ... */ }
|
||||
};
|
||||
#if AMS_SF_MITM_SUPPORTED
|
||||
class IMitmServiceObject : public IServiceObject {
|
||||
public:
|
||||
virtual ~IMitmServiceObject() { /* ... */ }
|
||||
};
|
||||
|
||||
class MitmServiceImplBase {
|
||||
protected:
|
||||
std::shared_ptr<::Service> m_forward_service;
|
||||
sm::MitmProcessInfo m_client_info;
|
||||
public:
|
||||
MitmServiceImplBase(std::shared_ptr<::Service> &&s, const sm::MitmProcessInfo &c) : m_forward_service(std::move(s)), m_client_info(c) { /* ... */ }
|
||||
};
|
||||
class MitmServiceImplBase {
|
||||
protected:
|
||||
std::shared_ptr<::Service> m_forward_service;
|
||||
sm::MitmProcessInfo m_client_info;
|
||||
public:
|
||||
MitmServiceImplBase(std::shared_ptr<::Service> &&s, const sm::MitmProcessInfo &c) : m_forward_service(std::move(s)), m_client_info(c) { /* ... */ }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
concept IsMitmServiceObject = IsServiceObject<T> && std::derived_from<T, IMitmServiceObject>;
|
||||
template<typename T>
|
||||
concept IsMitmServiceObject = IsServiceObject<T> && std::derived_from<T, IMitmServiceObject>;
|
||||
|
||||
template<typename T>
|
||||
concept IsMitmServiceImpl = requires (std::shared_ptr<::Service> &&s, const sm::MitmProcessInfo &c) {
|
||||
{ T(std::forward<std::shared_ptr<::Service>>(s), c) };
|
||||
{ T::ShouldMitm(c) } -> std::same_as<bool>;
|
||||
};
|
||||
template<typename T>
|
||||
concept IsMitmServiceImpl = requires (std::shared_ptr<::Service> &&s, const sm::MitmProcessInfo &c) {
|
||||
{ T(std::forward<std::shared_ptr<::Service>>(s), c) };
|
||||
{ T::ShouldMitm(c) } -> std::same_as<bool>;
|
||||
};
|
||||
#else
|
||||
template<typename T>
|
||||
concept IsMitmServiceObject = false;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
#pragma once
|
||||
#include <stratosphere/sf/sf_common.hpp>
|
||||
#include <stratosphere/sf/sf_mitm_config.hpp>
|
||||
#include <stratosphere/sf/sf_out.hpp>
|
||||
|
||||
namespace ams::sf {
|
||||
|
||||
506
libraries/libstratosphere/include/stratosphere/sf/sf_types.hpp
Normal file
506
libraries/libstratosphere/include/stratosphere/sf/sf_types.hpp
Normal file
@@ -0,0 +1,506 @@
|
||||
/*
|
||||
* Copyright (c) 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>
|
||||
|
||||
#if defined(ATMOSPHERE_OS_WINDOWS) || defined(ATMOSPHERE_OS_LINUX) || defined(ATMOSPHERE_OS_MACOS)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(ATMOSPHERE_COMPILER_CLANG)
|
||||
#define AMS_SF_HIPC_PARSE_IMPL_CONSTEXPR ALWAYS_INLINE
|
||||
#else
|
||||
#define AMS_SF_HIPC_PARSE_IMPL_CONSTEXPR constexpr ALWAYS_INLINE
|
||||
#endif
|
||||
|
||||
#define HIPC_AUTO_RECV_STATIC UINT8_MAX
|
||||
#define HIPC_RESPONSE_NO_PID UINT32_MAX
|
||||
|
||||
typedef struct HipcMetadata {
|
||||
u32 type;
|
||||
u32 num_send_statics;
|
||||
u32 num_send_buffers;
|
||||
u32 num_recv_buffers;
|
||||
u32 num_exch_buffers;
|
||||
u32 num_data_words;
|
||||
u32 num_recv_statics; // also accepts HIPC_AUTO_RECV_STATIC
|
||||
u32 send_pid;
|
||||
u32 num_copy_handles;
|
||||
u32 num_move_handles;
|
||||
} HipcMetadata;
|
||||
|
||||
typedef struct HipcHeader {
|
||||
u32 type : 16;
|
||||
u32 num_send_statics : 4;
|
||||
u32 num_send_buffers : 4;
|
||||
u32 num_recv_buffers : 4;
|
||||
u32 num_exch_buffers : 4;
|
||||
u32 num_data_words : 10;
|
||||
u32 recv_static_mode : 4;
|
||||
u32 padding : 6;
|
||||
u32 recv_list_offset : 11; // Unused.
|
||||
u32 has_special_header : 1;
|
||||
} HipcHeader;
|
||||
|
||||
typedef struct HipcSpecialHeader {
|
||||
u32 send_pid : 1;
|
||||
u32 num_copy_handles : 4;
|
||||
u32 num_move_handles : 4;
|
||||
u32 padding : 23;
|
||||
} HipcSpecialHeader;
|
||||
|
||||
typedef struct HipcStaticDescriptor {
|
||||
u32 index : 6;
|
||||
u32 address_high : 6;
|
||||
u32 address_mid : 4;
|
||||
u32 size : 16;
|
||||
u32 address_low;
|
||||
} HipcStaticDescriptor;
|
||||
|
||||
typedef struct HipcBufferDescriptor {
|
||||
u32 size_low;
|
||||
u32 address_low;
|
||||
u32 mode : 2;
|
||||
u32 address_high : 22;
|
||||
u32 size_high : 4;
|
||||
u32 address_mid : 4;
|
||||
} HipcBufferDescriptor;
|
||||
|
||||
typedef struct HipcRecvListEntry {
|
||||
u32 address_low;
|
||||
u32 address_high : 16;
|
||||
u32 size : 16;
|
||||
} HipcRecvListEntry;
|
||||
|
||||
typedef struct HipcRequest {
|
||||
HipcStaticDescriptor* send_statics;
|
||||
HipcBufferDescriptor* send_buffers;
|
||||
HipcBufferDescriptor* recv_buffers;
|
||||
HipcBufferDescriptor* exch_buffers;
|
||||
u32* data_words;
|
||||
HipcRecvListEntry* recv_list;
|
||||
u32* copy_handles;
|
||||
u32* move_handles;
|
||||
} HipcRequest;
|
||||
|
||||
typedef struct HipcParsedRequest {
|
||||
HipcMetadata meta;
|
||||
HipcRequest data;
|
||||
u64 pid;
|
||||
} HipcParsedRequest;
|
||||
|
||||
typedef struct HipcResponse {
|
||||
u64 pid;
|
||||
u32 num_statics;
|
||||
u32 num_data_words;
|
||||
u32 num_copy_handles;
|
||||
u32 num_move_handles;
|
||||
HipcStaticDescriptor* statics;
|
||||
u32* data_words;
|
||||
u32* copy_handles;
|
||||
u32* move_handles;
|
||||
} HipcResponse;
|
||||
|
||||
typedef enum HipcBufferMode {
|
||||
HipcBufferMode_Normal = 0,
|
||||
HipcBufferMode_NonSecure = 1,
|
||||
HipcBufferMode_Invalid = 2,
|
||||
HipcBufferMode_NonDevice = 3,
|
||||
} HipcBufferMode;
|
||||
|
||||
|
||||
AMS_SF_HIPC_PARSE_IMPL_CONSTEXPR HipcStaticDescriptor hipcMakeSendStatic(const void* buffer, size_t size, u8 index) {
|
||||
return (HipcStaticDescriptor){
|
||||
.index = index,
|
||||
.address_high = (u32)((uintptr_t)buffer >> 36),
|
||||
.address_mid = (u32)((uintptr_t)buffer >> 32),
|
||||
.size = (u32)size,
|
||||
.address_low = (u32)(uintptr_t)buffer,
|
||||
};
|
||||
}
|
||||
|
||||
AMS_SF_HIPC_PARSE_IMPL_CONSTEXPR HipcBufferDescriptor hipcMakeBuffer(const void* buffer, size_t size, HipcBufferMode mode) {
|
||||
return (HipcBufferDescriptor){
|
||||
.size_low = (u32)size,
|
||||
.address_low = (u32)(uintptr_t)buffer,
|
||||
.mode = mode,
|
||||
.address_high = (u32)((uintptr_t)buffer >> 36),
|
||||
.size_high = (u32)(size >> 32),
|
||||
.address_mid = (u32)((uintptr_t)buffer >> 32),
|
||||
};
|
||||
}
|
||||
|
||||
AMS_SF_HIPC_PARSE_IMPL_CONSTEXPR HipcRecvListEntry hipcMakeRecvStatic(void* buffer, size_t size) {
|
||||
return (HipcRecvListEntry){
|
||||
.address_low = (u32)((uintptr_t)buffer),
|
||||
.address_high = (u32)((uintptr_t)buffer >> 32),
|
||||
.size = (u32)size,
|
||||
};
|
||||
}
|
||||
|
||||
AMS_SF_HIPC_PARSE_IMPL_CONSTEXPR void* hipcGetStaticAddress(const HipcStaticDescriptor* desc)
|
||||
{
|
||||
return (void*)(desc->address_low | ((uintptr_t)desc->address_mid << 32) | ((uintptr_t)desc->address_high << 36));
|
||||
}
|
||||
|
||||
AMS_SF_HIPC_PARSE_IMPL_CONSTEXPR size_t hipcGetStaticSize(const HipcStaticDescriptor* desc)
|
||||
{
|
||||
return desc->size;
|
||||
}
|
||||
|
||||
AMS_SF_HIPC_PARSE_IMPL_CONSTEXPR void* hipcGetBufferAddress(const HipcBufferDescriptor* desc)
|
||||
{
|
||||
return (void*)(desc->address_low | ((uintptr_t)desc->address_mid << 32) | ((uintptr_t)desc->address_high << 36));
|
||||
}
|
||||
|
||||
AMS_SF_HIPC_PARSE_IMPL_CONSTEXPR size_t hipcGetBufferSize(const HipcBufferDescriptor* desc)
|
||||
{
|
||||
return desc->size_low | ((size_t)desc->size_high << 32);
|
||||
}
|
||||
|
||||
AMS_SF_HIPC_PARSE_IMPL_CONSTEXPR HipcRequest hipcCalcRequestLayout(HipcMetadata meta, void* base) {
|
||||
// Copy handles
|
||||
u32* copy_handles = NULL;
|
||||
if (meta.num_copy_handles) {
|
||||
copy_handles = (u32*)base;
|
||||
base = copy_handles + meta.num_copy_handles;
|
||||
}
|
||||
|
||||
// Move handles
|
||||
u32* move_handles = NULL;
|
||||
if (meta.num_move_handles) {
|
||||
move_handles = (u32*)base;
|
||||
base = move_handles + meta.num_move_handles;
|
||||
}
|
||||
|
||||
// Send statics
|
||||
HipcStaticDescriptor* send_statics = NULL;
|
||||
if (meta.num_send_statics) {
|
||||
send_statics = (HipcStaticDescriptor*)base;
|
||||
base = send_statics + meta.num_send_statics;
|
||||
}
|
||||
|
||||
// Send buffers
|
||||
HipcBufferDescriptor* send_buffers = NULL;
|
||||
if (meta.num_send_buffers) {
|
||||
send_buffers = (HipcBufferDescriptor*)base;
|
||||
base = send_buffers + meta.num_send_buffers;
|
||||
}
|
||||
|
||||
// Recv buffers
|
||||
HipcBufferDescriptor* recv_buffers = NULL;
|
||||
if (meta.num_recv_buffers) {
|
||||
recv_buffers = (HipcBufferDescriptor*)base;
|
||||
base = recv_buffers + meta.num_recv_buffers;
|
||||
}
|
||||
|
||||
// Exch buffers
|
||||
HipcBufferDescriptor* exch_buffers = NULL;
|
||||
if (meta.num_exch_buffers) {
|
||||
exch_buffers = (HipcBufferDescriptor*)base;
|
||||
base = exch_buffers + meta.num_exch_buffers;
|
||||
}
|
||||
|
||||
// Data words
|
||||
u32* data_words = NULL;
|
||||
if (meta.num_data_words) {
|
||||
data_words = (u32*)base;
|
||||
base = data_words + meta.num_data_words;
|
||||
}
|
||||
|
||||
// Recv list
|
||||
HipcRecvListEntry* recv_list = NULL;
|
||||
if (meta.num_recv_statics)
|
||||
recv_list = (HipcRecvListEntry*)base;
|
||||
|
||||
return (HipcRequest){
|
||||
.send_statics = send_statics,
|
||||
.send_buffers = send_buffers,
|
||||
.recv_buffers = recv_buffers,
|
||||
.exch_buffers = exch_buffers,
|
||||
.data_words = data_words,
|
||||
.recv_list = recv_list,
|
||||
.copy_handles = copy_handles,
|
||||
.move_handles = move_handles,
|
||||
};
|
||||
}
|
||||
|
||||
AMS_SF_HIPC_PARSE_IMPL_CONSTEXPR HipcRequest hipcMakeRequest(void* base, HipcMetadata meta) {
|
||||
// Write message header
|
||||
bool has_special_header = meta.send_pid || meta.num_copy_handles || meta.num_move_handles;
|
||||
HipcHeader* hdr = (HipcHeader*)base;
|
||||
base = hdr+1;
|
||||
*hdr = (HipcHeader){
|
||||
.type = meta.type,
|
||||
.num_send_statics = meta.num_send_statics,
|
||||
.num_send_buffers = meta.num_send_buffers,
|
||||
.num_recv_buffers = meta.num_recv_buffers,
|
||||
.num_exch_buffers = meta.num_exch_buffers,
|
||||
.num_data_words = meta.num_data_words,
|
||||
.recv_static_mode = meta.num_recv_statics ? (meta.num_recv_statics != HIPC_AUTO_RECV_STATIC ? 2u + meta.num_recv_statics : 2u) : 0u,
|
||||
.padding = 0,
|
||||
.recv_list_offset = 0,
|
||||
.has_special_header = has_special_header,
|
||||
};
|
||||
|
||||
// Write special header
|
||||
if (has_special_header) {
|
||||
HipcSpecialHeader* sphdr = (HipcSpecialHeader*)base;
|
||||
base = sphdr+1;
|
||||
*sphdr = (HipcSpecialHeader){
|
||||
.send_pid = meta.send_pid,
|
||||
.num_copy_handles = meta.num_copy_handles,
|
||||
.num_move_handles = meta.num_move_handles,
|
||||
};
|
||||
if (meta.send_pid)
|
||||
base = (u8*)base + sizeof(u64);
|
||||
}
|
||||
|
||||
// Calculate layout
|
||||
return hipcCalcRequestLayout(meta, base);
|
||||
}
|
||||
|
||||
#define hipcMakeRequestInline(_base,...) hipcMakeRequest((_base),(HipcMetadata){ __VA_ARGS__ })
|
||||
|
||||
AMS_SF_HIPC_PARSE_IMPL_CONSTEXPR HipcParsedRequest hipcParseRequest(void* base) {
|
||||
// Parse message header
|
||||
HipcHeader hdr = {};
|
||||
__builtin_memcpy(&hdr, base, sizeof(hdr));
|
||||
base = (u8*)base + sizeof(hdr);
|
||||
u32 num_recv_statics = 0;
|
||||
u64 pid = 0;
|
||||
|
||||
// Parse recv static mode
|
||||
if (hdr.recv_static_mode) {
|
||||
if (hdr.recv_static_mode == 2u)
|
||||
num_recv_statics = HIPC_AUTO_RECV_STATIC;
|
||||
else if (hdr.recv_static_mode > 2u)
|
||||
num_recv_statics = hdr.recv_static_mode - 2u;
|
||||
}
|
||||
|
||||
// Parse special header
|
||||
HipcSpecialHeader sphdr = {};
|
||||
if (hdr.has_special_header) {
|
||||
__builtin_memcpy(&sphdr, base, sizeof(sphdr));
|
||||
base = (u8*)base + sizeof(sphdr);
|
||||
|
||||
// Read PID descriptor
|
||||
if (sphdr.send_pid) {
|
||||
pid = *(u64*)base;
|
||||
base = (u8*)base + sizeof(u64);
|
||||
}
|
||||
}
|
||||
|
||||
const HipcMetadata meta = {
|
||||
.type = hdr.type,
|
||||
.num_send_statics = hdr.num_send_statics,
|
||||
.num_send_buffers = hdr.num_send_buffers,
|
||||
.num_recv_buffers = hdr.num_recv_buffers,
|
||||
.num_exch_buffers = hdr.num_exch_buffers,
|
||||
.num_data_words = hdr.num_data_words,
|
||||
.num_recv_statics = num_recv_statics,
|
||||
.send_pid = sphdr.send_pid,
|
||||
.num_copy_handles = sphdr.num_copy_handles,
|
||||
.num_move_handles = sphdr.num_move_handles,
|
||||
};
|
||||
|
||||
return (HipcParsedRequest){
|
||||
.meta = meta,
|
||||
.data = hipcCalcRequestLayout(meta, base),
|
||||
.pid = pid,
|
||||
};
|
||||
}
|
||||
|
||||
AMS_SF_HIPC_PARSE_IMPL_CONSTEXPR HipcResponse hipcParseResponse(void* base) {
|
||||
// Parse header
|
||||
HipcHeader hdr = {};
|
||||
__builtin_memcpy(&hdr, base, sizeof(hdr));
|
||||
base = (u8*)base + sizeof(hdr);
|
||||
|
||||
// Initialize response
|
||||
HipcResponse response = {};
|
||||
response.num_statics = hdr.num_send_statics;
|
||||
response.num_data_words = hdr.num_data_words;
|
||||
response.pid = HIPC_RESPONSE_NO_PID;
|
||||
|
||||
// Parse special header
|
||||
if (hdr.has_special_header)
|
||||
{
|
||||
HipcSpecialHeader sphdr = {};
|
||||
__builtin_memcpy(&sphdr, base, sizeof(sphdr));
|
||||
base = (u8*)base + sizeof(sphdr);
|
||||
|
||||
// Update response
|
||||
response.num_copy_handles = sphdr.num_copy_handles;
|
||||
response.num_move_handles = sphdr.num_move_handles;
|
||||
|
||||
// Parse PID descriptor
|
||||
if (sphdr.send_pid) {
|
||||
response.pid = *(u64*)base;
|
||||
base = (u8*)base + sizeof(u64);
|
||||
}
|
||||
}
|
||||
|
||||
// Copy handles
|
||||
response.copy_handles = (u32*)base;
|
||||
base = response.copy_handles + response.num_copy_handles;
|
||||
|
||||
// Move handles
|
||||
response.move_handles = (u32*)base;
|
||||
base = response.move_handles + response.num_move_handles;
|
||||
|
||||
// Send statics
|
||||
response.statics = (HipcStaticDescriptor*)base;
|
||||
base = response.statics + response.num_statics;
|
||||
|
||||
// Data words
|
||||
response.data_words = (u32*)base;
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
typedef enum CmifCommandType {
|
||||
CmifCommandType_Invalid = 0,
|
||||
CmifCommandType_LegacyRequest = 1,
|
||||
CmifCommandType_Close = 2,
|
||||
CmifCommandType_LegacyControl = 3,
|
||||
CmifCommandType_Request = 4,
|
||||
CmifCommandType_Control = 5,
|
||||
CmifCommandType_RequestWithContext = 6,
|
||||
CmifCommandType_ControlWithContext = 7,
|
||||
} CmifCommandType;
|
||||
|
||||
typedef enum CmifDomainRequestType {
|
||||
CmifDomainRequestType_Invalid = 0,
|
||||
CmifDomainRequestType_SendMessage = 1,
|
||||
CmifDomainRequestType_Close = 2,
|
||||
} CmifDomainRequestType;
|
||||
|
||||
typedef struct CmifInHeader {
|
||||
u32 magic;
|
||||
u32 version;
|
||||
u32 command_id;
|
||||
u32 token;
|
||||
} CmifInHeader;
|
||||
|
||||
typedef struct CmifOutHeader {
|
||||
u32 magic;
|
||||
u32 version;
|
||||
Result result;
|
||||
u32 token;
|
||||
} CmifOutHeader;
|
||||
|
||||
typedef struct CmifDomainInHeader {
|
||||
u8 type;
|
||||
u8 num_in_objects;
|
||||
u16 data_size;
|
||||
u32 object_id;
|
||||
u32 padding;
|
||||
u32 token;
|
||||
} CmifDomainInHeader;
|
||||
|
||||
typedef struct CmifDomainOutHeader {
|
||||
u32 num_out_objects;
|
||||
u32 padding[3];
|
||||
} CmifDomainOutHeader;
|
||||
|
||||
typedef struct CmifRequestFormat {
|
||||
u32 object_id;
|
||||
u32 request_id;
|
||||
u32 context;
|
||||
u32 data_size;
|
||||
u32 server_pointer_size;
|
||||
u32 num_in_auto_buffers;
|
||||
u32 num_out_auto_buffers;
|
||||
u32 num_in_buffers;
|
||||
u32 num_out_buffers;
|
||||
u32 num_inout_buffers;
|
||||
u32 num_in_pointers;
|
||||
u32 num_out_pointers;
|
||||
u32 num_out_fixed_pointers;
|
||||
u32 num_objects;
|
||||
u32 num_handles;
|
||||
u32 send_pid;
|
||||
} CmifRequestFormat;
|
||||
|
||||
typedef struct CmifRequest {
|
||||
HipcRequest hipc;
|
||||
void* data;
|
||||
u16* out_pointer_sizes;
|
||||
u32* objects;
|
||||
u32 server_pointer_size;
|
||||
u32 cur_in_ptr_id;
|
||||
} CmifRequest;
|
||||
|
||||
typedef struct CmifResponse {
|
||||
void* data;
|
||||
u32* objects;
|
||||
u32* copy_handles;
|
||||
u32* move_handles;
|
||||
} CmifResponse;
|
||||
|
||||
enum {
|
||||
SfBufferAttr_In = BIT(0),
|
||||
SfBufferAttr_Out = BIT(1),
|
||||
SfBufferAttr_HipcMapAlias = BIT(2),
|
||||
SfBufferAttr_HipcPointer = BIT(3),
|
||||
SfBufferAttr_FixedSize = BIT(4),
|
||||
SfBufferAttr_HipcAutoSelect = BIT(5),
|
||||
SfBufferAttr_HipcMapTransferAllowsNonSecure = BIT(6),
|
||||
SfBufferAttr_HipcMapTransferAllowsNonDevice = BIT(7),
|
||||
};
|
||||
|
||||
typedef struct SfBufferAttrs {
|
||||
u32 attr0;
|
||||
u32 attr1;
|
||||
u32 attr2;
|
||||
u32 attr3;
|
||||
u32 attr4;
|
||||
u32 attr5;
|
||||
u32 attr6;
|
||||
u32 attr7;
|
||||
} SfBufferAttrs;
|
||||
|
||||
typedef struct SfBuffer {
|
||||
const void* ptr;
|
||||
size_t size;
|
||||
} SfBuffer;
|
||||
|
||||
typedef enum SfOutHandleAttr {
|
||||
SfOutHandleAttr_None = 0,
|
||||
SfOutHandleAttr_HipcCopy = 1,
|
||||
SfOutHandleAttr_HipcMove = 2,
|
||||
} SfOutHandleAttr;
|
||||
|
||||
typedef struct SfOutHandleAttrs {
|
||||
SfOutHandleAttr attr0;
|
||||
SfOutHandleAttr attr1;
|
||||
SfOutHandleAttr attr2;
|
||||
SfOutHandleAttr attr3;
|
||||
SfOutHandleAttr attr4;
|
||||
SfOutHandleAttr attr5;
|
||||
SfOutHandleAttr attr6;
|
||||
SfOutHandleAttr attr7;
|
||||
} SfOutHandleAttrs;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user