Revert "hoc-clk: add live vdd2, live boost clock and basic pwm dimming"
This reverts commit 15b7df8ef1.
This commit is contained in:
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* 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 <stratosphere/sf/sf_common.hpp>
|
||||
#include <stratosphere/sf/cmif/sf_cmif_service_object_holder.hpp>
|
||||
|
||||
namespace ams::sf::cmif {
|
||||
|
||||
struct DomainObjectId {
|
||||
u32 value;
|
||||
|
||||
constexpr void SetValue(u32 new_value) { this->value = new_value; }
|
||||
};
|
||||
|
||||
static_assert(std::is_trivial<DomainObjectId>::value && sizeof(DomainObjectId) == sizeof(u32), "DomainObjectId");
|
||||
|
||||
inline constexpr bool operator==(const DomainObjectId &lhs, const DomainObjectId &rhs) {
|
||||
return lhs.value == rhs.value;
|
||||
}
|
||||
|
||||
inline constexpr bool operator!=(const DomainObjectId &lhs, const DomainObjectId &rhs) {
|
||||
return lhs.value != rhs.value;
|
||||
}
|
||||
|
||||
inline constexpr bool operator<(const DomainObjectId &lhs, const DomainObjectId &rhs) {
|
||||
return lhs.value < rhs.value;
|
||||
}
|
||||
|
||||
inline constexpr bool operator<=(const DomainObjectId &lhs, const DomainObjectId &rhs) {
|
||||
return lhs.value <= rhs.value;
|
||||
}
|
||||
|
||||
inline constexpr bool operator>(const DomainObjectId &lhs, const DomainObjectId &rhs) {
|
||||
return lhs.value > rhs.value;
|
||||
}
|
||||
|
||||
inline constexpr bool operator>=(const DomainObjectId &lhs, const DomainObjectId &rhs) {
|
||||
return lhs.value >= rhs.value;
|
||||
}
|
||||
|
||||
constexpr inline const DomainObjectId InvalidDomainObjectId = { .value = 0 };
|
||||
|
||||
class ServerDomainBase {
|
||||
public:
|
||||
virtual Result ReserveIds(DomainObjectId *out_ids, size_t count) = 0;
|
||||
virtual void ReserveSpecificIds(const DomainObjectId *ids, size_t count) = 0;
|
||||
virtual void UnreserveIds(const DomainObjectId *ids, size_t count) = 0;
|
||||
virtual void RegisterObject(DomainObjectId id, ServiceObjectHolder &&obj) = 0;
|
||||
|
||||
virtual ServiceObjectHolder UnregisterObject(DomainObjectId id) = 0;
|
||||
virtual ServiceObjectHolder GetObject(DomainObjectId id) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,140 +0,0 @@
|
||||
/*
|
||||
* 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 <stratosphere/sf/sf_common.hpp>
|
||||
#include <stratosphere/sf/cmif/sf_cmif_domain_api.hpp>
|
||||
#include <stratosphere/sf/cmif/sf_cmif_domain_service_object.hpp>
|
||||
#include <stratosphere/sf/impl/sf_service_object_impl.hpp>
|
||||
|
||||
namespace ams::sf::cmif {
|
||||
|
||||
class ServerDomainManager {
|
||||
NON_COPYABLE(ServerDomainManager);
|
||||
NON_MOVEABLE(ServerDomainManager);
|
||||
private:
|
||||
class Domain;
|
||||
|
||||
struct Entry {
|
||||
NON_COPYABLE(Entry);
|
||||
NON_MOVEABLE(Entry);
|
||||
|
||||
util::IntrusiveListNode free_list_node;
|
||||
util::IntrusiveListNode domain_list_node;
|
||||
Domain *owner;
|
||||
ServiceObjectHolder object;
|
||||
|
||||
explicit Entry() : owner(nullptr) { /* ... */ }
|
||||
};
|
||||
|
||||
class Domain final : public DomainServiceObject, private sf::impl::ServiceObjectImplBase2 {
|
||||
NON_COPYABLE(Domain);
|
||||
NON_MOVEABLE(Domain);
|
||||
private:
|
||||
using EntryList = typename util::IntrusiveListMemberTraits<&Entry::domain_list_node>::ListType;
|
||||
private:
|
||||
ServerDomainManager *m_manager;
|
||||
EntryList m_entries;
|
||||
public:
|
||||
explicit Domain(ServerDomainManager *m) : m_manager(m) { /* ... */ }
|
||||
~Domain();
|
||||
|
||||
void DisposeImpl();
|
||||
|
||||
virtual void AddReference() override {
|
||||
ServiceObjectImplBase2::AddReferenceImpl();
|
||||
}
|
||||
|
||||
virtual void Release() override {
|
||||
if (ServiceObjectImplBase2::ReleaseImpl()) {
|
||||
this->DisposeImpl();
|
||||
}
|
||||
}
|
||||
|
||||
virtual ServerDomainBase *GetServerDomain() override final {
|
||||
return static_cast<ServerDomainBase *>(this);
|
||||
}
|
||||
|
||||
virtual Result ReserveIds(DomainObjectId *out_ids, size_t count) override final;
|
||||
virtual void ReserveSpecificIds(const DomainObjectId *ids, size_t count) override final;
|
||||
virtual void UnreserveIds(const DomainObjectId *ids, size_t count) override final;
|
||||
virtual void RegisterObject(DomainObjectId id, ServiceObjectHolder &&obj) override final;
|
||||
|
||||
virtual ServiceObjectHolder UnregisterObject(DomainObjectId id) override final;
|
||||
virtual ServiceObjectHolder GetObject(DomainObjectId id) override final;
|
||||
};
|
||||
public:
|
||||
using DomainEntryStorage = util::TypedStorage<Entry>;
|
||||
using DomainStorage = util::TypedStorage<Domain>;
|
||||
private:
|
||||
class EntryManager {
|
||||
private:
|
||||
using EntryList = typename util::IntrusiveListMemberTraits<&Entry::free_list_node>::ListType;
|
||||
private:
|
||||
os::SdkMutex m_lock;
|
||||
EntryList m_free_list;
|
||||
Entry *m_entries;
|
||||
size_t m_num_entries;
|
||||
public:
|
||||
EntryManager(DomainEntryStorage *entry_storage, size_t entry_count);
|
||||
~EntryManager();
|
||||
Entry *AllocateEntry();
|
||||
void FreeEntry(Entry *);
|
||||
|
||||
void AllocateSpecificEntries(const DomainObjectId *ids, size_t count);
|
||||
|
||||
inline DomainObjectId GetId(Entry *e) {
|
||||
const size_t index = e - m_entries;
|
||||
AMS_ABORT_UNLESS(index < m_num_entries);
|
||||
return DomainObjectId{ u32(index + 1) };
|
||||
}
|
||||
|
||||
inline Entry *GetEntry(DomainObjectId id) {
|
||||
if (id == InvalidDomainObjectId) {
|
||||
return nullptr;
|
||||
}
|
||||
const size_t index = id.value - 1;
|
||||
if (!(index < m_num_entries)) {
|
||||
return nullptr;
|
||||
}
|
||||
return m_entries + index;
|
||||
}
|
||||
};
|
||||
private:
|
||||
os::SdkMutex m_entry_owner_lock;
|
||||
EntryManager m_entry_manager;
|
||||
private:
|
||||
virtual void *AllocateDomain() = 0;
|
||||
virtual void FreeDomain(void *) = 0;
|
||||
protected:
|
||||
ServerDomainManager(DomainEntryStorage *entry_storage, size_t entry_count) : m_entry_owner_lock(), m_entry_manager(entry_storage, entry_count) { /* ... */ }
|
||||
|
||||
inline DomainServiceObject *AllocateDomainServiceObject() {
|
||||
void *storage = this->AllocateDomain();
|
||||
if (storage == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::construct_at(static_cast<Domain *>(storage), this);
|
||||
}
|
||||
public:
|
||||
static void DestroyDomainServiceObject(DomainServiceObject *obj) {
|
||||
static_cast<Domain *>(obj)->DisposeImpl();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
@@ -1,137 +0,0 @@
|
||||
/*
|
||||
* 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 <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>
|
||||
|
||||
namespace ams::sf::cmif {
|
||||
|
||||
class DomainServiceObjectDispatchTable : public impl::ServiceDispatchTableBase {
|
||||
private:
|
||||
Result ProcessMessageImpl(ServiceDispatchContext &ctx, ServerDomainBase *domain, const cmif::PointerAndSize &in_raw_data) const;
|
||||
Result ProcessMessageForMitmImpl(ServiceDispatchContext &ctx, ServerDomainBase *domain, const cmif::PointerAndSize &in_raw_data) const;
|
||||
public:
|
||||
Result ProcessMessage(ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data) const;
|
||||
Result ProcessMessageForMitm(ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data) const;
|
||||
};
|
||||
|
||||
|
||||
class DomainServiceObjectProcessor : public ServerMessageProcessor {
|
||||
private:
|
||||
ServerMessageProcessor *m_impl_processor;
|
||||
ServerDomainBase *m_domain;
|
||||
DomainObjectId *m_in_object_ids;
|
||||
DomainObjectId *m_out_object_ids;
|
||||
size_t m_num_in_objects;
|
||||
ServerMessageRuntimeMetadata m_impl_metadata;
|
||||
public:
|
||||
DomainServiceObjectProcessor(ServerDomainBase *d, DomainObjectId *in_obj_ids, size_t num_in_objs) : m_domain(d), m_in_object_ids(in_obj_ids), m_num_in_objects(num_in_objs) {
|
||||
AMS_ABORT_UNLESS(m_domain != nullptr);
|
||||
AMS_ABORT_UNLESS(m_in_object_ids != nullptr);
|
||||
m_impl_processor = nullptr;
|
||||
m_out_object_ids = nullptr;
|
||||
m_impl_metadata = {};
|
||||
}
|
||||
|
||||
constexpr size_t GetInObjectCount() const {
|
||||
return m_num_in_objects;
|
||||
}
|
||||
|
||||
constexpr size_t GetOutObjectCount() const {
|
||||
return m_impl_metadata.GetOutObjectCount();
|
||||
}
|
||||
|
||||
constexpr size_t GetImplOutHeadersSize() const {
|
||||
return m_impl_metadata.GetOutHeadersSize();
|
||||
}
|
||||
|
||||
constexpr size_t GetImplOutDataTotalSize() const {
|
||||
return m_impl_metadata.GetUnalignedOutDataSize() + m_impl_metadata.GetOutHeadersSize();
|
||||
}
|
||||
public:
|
||||
/* Used to enabled templated message processors. */
|
||||
virtual void SetImplementationProcessor(ServerMessageProcessor *impl) override final {
|
||||
if (m_impl_processor == nullptr) {
|
||||
m_impl_processor = impl;
|
||||
} else {
|
||||
m_impl_processor->SetImplementationProcessor(impl);
|
||||
}
|
||||
|
||||
m_impl_metadata = m_impl_processor->GetRuntimeMetadata();
|
||||
}
|
||||
|
||||
virtual const ServerMessageRuntimeMetadata GetRuntimeMetadata() const override final {
|
||||
const auto runtime_metadata = m_impl_processor->GetRuntimeMetadata();
|
||||
|
||||
return ServerMessageRuntimeMetadata {
|
||||
.in_data_size = static_cast<u16>(runtime_metadata.GetInDataSize() + runtime_metadata.GetInObjectCount() * sizeof(DomainObjectId)),
|
||||
.unaligned_out_data_size = static_cast<u16>(runtime_metadata.GetOutDataSize() + runtime_metadata.GetOutObjectCount() * sizeof(DomainObjectId)),
|
||||
.in_headers_size = static_cast<u8>(runtime_metadata.GetInHeadersSize() + sizeof(CmifDomainInHeader)),
|
||||
.out_headers_size = static_cast<u8>(runtime_metadata.GetOutHeadersSize() + sizeof(CmifDomainOutHeader)),
|
||||
.in_object_count = 0,
|
||||
.out_object_count = 0,
|
||||
};
|
||||
}
|
||||
|
||||
virtual Result PrepareForProcess(const ServiceDispatchContext &ctx, const ServerMessageRuntimeMetadata runtime_metadata) const override final;
|
||||
virtual Result GetInObjects(ServiceObjectHolder *in_objects) const override final;
|
||||
virtual HipcRequest PrepareForReply(const cmif::ServiceDispatchContext &ctx, PointerAndSize &out_raw_data, const ServerMessageRuntimeMetadata runtime_metadata) override final;
|
||||
virtual void PrepareForErrorReply(const cmif::ServiceDispatchContext &ctx, PointerAndSize &out_raw_data, const ServerMessageRuntimeMetadata runtime_metadata) override final;
|
||||
virtual void SetOutObjects(const cmif::ServiceDispatchContext &ctx, const HipcRequest &response, ServiceObjectHolder *out_objects, DomainObjectId *ids) override final;
|
||||
};
|
||||
|
||||
class DomainServiceObject : public IServiceObject, public ServerDomainBase {
|
||||
friend class DomainServiceObjectDispatchTable;
|
||||
public:
|
||||
static constexpr inline DomainServiceObjectDispatchTable s_CmifServiceDispatchTable{};
|
||||
private:
|
||||
virtual ServerDomainBase *GetServerDomain() = 0;
|
||||
};
|
||||
|
||||
class MitmDomainServiceObject : public DomainServiceObject{};
|
||||
|
||||
static_assert(sizeof(DomainServiceObject) == sizeof(MitmDomainServiceObject));
|
||||
|
||||
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;
|
||||
static constexpr ProcessHandlerType ProcessHandlerImpl = &impl::ServiceDispatchTableBase::ProcessMessage<DispatchTableType>;
|
||||
|
||||
static constexpr inline ServiceDispatchMeta Meta{std::addressof(DomainServiceObject::s_CmifServiceDispatchTable), ProcessHandlerImpl};
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ServiceDispatchTraits<MitmDomainServiceObject> {
|
||||
static_assert(std::is_base_of<DomainServiceObject, MitmDomainServiceObject>::value, "MitmDomainServiceObject must derive from DomainServiceObject");
|
||||
using ProcessHandlerType = decltype(ServiceDispatchMeta::ProcessHandler);
|
||||
|
||||
using DispatchTableType = DomainServiceObjectDispatchTable;
|
||||
static constexpr ProcessHandlerType ProcessHandlerImpl = &impl::ServiceDispatchTableBase::ProcessMessageForMitm<DispatchTableType>;
|
||||
|
||||
static constexpr inline ServiceDispatchMeta Meta{std::addressof(DomainServiceObject::s_CmifServiceDispatchTable), ProcessHandlerImpl};
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* 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 <stratosphere/sf/sf_common.hpp>
|
||||
|
||||
namespace ams::sf::cmif {
|
||||
|
||||
using InlineContext = u32;
|
||||
|
||||
InlineContext GetInlineContext();
|
||||
InlineContext SetInlineContext(InlineContext ctx);
|
||||
|
||||
class ScopedInlineContextChanger {
|
||||
private:
|
||||
InlineContext m_prev_ctx;
|
||||
public:
|
||||
ALWAYS_INLINE explicit ScopedInlineContextChanger(InlineContext new_ctx) : m_prev_ctx(SetInlineContext(new_ctx)) { /* ... */ }
|
||||
~ScopedInlineContextChanger() { SetInlineContext(m_prev_ctx); }
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* 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 <stratosphere/sf/sf_common.hpp>
|
||||
|
||||
namespace ams::sf::cmif {
|
||||
|
||||
class PointerAndSize {
|
||||
private:
|
||||
uintptr_t m_pointer;
|
||||
size_t m_size;
|
||||
public:
|
||||
constexpr PointerAndSize() : m_pointer(0), m_size(0) { /* ... */ }
|
||||
constexpr PointerAndSize(uintptr_t ptr, size_t sz) : m_pointer(ptr), m_size(sz) { /* ... */ }
|
||||
PointerAndSize(void *ptr, size_t sz) : PointerAndSize(reinterpret_cast<uintptr_t>(ptr), sz) { /* ... */ }
|
||||
|
||||
void *GetPointer() const {
|
||||
return reinterpret_cast<void *>(m_pointer);
|
||||
}
|
||||
|
||||
constexpr uintptr_t GetAddress() const {
|
||||
return m_pointer;
|
||||
}
|
||||
|
||||
constexpr size_t GetSize() const {
|
||||
return m_size;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
/*
|
||||
* 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 <stratosphere/sf/sf_service_object.hpp>
|
||||
#include <stratosphere/sf/cmif/sf_cmif_pointer_and_size.hpp>
|
||||
|
||||
namespace ams::sf::cmif {
|
||||
|
||||
/* Forward declare ServiceDispatchContext, ServiceObjectHolder. */
|
||||
struct ServiceDispatchContext;
|
||||
class ServiceObjectHolder;
|
||||
struct DomainObjectId;
|
||||
|
||||
/* This is needed for non-templated domain message processing. */
|
||||
struct ServerMessageRuntimeMetadata {
|
||||
u16 in_data_size;
|
||||
u16 unaligned_out_data_size;
|
||||
u8 in_headers_size;
|
||||
u8 out_headers_size;
|
||||
u8 in_object_count;
|
||||
u8 out_object_count;
|
||||
|
||||
constexpr size_t GetInDataSize() const {
|
||||
return static_cast<size_t>(this->in_data_size);
|
||||
}
|
||||
|
||||
constexpr size_t GetOutDataSize() const {
|
||||
return static_cast<size_t>(util::AlignUp(this->unaligned_out_data_size, sizeof(u32)));
|
||||
}
|
||||
|
||||
constexpr size_t GetUnalignedOutDataSize() const {
|
||||
return static_cast<size_t>(this->unaligned_out_data_size);
|
||||
}
|
||||
|
||||
constexpr size_t GetInHeadersSize() const {
|
||||
return static_cast<size_t>(this->in_headers_size);
|
||||
}
|
||||
|
||||
constexpr size_t GetOutHeadersSize() const {
|
||||
return static_cast<size_t>(this->out_headers_size);
|
||||
}
|
||||
|
||||
constexpr size_t GetInObjectCount() const {
|
||||
return static_cast<size_t>(this->in_object_count);
|
||||
}
|
||||
|
||||
constexpr size_t GetOutObjectCount() const {
|
||||
return static_cast<size_t>(this->out_object_count);
|
||||
}
|
||||
|
||||
constexpr size_t GetUnfixedOutPointerSizeOffset() const {
|
||||
return this->GetInDataSize() + this->GetInHeadersSize() + 0x10 /* padding. */;
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(util::is_pod<ServerMessageRuntimeMetadata>::value, "util::is_pod<ServerMessageRuntimeMetadata>::value");
|
||||
static_assert(sizeof(ServerMessageRuntimeMetadata) == sizeof(u64), "sizeof(ServerMessageRuntimeMetadata)");
|
||||
|
||||
class ServerMessageProcessor {
|
||||
public:
|
||||
/* Used to enabled templated message processors. */
|
||||
virtual void SetImplementationProcessor(ServerMessageProcessor *impl) = 0;
|
||||
virtual const ServerMessageRuntimeMetadata GetRuntimeMetadata() const = 0;
|
||||
|
||||
virtual Result PrepareForProcess(const ServiceDispatchContext &ctx, const ServerMessageRuntimeMetadata runtime_metadata) const = 0;
|
||||
virtual Result GetInObjects(ServiceObjectHolder *in_objects) const = 0;
|
||||
virtual HipcRequest PrepareForReply(const cmif::ServiceDispatchContext &ctx, PointerAndSize &out_raw_data, const ServerMessageRuntimeMetadata runtime_metadata) = 0;
|
||||
virtual void PrepareForErrorReply(const cmif::ServiceDispatchContext &ctx, PointerAndSize &out_raw_data, const ServerMessageRuntimeMetadata runtime_metadata) = 0;
|
||||
virtual void SetOutObjects(const cmif::ServiceDispatchContext &ctx, const HipcRequest &response, ServiceObjectHolder *out_objects, DomainObjectId *ids) = 0;
|
||||
};
|
||||
}
|
||||
@@ -1,177 +0,0 @@
|
||||
/*
|
||||
* 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 <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>
|
||||
|
||||
namespace ams::sf::hipc {
|
||||
|
||||
class ServerSessionManager;
|
||||
class ServerSession;
|
||||
|
||||
}
|
||||
|
||||
namespace ams::sf::cmif {
|
||||
|
||||
class ServerMessageProcessor;
|
||||
|
||||
struct HandlesToClose {
|
||||
os::NativeHandle handles[8];
|
||||
size_t num_handles;
|
||||
};
|
||||
|
||||
struct ServiceDispatchContext {
|
||||
sf::IServiceObject *srv_obj;
|
||||
hipc::ServerSessionManager *manager;
|
||||
hipc::ServerSession *session;
|
||||
ServerMessageProcessor *processor;
|
||||
HandlesToClose *handles_to_close;
|
||||
const PointerAndSize pointer_buffer;
|
||||
const PointerAndSize in_message_buffer;
|
||||
const PointerAndSize out_message_buffer;
|
||||
const HipcParsedRequest request;
|
||||
};
|
||||
|
||||
struct ServiceCommandMeta {
|
||||
hos::Version hosver_low;
|
||||
hos::Version hosver_high;
|
||||
u32 cmd_id;
|
||||
Result (*handler)(CmifOutHeader **out_header_ptr, ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data);
|
||||
|
||||
constexpr inline bool MatchesVersion(hos::Version hosver) const {
|
||||
const bool min_valid = this->hosver_low == hos::Version_Min;
|
||||
const bool max_valid = this->hosver_high == hos::Version_Max;
|
||||
|
||||
return (min_valid || this->hosver_low <= hosver) && (max_valid || hosver <= this->hosver_high);
|
||||
}
|
||||
|
||||
constexpr inline bool Matches(u32 cmd_id, hos::Version hosver) const {
|
||||
return this->cmd_id == cmd_id && this->MatchesVersion(hosver);
|
||||
}
|
||||
|
||||
constexpr inline decltype(handler) GetHandler() const {
|
||||
return this->handler;
|
||||
}
|
||||
|
||||
constexpr inline bool operator>(const ServiceCommandMeta &rhs) const {
|
||||
if (this->cmd_id > rhs.cmd_id) {
|
||||
return true;
|
||||
} else if (this->cmd_id == rhs.cmd_id && this->hosver_low > rhs.hosver_low) {
|
||||
return true;
|
||||
} else if (this->cmd_id == rhs.cmd_id && this->hosver_low == rhs.hosver_low && this->hosver_high == rhs.hosver_high){
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
static_assert(util::is_pod<ServiceCommandMeta>::value && sizeof(ServiceCommandMeta) == 0x18, "sizeof(ServiceCommandMeta)");
|
||||
|
||||
namespace impl {
|
||||
|
||||
|
||||
class ServiceDispatchTableBase {
|
||||
protected:
|
||||
Result ProcessMessageImpl(ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data, const ServiceCommandMeta *entries, const size_t entry_count, u32 interface_id_for_debug) const;
|
||||
Result ProcessMessageForMitmImpl(ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data, const ServiceCommandMeta *entries, const size_t entry_count, u32 interface_id_for_debug) const;
|
||||
public:
|
||||
/* CRTP. */
|
||||
template<typename T>
|
||||
Result ProcessMessage(ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data) const {
|
||||
static_assert(std::is_base_of<ServiceDispatchTableBase, T>::value, "ServiceDispatchTableBase::Process<T>");
|
||||
R_RETURN(static_cast<const T *>(this)->ProcessMessage(ctx, in_raw_data));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Result ProcessMessageForMitm(ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data) const {
|
||||
static_assert(std::is_base_of<ServiceDispatchTableBase, T>::value, "ServiceDispatchTableBase::ProcessForMitm<T>");
|
||||
R_RETURN(static_cast<const T *>(this)->ProcessMessageForMitm(ctx, in_raw_data));
|
||||
}
|
||||
};
|
||||
|
||||
template<u32 InterfaceIdForDebug, size_t N>
|
||||
class ServiceDispatchTableImpl : public ServiceDispatchTableBase {
|
||||
public:
|
||||
static constexpr size_t NumEntries = N;
|
||||
private:
|
||||
const std::array<ServiceCommandMeta, N> m_entries;
|
||||
public:
|
||||
explicit constexpr ServiceDispatchTableImpl(const std::array<ServiceCommandMeta, N> &e) : m_entries{e} { /* ... */ }
|
||||
|
||||
Result ProcessMessage(ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data) const {
|
||||
R_RETURN(this->ProcessMessageImpl(ctx, in_raw_data, m_entries.data(), m_entries.size(), InterfaceIdForDebug));
|
||||
}
|
||||
|
||||
Result ProcessMessageForMitm(ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data) const {
|
||||
R_RETURN(this->ProcessMessageForMitmImpl(ctx, in_raw_data, m_entries.data(), m_entries.size(), InterfaceIdForDebug));
|
||||
}
|
||||
|
||||
constexpr const std::array<ServiceCommandMeta, N> &GetEntries() const {
|
||||
return m_entries;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<u32 InterfaceIdForDebug, size_t N>
|
||||
class ServiceDispatchTable : public impl::ServiceDispatchTableImpl<InterfaceIdForDebug, N> {
|
||||
public:
|
||||
explicit constexpr ServiceDispatchTable(const std::array<ServiceCommandMeta, N> &e) : impl::ServiceDispatchTableImpl<InterfaceIdForDebug, N>(e) { /* ... */ }
|
||||
};
|
||||
|
||||
struct ServiceDispatchMeta {
|
||||
const impl::ServiceDispatchTableBase *DispatchTable;
|
||||
Result (impl::ServiceDispatchTableBase::*ProcessHandler)(ServiceDispatchContext &, const cmif::PointerAndSize &) const;
|
||||
|
||||
uintptr_t GetServiceId() const {
|
||||
return reinterpret_cast<uintptr_t>(this->DispatchTable);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T> requires sf::IsServiceObject<T>
|
||||
struct ServiceDispatchTraits {
|
||||
using ProcessHandlerType = decltype(ServiceDispatchMeta::ProcessHandler);
|
||||
|
||||
static constexpr inline auto DispatchTable = T::template s_CmifServiceDispatchTable<T>;
|
||||
using DispatchTableType = decltype(DispatchTable);
|
||||
|
||||
static constexpr ProcessHandlerType ProcessHandlerImpl = sf::IsMitmServiceObject<T> ? (&impl::ServiceDispatchTableBase::ProcessMessageForMitm<DispatchTableType>)
|
||||
: (&impl::ServiceDispatchTableBase::ProcessMessage<DispatchTableType>);
|
||||
|
||||
static constexpr inline ServiceDispatchMeta Meta{std::addressof(DispatchTable), ProcessHandlerImpl};
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ServiceDispatchTraits<sf::IServiceObject> {
|
||||
static constexpr inline auto DispatchTable = ServiceDispatchTable<0, 0>(std::array<ServiceCommandMeta, 0>{});
|
||||
};
|
||||
|
||||
#if AMS_SF_MITM_SUPPORTED
|
||||
template<>
|
||||
struct ServiceDispatchTraits<sf::IMitmServiceObject> {
|
||||
static constexpr inline auto DispatchTable = ServiceDispatchTable<0, 0>(std::array<ServiceCommandMeta, 0>{});
|
||||
};
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
constexpr ALWAYS_INLINE const ServiceDispatchMeta *GetServiceDispatchMeta() {
|
||||
return std::addressof(ServiceDispatchTraits<T>::Meta);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
/*
|
||||
* 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 <stratosphere/sf/sf_service_object.hpp>
|
||||
#include <stratosphere/sf/cmif/sf_cmif_service_dispatch.hpp>
|
||||
|
||||
namespace ams::sf::cmif {
|
||||
|
||||
class ServiceObjectHolder {
|
||||
private:
|
||||
SharedPointer<IServiceObject> m_srv;
|
||||
const ServiceDispatchMeta *m_dispatch_meta;
|
||||
private:
|
||||
/* Copy constructor. */
|
||||
ServiceObjectHolder(const ServiceObjectHolder &o) : m_srv(o.m_srv), m_dispatch_meta(o.m_dispatch_meta) { /* ... */ }
|
||||
ServiceObjectHolder &operator=(const ServiceObjectHolder &o) = delete;
|
||||
public:
|
||||
/* Default constructor, null all members. */
|
||||
ServiceObjectHolder() : m_srv(nullptr, false), m_dispatch_meta(nullptr) { /* ... */ }
|
||||
|
||||
~ServiceObjectHolder() {
|
||||
m_dispatch_meta = nullptr;
|
||||
}
|
||||
|
||||
/* Ensure correct type id at runtime through template constructor. */
|
||||
template<typename ServiceImpl>
|
||||
constexpr explicit ServiceObjectHolder(SharedPointer<ServiceImpl> &&s) : m_srv(std::move(s)), m_dispatch_meta(GetServiceDispatchMeta<ServiceImpl>()) {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* Move constructor, assignment operator. */
|
||||
ServiceObjectHolder(ServiceObjectHolder &&o) : m_srv(std::move(o.m_srv)), m_dispatch_meta(std::move(o.m_dispatch_meta)) {
|
||||
o.m_dispatch_meta = nullptr;
|
||||
}
|
||||
|
||||
ServiceObjectHolder &operator=(ServiceObjectHolder &&o) {
|
||||
ServiceObjectHolder tmp(std::move(o));
|
||||
tmp.swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* State management. */
|
||||
void swap(ServiceObjectHolder &o) {
|
||||
m_srv.swap(o.m_srv);
|
||||
std::swap(m_dispatch_meta, o.m_dispatch_meta);
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
m_srv = nullptr;
|
||||
m_dispatch_meta = nullptr;
|
||||
}
|
||||
|
||||
ServiceObjectHolder Clone() const {
|
||||
return ServiceObjectHolder(*this);
|
||||
}
|
||||
|
||||
/* Boolean operators. */
|
||||
explicit constexpr operator bool() const {
|
||||
return m_srv != nullptr;
|
||||
}
|
||||
|
||||
constexpr bool operator!() const {
|
||||
return m_srv == nullptr;
|
||||
}
|
||||
|
||||
/* Getters. */
|
||||
constexpr uintptr_t GetServiceId() const {
|
||||
if (m_dispatch_meta) {
|
||||
return m_dispatch_meta->GetServiceId();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename Interface>
|
||||
constexpr inline bool IsServiceObjectValid() const {
|
||||
return this->GetServiceId() == GetServiceDispatchMeta<Interface>()->GetServiceId();
|
||||
}
|
||||
|
||||
template<typename Interface>
|
||||
inline Interface *GetServiceObject() const {
|
||||
if (this->GetServiceId() == GetServiceDispatchMeta<Interface>()->GetServiceId()) {
|
||||
return static_cast<Interface *>(m_srv.Get());
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
inline sf::IServiceObject *GetServiceObjectUnsafe() const {
|
||||
return static_cast<sf::IServiceObject *>(m_srv.Get());
|
||||
}
|
||||
|
||||
/* Processing. */
|
||||
Result ProcessMessage(ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data) const;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* 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 <stratosphere/sf/sf_common.hpp>
|
||||
#include <stratosphere/sf/cmif/sf_cmif_pointer_and_size.hpp>
|
||||
|
||||
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,
|
||||
NeedsRetry,
|
||||
};
|
||||
|
||||
void AttachMultiWaitHolderForAccept(os::MultiWaitHolderType *holder, os::NativeHandle port);
|
||||
void AttachMultiWaitHolderForReply(os::MultiWaitHolderType *holder, os::NativeHandle request);
|
||||
|
||||
Result Receive(ReceiveResult *out_recv_result, os::NativeHandle session_handle, const cmif::PointerAndSize &message_buffer);
|
||||
Result Receive(bool *out_closed, os::NativeHandle session_handle, const cmif::PointerAndSize &message_buffer);
|
||||
Result Reply(os::NativeHandle session_handle, const cmif::PointerAndSize &message_buffer);
|
||||
|
||||
Result CreateSession(os::NativeHandle *out_server_handle, os::NativeHandle *out_client_handle);
|
||||
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* 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 <stratosphere/sf/hipc/sf_hipc_server_session_manager.hpp>
|
||||
#include <stratosphere/sf/cmif/sf_cmif_domain_manager.hpp>
|
||||
|
||||
namespace ams::sf::hipc {
|
||||
|
||||
class ServerDomainSessionManager : public ServerSessionManager, private cmif::ServerDomainManager {
|
||||
protected:
|
||||
using cmif::ServerDomainManager::DomainEntryStorage;
|
||||
using cmif::ServerDomainManager::DomainStorage;
|
||||
protected:
|
||||
virtual Result DispatchManagerRequest(ServerSession *session, const cmif::PointerAndSize &in_message, const cmif::PointerAndSize &out_message) override final;
|
||||
public:
|
||||
ServerDomainSessionManager(DomainEntryStorage *entry_storage, size_t entry_count) : ServerDomainManager(entry_storage, entry_count) { /* ... */ }
|
||||
|
||||
inline cmif::DomainServiceObject *AllocateDomainServiceObject() {
|
||||
return cmif::ServerDomainManager::AllocateDomainServiceObject();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,511 +0,0 @@
|
||||
/*
|
||||
* 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 <stratosphere/sf/sf_mitm_config.hpp>
|
||||
#include <stratosphere/sf/hipc/sf_hipc_server_domain_session_manager.hpp>
|
||||
#include <stratosphere/sm.hpp>
|
||||
|
||||
namespace ams::sf::hipc {
|
||||
|
||||
struct DefaultServerManagerOptions {
|
||||
static constexpr size_t PointerBufferSize = 0;
|
||||
static constexpr size_t MaxDomains = 0;
|
||||
static constexpr size_t MaxDomainObjects = 0;
|
||||
static constexpr bool CanDeferInvokeRequest = false;
|
||||
static constexpr bool CanManageMitmServers = false;
|
||||
};
|
||||
|
||||
static constexpr size_t ServerSessionCountMax = 0x40;
|
||||
static_assert(ServerSessionCountMax == 0x40, "ServerSessionCountMax isn't 0x40 somehow, this assert is a reminder that this will break lots of things");
|
||||
|
||||
template<size_t, typename, size_t>
|
||||
class ServerManager;
|
||||
|
||||
class ServerManagerBase : public ServerDomainSessionManager {
|
||||
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;
|
||||
using ServerDomainSessionManager::DomainStorage;
|
||||
protected:
|
||||
class Server : public os::MultiWaitHolderType {
|
||||
friend class ServerManagerBase;
|
||||
template<size_t, typename, size_t>
|
||||
friend class ServerManager;
|
||||
NON_COPYABLE(Server);
|
||||
NON_MOVEABLE(Server);
|
||||
private:
|
||||
cmif::ServiceObjectHolder m_static_object;
|
||||
os::NativeHandle m_port_handle;
|
||||
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);
|
||||
|
||||
/* Create forward service. */
|
||||
*out_fsrv = ServerSession::CreateForwardService();
|
||||
|
||||
/* 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;
|
||||
os::Event m_request_stop_event;
|
||||
os::MultiWaitHolderType m_request_stop_event_holder;
|
||||
os::Event m_notify_event;
|
||||
os::MultiWaitHolderType m_notify_event_holder;
|
||||
|
||||
os::SdkMutex m_selection_mutex;
|
||||
|
||||
os::SdkMutex m_deferred_list_mutex;
|
||||
os::MultiWaitType m_deferred_list;
|
||||
|
||||
/* Boolean values. */
|
||||
const bool m_is_defer_supported;
|
||||
const bool m_is_mitm_supported;
|
||||
private:
|
||||
virtual void RegisterServerSessionToWait(ServerSession *session) override final;
|
||||
void LinkToDeferredList(os::MultiWaitHolderType *holder);
|
||||
void LinkDeferred();
|
||||
|
||||
bool WaitAndProcessImpl();
|
||||
|
||||
Result ProcessForServer(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. */
|
||||
AMS_ABORT_UNLESS(this->CanManageMitmServers());
|
||||
os::SetMultiWaitHolderUserData(server, static_cast<uintptr_t>(UserDataTag::MitmServer));
|
||||
} else {
|
||||
/* 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);
|
||||
}
|
||||
|
||||
void RegisterServerImpl(int index, cmif::ServiceObjectHolder &&static_holder, os::NativeHandle port_handle, bool is_mitm_server) {
|
||||
/* Allocate server memory. */
|
||||
auto *server = this->AllocateServer();
|
||||
AMS_ABORT_UNLESS(server != nullptr);
|
||||
server->m_service_managed = false;
|
||||
|
||||
if (static_holder) {
|
||||
server->m_static_object = std::move(static_holder);
|
||||
} else {
|
||||
server->m_index = index;
|
||||
}
|
||||
|
||||
this->RegisterServerImpl(server, port_handle, is_mitm_server);
|
||||
}
|
||||
|
||||
Result RegisterServerImpl(int index, cmif::ServiceObjectHolder &&static_holder, sm::ServiceName service_name, size_t max_sessions) {
|
||||
/* Register service. */
|
||||
os::NativeHandle port_handle;
|
||||
R_TRY(sm::RegisterService(&port_handle, service_name, max_sessions, false));
|
||||
|
||||
/* Allocate server memory. */
|
||||
auto *server = this->AllocateServer();
|
||||
AMS_ABORT_UNLESS(server != nullptr);
|
||||
server->m_service_managed = true;
|
||||
server->m_service_name = service_name;
|
||||
|
||||
if (static_holder) {
|
||||
server->m_static_object = std::move(static_holder);
|
||||
} else {
|
||||
server->m_index = index;
|
||||
}
|
||||
|
||||
this->RegisterServerImpl(server, port_handle, false);
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
#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;
|
||||
virtual Result OnNeedsToAccept(int port_index, Server *server) {
|
||||
AMS_UNUSED(port_index, server);
|
||||
AMS_ABORT("OnNeedsToAccept must be overridden when using indexed ports");
|
||||
}
|
||||
|
||||
template<typename Interface>
|
||||
Result AcceptImpl(Server *server, SharedPointer<Interface> p) {
|
||||
R_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());
|
||||
R_RETURN(ServerSessionManager::AcceptMitmSession(server->m_port_handle, std::move(p), std::move(forward_service)));
|
||||
}
|
||||
|
||||
template<typename Interface>
|
||||
Result RegisterMitmServerImpl(int index, cmif::ServiceObjectHolder &&static_holder, sm::ServiceName service_name) {
|
||||
/* Install mitm service. */
|
||||
os::NativeHandle port_handle;
|
||||
R_TRY(this->InstallMitmServerImpl(&port_handle, service_name, &Interface::ShouldMitm));
|
||||
|
||||
/* Allocate server memory. */
|
||||
auto *server = this->AllocateServer();
|
||||
AMS_ABORT_UNLESS(server != nullptr);
|
||||
server->m_service_managed = true;
|
||||
server->m_service_name = service_name;
|
||||
|
||||
if (static_holder) {
|
||||
server->m_static_object = std::move(static_holder);
|
||||
} else {
|
||||
server->m_index = index;
|
||||
}
|
||||
|
||||
this->RegisterServerImpl(server, port_handle, true);
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
#endif
|
||||
public:
|
||||
ServerManagerBase(DomainEntryStorage *entry_storage, size_t entry_count, bool defer_supported, bool mitm_supported) :
|
||||
ServerDomainSessionManager(entry_storage, entry_count),
|
||||
m_request_stop_event(os::EventClearMode_ManualClear), m_notify_event(os::EventClearMode_ManualClear),
|
||||
m_selection_mutex(), m_deferred_list_mutex(), m_is_defer_supported(defer_supported), m_is_mitm_supported(mitm_supported)
|
||||
{
|
||||
/* Link multi-wait holders. */
|
||||
os::InitializeMultiWait(std::addressof(m_multi_wait));
|
||||
os::InitializeMultiWaitHolder(std::addressof(m_request_stop_event_holder), m_request_stop_event.GetBase());
|
||||
os::LinkMultiWaitHolder(std::addressof(m_multi_wait), std::addressof(m_request_stop_event_holder));
|
||||
os::InitializeMultiWaitHolder(std::addressof(m_notify_event_holder), m_notify_event.GetBase());
|
||||
os::LinkMultiWaitHolder(std::addressof(m_multi_wait), std::addressof(m_notify_event_holder));
|
||||
|
||||
os::InitializeMultiWait(std::addressof(m_deferred_list));
|
||||
}
|
||||
|
||||
virtual ~ServerManagerBase() = default;
|
||||
|
||||
static ALWAYS_INLINE bool CanAnyDeferInvokeRequest() {
|
||||
return g_is_any_deferred_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) {
|
||||
this->RegisterServerImpl(0, cmif::ServiceObjectHolder(std::move(static_object)), port_handle, false);
|
||||
}
|
||||
|
||||
template<typename Interface>
|
||||
Result RegisterObjectForServer(SharedPointer<Interface> static_object, sm::ServiceName service_name, size_t max_sessions) {
|
||||
R_RETURN(this->RegisterServerImpl(0, cmif::ServiceObjectHolder(std::move(static_object)), service_name, max_sessions));
|
||||
}
|
||||
|
||||
void RegisterServer(int port_index, os::NativeHandle port_handle) {
|
||||
this->RegisterServerImpl(port_index, cmif::ServiceObjectHolder(), port_handle, false);
|
||||
}
|
||||
|
||||
Result RegisterServer(int port_index, sm::ServiceName service_name, size_t max_sessions) {
|
||||
R_RETURN(this->RegisterServerImpl(port_index, cmif::ServiceObjectHolder(), service_name, max_sessions));
|
||||
}
|
||||
|
||||
/* Processing. */
|
||||
os::MultiWaitHolderType *WaitSignaled();
|
||||
|
||||
void ResumeProcessing();
|
||||
void RequestStopProcessing();
|
||||
void AddUserMultiWaitHolder(os::MultiWaitHolderType *holder);
|
||||
|
||||
Result Process(os::MultiWaitHolderType *holder);
|
||||
void WaitAndProcess();
|
||||
void LoopProcess();
|
||||
};
|
||||
|
||||
template<size_t MaxServers, typename ManagerOptions = DefaultServerManagerOptions, size_t MaxSessions = ServerSessionCountMax - MaxServers>
|
||||
class ServerManager : public ServerManagerBase {
|
||||
NON_COPYABLE(ServerManager);
|
||||
NON_MOVEABLE(ServerManager);
|
||||
static_assert(MaxServers <= ServerSessionCountMax, "MaxServers can never be larger than ServerSessionCountMax (0x40).");
|
||||
static_assert(MaxSessions <= ServerSessionCountMax, "MaxSessions can never be larger than ServerSessionCountMax (0x40).");
|
||||
static_assert(MaxServers + MaxSessions <= ServerSessionCountMax, "MaxServers + MaxSessions can never be larger than ServerSessionCountMax (0x40).");
|
||||
private:
|
||||
static constexpr inline bool DomainCountsValid = [] {
|
||||
if constexpr (ManagerOptions::MaxDomains > 0) {
|
||||
return ManagerOptions::MaxDomainObjects > 0;
|
||||
} else {
|
||||
return ManagerOptions::MaxDomainObjects == 0;
|
||||
}
|
||||
}();
|
||||
static_assert(DomainCountsValid, "Invalid Domain Counts");
|
||||
|
||||
#if !(AMS_SF_MITM_SUPPORTED)
|
||||
static_assert(!ManagerOptions::CanManageMitmServers);
|
||||
#endif
|
||||
protected:
|
||||
using ServerManagerBase::DomainEntryStorage;
|
||||
using ServerManagerBase::DomainStorage;
|
||||
private:
|
||||
/* Resource storage. */
|
||||
os::SdkMutex m_resource_mutex;
|
||||
util::TypedStorage<Server> m_server_storages[MaxServers];
|
||||
bool m_server_allocated[MaxServers];
|
||||
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;
|
||||
|
||||
/* Domain resources. */
|
||||
DomainStorage m_domain_storages[ManagerOptions::MaxDomains];
|
||||
bool m_domain_allocated[ManagerOptions::MaxDomains];
|
||||
DomainEntryStorage m_domain_entry_storages[ManagerOptions::MaxDomainObjects];
|
||||
private:
|
||||
constexpr inline size_t GetServerIndex(const Server *server) const {
|
||||
const size_t i = server - GetPointer(m_server_storages[0]);
|
||||
AMS_ABORT_UNLESS(i < MaxServers);
|
||||
return i;
|
||||
}
|
||||
|
||||
constexpr inline size_t GetSessionIndex(const ServerSession *session) const {
|
||||
const size_t i = session - GetPointer(m_session_storages[0]);
|
||||
AMS_ABORT_UNLESS(i < MaxSessions);
|
||||
return i;
|
||||
}
|
||||
|
||||
constexpr inline cmif::PointerAndSize GetObjectBySessionIndex(const ServerSession *session, uintptr_t start, size_t size) const {
|
||||
return cmif::PointerAndSize(start + this->GetSessionIndex(session) * size, size);
|
||||
}
|
||||
protected:
|
||||
virtual ServerSession *AllocateSession() override final {
|
||||
if constexpr (MaxSessions > 0) {
|
||||
std::scoped_lock lk(m_resource_mutex);
|
||||
|
||||
for (size_t i = 0; i < MaxSessions; i++) {
|
||||
if (!m_session_allocated[i]) {
|
||||
m_session_allocated[i] = true;
|
||||
return GetPointer(m_session_storages[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual void FreeSession(ServerSession *session) override final {
|
||||
std::scoped_lock lk(m_resource_mutex);
|
||||
const size_t index = this->GetSessionIndex(session);
|
||||
AMS_ABORT_UNLESS(m_session_allocated[index]);
|
||||
m_session_allocated[index] = false;
|
||||
}
|
||||
|
||||
virtual Server *AllocateServer() override final {
|
||||
if constexpr (MaxServers > 0) {
|
||||
std::scoped_lock lk(m_resource_mutex);
|
||||
|
||||
for (size_t i = 0; i < MaxServers; i++) {
|
||||
if (!m_server_allocated[i]) {
|
||||
m_server_allocated[i] = true;
|
||||
return GetPointer(m_server_storages[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual void DestroyServer(Server *server) override final {
|
||||
std::scoped_lock lk(m_resource_mutex);
|
||||
const size_t index = this->GetServerIndex(server);
|
||||
AMS_ABORT_UNLESS(m_server_allocated[index]);
|
||||
{
|
||||
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));
|
||||
} else {
|
||||
R_ABORT_UNLESS(sm::UnregisterService(server->m_service_name));
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
m_server_allocated[index] = false;
|
||||
}
|
||||
|
||||
virtual void *AllocateDomain() override final {
|
||||
std::scoped_lock lk(m_resource_mutex);
|
||||
for (size_t i = 0; i < ManagerOptions::MaxDomains; i++) {
|
||||
if (!m_domain_allocated[i]) {
|
||||
m_domain_allocated[i] = true;
|
||||
return GetPointer(m_domain_storages[i]);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual void FreeDomain(void *domain) override final {
|
||||
std::scoped_lock lk(m_resource_mutex);
|
||||
DomainStorage *ptr = static_cast<DomainStorage *>(domain);
|
||||
const size_t index = ptr - m_domain_storages;
|
||||
AMS_ABORT_UNLESS(index < ManagerOptions::MaxDomains);
|
||||
AMS_ABORT_UNLESS(m_domain_allocated[index]);
|
||||
m_domain_allocated[index] = false;
|
||||
}
|
||||
|
||||
virtual cmif::PointerAndSize GetSessionPointerBuffer(const ServerSession *session) const override final {
|
||||
if constexpr (ManagerOptions::PointerBufferSize > 0) {
|
||||
return this->GetObjectBySessionIndex(session, m_pointer_buffers_start, ManagerOptions::PointerBufferSize);
|
||||
} else {
|
||||
return cmif::PointerAndSize();
|
||||
}
|
||||
}
|
||||
|
||||
virtual cmif::PointerAndSize GetSessionSavedMessageBuffer(const ServerSession *session) const override final {
|
||||
if constexpr (ManagerOptions::CanDeferInvokeRequest || ManagerOptions::CanManageMitmServers) {
|
||||
return this->GetObjectBySessionIndex(session, m_saved_messages_start, hipc::TlsMessageBufferSize);
|
||||
} else {
|
||||
return cmif::PointerAndSize();
|
||||
}
|
||||
}
|
||||
public:
|
||||
ServerManager() : ServerManagerBase(m_domain_entry_storages, ManagerOptions::MaxDomainObjects, ManagerOptions::CanDeferInvokeRequest, ManagerOptions::CanManageMitmServers), m_resource_mutex() {
|
||||
/* Clear storages. */
|
||||
#define SF_SM_MEMCLEAR(obj) if constexpr (sizeof(obj) > 0) { std::memset(obj, 0, sizeof(obj)); }
|
||||
SF_SM_MEMCLEAR(m_server_storages);
|
||||
SF_SM_MEMCLEAR(m_server_allocated);
|
||||
SF_SM_MEMCLEAR(m_session_storages);
|
||||
SF_SM_MEMCLEAR(m_session_allocated);
|
||||
SF_SM_MEMCLEAR(m_pointer_buffer_storage);
|
||||
SF_SM_MEMCLEAR(m_saved_message_storage);
|
||||
SF_SM_MEMCLEAR(m_domain_allocated);
|
||||
#undef SF_SM_MEMCLEAR
|
||||
|
||||
/* Set resource starts. */
|
||||
m_pointer_buffers_start = util::AlignUp(reinterpret_cast<uintptr_t>(m_pointer_buffer_storage), 0x10);
|
||||
m_saved_messages_start = util::AlignUp(reinterpret_cast<uintptr_t>(m_saved_message_storage), 0x10);
|
||||
|
||||
/* Update globals. */
|
||||
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() {
|
||||
/* Close all sessions. */
|
||||
if constexpr (MaxSessions > 0) {
|
||||
for (size_t i = 0; i < MaxSessions; i++) {
|
||||
if (m_session_allocated[i]) {
|
||||
this->CloseSessionImpl(GetPointer(m_session_storages[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Close all servers. */
|
||||
if constexpr (MaxServers > 0) {
|
||||
for (size_t i = 0; i < MaxServers; i++) {
|
||||
if (m_server_allocated[i]) {
|
||||
this->DestroyServer(GetPointer(m_server_storages[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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());
|
||||
R_RETURN(this->template RegisterMitmServerImpl<Interface>(port_index, cmif::ServiceObjectHolder(), service_name));
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,205 +0,0 @@
|
||||
/*
|
||||
* 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 <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>
|
||||
#include <stratosphere/sf/hipc/sf_hipc_api.hpp>
|
||||
|
||||
namespace ams::sf::cmif {
|
||||
|
||||
struct ServiceDispatchContext;
|
||||
|
||||
}
|
||||
|
||||
namespace ams::sf::hipc {
|
||||
|
||||
class ServerSessionManager;
|
||||
class ServerManagerBase;
|
||||
|
||||
namespace impl {
|
||||
|
||||
class HipcManagerImpl;
|
||||
|
||||
}
|
||||
|
||||
class ServerSession : public os::MultiWaitHolderType {
|
||||
friend class ServerSessionManager;
|
||||
friend class ServerManagerBase;
|
||||
friend class impl::HipcManagerImpl;
|
||||
NON_COPYABLE(ServerSession);
|
||||
NON_MOVEABLE(ServerSession);
|
||||
private:
|
||||
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;
|
||||
const bool m_has_forward_service;
|
||||
public:
|
||||
ServerSession(os::NativeHandle h, cmif::ServiceObjectHolder &&obj) : m_srv_obj_holder(std::move(obj)), m_session_handle(h), m_has_forward_service(false) {
|
||||
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;
|
||||
m_has_received = false;
|
||||
util::ConstructAt(m_forward_service, std::move(fsrv));
|
||||
AMS_ABORT_UNLESS(util::GetReference(m_forward_service) != nullptr);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE bool IsMitmSession() const {
|
||||
return m_has_forward_service;
|
||||
}
|
||||
|
||||
Result ForwardRequest(const cmif::ServiceDispatchContext &ctx) const;
|
||||
|
||||
static inline void ForwardServiceDeleter(Service *srv) {
|
||||
serviceClose(srv);
|
||||
delete srv;
|
||||
}
|
||||
|
||||
static inline std::shared_ptr<::Service> CreateForwardService() {
|
||||
return std::shared_ptr<::Service>(new ::Service(), ForwardServiceDeleter);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
class ServerSessionManager {
|
||||
private:
|
||||
template<typename Constructor>
|
||||
Result CreateSessionImpl(ServerSession **out, const Constructor &ctor) {
|
||||
/* Allocate session. */
|
||||
ServerSession *session_memory = this->AllocateSession();
|
||||
R_UNLESS(session_memory != nullptr, sf::hipc::ResultOutOfSessionMemory());
|
||||
ON_RESULT_FAILURE { this->DestroySession(session_memory); };
|
||||
|
||||
/* Register session. */
|
||||
R_TRY(ctor(session_memory));
|
||||
|
||||
/* Save new session to output. */
|
||||
*out = session_memory;
|
||||
R_SUCCEED();
|
||||
}
|
||||
void DestroySession(ServerSession *session);
|
||||
|
||||
Result ProcessRequestImpl(ServerSession *session, const cmif::PointerAndSize &in_message, const cmif::PointerAndSize &out_message);
|
||||
virtual void RegisterServerSessionToWait(ServerSession *session) = 0;
|
||||
protected:
|
||||
Result DispatchRequest(cmif::ServiceObjectHolder &&obj, ServerSession *session, const cmif::PointerAndSize &in_message, const cmif::PointerAndSize &out_message);
|
||||
virtual Result DispatchManagerRequest(ServerSession *session, const cmif::PointerAndSize &in_message, const cmif::PointerAndSize &out_message);
|
||||
protected:
|
||||
virtual ServerSession *AllocateSession() = 0;
|
||||
virtual void FreeSession(ServerSession *session) = 0;
|
||||
virtual cmif::PointerAndSize GetSessionPointerBuffer(const ServerSession *session) const = 0;
|
||||
virtual cmif::PointerAndSize GetSessionSavedMessageBuffer(const ServerSession *session) const = 0;
|
||||
|
||||
Result ReceiveRequestImpl(ServerSession *session, const cmif::PointerAndSize &message);
|
||||
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) {
|
||||
R_RETURN(this->ReceiveRequestImpl(session, message));
|
||||
}
|
||||
|
||||
Result RegisterSession(ServerSession **out, os::NativeHandle session_handle, cmif::ServiceObjectHolder &&obj) {
|
||||
auto ctor = [&](ServerSession *session_memory) -> Result {
|
||||
R_RETURN(this->RegisterSessionImpl(session_memory, session_handle, std::forward<cmif::ServiceObjectHolder>(obj)));
|
||||
};
|
||||
R_RETURN(this->CreateSessionImpl(out, ctor));
|
||||
}
|
||||
|
||||
Result AcceptSession(ServerSession **out, os::NativeHandle port_handle, cmif::ServiceObjectHolder &&obj) {
|
||||
auto ctor = [&](ServerSession *session_memory) -> Result {
|
||||
R_RETURN(this->AcceptSessionImpl(session_memory, port_handle, std::forward<cmif::ServiceObjectHolder>(obj)));
|
||||
};
|
||||
R_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 {
|
||||
R_RETURN(this->RegisterMitmSessionImpl(session_memory, mitm_session_handle, std::forward<cmif::ServiceObjectHolder>(obj), std::forward<std::shared_ptr<::Service>>(fsrv)));
|
||||
};
|
||||
R_RETURN(this->CreateSessionImpl(out, ctor));
|
||||
}
|
||||
|
||||
Result AcceptMitmSession(ServerSession **out, os::NativeHandle mitm_port_handle, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv) {
|
||||
auto ctor = [&](ServerSession *session_memory) -> Result {
|
||||
R_RETURN(this->AcceptMitmSessionImpl(session_memory, mitm_port_handle, std::forward<cmif::ServiceObjectHolder>(obj), std::forward<std::shared_ptr<::Service>>(fsrv)));
|
||||
};
|
||||
R_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) {
|
||||
R_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) {
|
||||
R_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);
|
||||
|
||||
virtual ServerSessionManager *GetSessionManagerByTag(u32 tag) {
|
||||
/* This is unused. */
|
||||
AMS_UNUSED(tag);
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* 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>
|
||||
#include <stratosphere/sf/impl/sf_impl_autogen_interface_macros.hpp>
|
||||
#include <stratosphere/sf/impl/sf_impl_template_base.hpp>
|
||||
|
||||
namespace ams::sf::impl {
|
||||
|
||||
#define AMS_SF_IMPL_DEFINE_IMPL_SYNC_METHOD(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, ARGNAMES, VERSION_MIN, VERSION_MAX) \
|
||||
virtual RETURN AMS_SF_IMPL_SYNC_FUNCTION_NAME(NAME) ARGS override { \
|
||||
return ImplGetter::GetImplPointer(static_cast<ImplHolder *>(this))->NAME ARGNAMES; \
|
||||
}
|
||||
|
||||
#define AMS_SF_DEFINE_INTERFACE_WITH_DEFAULT_BASE(NAMESPACE, INTERFACE, BASE, CMD_MACRO, INTF_ID) \
|
||||
namespace NAMESPACE { \
|
||||
\
|
||||
AMS_SF_DEFINE_INTERFACE_IMPL(BASE, INTERFACE, CMD_MACRO, INTF_ID) \
|
||||
\
|
||||
} \
|
||||
\
|
||||
namespace ams::sf::impl { \
|
||||
\
|
||||
template<typename Base, typename ImplHolder, typename ImplGetter, typename Root> \
|
||||
class ImplTemplateBaseT<::NAMESPACE::INTERFACE, Base, ImplHolder, ImplGetter, Root> : public Base, public ImplHolder { \
|
||||
public: \
|
||||
template<typename... Args> \
|
||||
constexpr explicit ImplTemplateBaseT(Args &&...args) : ImplHolder(std::forward<Args>(args)...) { } \
|
||||
private: \
|
||||
CMD_MACRO(CLASSNAME, AMS_SF_IMPL_DEFINE_IMPL_SYNC_METHOD) \
|
||||
}; \
|
||||
\
|
||||
}
|
||||
|
||||
#define AMS_SF_DEFINE_INTERFACE(NAMESPACE, INTERFACE, CMD_MACRO, INTF_ID) \
|
||||
AMS_SF_DEFINE_INTERFACE_WITH_DEFAULT_BASE(NAMESPACE, INTERFACE, ::ams::sf::IServiceObject, CMD_MACRO, INTF_ID)
|
||||
|
||||
#define AMS_SF_DEFINE_MITM_INTERFACE(NAMESPACE, INTERFACE, CMD_MACRO, INTF_ID) \
|
||||
AMS_SF_DEFINE_INTERFACE_WITH_DEFAULT_BASE(NAMESPACE, INTERFACE, ::ams::sf::IMitmServiceObject, CMD_MACRO, INTF_ID)
|
||||
|
||||
#define AMS_SF_DEFINE_INTERFACE_WITH_BASE(NAMESPACE, INTERFACE, BASE, CMD_MACRO, INTF_ID) \
|
||||
namespace NAMESPACE { \
|
||||
\
|
||||
AMS_SF_DEFINE_INTERFACE_IMPL(BASE, INTERFACE, CMD_MACRO, INTF_ID) \
|
||||
\
|
||||
} \
|
||||
\
|
||||
namespace ams::sf::impl { \
|
||||
\
|
||||
template<typename Base, typename ImplHolder, typename ImplGetter, typename Root> \
|
||||
class ImplTemplateBaseT<::NAMESPACE::INTERFACE, Base, ImplHolder, ImplGetter, Root> : public ImplTemplateBaseT<BASE, Base, ImplHolder, ImplGetter, Root> { \
|
||||
private: \
|
||||
using BaseImplTemplateBase = ImplTemplateBaseT<BASE, Base, ImplHolder, ImplGetter, Root>; \
|
||||
public: \
|
||||
template<typename... Args> \
|
||||
constexpr explicit ImplTemplateBaseT(Args &&...args) : BaseImplTemplateBase(std::forward<Args>(args)...) { } \
|
||||
private: \
|
||||
CMD_MACRO(CLASSNAME, AMS_SF_IMPL_DEFINE_IMPL_SYNC_METHOD) \
|
||||
}; \
|
||||
\
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,171 +0,0 @@
|
||||
/*
|
||||
* 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>
|
||||
|
||||
namespace ams::sf::impl {
|
||||
|
||||
struct SyncFunctionTraits {
|
||||
public:
|
||||
template<typename R, typename C, typename... A>
|
||||
static std::tuple<A...> GetArgsImpl(R(C::*)(A...));
|
||||
};
|
||||
|
||||
template<auto F>
|
||||
using SyncFunctionArgsType = decltype(SyncFunctionTraits::GetArgsImpl(F));
|
||||
|
||||
template<typename T>
|
||||
struct TypeTag{};
|
||||
|
||||
template<size_t First, size_t... Ix>
|
||||
static constexpr inline size_t ParameterCount = sizeof...(Ix);
|
||||
|
||||
#define AMS_SF_IMPL_SYNC_FUNCTION_NAME(FUNCNAME) \
|
||||
_ams_sf_sync_##FUNCNAME
|
||||
|
||||
#define AMS_SF_IMPL_DEFINE_INTERFACE_SYNC_METHOD(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, ARGNAMES, VERSION_MIN, VERSION_MAX) \
|
||||
virtual RETURN AMS_SF_IMPL_SYNC_FUNCTION_NAME(NAME) ARGS = 0;
|
||||
|
||||
#define AMS_SF_IMPL_EXTRACT_INTERFACE_SYNC_METHOD_ARGUMENTS(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, ARGNAMES, VERSION_MIN, VERSION_MAX) \
|
||||
using NAME##ArgumentsType = ::ams::sf::impl::SyncFunctionArgsType<&CLASSNAME::AMS_SF_IMPL_SYNC_FUNCTION_NAME(NAME)>;
|
||||
|
||||
#define AMS_SF_IMPL_DEFINE_INTERFACE_METHOD(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, ARGNAMES, VERSION_MIN, VERSION_MAX) \
|
||||
ALWAYS_INLINE RETURN NAME ARGS { \
|
||||
return this->AMS_SF_IMPL_SYNC_FUNCTION_NAME(NAME) ARGNAMES; \
|
||||
}
|
||||
|
||||
#define AMS_SF_IMPL_DEFINE_INTERFACE_SERVICE_COMMAND_META_HOLDER(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, ARGNAMES, VERSION_MIN, VERSION_MAX) \
|
||||
template<typename Interface, typename A> struct NAME##ServiceCommandMetaHolder; \
|
||||
\
|
||||
template<typename Interface, typename ...Arguments> \
|
||||
requires std::same_as<std::tuple<Arguments...>, NAME##ArgumentsType> \
|
||||
struct NAME##ServiceCommandMetaHolder<Interface, std::tuple<Arguments...>> { \
|
||||
static constexpr auto Value = ::ams::sf::impl::MakeServiceCommandMeta<VERSION_MIN, VERSION_MAX, CMD_ID, &Interface::AMS_SF_IMPL_SYNC_FUNCTION_NAME(NAME), RETURN, Interface, Arguments...>(); \
|
||||
};
|
||||
|
||||
#define AMS_SF_IMPL_GET_NULL_FOR_PARAMETER_COUNT(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, ARGNAMES, VERSION_MIN, VERSION_MAX) \
|
||||
, 0
|
||||
|
||||
#define AMS_SF_IMPL_DEFINE_CMIF_SERVICE_COMMAND_META_TABLE_ENTRY(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, ARGNAMES, VERSION_MIN, VERSION_MAX) \
|
||||
NAME##ServiceCommandMetaHolder<Interface, NAME##ArgumentsType>::Value,
|
||||
|
||||
template<typename...>
|
||||
struct Print;
|
||||
|
||||
#define AMS_SF_IMPL_DEFINE_INTERFACE(BASECLASS, CLASSNAME, CMD_MACRO, INTF_ID) \
|
||||
class CLASSNAME : public BASECLASS { \
|
||||
public: \
|
||||
static constexpr u32 InterfaceIdForDebug = INTF_ID; \
|
||||
private: \
|
||||
CMD_MACRO(CLASSNAME, AMS_SF_IMPL_DEFINE_INTERFACE_SYNC_METHOD) \
|
||||
public: \
|
||||
CMD_MACRO(CLASSNAME, AMS_SF_IMPL_EXTRACT_INTERFACE_SYNC_METHOD_ARGUMENTS) \
|
||||
public: \
|
||||
CMD_MACRO(CLASSNAME, AMS_SF_IMPL_DEFINE_INTERFACE_METHOD) \
|
||||
private: \
|
||||
CMD_MACRO(CLASSNAME, AMS_SF_IMPL_DEFINE_INTERFACE_SERVICE_COMMAND_META_HOLDER) \
|
||||
public: \
|
||||
template<typename Interface> \
|
||||
static constexpr inline ::ams::sf::cmif::ServiceDispatchTable s_CmifServiceDispatchTable { \
|
||||
[] { \
|
||||
constexpr size_t CurSize = ::ams::sf::impl::ParameterCount<0 CMD_MACRO(CLASSNAME, AMS_SF_IMPL_GET_NULL_FOR_PARAMETER_COUNT) >; \
|
||||
std::array<::ams::sf::cmif::ServiceCommandMeta, CurSize> cur_entries { CMD_MACRO(CLASSNAME, AMS_SF_IMPL_DEFINE_CMIF_SERVICE_COMMAND_META_TABLE_ENTRY) }; \
|
||||
\
|
||||
constexpr const auto &BaseEntries = ::ams::sf::cmif::ServiceDispatchTraits<BASECLASS>::DispatchTable.GetEntries(); \
|
||||
constexpr size_t BaseSize = BaseEntries.size(); \
|
||||
\
|
||||
constexpr size_t CombinedSize = BaseSize + CurSize; \
|
||||
\
|
||||
std::array<size_t, CombinedSize> map{}; \
|
||||
for (size_t i = 0; i < CombinedSize; ++i) { map[i] = i; } \
|
||||
\
|
||||
for (size_t i = 1; i < CombinedSize; ++i) { \
|
||||
size_t j = i; \
|
||||
while (j > 0) { \
|
||||
const auto li = map[j]; \
|
||||
const auto ri = map[j - 1]; \
|
||||
\
|
||||
const auto &lhs = (li < BaseSize) ? BaseEntries[li] : cur_entries[li - BaseSize]; \
|
||||
const auto &rhs = (ri < BaseSize) ? BaseEntries[ri] : cur_entries[ri - BaseSize]; \
|
||||
\
|
||||
if (!(rhs > lhs)) { \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
std::swap(map[j], map[j - 1]); \
|
||||
\
|
||||
--j; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
std::array<::ams::sf::cmif::ServiceCommandMeta, CombinedSize> combined_entries{}; \
|
||||
for (size_t i = 0; i < CombinedSize; ++i) { \
|
||||
if (map[i] < BaseSize) { \
|
||||
combined_entries[i] = BaseEntries[map[i]]; \
|
||||
} else { \
|
||||
combined_entries[i] = cur_entries[map[i] - BaseSize]; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
return ::ams::sf::cmif::ServiceDispatchTable<Interface::InterfaceIdForDebug, CombinedSize> { combined_entries }; \
|
||||
}() \
|
||||
}; \
|
||||
};
|
||||
|
||||
#define AMS_SF_IMPL_DEFINE_CONCEPT_HELPERS(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, ARGNAMES, VERSION_MIN, VERSION_MAX) \
|
||||
template<typename T, typename... Args> \
|
||||
concept Is##CLASSNAME##__##NAME##Impl = requires (T &t, Args &&... args) { \
|
||||
{ t.NAME(std::forward<Args>(args)...) } -> std::same_as<RETURN>; \
|
||||
}; \
|
||||
\
|
||||
template<typename T, typename A> \
|
||||
struct Is##CLASSNAME##__##NAME##Holder : std::false_type{}; \
|
||||
\
|
||||
template<typename T, typename... Args> requires std::same_as<std::tuple<Args...>, CLASSNAME::NAME##ArgumentsType> \
|
||||
struct Is##CLASSNAME##__##NAME##Holder<T, std::tuple<Args...>> : std::bool_constant<Is##CLASSNAME##__##NAME##Impl<T, Args...>>{}; \
|
||||
\
|
||||
template<typename T> \
|
||||
static constexpr inline bool Is##CLASSNAME##__##NAME = Is##CLASSNAME##__##NAME##Holder<T, CLASSNAME::NAME##ArgumentsType>::value;
|
||||
|
||||
#define AMS_SF_IMPL_CHECK_CONCEPT_HELPER(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, ARGNAMES, VERSION_MIN, VERSION_MAX) \
|
||||
Is##CLASSNAME##__##NAME<T> &&
|
||||
|
||||
#define AMS_SF_IMPL_DEFINE_CONCEPT(CLASSNAME, CMD_MACRO) \
|
||||
CMD_MACRO(CLASSNAME, AMS_SF_IMPL_DEFINE_CONCEPT_HELPERS) \
|
||||
\
|
||||
template<typename T> \
|
||||
concept Is##CLASSNAME = CMD_MACRO(CLASSNAME, AMS_SF_IMPL_CHECK_CONCEPT_HELPER) true;
|
||||
|
||||
#define AMS_SF_DEFINE_INTERFACE_IMPL(BASECLASS, CLASSNAME, CMD_MACRO, INTF_ID) \
|
||||
AMS_SF_IMPL_DEFINE_INTERFACE(BASECLASS, CLASSNAME, CMD_MACRO, INTF_ID) \
|
||||
AMS_SF_IMPL_DEFINE_CONCEPT(CLASSNAME, CMD_MACRO) \
|
||||
static_assert(Is##CLASSNAME<CLASSNAME>);
|
||||
|
||||
#define AMS_SF_METHOD_INFO_7(CLASSNAME, HANDLER, CMD_ID, RETURN, NAME, ARGS, ARGNAMES) \
|
||||
HANDLER(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, ARGNAMES, hos::Version_Min, hos::Version_Max)
|
||||
|
||||
#define AMS_SF_METHOD_INFO_8(CLASSNAME, HANDLER, CMD_ID, RETURN, NAME, ARGS, ARGNAMES, VERSION_MIN) \
|
||||
HANDLER(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, ARGNAMES, VERSION_MIN, hos::Version_Max)
|
||||
|
||||
#define AMS_SF_METHOD_INFO_9(CLASSNAME, HANDLER, CMD_ID, RETURN, NAME, ARGS, ARGNAMES, VERSION_MIN, VERSION_MAX) \
|
||||
HANDLER(CLASSNAME, CMD_ID, RETURN, NAME, ARGS, ARGNAMES, VERSION_MIN, VERSION_MAX)
|
||||
|
||||
#define AMS_SF_METHOD_INFO_X(_, _0, _1, _2, _3, _4, _5, _6, _7, _8, FUNC, ...) FUNC
|
||||
|
||||
#define AMS_SF_METHOD_INFO(...) \
|
||||
AMS_SF_METHOD_INFO_X(, ## __VA_ARGS__, AMS_SF_METHOD_INFO_9(__VA_ARGS__), AMS_SF_METHOD_INFO_8(__VA_ARGS__), AMS_SF_METHOD_INFO_7(__VA_ARGS__))
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* 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>
|
||||
|
||||
namespace ams::sf::impl {
|
||||
|
||||
template<typename Interface, typename Base, typename ImplHolder, typename ImplGetter, typename Root>
|
||||
class ImplTemplateBaseT;
|
||||
|
||||
template<typename Interface, typename Base, typename ImplHolder, typename ImplGetter>
|
||||
class ImplTemplateBase : public ImplTemplateBaseT<Interface, Base, ImplHolder, ImplGetter, Interface> {
|
||||
private:
|
||||
using BaseImpl = ImplTemplateBaseT<Interface, Base, ImplHolder, ImplGetter, Interface>;
|
||||
public:
|
||||
using BaseImpl::BaseImpl;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* 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>
|
||||
|
||||
namespace ams::sf::impl {
|
||||
|
||||
class ServiceObjectImplBase2 {
|
||||
private:
|
||||
std::atomic<u32> m_ref_count;
|
||||
protected:
|
||||
constexpr ServiceObjectImplBase2() : m_ref_count(1) { /* ... */ }
|
||||
|
||||
void AddReferenceImpl() {
|
||||
const auto prev = m_ref_count.fetch_add(1);
|
||||
AMS_ABORT_UNLESS(prev < std::numeric_limits<u32>::max());
|
||||
}
|
||||
|
||||
bool ReleaseImpl() {
|
||||
const auto prev = m_ref_count.fetch_sub(1);
|
||||
AMS_ABORT_UNLESS(prev != 0);
|
||||
return prev == 1;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
/*
|
||||
* 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>
|
||||
|
||||
namespace ams::sf {
|
||||
|
||||
namespace impl {
|
||||
|
||||
struct StatelessDummyAllocator;
|
||||
|
||||
}
|
||||
|
||||
template<typename A>
|
||||
class StatelessAllocationPolicy {
|
||||
public:
|
||||
static constexpr bool HasStatefulAllocator = false;
|
||||
using Allocator = impl::StatelessDummyAllocator;
|
||||
|
||||
template<typename>
|
||||
using StatelessAllocator = A;
|
||||
|
||||
template<typename>
|
||||
static void *AllocateAligned(size_t size, size_t align) {
|
||||
AMS_UNUSED(align);
|
||||
return A().Allocate(size);
|
||||
}
|
||||
|
||||
template<typename>
|
||||
static void DeallocateAligned(void *ptr, size_t size, size_t align) {
|
||||
AMS_UNUSED(align);
|
||||
A().Deallocate(ptr, size);
|
||||
}
|
||||
};
|
||||
|
||||
template<template<typename> typename A>
|
||||
class StatelessTypedAllocationPolicy {
|
||||
public:
|
||||
static constexpr bool HasStatefulAllocator = false;
|
||||
using Allocator = impl::StatelessDummyAllocator;
|
||||
|
||||
template<typename T>
|
||||
using StatelessAllocator = A<T>;
|
||||
|
||||
template<typename T>
|
||||
static void *AllocateAligned(size_t size, size_t align) {
|
||||
AMS_UNUSED(align);
|
||||
return StatelessAllocator<T>().Allocate(size);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void DeallocateAligned(void *ptr, size_t size, size_t align) {
|
||||
AMS_UNUSED(align);
|
||||
StatelessAllocator<T>().Deallocate(ptr, size);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename A>
|
||||
class StatefulAllocationPolicy {
|
||||
public:
|
||||
static constexpr bool HasStatefulAllocator = true;
|
||||
using Allocator = A;
|
||||
|
||||
static void *AllocateAligned(Allocator *allocator, size_t size, size_t align) {
|
||||
AMS_UNUSED(align);
|
||||
return allocator->Allocate(size);
|
||||
}
|
||||
|
||||
static void DeallocateAligned(Allocator *allocator, void *ptr, size_t size, size_t align) {
|
||||
AMS_UNUSED(align);
|
||||
allocator->Deallocate(ptr, size);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
concept IsStatefulPolicy = T::HasStatefulAllocator;
|
||||
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
namespace ams::sf {
|
||||
|
||||
/* Helper structs for serialization of buffers. */
|
||||
struct LargeData{};
|
||||
|
||||
struct PrefersMapAliasTransferMode{};
|
||||
|
||||
struct PrefersPointerTransferMode{};
|
||||
|
||||
struct PrefersAutoSelectTransferMode{};
|
||||
|
||||
}
|
||||
@@ -1,315 +0,0 @@
|
||||
/*
|
||||
* 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 <stratosphere/sf/sf_common.hpp>
|
||||
#include <stratosphere/sf/sf_out.hpp>
|
||||
#include <stratosphere/sf/cmif/sf_cmif_pointer_and_size.hpp>
|
||||
#include <stratosphere/sf/sf_buffer_tags.hpp>
|
||||
|
||||
namespace ams::sf {
|
||||
|
||||
enum class BufferTransferMode {
|
||||
MapAlias,
|
||||
Pointer,
|
||||
AutoSelect,
|
||||
};
|
||||
|
||||
namespace impl {
|
||||
|
||||
/* Buffer utilities. */
|
||||
struct BufferBaseTag{};
|
||||
|
||||
template<BufferTransferMode TransferMode>
|
||||
constexpr inline u32 BufferTransferModeAttributes = [] {
|
||||
if constexpr (TransferMode == BufferTransferMode::MapAlias) {
|
||||
return SfBufferAttr_HipcMapAlias;
|
||||
} else if constexpr (TransferMode == BufferTransferMode::Pointer) {
|
||||
return SfBufferAttr_HipcPointer;
|
||||
} else if constexpr(TransferMode == BufferTransferMode::AutoSelect) {
|
||||
return SfBufferAttr_HipcAutoSelect;
|
||||
} else {
|
||||
static_assert(false, "Invalid BufferTransferMode");
|
||||
}
|
||||
}();
|
||||
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr inline bool IsLargeData = std::is_base_of<sf::LargeData, T>::value;
|
||||
|
||||
template<typename T>
|
||||
constexpr inline bool IsLargeData<Out<T>> = IsLargeData<T>;
|
||||
|
||||
template<typename T>
|
||||
constexpr inline size_t LargeDataSize = sizeof(T);
|
||||
|
||||
template<typename T>
|
||||
constexpr inline size_t LargeDataSize<Out<T>> = sizeof(T);
|
||||
|
||||
template<typename T>
|
||||
constexpr inline BufferTransferMode PreferredTransferMode = [] {
|
||||
constexpr bool prefers_map_alias = std::is_base_of<PrefersMapAliasTransferMode, T>::value;
|
||||
constexpr bool prefers_pointer = std::is_base_of<PrefersPointerTransferMode, T>::value;
|
||||
constexpr bool prefers_auto_select = std::is_base_of<PrefersAutoSelectTransferMode, T>::value;
|
||||
if constexpr (prefers_map_alias) {
|
||||
static_assert(!prefers_pointer && !prefers_auto_select, "Type T must only prefer one transfer mode.");
|
||||
return BufferTransferMode::MapAlias;
|
||||
} else if constexpr (prefers_pointer) {
|
||||
static_assert(!prefers_map_alias && !prefers_auto_select, "Type T must only prefer one transfer mode.");
|
||||
return BufferTransferMode::Pointer;
|
||||
} else if constexpr (prefers_auto_select) {
|
||||
static_assert(!prefers_map_alias && !prefers_pointer, "Type T must only prefer one transfer mode.");
|
||||
return BufferTransferMode::AutoSelect;
|
||||
} else if constexpr (IsLargeData<T>) {
|
||||
return BufferTransferMode::Pointer;
|
||||
} else {
|
||||
return BufferTransferMode::MapAlias;
|
||||
}
|
||||
}();
|
||||
|
||||
template<typename T>
|
||||
constexpr inline BufferTransferMode PreferredTransferMode<Out<T>> = PreferredTransferMode<T>;
|
||||
|
||||
namespace impl {
|
||||
|
||||
class BufferBase : public BufferBaseTag {
|
||||
public:
|
||||
static constexpr u32 AdditionalAttributes = 0;
|
||||
private:
|
||||
const cmif::PointerAndSize m_pas;
|
||||
protected:
|
||||
constexpr uintptr_t GetAddressImpl() const {
|
||||
return m_pas.GetAddress();
|
||||
}
|
||||
|
||||
template<typename Entry>
|
||||
constexpr inline size_t GetSizeImpl() const {
|
||||
return m_pas.GetSize() / sizeof(Entry);
|
||||
}
|
||||
public:
|
||||
constexpr BufferBase() : m_pas() { /* ... */ }
|
||||
constexpr BufferBase(const cmif::PointerAndSize &pas) : m_pas(pas) { /* ... */ }
|
||||
constexpr BufferBase(uintptr_t ptr, size_t sz) : m_pas(ptr, sz) { /* ... */ }
|
||||
};
|
||||
|
||||
class InBufferBase : public BufferBase {
|
||||
public:
|
||||
using BaseType = BufferBase;
|
||||
static constexpr u32 AdditionalAttributes = BaseType::AdditionalAttributes |
|
||||
SfBufferAttr_In;
|
||||
public:
|
||||
constexpr InBufferBase() : BaseType() { /* ... */ }
|
||||
constexpr InBufferBase(const cmif::PointerAndSize &pas) : BaseType(pas) { /* ... */ }
|
||||
constexpr InBufferBase(uintptr_t ptr, size_t sz) : BaseType(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 {
|
||||
public:
|
||||
using BaseType = BufferBase;
|
||||
static constexpr u32 AdditionalAttributes = BaseType::AdditionalAttributes |
|
||||
SfBufferAttr_Out;
|
||||
public:
|
||||
constexpr OutBufferBase() : BaseType() { /* ... */ }
|
||||
constexpr OutBufferBase(const cmif::PointerAndSize &pas) : BaseType(pas) { /* ... */ }
|
||||
constexpr OutBufferBase(uintptr_t ptr, size_t sz) : BaseType(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>
|
||||
class InBufferImpl : public InBufferBase {
|
||||
public:
|
||||
using BaseType = InBufferBase;
|
||||
static constexpr BufferTransferMode TransferMode = TMode;
|
||||
static constexpr u32 AdditionalAttributes = BaseType::AdditionalAttributes |
|
||||
ExtraAttributes;
|
||||
public:
|
||||
constexpr InBufferImpl() : BaseType() { /* ... */ }
|
||||
constexpr InBufferImpl(const cmif::PointerAndSize &pas) : BaseType(pas) { /* ... */ }
|
||||
constexpr InBufferImpl(uintptr_t ptr, size_t sz) : BaseType(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());
|
||||
}
|
||||
|
||||
constexpr size_t GetSize() const {
|
||||
return this->GetSizeImpl<u8>();
|
||||
}
|
||||
};
|
||||
|
||||
template<BufferTransferMode TMode, u32 ExtraAttributes = 0>
|
||||
class OutBufferImpl : public OutBufferBase {
|
||||
public:
|
||||
using BaseType = OutBufferBase;
|
||||
static constexpr BufferTransferMode TransferMode = TMode;
|
||||
static constexpr u32 AdditionalAttributes = BaseType::AdditionalAttributes |
|
||||
ExtraAttributes;
|
||||
public:
|
||||
constexpr OutBufferImpl() : BaseType() { /* ... */ }
|
||||
constexpr OutBufferImpl(const cmif::PointerAndSize &pas) : BaseType(pas) { /* ... */ }
|
||||
constexpr OutBufferImpl(uintptr_t ptr, size_t sz) : BaseType(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());
|
||||
}
|
||||
|
||||
constexpr size_t GetSize() const {
|
||||
return this->GetSizeImpl<u8>();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, BufferTransferMode TMode = PreferredTransferMode<T>>
|
||||
struct InArrayImpl : public InBufferBase {
|
||||
public:
|
||||
using BaseType = InBufferBase;
|
||||
static constexpr BufferTransferMode TransferMode = TMode;
|
||||
static constexpr u32 AdditionalAttributes = BaseType::AdditionalAttributes;
|
||||
public:
|
||||
constexpr InArrayImpl() : BaseType() { /* ... */ }
|
||||
constexpr InArrayImpl(const cmif::PointerAndSize &pas) : BaseType(pas) { /* ... */ }
|
||||
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());
|
||||
}
|
||||
|
||||
constexpr size_t GetSize() const {
|
||||
return this->GetSizeImpl<T>();
|
||||
}
|
||||
|
||||
constexpr const T &operator[](size_t i) const {
|
||||
return this->GetPointer()[i];
|
||||
}
|
||||
|
||||
constexpr explicit operator Span<const T>() const {
|
||||
return {this->GetPointer(), this->GetSize()};
|
||||
}
|
||||
|
||||
constexpr Span<const T> ToSpan() const {
|
||||
return {this->GetPointer(), this->GetSize()};
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, BufferTransferMode TMode = PreferredTransferMode<T>>
|
||||
struct OutArrayImpl : public OutBufferBase {
|
||||
public:
|
||||
using BaseType = OutBufferBase;
|
||||
static constexpr BufferTransferMode TransferMode = TMode;
|
||||
static constexpr u32 AdditionalAttributes = BaseType::AdditionalAttributes;
|
||||
public:
|
||||
constexpr OutArrayImpl() : BaseType() { /* ... */ }
|
||||
constexpr OutArrayImpl(const cmif::PointerAndSize &pas) : BaseType(pas) { /* ... */ }
|
||||
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());
|
||||
}
|
||||
|
||||
constexpr size_t GetSize() const {
|
||||
return this->GetSizeImpl<T>();
|
||||
}
|
||||
|
||||
constexpr T &operator[](size_t i) const {
|
||||
return this->GetPointer()[i];
|
||||
}
|
||||
|
||||
constexpr explicit operator Span<T>() const {
|
||||
return {this->GetPointer(), this->GetSize()};
|
||||
}
|
||||
|
||||
constexpr Span<T> ToSpan() const {
|
||||
return {this->GetPointer(), this->GetSize()};
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/* Buffer Types. */
|
||||
using InBuffer = typename impl::InBufferImpl<BufferTransferMode::MapAlias>;
|
||||
using InMapAliasBuffer = typename impl::InBufferImpl<BufferTransferMode::MapAlias>;
|
||||
using InPointerBuffer = typename impl::InBufferImpl<BufferTransferMode::Pointer>;
|
||||
using InAutoSelectBuffer = typename impl::InBufferImpl<BufferTransferMode::AutoSelect>;
|
||||
using InNonSecureBuffer = typename impl::InBufferImpl<BufferTransferMode::MapAlias, SfBufferAttr_HipcMapTransferAllowsNonSecure>;
|
||||
using InNonDeviceBuffer = typename impl::InBufferImpl<BufferTransferMode::MapAlias, SfBufferAttr_HipcMapTransferAllowsNonDevice>;
|
||||
|
||||
using InNonSecureAutoSelectBuffer = typename impl::InBufferImpl<BufferTransferMode::AutoSelect, SfBufferAttr_HipcMapTransferAllowsNonSecure>;
|
||||
|
||||
using OutBuffer = typename impl::OutBufferImpl<BufferTransferMode::MapAlias>;
|
||||
using OutMapAliasBuffer = typename impl::OutBufferImpl<BufferTransferMode::MapAlias>;
|
||||
using OutPointerBuffer = typename impl::OutBufferImpl<BufferTransferMode::Pointer>;
|
||||
using OutAutoSelectBuffer = typename impl::OutBufferImpl<BufferTransferMode::AutoSelect>;
|
||||
using OutNonSecureBuffer = typename impl::OutBufferImpl<BufferTransferMode::MapAlias, SfBufferAttr_HipcMapTransferAllowsNonSecure>;
|
||||
using OutNonDeviceBuffer = typename impl::OutBufferImpl<BufferTransferMode::MapAlias, SfBufferAttr_HipcMapTransferAllowsNonDevice>;
|
||||
|
||||
using OutNonSecureAutoSelectBuffer = typename impl::OutBufferImpl<BufferTransferMode::AutoSelect, SfBufferAttr_HipcMapTransferAllowsNonSecure>;
|
||||
|
||||
template<typename T>
|
||||
using InArray = typename impl::InArrayImpl<T>;
|
||||
template<typename T>
|
||||
using InMapAliasArray = typename impl::InArrayImpl<T, BufferTransferMode::MapAlias>;
|
||||
template<typename T>
|
||||
using InPointerArray = typename impl::InArrayImpl<T, BufferTransferMode::Pointer>;
|
||||
template<typename T>
|
||||
using InAutoSelectArray = typename impl::InArrayImpl<T, BufferTransferMode::AutoSelect>;
|
||||
|
||||
template<typename T>
|
||||
using OutArray = typename impl::OutArrayImpl<T>;
|
||||
template<typename T>
|
||||
using OutMapAliasArray = typename impl::OutArrayImpl<T, BufferTransferMode::MapAlias>;
|
||||
template<typename T>
|
||||
using OutPointerArray = typename impl::OutArrayImpl<T, BufferTransferMode::Pointer>;
|
||||
template<typename T>
|
||||
using OutAutoSelectArray = typename impl::OutArrayImpl<T, BufferTransferMode::AutoSelect>;
|
||||
|
||||
/* Attribute serialization structs. */
|
||||
template<typename T>
|
||||
constexpr inline bool IsBuffer = [] {
|
||||
const bool is_buffer = std::is_base_of<impl::BufferBaseTag, T>::value;
|
||||
const bool is_large_data = IsLargeData<T>;
|
||||
static_assert(!(is_buffer && is_large_data), "Invalid sf::IsBuffer state");
|
||||
return is_buffer || is_large_data;
|
||||
}();
|
||||
|
||||
template<typename T>
|
||||
constexpr inline u32 BufferAttributes = [] {
|
||||
static_assert(IsBuffer<T>, "BufferAttributes requires IsBuffer");
|
||||
if constexpr (std::is_base_of<impl::BufferBaseTag, T>::value) {
|
||||
return impl::BufferTransferModeAttributes<T::TransferMode> | T::AdditionalAttributes;
|
||||
} else if constexpr (IsLargeData<T>) {
|
||||
u32 attr = SfBufferAttr_FixedSize | impl::BufferTransferModeAttributes<PreferredTransferMode<T>>;
|
||||
if constexpr (std::is_base_of<impl::OutBaseTag, T>::value) {
|
||||
attr |= SfBufferAttr_Out;
|
||||
} else {
|
||||
attr |= SfBufferAttr_In;
|
||||
}
|
||||
return attr;
|
||||
} else {
|
||||
static_assert(!std::is_same<T, T>::value, "Invalid BufferAttributes<T>");
|
||||
}
|
||||
}();
|
||||
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
* 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>
|
||||
#include <stratosphere/ams.hpp>
|
||||
#include <stratosphere/os.hpp>
|
||||
#include <stratosphere/sm/sm_types.hpp>
|
||||
#include <stratosphere/sf/sf_types.hpp>
|
||||
#include <stratosphere/sf/sf_mitm_config.hpp>
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* 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 <stratosphere/sf/sf_common.hpp>
|
||||
#include <stratosphere/sf/sf_allocation_policies.hpp>
|
||||
|
||||
namespace ams::sf {
|
||||
|
||||
namespace impl {
|
||||
|
||||
void *DefaultAllocateImpl(size_t size, size_t align, size_t offset);
|
||||
void DefaultDeallocateImpl(void *ptr, size_t size, size_t align, size_t offset);
|
||||
|
||||
template<typename T>
|
||||
class DefaultAllocationPolicyAllocator {
|
||||
private:
|
||||
struct Holder {
|
||||
MemoryResource *allocator;
|
||||
alignas(alignof(T)) std::byte storage[sizeof(T)];
|
||||
};
|
||||
public:
|
||||
void *Allocate(size_t size) {
|
||||
AMS_ASSERT(size == sizeof(T));
|
||||
AMS_UNUSED(size);
|
||||
return DefaultAllocateImpl(sizeof(Holder), alignof(Holder), AMS_OFFSETOF(Holder, storage));
|
||||
}
|
||||
|
||||
void Deallocate(void *ptr, size_t size) {
|
||||
AMS_ASSERT(size == sizeof(T));
|
||||
AMS_UNUSED(size);
|
||||
return DefaultDeallocateImpl(ptr, sizeof(Holder), alignof(Holder), AMS_OFFSETOF(Holder, storage));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
using DefaultAllocationPolicy = StatelessTypedAllocationPolicy<impl::DefaultAllocationPolicyAllocator>;
|
||||
|
||||
MemoryResource *GetGlobalDefaultMemoryResource();
|
||||
MemoryResource *GetCurrentEffectiveMemoryResource();
|
||||
MemoryResource *GetCurrentMemoryResource();
|
||||
MemoryResource *GetNewDeleteMemoryResource();
|
||||
|
||||
MemoryResource *SetGlobalDefaultMemoryResource(MemoryResource *mr);
|
||||
MemoryResource *SetCurrentMemoryResource(MemoryResource *mr);
|
||||
|
||||
class ScopedCurrentMemoryResourceSetter {
|
||||
NON_COPYABLE(ScopedCurrentMemoryResourceSetter);
|
||||
NON_MOVEABLE(ScopedCurrentMemoryResourceSetter);
|
||||
private:
|
||||
MemoryResource *m_prev;
|
||||
public:
|
||||
explicit ScopedCurrentMemoryResourceSetter(MemoryResource *mr);
|
||||
~ScopedCurrentMemoryResourceSetter();
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
* 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 <stratosphere/sf/sf_common.hpp>
|
||||
#include <stratosphere/sf/sf_allocation_policies.hpp>
|
||||
|
||||
namespace ams::sf {
|
||||
|
||||
struct ExpHeapAllocator {
|
||||
using Policy = StatefulAllocationPolicy<ExpHeapAllocator>;
|
||||
|
||||
lmem::HeapHandle _handle;
|
||||
os::SdkMutexType _mutex;
|
||||
|
||||
void Attach(lmem::HeapHandle h) {
|
||||
this->_handle = h;
|
||||
os::InitializeSdkMutex(std::addressof(this->_mutex));
|
||||
}
|
||||
|
||||
void Detach() {
|
||||
this->_handle = {};
|
||||
}
|
||||
|
||||
void *Allocate(size_t size) {
|
||||
os::LockSdkMutex(std::addressof(this->_mutex));
|
||||
auto ptr = lmem::AllocateFromExpHeap(this->_handle, size);
|
||||
os::UnlockSdkMutex(std::addressof(this->_mutex));
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void Deallocate(void *ptr, size_t size) {
|
||||
AMS_UNUSED(size);
|
||||
|
||||
os::LockSdkMutex(std::addressof(this->_mutex));
|
||||
lmem::FreeToExpHeap(this->_handle, ptr);
|
||||
os::UnlockSdkMutex(std::addressof(this->_mutex));
|
||||
}
|
||||
};
|
||||
static_assert(util::is_pod<ExpHeapAllocator>::value);
|
||||
|
||||
template<size_t Size, typename Tag = void>
|
||||
struct ExpHeapStaticAllocator {
|
||||
using Policy = StatelessAllocationPolicy<ExpHeapStaticAllocator<Size, Tag>>;
|
||||
|
||||
struct Globals {
|
||||
ExpHeapAllocator allocator;
|
||||
alignas(0x10) std::byte buffer[Size == 0 ? 1 : Size];
|
||||
};
|
||||
|
||||
static constinit inline Globals _globals = {};
|
||||
|
||||
|
||||
static void Initialize(int option) {
|
||||
_globals.allocator.Attach(lmem::CreateExpHeap(std::addressof(_globals.buffer), Size, option));
|
||||
}
|
||||
|
||||
static void Initialize(lmem::HeapHandle handle) {
|
||||
_globals.allocator.Attach(handle);
|
||||
}
|
||||
|
||||
static void *Allocate(size_t size) {
|
||||
return _globals.allocator.Allocate(size);
|
||||
}
|
||||
|
||||
static void Deallocate(void *ptr, size_t size) {
|
||||
return _globals.allocator.Deallocate(ptr, size);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* 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 <stratosphere/sf/sf_common.hpp>
|
||||
|
||||
namespace ams::os {
|
||||
|
||||
struct ThreadType;
|
||||
|
||||
}
|
||||
|
||||
namespace ams::sf {
|
||||
|
||||
u8 GetFsInlineContext(os::ThreadType *thread);
|
||||
u8 SetFsInlineContext(os::ThreadType *thread, u8 ctx);
|
||||
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* 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 <stratosphere/sf/sf_common.hpp>
|
||||
#include <stratosphere/lmem.hpp>
|
||||
|
||||
namespace ams::sf {
|
||||
|
||||
class ExpHeapMemoryResource : public MemoryResource {
|
||||
private:
|
||||
lmem::HeapHandle m_handle;
|
||||
public:
|
||||
constexpr ExpHeapMemoryResource() : m_handle() { /* ... */ }
|
||||
constexpr explicit ExpHeapMemoryResource(lmem::HeapHandle h) : m_handle(h) { /* ... */ }
|
||||
|
||||
void Attach(lmem::HeapHandle h) {
|
||||
AMS_ABORT_UNLESS(m_handle == lmem::HeapHandle());
|
||||
m_handle = h;
|
||||
}
|
||||
|
||||
lmem::HeapHandle GetHandle() const { return m_handle; }
|
||||
private:
|
||||
virtual void *AllocateImpl(size_t size, size_t alignment) override {
|
||||
return lmem::AllocateFromExpHeap(m_handle, size, static_cast<int>(alignment));
|
||||
}
|
||||
|
||||
virtual void DeallocateImpl(void *buffer, size_t size, size_t alignment) override {
|
||||
AMS_UNUSED(size, alignment);
|
||||
return lmem::FreeToExpHeap(m_handle, buffer);
|
||||
}
|
||||
|
||||
virtual bool IsEqualImpl(const MemoryResource &resource) const override {
|
||||
return this == std::addressof(resource);
|
||||
}
|
||||
};
|
||||
|
||||
class UnitHeapMemoryResource : public MemoryResource {
|
||||
private:
|
||||
lmem::HeapHandle m_handle;
|
||||
public:
|
||||
constexpr UnitHeapMemoryResource() : m_handle() { /* ... */ }
|
||||
constexpr explicit UnitHeapMemoryResource(lmem::HeapHandle h) : m_handle(h) { /* ... */ }
|
||||
|
||||
void Attach(lmem::HeapHandle h) {
|
||||
AMS_ABORT_UNLESS(m_handle == lmem::HeapHandle());
|
||||
m_handle = h;
|
||||
}
|
||||
|
||||
lmem::HeapHandle GetHandle() const { return m_handle; }
|
||||
private:
|
||||
virtual void *AllocateImpl(size_t size, size_t alignment) override {
|
||||
AMS_ASSERT(size <= lmem::GetUnitHeapUnitSize(m_handle));
|
||||
AMS_ASSERT(alignment <= static_cast<size_t>(lmem::GetUnitHeapAlignment(m_handle)));
|
||||
AMS_UNUSED(size, alignment);
|
||||
|
||||
return lmem::AllocateFromUnitHeap(m_handle);
|
||||
}
|
||||
|
||||
virtual void DeallocateImpl(void *buffer, size_t size, size_t alignment) override {
|
||||
AMS_UNUSED(size, alignment);
|
||||
|
||||
return lmem::FreeToUnitHeap(m_handle, buffer);
|
||||
}
|
||||
|
||||
virtual bool IsEqualImpl(const MemoryResource &resource) const override {
|
||||
return this == std::addressof(resource);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* 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 <stratosphere/sf/sf_common.hpp>
|
||||
#include <stratosphere/mem.hpp>
|
||||
|
||||
namespace ams::sf {
|
||||
|
||||
class StandardAllocatorMemoryResource : public MemoryResource {
|
||||
private:
|
||||
mem::StandardAllocator *m_standard_allocator;
|
||||
public:
|
||||
explicit StandardAllocatorMemoryResource(mem::StandardAllocator *sa) : m_standard_allocator(sa) { /* ... */ }
|
||||
|
||||
mem::StandardAllocator *GetAllocator() const { return m_standard_allocator; }
|
||||
private:
|
||||
virtual void *AllocateImpl(size_t size, size_t alignment) override {
|
||||
return m_standard_allocator->Allocate(size, alignment);
|
||||
}
|
||||
|
||||
virtual void DeallocateImpl(void *buffer, size_t size, size_t alignment) override {
|
||||
AMS_UNUSED(size, alignment);
|
||||
return m_standard_allocator->Free(buffer);
|
||||
}
|
||||
|
||||
virtual bool IsEqualImpl(const MemoryResource &resource) const override {
|
||||
return this == std::addressof(resource);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* 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 <stratosphere/sf/sf_common.hpp>
|
||||
#include <stratosphere/sf/sf_allocation_policies.hpp>
|
||||
|
||||
namespace ams::sf {
|
||||
|
||||
struct MemoryResourceAllocationPolicy {
|
||||
static constexpr bool HasStatefulAllocator = true;
|
||||
using Allocator = MemoryResource;
|
||||
|
||||
static void *AllocateAligned(MemoryResource *mr, size_t size, size_t align) {
|
||||
return mr->allocate(size, align);
|
||||
}
|
||||
|
||||
static void DeallocateAligned(MemoryResource *mr, void *ptr, size_t size, size_t align) {
|
||||
return mr->deallocate(ptr, size, align);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct MemoryResourceStaticAllocator {
|
||||
static constinit inline MemoryResource *g_memory_resource = nullptr;
|
||||
|
||||
static constexpr void Initialize(MemoryResource *mr) {
|
||||
g_memory_resource = mr;
|
||||
}
|
||||
|
||||
struct Policy {
|
||||
static constexpr bool HasStatefulAllocator = false;
|
||||
using Allocator = MemoryResource;
|
||||
|
||||
template<typename>
|
||||
using StatelessAllocator = Allocator;
|
||||
|
||||
template<typename>
|
||||
static void *AllocateAligned(size_t size, size_t align) {
|
||||
return g_memory_resource->allocate(size, align);
|
||||
}
|
||||
|
||||
template<typename>
|
||||
static void DeallocateAligned(void *ptr, size_t size, size_t align) {
|
||||
g_memory_resource->deallocate(ptr, size, align);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
/*
|
||||
* 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 <stratosphere/sf/sf_mitm_config.hpp>
|
||||
|
||||
#if AMS_SF_MITM_SUPPORTED
|
||||
#include <switch.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
Handle target_session;
|
||||
u32 context;
|
||||
|
||||
SfBufferAttrs buffer_attrs;
|
||||
SfBuffer buffers[8];
|
||||
|
||||
bool in_send_pid;
|
||||
|
||||
u32 in_num_objects;
|
||||
const Service* in_objects[8];
|
||||
|
||||
u32 in_num_handles;
|
||||
Handle in_handles[8];
|
||||
|
||||
u32 out_num_objects;
|
||||
Service* out_objects;
|
||||
|
||||
SfOutHandleAttrs out_handle_attrs;
|
||||
Handle* out_handles;
|
||||
|
||||
u64 override_pid;
|
||||
} SfMitmDispatchParams;
|
||||
|
||||
NX_INLINE Result serviceMitmDispatchImpl(
|
||||
Service* s, u32 request_id,
|
||||
const void* in_data, u32 in_data_size,
|
||||
void* out_data, u32 out_data_size,
|
||||
SfMitmDispatchParams disp
|
||||
)
|
||||
{
|
||||
// Make a copy of the service struct, so that the compiler can assume that it won't be modified by function calls.
|
||||
Service srv = *s;
|
||||
|
||||
void* in = serviceMakeRequest(&srv, request_id, disp.context,
|
||||
in_data_size, disp.in_send_pid,
|
||||
disp.buffer_attrs, disp.buffers,
|
||||
disp.in_num_objects, disp.in_objects,
|
||||
disp.in_num_handles, disp.in_handles);
|
||||
|
||||
if (in_data_size)
|
||||
__builtin_memcpy(in, in_data, in_data_size);
|
||||
|
||||
if (disp.in_send_pid && disp.override_pid) {
|
||||
const u64 pid = (disp.override_pid & 0x0000FFFFFFFFFFFFul) | 0xFFFE000000000000ul;
|
||||
__builtin_memcpy((u8 *)armGetTls() + 0xC, &pid, sizeof(pid));
|
||||
}
|
||||
|
||||
Result rc = svcSendSyncRequest(disp.target_session == INVALID_HANDLE ? s->session : disp.target_session);
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
void* out = NULL;
|
||||
rc = serviceParseResponse(&srv,
|
||||
out_data_size, &out,
|
||||
disp.out_num_objects, disp.out_objects,
|
||||
disp.out_handle_attrs, disp.out_handles);
|
||||
|
||||
if (R_SUCCEEDED(rc) && out_data && out_data_size)
|
||||
__builtin_memcpy(out_data, out, out_data_size);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#define serviceMitmDispatch(_s,_rid,...) \
|
||||
serviceMitmDispatchImpl((_s),(_rid),NULL,0,NULL,0,(SfMitmDispatchParams){ __VA_ARGS__ })
|
||||
|
||||
#define serviceMitmDispatchIn(_s,_rid,_in,...) \
|
||||
serviceMitmDispatchImpl((_s),(_rid),&(_in),sizeof(_in),NULL,0,(SfMitmDispatchParams){ __VA_ARGS__ })
|
||||
|
||||
#define serviceMitmDispatchOut(_s,_rid,_out,...) \
|
||||
serviceMitmDispatchImpl((_s),(_rid),NULL,0,&(_out),sizeof(_out),(SfMitmDispatchParams){ __VA_ARGS__ })
|
||||
|
||||
#define serviceMitmDispatchInOut(_s,_rid,_in,_out,...) \
|
||||
serviceMitmDispatchImpl((_s),(_rid),&(_in),sizeof(_in),&(_out),sizeof(_out),(SfMitmDispatchParams){ __VA_ARGS__ })
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,140 +0,0 @@
|
||||
/*
|
||||
* 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 <stratosphere/os/os_native_handle.hpp>
|
||||
#include <stratosphere/sf/sf_common.hpp>
|
||||
#include <stratosphere/sf/sf_out.hpp>
|
||||
|
||||
namespace ams::sf {
|
||||
|
||||
class NativeHandle {
|
||||
protected:
|
||||
NON_COPYABLE(NativeHandle);
|
||||
private:
|
||||
os::NativeHandle m_handle;
|
||||
bool m_managed;
|
||||
public:
|
||||
constexpr NativeHandle() : m_handle(os::InvalidNativeHandle), m_managed(false) { /* ... */ }
|
||||
|
||||
constexpr NativeHandle(os::NativeHandle handle, bool managed) : m_handle(handle), m_managed(managed) { /* ... */ }
|
||||
|
||||
constexpr NativeHandle(NativeHandle &&rhs) : m_handle(rhs.m_handle), m_managed(rhs.m_managed) {
|
||||
rhs.m_managed = false;
|
||||
rhs.m_handle = os::InvalidNativeHandle;
|
||||
}
|
||||
|
||||
constexpr NativeHandle &operator=(NativeHandle &&rhs) {
|
||||
NativeHandle(std::move(rhs)).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr ~NativeHandle() {
|
||||
if (m_managed) {
|
||||
os::CloseNativeHandle(m_handle);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr void Detach() {
|
||||
m_managed = false;
|
||||
m_handle = os::InvalidNativeHandle;
|
||||
}
|
||||
|
||||
constexpr void Swap(NativeHandle &rhs) {
|
||||
std::swap(m_handle, rhs.m_handle);
|
||||
std::swap(m_managed, rhs.m_managed);
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE void swap(NativeHandle &rhs) {
|
||||
return Swap(rhs);
|
||||
}
|
||||
|
||||
constexpr NativeHandle GetShared() const {
|
||||
return NativeHandle(m_handle, false);
|
||||
}
|
||||
|
||||
constexpr os::NativeHandle GetOsHandle() const {
|
||||
return m_handle;
|
||||
}
|
||||
|
||||
constexpr bool IsManaged() const {
|
||||
return m_managed;
|
||||
}
|
||||
|
||||
constexpr void Reset() {
|
||||
NativeHandle().swap(*this);
|
||||
}
|
||||
};
|
||||
|
||||
class CopyHandle : public NativeHandle {
|
||||
public:
|
||||
using NativeHandle::NativeHandle;
|
||||
using NativeHandle::operator=;
|
||||
};
|
||||
|
||||
class MoveHandle : public NativeHandle {
|
||||
public:
|
||||
using NativeHandle::NativeHandle;
|
||||
using NativeHandle::operator=;
|
||||
};
|
||||
|
||||
constexpr ALWAYS_INLINE void swap(NativeHandle &lhs, NativeHandle &rhs) {
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
template<>
|
||||
class Out<CopyHandle> {
|
||||
private:
|
||||
NativeHandle *m_ptr;
|
||||
public:
|
||||
Out(NativeHandle *p) : m_ptr(p) { /* ... */ }
|
||||
|
||||
void SetValue(NativeHandle v) const {
|
||||
*m_ptr = std::move(v);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void SetValue(os::NativeHandle os_handle, bool managed) const {
|
||||
return this->SetValue(NativeHandle(os_handle, managed));
|
||||
}
|
||||
|
||||
NativeHandle &operator*() const {
|
||||
return *m_ptr;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class Out<MoveHandle> {
|
||||
private:
|
||||
NativeHandle *m_ptr;
|
||||
public:
|
||||
Out(NativeHandle *p) : m_ptr(p) { /* ... */ }
|
||||
|
||||
void SetValue(NativeHandle v) const {
|
||||
*m_ptr = std::move(v);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void SetValue(os::NativeHandle os_handle, bool managed) const {
|
||||
return this->SetValue(NativeHandle(os_handle, managed));
|
||||
}
|
||||
|
||||
NativeHandle &operator*() const {
|
||||
return *m_ptr;
|
||||
}
|
||||
};
|
||||
|
||||
using OutCopyHandle = Out<CopyHandle>;
|
||||
using OutMoveHandle = Out<MoveHandle>;
|
||||
|
||||
}
|
||||
@@ -1,355 +0,0 @@
|
||||
/*
|
||||
* 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>
|
||||
#include <stratosphere/sf/sf_common.hpp>
|
||||
#include <stratosphere/sf/impl/sf_impl_template_base.hpp>
|
||||
#include <stratosphere/sf/sf_object_impl_factory.hpp>
|
||||
#include <stratosphere/sf/sf_memory_resource.hpp>
|
||||
#include <stratosphere/sf/sf_default_allocation_policy.hpp>
|
||||
|
||||
namespace ams::sf {
|
||||
|
||||
namespace impl {
|
||||
|
||||
template<typename>
|
||||
struct IsSmartPointer : public std::false_type{};
|
||||
|
||||
template<typename T>
|
||||
struct IsSmartPointer<SharedPointer<T>> : public std::true_type{};
|
||||
|
||||
template<typename T>
|
||||
struct IsSmartPointer<std::shared_ptr<T>> : public std::true_type{};
|
||||
|
||||
template<typename T, typename D>
|
||||
struct IsSmartPointer<std::unique_ptr<T, D>> : public std::true_type{};
|
||||
|
||||
template<typename Impl>
|
||||
struct UnmanagedEmplaceImplHolderBaseGetter {
|
||||
using Type = Impl;
|
||||
};
|
||||
|
||||
template<typename Impl> requires (std::is_abstract<Impl>::value)
|
||||
struct UnmanagedEmplaceImplHolderBaseGetter<Impl> {
|
||||
class Impl2 : public Impl {
|
||||
public:
|
||||
using Impl::Impl;
|
||||
private:
|
||||
constexpr virtual void AddReference() override { /* ... */ }
|
||||
constexpr virtual void Release() override { /* ... */ }
|
||||
};
|
||||
|
||||
using Type = Impl2;
|
||||
};
|
||||
|
||||
template<typename Impl>
|
||||
class UnmanagedEmplacedImplHolder {
|
||||
template<typename, typename, typename, typename, typename>
|
||||
friend class impl::ImplTemplateBaseT;
|
||||
private:
|
||||
using Impl2 = typename UnmanagedEmplaceImplHolderBaseGetter<Impl>::Type;
|
||||
static_assert(!std::is_abstract<Impl2>::value);
|
||||
private:
|
||||
Impl2 m_impl;
|
||||
private:
|
||||
template<typename... Args>
|
||||
constexpr explicit UnmanagedEmplacedImplHolder(Args &&... args) : m_impl(std::forward<Args>(args)...) { /* ... */ }
|
||||
public:
|
||||
static constexpr Impl *GetImplPointer(UnmanagedEmplacedImplHolder *holder) {
|
||||
return std::addressof(holder->m_impl);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Impl>
|
||||
class EmplacedImplHolder : private Impl {
|
||||
template<typename, typename, typename, typename, typename>
|
||||
friend class impl::ImplTemplateBaseT;
|
||||
private:
|
||||
template<typename... Args>
|
||||
constexpr explicit EmplacedImplHolder(Args &&... args) : Impl(std::forward<Args>(args)...) { /* ... */ }
|
||||
public:
|
||||
static constexpr Impl *GetImplPointer(EmplacedImplHolder *holder) {
|
||||
return holder;
|
||||
}
|
||||
|
||||
template<typename Interface>
|
||||
static constexpr Impl *GetEmplacedImplPointerImpl(const SharedPointer<Interface> &sp) {
|
||||
using Base = impl::ImplTemplateBase<Interface, Interface, EmplacedImplHolder, EmplacedImplHolder>;
|
||||
return static_cast<Base *>(sp.Get());
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Impl> requires (IsSmartPointer<Impl>::value)
|
||||
class EmplacedImplHolder<Impl> : private Impl {
|
||||
template<typename, typename, typename, typename, typename>
|
||||
friend class impl::ImplTemplateBaseT;
|
||||
private:
|
||||
template<typename... Args>
|
||||
constexpr explicit EmplacedImplHolder(Args &&... args) : Impl(std::forward<Args>(args)...) { /* ... */ }
|
||||
public:
|
||||
static constexpr auto *GetImplPointer(EmplacedImplHolder *holder) {
|
||||
return static_cast<Impl *>(holder)->operator ->();
|
||||
}
|
||||
|
||||
template<typename Interface>
|
||||
static constexpr Impl *GetEmplacedImplPointerImpl(const SharedPointer<Interface> &sp) {
|
||||
using Base = impl::ImplTemplateBase<Interface, Interface, EmplacedImplHolder, EmplacedImplHolder>;
|
||||
return static_cast<Base *>(sp.Get());
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using SmartPointerHolder = EmplacedImplHolder<T>;
|
||||
|
||||
template<typename T>
|
||||
class ManagedPointerHolder {
|
||||
template<typename, typename, typename, typename, typename>
|
||||
friend class impl::ImplTemplateBaseT;
|
||||
private:
|
||||
T *m_p;
|
||||
private:
|
||||
constexpr explicit ManagedPointerHolder(T *p) : m_p(p) { /* ... */ }
|
||||
constexpr ~ManagedPointerHolder() { m_p->Release(); }
|
||||
|
||||
static constexpr T *GetImplPointer(ManagedPointerHolder *holder) {
|
||||
return holder->m_p;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class UnmanagedPointerHolder {
|
||||
template<typename, typename, typename, typename, typename>
|
||||
friend class impl::ImplTemplateBaseT;
|
||||
private:
|
||||
T *m_p;
|
||||
private:
|
||||
constexpr explicit UnmanagedPointerHolder(T *p) : m_p(p) { /* ... */ }
|
||||
|
||||
static constexpr T *GetImplPointer(UnmanagedPointerHolder *holder) {
|
||||
return holder->m_p;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<typename Interface, typename Impl>
|
||||
class UnmanagedServiceObject final : public impl::ImplTemplateBase<Interface, Interface, impl::UnmanagedEmplacedImplHolder<Impl>, impl::UnmanagedEmplacedImplHolder<Impl>> {
|
||||
private:
|
||||
using ImplBase = impl::ImplTemplateBase<Interface, Interface, impl::UnmanagedEmplacedImplHolder<Impl>, impl::UnmanagedEmplacedImplHolder<Impl>>;
|
||||
public:
|
||||
using ImplBase::ImplBase;
|
||||
|
||||
constexpr virtual void AddReference() override { /* ... */ }
|
||||
constexpr virtual void Release() override { /* ... */ }
|
||||
|
||||
constexpr Impl &GetImpl() { return *impl::UnmanagedEmplacedImplHolder<Impl>::GetImplPointer(this); }
|
||||
|
||||
constexpr SharedPointer<Interface> GetShared() { return SharedPointer<Interface>(this, false); }
|
||||
};
|
||||
|
||||
template<typename Interface, typename T>
|
||||
class UnmanagedServiceObjectByPointer final : public impl::ImplTemplateBase<Interface, Interface, impl::UnmanagedPointerHolder<T>, impl::UnmanagedPointerHolder<T>> {
|
||||
private:
|
||||
using ImplBase = impl::ImplTemplateBase<Interface, Interface, impl::UnmanagedPointerHolder<T>, impl::UnmanagedPointerHolder<T>>;
|
||||
public:
|
||||
constexpr explicit UnmanagedServiceObjectByPointer(T *ptr) : ImplBase(ptr) { /* ... */ }
|
||||
|
||||
constexpr virtual void AddReference() override { /* ... */ }
|
||||
constexpr virtual void Release() override { /* ... */ }
|
||||
|
||||
constexpr SharedPointer<Interface> GetShared() { return SharedPointer<Interface>(this, false); }
|
||||
};
|
||||
|
||||
template<typename Policy>
|
||||
class ObjectFactory;
|
||||
|
||||
template<typename Interface, typename Impl>
|
||||
class EmplacedRef : public SharedPointer<Interface> {
|
||||
template<typename> friend class ObjectFactory;
|
||||
private:
|
||||
constexpr explicit EmplacedRef(Interface *ptr, bool incref) : SharedPointer<Interface>(ptr, incref) { /* ... */ }
|
||||
public:
|
||||
constexpr EmplacedRef() { /* ... */ }
|
||||
|
||||
constexpr Impl &GetImpl() const {
|
||||
return *impl::EmplacedImplHolder<Impl>::template GetEmplacedImplPointerImpl<Interface>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Policy> requires (!IsStatefulPolicy<Policy>)
|
||||
class ObjectFactory<Policy> {
|
||||
private:
|
||||
template<typename Interface, typename Holder, typename T>
|
||||
static constexpr SharedPointer<Interface> CreateSharedForPointer(T t) {
|
||||
using Base = impl::ImplTemplateBase<Interface, Interface, Holder, Holder>;
|
||||
return SharedPointer<Interface>(ObjectImplFactory<Base, Policy>::Create(std::forward<T>(t)), false);
|
||||
}
|
||||
public:
|
||||
template<typename Interface, typename Impl, typename... Args>
|
||||
static constexpr EmplacedRef<Interface, Impl> CreateSharedEmplaced(Args &&... args) {
|
||||
using Base = impl::ImplTemplateBase<Interface, Interface, impl::EmplacedImplHolder<Impl>, impl::EmplacedImplHolder<Impl>>;
|
||||
return EmplacedRef<Interface, Impl>(ObjectImplFactory<Base, Policy>::Create(std::forward<Args>(args)...), false);
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
static constexpr SharedPointer<T> CreateUserSharedObject(Args &&... args) {
|
||||
return SharedPointer<T>(ObjectImplFactory<T, Policy>::Create(std::forward<Args>(args)...), false);
|
||||
}
|
||||
|
||||
template<typename Impl, typename Interface>
|
||||
static constexpr Impl *GetEmplacedImplPointer(const SharedPointer<Interface> &sp) {
|
||||
return impl::EmplacedImplHolder<Impl>::template GetEmplacedImplPointerImpl<Interface>(sp);
|
||||
}
|
||||
|
||||
template<typename Interface, typename Smart>
|
||||
static constexpr SharedPointer<Interface> CreateShared(Smart &&sp) {
|
||||
return CreateSharedForPointer<Interface, impl::SmartPointerHolder<typename std::decay<decltype(sp)>::type>>(std::forward<Smart>(sp));
|
||||
}
|
||||
|
||||
template<typename Interface, typename T>
|
||||
static constexpr SharedPointer<Interface> CreateShared(T *p) {
|
||||
return CreateSharedForPointer<Interface, impl::ManagedPointerHolder<T>>(p);
|
||||
}
|
||||
|
||||
template<typename Interface, typename T>
|
||||
static constexpr SharedPointer<Interface> CreateSharedWithoutManagement(T *p) {
|
||||
return CreateSharedForPointer<Interface, impl::UnmanagedPointerHolder<T>>(p);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Policy> requires (IsStatefulPolicy<Policy>)
|
||||
class ObjectFactory<Policy> {
|
||||
public:
|
||||
using Allocator = typename Policy::Allocator;
|
||||
private:
|
||||
template<typename Interface, typename Holder, typename T>
|
||||
static constexpr SharedPointer<Interface> CreateSharedForPointer(Allocator *a, T t) {
|
||||
using Base = impl::ImplTemplateBase<Interface, Interface, Holder, Holder>;
|
||||
return SharedPointer<Interface>(ObjectImplFactory<Base, Policy>::Create(a, std::forward<T>(t)), false);
|
||||
}
|
||||
public:
|
||||
template<typename Interface, typename Impl, typename... Args>
|
||||
static constexpr EmplacedRef<Interface, Impl> CreateSharedEmplaced(Allocator *a, Args &&... args) {
|
||||
using Base = impl::ImplTemplateBase<Interface, Interface, impl::EmplacedImplHolder<Impl>, impl::EmplacedImplHolder<Impl>>;
|
||||
return EmplacedRef<Interface, Impl>(ObjectImplFactory<Base, Policy>::Create(a, std::forward<Args>(args)...), false);
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
static constexpr SharedPointer<T> CreateUserSharedObject(Allocator *a, Args &&... args) {
|
||||
return SharedPointer<T>(ObjectImplFactory<T, Policy>::Create(a, std::forward<Args>(args)...), false);
|
||||
}
|
||||
|
||||
template<typename Impl, typename Interface>
|
||||
static constexpr Impl *GetEmplacedImplPointer(const SharedPointer<Interface> &sp) {
|
||||
return impl::EmplacedImplHolder<Impl>::template GetEmplacedImplPointerImpl<Interface>(sp);
|
||||
}
|
||||
|
||||
template<typename Interface, typename Smart>
|
||||
static constexpr SharedPointer<Interface> CreateShared(Allocator *a, Smart &&sp) {
|
||||
return CreateSharedForPointer<Interface, impl::SmartPointerHolder<typename std::decay<decltype(sp)>::type>>(a, std::forward<Smart>(sp));
|
||||
}
|
||||
|
||||
template<typename Interface, typename T>
|
||||
static constexpr SharedPointer<Interface> CreateShared(Allocator *a, T *p) {
|
||||
return CreateSharedForPointer<Interface, impl::ManagedPointerHolder<T>>(a, p);
|
||||
}
|
||||
|
||||
template<typename Interface, typename T>
|
||||
static constexpr SharedPointer<Interface> CreateSharedWithoutManagement(Allocator *a, T *p) {
|
||||
return CreateSharedForPointer<Interface, impl::UnmanagedPointerHolder<T>>(a, p);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Policy>
|
||||
class StatefulObjectFactory {
|
||||
public:
|
||||
using Allocator = typename Policy::Allocator;
|
||||
private:
|
||||
using StaticObjectFactory = ObjectFactory<Policy>;
|
||||
private:
|
||||
Allocator *m_allocator;
|
||||
public:
|
||||
constexpr explicit StatefulObjectFactory(Allocator *a) : m_allocator(a) { /* ... */ }
|
||||
|
||||
template<typename Interface, typename Impl, typename... Args>
|
||||
constexpr EmplacedRef<Interface, Impl> CreateSharedEmplaced(Args &&... args) {
|
||||
return StaticObjectFactory::template CreateSharedEmplaced<Interface, Impl>(m_allocator, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename Impl, typename Interface>
|
||||
static constexpr Impl *GetEmplacedImplPointer(const SharedPointer<Interface> &sp) {
|
||||
return StaticObjectFactory::template GetEmplacedImplPointer<Impl, Interface>(sp);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
using DefaultObjectFactory = ObjectFactory<DefaultAllocationPolicy>;
|
||||
using MemoryResourceObjectFactory = ObjectFactory<MemoryResourceAllocationPolicy>;
|
||||
|
||||
template<typename Interface, typename Impl, typename... Args>
|
||||
inline EmplacedRef<Interface, Impl> CreateSharedObjectEmplaced(Args &&... args) {
|
||||
return DefaultObjectFactory::CreateSharedEmplaced<Interface, Impl>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename Interface, typename Impl, typename... Args>
|
||||
inline EmplacedRef<Interface, Impl> CreateSharedObjectEmplaced(MemoryResource *mr, Args &&... args) {
|
||||
return MemoryResourceObjectFactory::CreateSharedEmplaced<Interface, Impl>(mr, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename Interface, typename Smart>
|
||||
inline SharedPointer<Interface> CreateSharedObject(Smart &&sp) {
|
||||
return DefaultObjectFactory::CreateShared<Interface, Smart>(std::forward<Smart>(sp));
|
||||
}
|
||||
|
||||
template<typename Interface, typename Smart>
|
||||
inline SharedPointer<Interface> CreateSharedObject(MemoryResource *mr, Smart &&sp) {
|
||||
return MemoryResourceObjectFactory::CreateShared<Interface, Smart>(mr, std::forward<Smart>(sp));
|
||||
}
|
||||
|
||||
template<typename Interface, typename T>
|
||||
inline SharedPointer<Interface> CreateSharedObject(T *ptr) {
|
||||
return DefaultObjectFactory::CreateShared<Interface, T>(std::move(ptr));
|
||||
}
|
||||
|
||||
template<typename Interface, typename T>
|
||||
inline SharedPointer<Interface> CreateSharedObjectWithoutManagement(T *ptr) {
|
||||
return DefaultObjectFactory::CreateSharedWithoutManagement<Interface, T>(std::move(ptr));
|
||||
}
|
||||
|
||||
template<typename Interface, typename T>
|
||||
inline SharedPointer<Interface> CreateSharedObjectWithoutManagement(MemoryResource *mr, T *ptr) {
|
||||
return DefaultObjectFactory::CreateSharedWithoutManagement<Interface, T>(mr, std::move(ptr));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,156 +0,0 @@
|
||||
/*
|
||||
* 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>
|
||||
#include <stratosphere/sf/sf_common.hpp>
|
||||
#include <stratosphere/sf/sf_allocation_policies.hpp>
|
||||
#include <stratosphere/sf/impl/sf_service_object_impl.hpp>
|
||||
|
||||
namespace ams::sf {
|
||||
|
||||
namespace impl {
|
||||
|
||||
struct StatelessDummyAllocator{};
|
||||
|
||||
template<typename Base, typename Policy>
|
||||
class ObjectImplFactoryWithStatelessAllocator {
|
||||
public:
|
||||
class Object;
|
||||
using Allocator = StatelessDummyAllocator;
|
||||
using StatelessAllocator = typename Policy::template StatelessAllocator<Object>;
|
||||
|
||||
class Object final : private ::ams::sf::impl::ServiceObjectImplBase2, public Base {
|
||||
NON_COPYABLE(Object);
|
||||
NON_MOVEABLE(Object);
|
||||
friend class ObjectImplFactoryWithStatelessAllocator;
|
||||
private:
|
||||
template<typename... Args>
|
||||
explicit Object(Args &&... args) : Base(std::forward<Args>(args)...) { /* ... */ }
|
||||
|
||||
static void *operator new(size_t size) {
|
||||
return Policy::template AllocateAligned<Object>(size, alignof(Object));
|
||||
}
|
||||
|
||||
static void operator delete(void *ptr, size_t size) {
|
||||
return Policy::template DeallocateAligned<Object>(ptr, size, alignof(Object));
|
||||
}
|
||||
|
||||
static void *operator new(size_t size, Allocator *);
|
||||
static void operator delete(void *ptr, Allocator *);
|
||||
|
||||
void DisposeImpl() {
|
||||
delete this;
|
||||
}
|
||||
public:
|
||||
void AddReference() {
|
||||
ServiceObjectImplBase2::AddReferenceImpl();
|
||||
}
|
||||
|
||||
void Release() {
|
||||
if (ServiceObjectImplBase2::ReleaseImpl()) {
|
||||
this->DisposeImpl();
|
||||
}
|
||||
}
|
||||
|
||||
Allocator *GetAllocator() const {
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename... Args>
|
||||
static Object *Create(Args &&... args) {
|
||||
return new Object(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
static Object *Create(Allocator *, Args &&... args) {
|
||||
return new Object(std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Base, typename Policy>
|
||||
class ObjectImplFactoryWithStatefulAllocator {
|
||||
public:
|
||||
using Allocator = typename Policy::Allocator;
|
||||
|
||||
class Object final : private ::ams::sf::impl::ServiceObjectImplBase2, public Base {
|
||||
NON_COPYABLE(Object);
|
||||
NON_MOVEABLE(Object);
|
||||
friend class ObjectImplFactoryWithStatefulAllocator;
|
||||
private:
|
||||
Allocator *m_allocator;
|
||||
private:
|
||||
template<typename... Args>
|
||||
explicit Object(Args &&... args) : Base(std::forward<Args>(args)...) { /* ... */ }
|
||||
|
||||
static void *operator new(size_t size);
|
||||
|
||||
static void operator delete(void *ptr, size_t size) {
|
||||
AMS_UNUSED(ptr, size);
|
||||
}
|
||||
|
||||
static void *operator new(size_t size, Allocator *a) {
|
||||
return Policy::AllocateAligned(a, size, alignof(Object));
|
||||
}
|
||||
|
||||
static void operator delete(void *ptr, Allocator *a) {
|
||||
return Policy::DeallocateAligned(a, ptr, sizeof(Object), alignof(Object));
|
||||
}
|
||||
|
||||
void DisposeImpl() {
|
||||
Allocator *a = this->GetAllocator();
|
||||
std::destroy_at(this);
|
||||
operator delete(this, a);
|
||||
}
|
||||
public:
|
||||
void AddReference() {
|
||||
ServiceObjectImplBase2::AddReferenceImpl();
|
||||
}
|
||||
|
||||
void Release() {
|
||||
if (ServiceObjectImplBase2::ReleaseImpl()) {
|
||||
this->DisposeImpl();
|
||||
}
|
||||
}
|
||||
|
||||
Allocator *GetAllocator() const {
|
||||
return m_allocator;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename... Args>
|
||||
static Object *Create(Allocator *a, Args &&... args) {
|
||||
auto *ptr = new (a) Object(std::forward<Args>(args)...);
|
||||
if (ptr != nullptr) {
|
||||
ptr->m_allocator = a;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<typename Base, typename Policy>
|
||||
class ObjectImplFactory;
|
||||
|
||||
template<typename Base, typename Policy> requires (!IsStatefulPolicy<Policy>)
|
||||
class ObjectImplFactory<Base, Policy> : public impl::ObjectImplFactoryWithStatelessAllocator<Base, Policy>{};
|
||||
|
||||
template<typename Base, typename Policy> requires (IsStatefulPolicy<Policy>)
|
||||
class ObjectImplFactory<Base, Policy> : public impl::ObjectImplFactoryWithStatefulAllocator<Base, Policy>{};
|
||||
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* 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 <stratosphere/sf/sf_common.hpp>
|
||||
#include <stratosphere/sf/cmif/sf_cmif_pointer_and_size.hpp>
|
||||
|
||||
namespace ams::sf {
|
||||
|
||||
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 *m_ptr;
|
||||
public:
|
||||
constexpr Out(uintptr_t p) : m_ptr(reinterpret_cast<T *>(p)) { /* ... */ }
|
||||
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;
|
||||
}
|
||||
|
||||
const T &GetValue() const {
|
||||
return *m_ptr;
|
||||
}
|
||||
|
||||
T *GetPointer() const {
|
||||
return m_ptr;
|
||||
}
|
||||
|
||||
/* Convenience operators. */
|
||||
T &operator*() const {
|
||||
return *m_ptr;
|
||||
}
|
||||
|
||||
T *operator->() const {
|
||||
return m_ptr;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class Out<T *> {
|
||||
static_assert(!std::is_same<T, T>::value, "Invalid sf::Out<T> (Raw Pointer)");
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* 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 <stratosphere/sf/sf_common.hpp>
|
||||
#include <stratosphere/sf/sf_out.hpp>
|
||||
#include <stratosphere/sf/sf_shared_object.hpp>
|
||||
|
||||
namespace ams::sf {
|
||||
|
||||
class IServiceObject : public ISharedObject {
|
||||
public:
|
||||
virtual ~IServiceObject() { /* ... */ }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
concept IsServiceObject = std::derived_from<T, IServiceObject>;
|
||||
|
||||
#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) { /* ... */ }
|
||||
};
|
||||
|
||||
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>;
|
||||
};
|
||||
#else
|
||||
template<typename T>
|
||||
concept IsMitmServiceObject = false;
|
||||
#endif
|
||||
|
||||
}
|
||||
@@ -1,200 +0,0 @@
|
||||
/*
|
||||
* 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 <stratosphere/sf/sf_common.hpp>
|
||||
#include <stratosphere/sf/sf_mitm_config.hpp>
|
||||
#include <stratosphere/sf/sf_out.hpp>
|
||||
|
||||
namespace ams::sf {
|
||||
|
||||
class ISharedObject {
|
||||
NON_COPYABLE(ISharedObject);
|
||||
NON_MOVEABLE(ISharedObject);
|
||||
protected:
|
||||
constexpr ISharedObject() { /* ... */ }
|
||||
~ISharedObject() { /* ... */ }
|
||||
public:
|
||||
constexpr virtual void AddReference() = 0;
|
||||
constexpr virtual void Release() = 0;
|
||||
};
|
||||
|
||||
namespace impl {
|
||||
|
||||
class SharedPointerBase {
|
||||
private:
|
||||
ISharedObject *m_ptr;
|
||||
private:
|
||||
constexpr void AddReferenceImpl() const {
|
||||
if (m_ptr != nullptr) {
|
||||
m_ptr->AddReference();
|
||||
}
|
||||
}
|
||||
|
||||
constexpr void ReleaseImpl() const {
|
||||
if (m_ptr != nullptr) {
|
||||
m_ptr->Release();
|
||||
}
|
||||
}
|
||||
public:
|
||||
constexpr SharedPointerBase() : m_ptr(nullptr) { /* ... */ }
|
||||
|
||||
constexpr SharedPointerBase(ISharedObject *ptr, bool incref) : m_ptr(ptr) {
|
||||
if (incref) {
|
||||
this->AddReferenceImpl();
|
||||
}
|
||||
}
|
||||
|
||||
constexpr ~SharedPointerBase() {
|
||||
this->ReleaseImpl();
|
||||
}
|
||||
|
||||
constexpr SharedPointerBase(const SharedPointerBase &rhs) : m_ptr(rhs.m_ptr) {
|
||||
this->AddReferenceImpl();
|
||||
}
|
||||
|
||||
constexpr SharedPointerBase(SharedPointerBase &&rhs) : m_ptr(rhs.m_ptr) {
|
||||
rhs.m_ptr = nullptr;
|
||||
}
|
||||
|
||||
constexpr SharedPointerBase &operator=(const SharedPointerBase &rhs) {
|
||||
SharedPointerBase tmp(rhs);
|
||||
tmp.swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr SharedPointerBase &operator=(SharedPointerBase &&rhs) {
|
||||
SharedPointerBase tmp(std::move(rhs));
|
||||
tmp.swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr void swap(SharedPointerBase &rhs) {
|
||||
std::swap(m_ptr, rhs.m_ptr);
|
||||
}
|
||||
|
||||
constexpr ISharedObject *Detach() {
|
||||
ISharedObject *ret = m_ptr;
|
||||
m_ptr = nullptr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
constexpr ISharedObject *Get() const {
|
||||
return m_ptr;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<typename I>
|
||||
class SharedPointer {
|
||||
template<typename> friend class ::ams::sf::SharedPointer;
|
||||
template<typename> friend class ::ams::sf::Out;
|
||||
public:
|
||||
using Interface = I;
|
||||
private:
|
||||
impl::SharedPointerBase m_base;
|
||||
public:
|
||||
constexpr SharedPointer() : m_base() { /* ... */ }
|
||||
|
||||
constexpr SharedPointer(std::nullptr_t) : m_base() { /* ... */ }
|
||||
|
||||
constexpr SharedPointer(Interface *ptr, bool incref) : m_base(static_cast<ISharedObject *>(ptr), incref) { /* ... */ }
|
||||
|
||||
constexpr SharedPointer(const SharedPointer &rhs) : m_base(rhs.m_base) { /* ... */ }
|
||||
|
||||
constexpr SharedPointer(SharedPointer &&rhs) : m_base(std::move(rhs.m_base)) { /* ... */ }
|
||||
|
||||
template<typename U> requires std::derived_from<U, Interface>
|
||||
constexpr SharedPointer(const SharedPointer<U> &rhs) : m_base(rhs.m_base) { /* ... */ }
|
||||
|
||||
template<typename U> requires std::derived_from<U, Interface>
|
||||
constexpr SharedPointer(SharedPointer<U> &&rhs) : m_base(std::move(rhs.m_base)) { /* ... */ }
|
||||
|
||||
constexpr SharedPointer &operator=(std::nullptr_t) {
|
||||
SharedPointer().swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr SharedPointer &operator=(const SharedPointer &rhs) {
|
||||
SharedPointer tmp(rhs);
|
||||
tmp.swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr SharedPointer &operator=(SharedPointer &&rhs) {
|
||||
SharedPointer tmp(std::move(rhs));
|
||||
tmp.swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename U> requires std::derived_from<U, Interface>
|
||||
constexpr SharedPointer &operator=(const SharedPointer<U> &rhs) {
|
||||
SharedPointer tmp(rhs);
|
||||
tmp.swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename U> requires std::derived_from<U, Interface>
|
||||
constexpr SharedPointer &operator=(SharedPointer<U> &&rhs) {
|
||||
SharedPointer tmp(std::move(rhs));
|
||||
tmp.swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr void swap(SharedPointer &rhs) {
|
||||
m_base.swap(rhs.m_base);
|
||||
}
|
||||
|
||||
constexpr Interface *Detach() {
|
||||
return static_cast<Interface *>(m_base.Detach());
|
||||
}
|
||||
|
||||
constexpr void Reset() {
|
||||
*this = nullptr;
|
||||
}
|
||||
|
||||
constexpr Interface *Get() const {
|
||||
return static_cast<Interface *>(m_base.Get());
|
||||
}
|
||||
|
||||
constexpr Interface *operator->() const {
|
||||
AMS_ASSERT(this->Get() != nullptr);
|
||||
return this->Get();
|
||||
}
|
||||
|
||||
constexpr bool operator!() const {
|
||||
return this->Get() == nullptr;
|
||||
}
|
||||
|
||||
constexpr bool operator==(std::nullptr_t) const {
|
||||
return this->Get() == nullptr;
|
||||
}
|
||||
|
||||
constexpr bool operator!=(std::nullptr_t) const {
|
||||
return this->Get() != nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Interface>
|
||||
constexpr void Swap(SharedPointer<Interface> &lhs, SharedPointer<Interface> &rhs) {
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
constexpr inline void ReleaseSharedObject(ISharedObject *ptr) {
|
||||
ptr->Release();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
* 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 <stratosphere/sf/sf_default_allocation_policy.hpp>
|
||||
|
||||
namespace ams::sf {
|
||||
|
||||
using StandardAllocationPolicy = DefaultAllocationPolicy;
|
||||
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* 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 <stratosphere/sf/sf_common.hpp>
|
||||
#include <stratosphere/sf/sf_allocation_policies.hpp>
|
||||
|
||||
namespace ams::sf {
|
||||
|
||||
template<template<typename> class StdAllocator>
|
||||
class StdAllocationPolicy {
|
||||
public:
|
||||
static constexpr bool HasStatefulAllocator = false;
|
||||
using Allocator = impl::StatelessDummyAllocator;
|
||||
|
||||
template<typename T>
|
||||
struct StatelessAllocator {
|
||||
static void *Allocate(size_t size) {
|
||||
return StdAllocator<T>().allocate(size / sizeof(T));
|
||||
}
|
||||
static void Deallocate(void *ptr, size_t size) {
|
||||
StdAllocator<T>().deallocate(static_cast<T *>(ptr), size / sizeof(T));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
static void *AllocateAligned(size_t size, size_t align) {
|
||||
AMS_UNUSED(align);
|
||||
return StdAllocator<T>().allocate(size / sizeof(T));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void DeallocateAligned(void *ptr, size_t size, size_t align) {
|
||||
AMS_UNUSED(align);
|
||||
StdAllocator<T>().deallocate(static_cast<T *>(ptr), size / sizeof(T));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,506 +0,0 @@
|
||||
/*
|
||||
* 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