ams-mtc: add ams-mtc
This commit is contained in:
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* 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 <mesosphere/svc/kern_svc_results.hpp>
|
||||
#include <mesosphere/kern_select_userspace_memory_access.hpp>
|
||||
|
||||
namespace ams::kern::svc {
|
||||
|
||||
namespace impl {
|
||||
|
||||
template<typename T>
|
||||
concept Pointer = std::is_pointer<T>::value;
|
||||
|
||||
template<typename T>
|
||||
concept NonConstPointer = Pointer<T> && !std::is_const<typename std::remove_pointer<T>::type>::value;
|
||||
|
||||
template<typename T>
|
||||
concept ConstPointer = Pointer<T> && std::is_const<typename std::remove_pointer<T>::type>::value;
|
||||
|
||||
template<typename T, size_t N>
|
||||
concept AlignedNPointer = Pointer<T> && alignof(typename std::remove_pointer<T>::type) >= N && util::IsAligned(sizeof(typename std::remove_pointer<T>::type), N);
|
||||
|
||||
template<typename T>
|
||||
concept Aligned8Pointer = AlignedNPointer<T, sizeof(u8)>;
|
||||
|
||||
template<typename T>
|
||||
concept Aligned16Pointer = AlignedNPointer<T, sizeof(u16)> && Aligned8Pointer<T>;
|
||||
|
||||
template<typename T>
|
||||
concept Aligned32Pointer = AlignedNPointer<T, sizeof(u32)> && Aligned16Pointer<T>;
|
||||
|
||||
template<typename T>
|
||||
concept Aligned64Pointer = AlignedNPointer<T, sizeof(u64)> && Aligned32Pointer<T>;
|
||||
|
||||
template<typename _T>
|
||||
class KUserPointerImplTraits;
|
||||
|
||||
template<typename _T> requires Aligned8Pointer<_T>
|
||||
class KUserPointerImplTraits<_T> {
|
||||
public:
|
||||
using T = typename std::remove_const<typename std::remove_pointer<_T>::type>::type;
|
||||
public:
|
||||
static ALWAYS_INLINE Result CopyFromUserspace(void *dst, const void *src, size_t size) {
|
||||
R_UNLESS(UserspaceAccess::CopyMemoryFromUser(dst, src, size), svc::ResultInvalidPointer());
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE Result CopyToUserspace(void *dst, const void *src, size_t size) {
|
||||
R_UNLESS(UserspaceAccess::CopyMemoryToUser(dst, src, size), svc::ResultInvalidPointer());
|
||||
R_SUCCEED();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename _T> requires Aligned32Pointer<_T>
|
||||
class KUserPointerImplTraits<_T> {
|
||||
public:
|
||||
using T = typename std::remove_const<typename std::remove_pointer<_T>::type>::type;
|
||||
public:
|
||||
static ALWAYS_INLINE Result CopyFromUserspace(void *dst, const void *src, size_t size) {
|
||||
R_UNLESS(UserspaceAccess::CopyMemoryFromUserAligned32Bit(dst, src, size), svc::ResultInvalidPointer());
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE Result CopyToUserspace(void *dst, const void *src, size_t size) {
|
||||
R_UNLESS(UserspaceAccess::CopyMemoryToUserAligned32Bit(dst, src, size), svc::ResultInvalidPointer());
|
||||
R_SUCCEED();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename _T> requires Aligned64Pointer<_T>
|
||||
class KUserPointerImplTraits<_T> {
|
||||
public:
|
||||
using T = typename std::remove_const<typename std::remove_pointer<_T>::type>::type;
|
||||
public:
|
||||
static ALWAYS_INLINE Result CopyFromUserspace(void *dst, const void *src, size_t size) {
|
||||
R_UNLESS(UserspaceAccess::CopyMemoryFromUserAligned64Bit(dst, src, size), svc::ResultInvalidPointer());
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE Result CopyToUserspace(void *dst, const void *src, size_t size) {
|
||||
R_UNLESS(UserspaceAccess::CopyMemoryToUserAligned64Bit(dst, src, size), svc::ResultInvalidPointer());
|
||||
R_SUCCEED();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename _T>
|
||||
class KUserPointerImpl;
|
||||
|
||||
template<typename _T> requires Aligned8Pointer<_T>
|
||||
class KUserPointerImpl<_T> : impl::KUserPointerTag {
|
||||
private:
|
||||
using Traits = KUserPointerImplTraits<_T>;
|
||||
protected:
|
||||
using CT = typename std::remove_pointer<_T>::type;
|
||||
using T = typename std::remove_const<CT>::type;
|
||||
private:
|
||||
CT *m_ptr;
|
||||
private:
|
||||
ALWAYS_INLINE Result CopyToImpl(void *p, size_t size) const {
|
||||
R_RETURN(Traits::CopyFromUserspace(p, m_ptr, size));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Result CopyFromImpl(const void *p, size_t size) const {
|
||||
R_RETURN(Traits::CopyToUserspace(m_ptr, p, size));
|
||||
}
|
||||
protected:
|
||||
ALWAYS_INLINE Result CopyTo(T *p) const { R_RETURN(this->CopyToImpl(p, sizeof(*p))); }
|
||||
ALWAYS_INLINE Result CopyFrom(const T *p) const { R_RETURN(this->CopyFromImpl(p, sizeof(*p))); }
|
||||
|
||||
ALWAYS_INLINE Result CopyArrayElementTo(T *p, size_t index) const { R_RETURN(Traits::CopyFromUserspace(p, m_ptr + index, sizeof(*p))); }
|
||||
ALWAYS_INLINE Result CopyArrayElementFrom(const T *p, size_t index) const { R_RETURN(Traits::CopyToUserspace(m_ptr + index, p, sizeof(*p))); }
|
||||
|
||||
ALWAYS_INLINE Result CopyArrayTo(T *arr, size_t count) const { R_RETURN(this->CopyToImpl(arr, sizeof(*arr) * count)); }
|
||||
ALWAYS_INLINE Result CopyArrayFrom(const T *arr, size_t count) const { R_RETURN(this->CopyFromImpl(arr, sizeof(*arr) * count)); }
|
||||
|
||||
constexpr ALWAYS_INLINE bool IsNull() const { return m_ptr == nullptr; }
|
||||
|
||||
constexpr ALWAYS_INLINE CT *GetUnsafePointer() const { return m_ptr; }
|
||||
};
|
||||
|
||||
template<>
|
||||
class KUserPointerImpl<const char *> : impl::KUserPointerTag {
|
||||
private:
|
||||
using Traits = KUserPointerImplTraits<const char *>;
|
||||
protected:
|
||||
using CT = const char;
|
||||
using T = char;
|
||||
private:
|
||||
const char *m_ptr;
|
||||
protected:
|
||||
ALWAYS_INLINE Result CopyStringTo(char *dst, size_t size) const {
|
||||
static_assert(sizeof(char) == 1);
|
||||
R_UNLESS(UserspaceAccess::CopyStringFromUser(dst, m_ptr, size) > 0, svc::ResultInvalidPointer());
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Result CopyArrayElementTo(char *dst, size_t index) const {
|
||||
R_RETURN(Traits::CopyFromUserspace(dst, m_ptr + index, sizeof(*dst)));
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE bool IsNull() const { return m_ptr == nullptr; }
|
||||
|
||||
constexpr ALWAYS_INLINE const char *GetUnsafePointer() const { return m_ptr; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct KUserPointer;
|
||||
|
||||
template<typename T> requires impl::ConstPointer<T>
|
||||
struct KUserPointer<T> : public impl::KUserPointerImpl<T> {
|
||||
public:
|
||||
static constexpr bool IsInput = true;
|
||||
public:
|
||||
using impl::KUserPointerImpl<T>::CopyTo;
|
||||
using impl::KUserPointerImpl<T>::CopyArrayElementTo;
|
||||
using impl::KUserPointerImpl<T>::CopyArrayTo;
|
||||
using impl::KUserPointerImpl<T>::IsNull;
|
||||
|
||||
using impl::KUserPointerImpl<T>::GetUnsafePointer;
|
||||
};
|
||||
|
||||
template<typename T> requires impl::NonConstPointer<T>
|
||||
struct KUserPointer<T> : public impl::KUserPointerImpl<T> {
|
||||
public:
|
||||
static constexpr bool IsInput = false;
|
||||
public:
|
||||
using impl::KUserPointerImpl<T>::CopyFrom;
|
||||
using impl::KUserPointerImpl<T>::CopyArrayElementFrom;
|
||||
using impl::KUserPointerImpl<T>::CopyArrayFrom;
|
||||
using impl::KUserPointerImpl<T>::IsNull;
|
||||
|
||||
using impl::KUserPointerImpl<T>::GetUnsafePointer;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct KUserPointer<const char *> : public impl::KUserPointerImpl<const char *> {
|
||||
public:
|
||||
static constexpr bool IsInput = true;
|
||||
public:
|
||||
using impl::KUserPointerImpl<const char *>::CopyStringTo;
|
||||
using impl::KUserPointerImpl<const char *>::CopyArrayElementTo;
|
||||
using impl::KUserPointerImpl<const char *>::IsNull;
|
||||
|
||||
using impl::KUserPointerImpl<const char *>::GetUnsafePointer;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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 <mesosphere/svc/kern_svc_k_user_pointer.hpp>
|
||||
#include <mesosphere/svc/kern_svc_results.hpp>
|
||||
|
||||
namespace ams::kern::svc {
|
||||
|
||||
static constexpr size_t NumSupervisorCalls = AMS_KERN_NUM_SUPERVISOR_CALLS;
|
||||
|
||||
#define AMS_KERN_SVC_DECLARE_ENUM_ID(ID, RETURN_TYPE, NAME, ...) \
|
||||
SvcId_##NAME = ID,
|
||||
|
||||
enum SvcId {
|
||||
AMS_SVC_FOREACH_KERN_DEFINITION(AMS_KERN_SVC_DECLARE_ENUM_ID, __invalid)
|
||||
SvcId_Count = NumSupervisorCalls,
|
||||
};
|
||||
|
||||
#undef AMS_KERN_SVC_DECLARE_ENUM_ID
|
||||
|
||||
#define AMS_KERN_SVC_DECLARE_PROTOTYPE_64(ID, RETURN_TYPE, NAME, ...) \
|
||||
NOINLINE RETURN_TYPE NAME##64(__VA_ARGS__);
|
||||
#define AMS_KERN_SVC_DECLARE_PROTOTYPE_64_FROM_32(ID, RETURN_TYPE, NAME, ...) \
|
||||
NOINLINE RETURN_TYPE NAME##64From32(__VA_ARGS__);
|
||||
|
||||
AMS_SVC_FOREACH_KERN_DEFINITION(AMS_KERN_SVC_DECLARE_PROTOTYPE_64, lp64)
|
||||
AMS_SVC_FOREACH_KERN_DEFINITION(AMS_KERN_SVC_DECLARE_PROTOTYPE_64_FROM_32, ilp32)
|
||||
|
||||
/* TODO: Support _32 ABI */
|
||||
|
||||
#undef AMS_KERN_SVC_DECLARE_PROTOTYPE_64
|
||||
#undef AMS_KERN_SVC_DECLARE_PROTOTYPE_64_FROM_32
|
||||
|
||||
struct SvcAccessFlagSetTag{};
|
||||
|
||||
using SvcAccessFlagSet = util::BitFlagSet<NumSupervisorCalls, SvcAccessFlagSetTag>;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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::kern::svc {
|
||||
|
||||
/* 7 */ using ::ams::svc::ResultOutOfSessions;
|
||||
|
||||
/* 14 */ using ::ams::svc::ResultInvalidArgument;
|
||||
|
||||
/* 33 */ using ::ams::svc::ResultNotImplemented;
|
||||
|
||||
/* 54 */ using ::ams::svc::ResultStopProcessingException;
|
||||
|
||||
/* 57 */ using ::ams::svc::ResultNoSynchronizationObject;
|
||||
|
||||
/* 59 */ using ::ams::svc::ResultTerminationRequested;
|
||||
|
||||
/* 70 */ using ::ams::svc::ResultNoEvent;
|
||||
|
||||
/* 101 */ using ::ams::svc::ResultInvalidSize;
|
||||
/* 102 */ using ::ams::svc::ResultInvalidAddress;
|
||||
/* 103 */ using ::ams::svc::ResultOutOfResource;
|
||||
/* 104 */ using ::ams::svc::ResultOutOfMemory;
|
||||
/* 105 */ using ::ams::svc::ResultOutOfHandles;
|
||||
/* 106 */ using ::ams::svc::ResultInvalidCurrentMemory;
|
||||
|
||||
/* 108 */ using ::ams::svc::ResultInvalidNewMemoryPermission;
|
||||
|
||||
/* 110 */ using ::ams::svc::ResultInvalidMemoryRegion;
|
||||
|
||||
/* 112 */ using ::ams::svc::ResultInvalidPriority;
|
||||
/* 113 */ using ::ams::svc::ResultInvalidCoreId;
|
||||
/* 114 */ using ::ams::svc::ResultInvalidHandle;
|
||||
/* 115 */ using ::ams::svc::ResultInvalidPointer;
|
||||
/* 116 */ using ::ams::svc::ResultInvalidCombination;
|
||||
/* 117 */ using ::ams::svc::ResultTimedOut;
|
||||
/* 118 */ using ::ams::svc::ResultCancelled;
|
||||
/* 119 */ using ::ams::svc::ResultOutOfRange;
|
||||
/* 120 */ using ::ams::svc::ResultInvalidEnumValue;
|
||||
/* 121 */ using ::ams::svc::ResultNotFound;
|
||||
/* 122 */ using ::ams::svc::ResultBusy;
|
||||
/* 123 */ using ::ams::svc::ResultSessionClosed;
|
||||
/* 124 */ using ::ams::svc::ResultNotHandled;
|
||||
/* 125 */ using ::ams::svc::ResultInvalidState;
|
||||
/* 126 */ using ::ams::svc::ResultReservedUsed;
|
||||
/* 127 */ using ::ams::svc::ResultNotSupported;
|
||||
/* 128 */ using ::ams::svc::ResultDebug;
|
||||
/* 129 */ using ::ams::svc::ResultNoThread;
|
||||
/* 130 */ using ::ams::svc::ResultUnknownThread;
|
||||
/* 131 */ using ::ams::svc::ResultPortClosed;
|
||||
/* 132 */ using ::ams::svc::ResultLimitReached;
|
||||
/* 133 */ using ::ams::svc::ResultInvalidMemoryPool;
|
||||
|
||||
/* 258 */ using ::ams::svc::ResultReceiveListBroken;
|
||||
/* 259 */ using ::ams::svc::ResultOutOfAddressSpace;
|
||||
/* 260 */ using ::ams::svc::ResultMessageTooLarge;
|
||||
|
||||
/* 517 */ using ::ams::svc::ResultInvalidProcessId;
|
||||
/* 518 */ using ::ams::svc::ResultInvalidThreadId;
|
||||
/* 519 */ using ::ams::svc::ResultInvalidId;
|
||||
/* 520 */ using ::ams::svc::ResultProcessTerminated;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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 <mesosphere/svc/kern_svc_prototypes.hpp>
|
||||
|
||||
namespace ams::kern::svc {
|
||||
|
||||
using SvcTableEntry = void (*)();
|
||||
|
||||
/* TODO: 32-bit ABI */
|
||||
|
||||
extern const std::array<SvcTableEntry, NumSupervisorCalls> SvcTable64From32;
|
||||
extern const std::array<SvcTableEntry, NumSupervisorCalls> SvcTable64;
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user