svc.h : updated MemOp enum and documented half of the file

This commit is contained in:
Lectem 2015-06-28 01:33:50 +02:00
parent 0c8c272bf4
commit 2b385581b9

View File

@ -1,17 +1,39 @@
/* /**
svc.h _ Syscall wrappers. * @file svc.h
*/ * @brief Syscall wrappers.
*/
#pragma once #pragma once
typedef enum { #include "types.h"
MEMOP_FREE =1, // Free heap
MEMOP_ALLOC=3, // Allocate heap
MEMOP_MAP =4, // Mirror mapping ///@name Memory management
MEMOP_UNMAP=5, // Mirror unmapping ///@{
MEMOP_PROT =6, // Change protection
/**
* @brief @ref svcControlMemory operation flags
*
* The lowest 8 bits are the operation
*/
typedef enum {
MEMOP_FREE = 1, ///< Memory un-mapping
MEMOP_RESERVE = 2, ///< Reserve memory
MEMOP_ALLOC = 3, ///< Memory mapping
MEMOP_MAP = 4, ///< Mirror mapping
MEMOP_UNMAP = 5, ///< Mirror unmapping
MEMOP_PROT = 6, ///< Change protection
MEMOP_REGION_APP = 0x100,
MEMOP_REGION_SYSTEM = 0x200,
MEMOP_REGION_BASE = 0x300,
MEMOP_OP_MASK = 0xFF,
MEMOP_REGION_MASK = 0xF00,
MEMOP_LINEAR_FLAG = 0x10000, ///< Flag for linear memory operations
MEMOP_ALLOC_LINEAR = MEMOP_LINEAR_FLAG | MEMOP_ALLOC,
MEMOP_ALLOC_LINEAR=0x10003 // Allocate linear heap
} MemOp; } MemOp;
typedef enum { typedef enum {
@ -29,19 +51,21 @@ typedef enum {
MEMSTATE_LOCKED = 11 MEMSTATE_LOCKED = 11
} MemState; } MemState;
/**
* @brief Memory permission flags
*/
typedef enum { typedef enum {
MEMPERM_READ = 1, MEMPERM_READ = 1,
MEMPERM_WRITE = 2, MEMPERM_WRITE = 2,
MEMPERM_EXECUTE = 4, MEMPERM_EXECUTE = 4,
MEMPERM_DONTCARE = 0x10000000, MEMPERM_DONTCARE = 0x10000000
MEMPERM_MAX = 0xFFFFFFFF //force 4-byte
} MemPerm; } MemPerm;
typedef struct { typedef struct {
u32 base_addr; u32 base_addr;
u32 size; u32 size;
u32 perm; u32 perm; ///< See @ref MemPerm
u32 state; u32 state; ///< See @ref MemState
} MemInfo; } MemInfo;
typedef struct { typedef struct {
@ -49,41 +73,49 @@ typedef struct {
} PageInfo; } PageInfo;
typedef enum { typedef enum {
ARBITER_FREE =0, ARBITER_FREE = 0,
ARBITER_ACQUIRE =1, ARBITER_ACQUIRE = 1,
ARBITER_KERNEL2 =2, ARBITER_KERNEL2 = 2,
ARBITER_ACQUIRE_TIMEOUT=3, ARBITER_ACQUIRE_TIMEOUT = 3,
ARBITER_KERNEL4 =4, ARBITER_KERNEL4 = 4,
} ArbitrationType; } ArbitrationType;
typedef enum { ///@}
DBG_EVENT_PROCESS = 0,
DBG_EVENT_CREATE_THREAD = 1,
DBG_EVENT_EXIT_THREAD = 2,
DBG_EVENT_EXIT_PROCESS = 3,
DBG_EVENT_EXCEPTION = 4,
DBG_EVENT_DLL_LOAD = 5,
DBG_EVENT_DLL_UNLOAD = 6,
DBG_EVENT_SCHEDULE_IN = 7,
DBG_EVENT_SCHEDULE_OUT = 8,
DBG_EVENT_SYSCALL_IN = 9,
DBG_EVENT_SYSCALL_OUT = 10,
DBG_EVENT_OUTPUT_STRING = 11,
DBG_EVENT_MAP = 12
} DebugEventType;
///@name Multithreading
///@{
typedef enum {
THREADINFO_TYPE_UNKNOWN
} ThreadInfoType;
///@}
///@name Debugging
///@{
typedef enum { typedef enum {
REASON_CREATE = 1, REASON_CREATE = 1,
REASON_ATTACH = 2 REASON_ATTACH = 2
} ProcessEventReason; } ProcessEventReason;
typedef struct { typedef struct {
u64 program_id; u64 program_id;
u8 process_name[8]; u8 process_name[8];
u32 process_id; u32 process_id;
u32 reason; u32 reason; ///< See @ref ProcessEventReason
} ProcessEvent; } ProcessEvent;
typedef enum {
EXITPROCESS_EVENT_NONE = 0,
EXITPROCESS_EVENT_TERMINATE = 1,
EXITPROCESS_EVENT_UNHANDLED_EXCEPTION = 2
} ExitProcessEventReason;
typedef struct {
u32 reason; ///< See @ref ExitProcessEventReason
} ExitProcessEvent;
typedef struct { typedef struct {
u32 creator_thread_id; u32 creator_thread_id;
u32 base_addr; u32 base_addr;
@ -97,50 +129,33 @@ typedef enum {
EXITTHREAD_EVENT_TERMINATE_PROCESS = 3 EXITTHREAD_EVENT_TERMINATE_PROCESS = 3
} ExitThreadEventReason; } ExitThreadEventReason;
typedef enum {
EXITPROCESS_EVENT_NONE = 0,
EXITPROCESS_EVENT_TERMINATE = 1,
EXITPROCESS_EVENT_UNHANDLED_EXCEPTION = 2
} ExitProcessEventReason;
typedef struct { typedef struct {
u32 reason; u32 reason; ///< See @ref ExitThreadEventReason
} ExitProcessEvent;
typedef struct {
u32 reason;
} ExitThreadEvent; } ExitThreadEvent;
typedef struct {
u32 type;
u32 address;
u32 argument;
} ExceptionEvent;
typedef enum {
EXC_EVENT_UNDEFINED_INSTRUCTION = 0, // arg: (None)
EXC_EVENT_UNKNOWN1 = 1, // arg: (None)
EXC_EVENT_UNKNOWN2 = 2, // arg: address
EXC_EVENT_UNKNOWN3 = 3, // arg: address
EXC_EVENT_ATTACH_BREAK = 4, // arg: (None)
EXC_EVENT_BREAKPOINT = 5, // arg: (None)
EXC_EVENT_USER_BREAK = 6, // arg: user break type
EXC_EVENT_DEBUGGER_BREAK = 7, // arg: (None)
EXC_EVENT_UNDEFINED_SYSCALL = 8 // arg: attempted syscall
} ExceptionEventType;
typedef enum { typedef enum {
USERBREAK_PANIC = 0, USERBREAK_PANIC = 0,
USERBREAK_ASSERT = 1, USERBREAK_ASSERT = 1,
USERBREAK_USER = 2 USERBREAK_USER = 2
} UserBreakType; } UserBreakType;
/**
* Type of the query for svcGetThreadInfo
*/
typedef enum { typedef enum {
THREADINFO_TYPE_UNKNOWN EXC_EVENT_UNDEFINED_INSTRUCTION = 0, ///< arg: (None)
} ThreadInfoType; EXC_EVENT_UNKNOWN1 = 1, ///< arg: (None)
EXC_EVENT_UNKNOWN2 = 2, ///< arg: address
EXC_EVENT_UNKNOWN3 = 3, ///< arg: address
EXC_EVENT_ATTACH_BREAK = 4, ///< arg: (None)
EXC_EVENT_BREAKPOINT = 5, ///< arg: (None)
EXC_EVENT_USER_BREAK = 6, ///< arg: @ref UserBreakType
EXC_EVENT_DEBUGGER_BREAK = 7, ///< arg: (None)
EXC_EVENT_UNDEFINED_SYSCALL = 8 ///< arg: attempted syscall
} ExceptionEventType;
typedef struct {
u32 type; ///< See @ref ExceptionEventType
u32 address;
u32 argument; ///< See @ref ExceptionEventType
} ExceptionEvent;
typedef struct { typedef struct {
u64 clock_tick; u64 clock_tick;
@ -163,8 +178,24 @@ typedef struct {
u32 memstate; u32 memstate;
} MapEvent; } MapEvent;
typedef enum {
DBG_EVENT_PROCESS = 0,
DBG_EVENT_CREATE_THREAD = 1,
DBG_EVENT_EXIT_THREAD = 2,
DBG_EVENT_EXIT_PROCESS = 3,
DBG_EVENT_EXCEPTION = 4,
DBG_EVENT_DLL_LOAD = 5,
DBG_EVENT_DLL_UNLOAD = 6,
DBG_EVENT_SCHEDULE_IN = 7,
DBG_EVENT_SCHEDULE_OUT = 8,
DBG_EVENT_SYSCALL_IN = 9,
DBG_EVENT_SYSCALL_OUT = 10,
DBG_EVENT_OUTPUT_STRING = 11,
DBG_EVENT_MAP = 12
} DebugEventType;
typedef struct { typedef struct {
u32 type; u32 type; ///< See @ref DebugEventType
u32 thread_id; u32 thread_id;
u32 unknown[2]; u32 unknown[2];
union { union {
@ -178,10 +209,12 @@ typedef struct {
SchedulerInOutEvent scheduler; SchedulerInOutEvent scheduler;
SyscallInOutEvent syscall; SyscallInOutEvent syscall;
OutputStringEvent output_string; OutputStringEvent output_string;
MapEvent map; MapEvent map;
}; };
} DebugEventInfo; } DebugEventInfo;
///@}
static inline void* getThreadLocalStorage(void) static inline void* getThreadLocalStorage(void)
{ {
void* ret; void* ret;
@ -194,62 +227,212 @@ static inline u32* getThreadCommandBuffer(void)
return (u32*)((u8*)getThreadLocalStorage() + 0x80); return (u32*)((u8*)getThreadLocalStorage() + 0x80);
} }
s32 svcControlMemory(u32* addr_out, u32 addr0, u32 addr1, u32 size, MemOp op, MemPerm perm); ///@name Memory management
s32 svcQueryMemory(MemInfo* info, PageInfo* out, u32 addr); ///@{
void __attribute__((noreturn)) svcExitProcess();
s32 svcCreateThread(Handle* thread, ThreadFunc entrypoint, u32 arg, u32* stack_top, s32 thread_priority, s32 processor_id); /**
void __attribute__((noreturn)) svcExitThread(); * @brief Controls memory mapping
void svcSleepThread(s64 ns); * @param[out] addr_out The virtual address resulting from the operation. Usually the same as addr0.
s32 svcGetThreadPriority(s32 *out, Handle handle); * @param addr0 The virtual address to be used for the operation.
s32 svcSetThreadPriority(Handle thread, s32 prio); * @param addr1 The virtual address to be (un)mirrored by @p addr0 when using @ref MEMOP_MAP or @ref MEMOP_UNMAP.
s32 svcGetThreadAffinityMask(u8* affinitymask, Handle thread, s32 processorcount); * It has to be pointing to a RW memory.
s32 svcSetThreadAffinityMask(Handle thread, u8* affinitymask, s32 processorcount); * Use NULL if the operation is @ref MEMOP_FREE or @ref MEMOP_ALLOC.
s32 svcGetThreadIdealProcessor(s32* processorid, Handle thread); * @param size The requested size for @ref MEMOP_ALLOC and @ref MEMOP_ALLOC_LINEAR.
s32 svcSetThreadIdealProcessor(Handle thread, s32 processorid); * @param op Operation flags. See @ref MemOp.
s32 svcGetProcessorID(); * @param perm A combination of @ref MEMPERM_READ and @ref MEMPERM_WRITE. Using MEMPERM_EXECUTE will return an error.
s32 svcCreateMutex(Handle* mutex, bool initially_locked); * Value 0 is used when unmapping memory.
s32 svcReleaseMutex(Handle handle); *
s32 svcCreateSemaphore(Handle* semaphore, s32 initial_count, s32 max_count); * If a memory is mapped for two or more addresses, you have to use MEMOP_UNMAP before being able to MEMOP_FREE it.
s32 svcReleaseSemaphore(s32* count, Handle semaphore, s32 release_count); * MEMOP_MAP will fail if @p addr1 was already mapped to another address.
s32 svcCreateEvent(Handle* event, u8 reset_type); *
s32 svcSignalEvent(Handle handle); * More information is available at http://3dbrew.org/wiki/SVC#Memory_Mapping.
s32 svcClearEvent(Handle handle); *
s32 svcCreateTimer(Handle* timer, u8 reset_type); * @sa svcControlProcessMemory
s32 svcSetTimer(Handle timer, s64 initial, s64 interval); */
s32 svcCancelTimer(Handle timer); Result svcControlMemory(u32* addr_out, u32 addr0, u32 addr1, u32 size, MemOp op, MemPerm perm);
s32 svcClearTimer(Handle timer);
s32 svcCreateMemoryBlock(Handle* memblock, u32 addr, u32 size, MemPerm my_perm, MemPerm other_perm); /**
s32 svcMapMemoryBlock(Handle memblock, u32 addr, MemPerm my_perm, MemPerm other_perm); * @brief Controls the memory mapping of a process
s32 svcUnmapMemoryBlock(Handle memblock, u32 addr); * @param addr0 The virtual address to map
s32 svcCreateAddressArbiter(Handle *arbiter); * @param addr1 The virtual address to be mapped by @p addr0
s32 svcArbitrateAddress(Handle arbiter, u32 addr, ArbitrationType type, s32 value, s64 nanoseconds); * @param type Only operations @ref MEMOP_MAP, @ref MEMOP_UNMAP and @ref MEMOP_PROT are allowed.
s32 svcWaitSynchronization(Handle handle, s64 nanoseconds); *
s32 svcWaitSynchronizationN(s32* out, Handle* handles, s32 handles_num, bool wait_all, s64 nanoseconds); * This is the only SVC which allows mapping executable memory.
s32 svcCloseHandle(Handle handle); * Using @ref MEMOP_PROT will change the memory permissions of an already mapped memory.
s32 svcDuplicateHandle(Handle* out, Handle original); *
u64 svcGetSystemTick(); * @note The pseudo handle for the current process is not supported by this service call.
s32 svcGetSystemInfo(s64* out, u32 type, s32 param); * @sa svcControlProcess
s32 svcGetProcessInfo(s64* out, Handle process, u32 type); */
s32 svcGetThreadInfo(s64* out, Handle thread, ThreadInfoType type); Result svcControlProcessMemory(Handle process, u32 addr0, u32 addr1, u32 size, u32 type, u32 perm);
s32 svcConnectToPort(volatile Handle* out, const char* portName);
s32 svcSendSyncRequest(Handle session); Result svcCreateMemoryBlock(Handle* memblock, u32 addr, u32 size, MemPerm my_perm, MemPerm other_perm);
Result svcMapMemoryBlock(Handle memblock, u32 addr, MemPerm my_perm, MemPerm other_perm);
Result svcMapProcessMemory(Handle process, u32 startAddr, u32 endAddr);
Result svcUnmapProcessMemory(Handle process, u32 startAddr, u32 endAddr);
Result svcUnmapMemoryBlock(Handle memblock, u32 addr);
/**
* @brief Memory information query
* @param addr Virtual memory address
*/
Result svcQueryMemory(MemInfo* info, PageInfo* out, u32 addr);
Result svcQueryProcessMemory(MemInfo* info, PageInfo* out, Handle process, u32 addr);
Result svcCreateAddressArbiter(Handle *arbiter);
Result svcArbitrateAddress(Handle arbiter, u32 addr, ArbitrationType type, s32 value, s64 nanoseconds);
Result svcReadProcessMemory(void* buffer, Handle debug, u32 addr, u32 size);
Result svcWriteProcessMemory(Handle debug, const void* buffer, u32 addr, u32 size);
///@}
///@name Process management
///@{
/**
* @brief Gets the handle of a process.
* @param[out] process The handle of the process
* @param processId The ID of the process to open
*/
Result svcOpenProcess(Handle* process, u32 processId); Result svcOpenProcess(Handle* process, u32 processId);
Result svcOpenThread(Handle* thread,Handle process, u32 threadId); void svcExitProcess() __attribute__((noreturn));
s32 svcGetProcessId(u32 *out, Handle handle);
s32 svcGetProcessIdOfThread(u32 *out, Handle handle); Result svcGetProcessInfo(s64* out, Handle process, u32 type);
s32 svcGetThreadId(u32 *out, Handle handle); Result svcGetProcessId(u32 *out, Handle handle);
s32 svcOutputDebugString(const char* str, int length); Result svcGetProcessList(s32* processCount, u32* processIds, s32 processIdMaxCount);
Result svcCreatePort(Handle* portServer, Handle* portClient, const char* name, s32 maxSessions); Result svcCreatePort(Handle* portServer, Handle* portClient, const char* name, s32 maxSessions);
Result svcConnectToPort(volatile Handle* out, const char* portName);
///@}
///@name Multithreading
///@{
/**
* @brief Creates a new thread.
* @param[out] thread The thread handle
* @param entrypoint The function that will be called first upon thread creation
* @param arg The argument passed to @p entrypoint
* @param stack_top The top of the thread's stack. Must be 0x8 bytes mem-aligned.
* @param thread_priority Low values gives the thread higher priority.
* For userland app, this has to be withing the range [0x18;0x3F]
* @param processor_id The id of the processor the thread should be ran on. Those are labelled starting from 0.
* For old 3ds it has to be <2, and for new 3DS <4.
* Value -1 means all CPUs and -2 read from the Exheader.
*
* The processor with ID 1 is the system processor.
* To enable multi-threading on this core you need to call APT_SetAppCpuTimeLimit at least once with a non-zero value.
*
* Since a thread is considered as a waitable object, you can use @ref svcWaitSynchronization
* and @ref svcWaitSynchronizationN to join with it.
*
* @note The kernel will clear the @p stack_top's address low 3 bits to make sure it is 0x8-bytes aligned.
*/
Result svcCreateThread(Handle* thread, ThreadFunc entrypoint, u32 arg, u32* stack_top, s32 thread_priority, s32 processor_id);
/**
* @brief Gets the handle of a thread.
* @param[out] thread The handle of the thread
* @param process The ID of the process linked to the thread
*/
Result svcOpenThread(Handle* thread,Handle process, u32 threadId);
/**
* @brief Exits the current thread.
*
* This will trigger a state change and hence release all @ref svcWaitSynchronization operations.
* It means that you can join a thread by calling @code svcWaitSynchronization(threadHandle,yourtimeout); @endcode
*/
void svcExitThread(void) __attribute__((noreturn));
/**
* @brief Puts the current thread to sleep.
* @param ns The minimum number of nanoseconds to sleep for.
*/
void svcSleepThread(s64 ns);
/**
* @brief Retrieves the priority of a thread.
*/
Result svcGetThreadPriority(s32 *out, Handle handle);
/**
* @brief Changes the priority of a thread
* @param prio For userland apps, this has to be withing the range [0x18;0x3F]
*
* Low values gives the thread higher priority.
*/
Result svcSetThreadPriority(Handle thread, s32 prio);
Result svcGetThreadAffinityMask(u8* affinitymask, Handle thread, s32 processorcount);
Result svcSetThreadAffinityMask(Handle thread, u8* affinitymask, s32 processorcount);
Result svcGetThreadIdealProcessor(s32* processorid, Handle thread);
Result svcSetThreadIdealProcessor(Handle thread, s32 processorid);
/**
* @brief Returns the ID of the processor the current thread is running on.
* @sa svcCreateThread
*/
s32 svcGetProcessorID();
/**
* @param out The thread ID of the thread @p handle.
*/
Result svcGetThreadId(u32 *out, Handle handle);
/**
* @param out The process ID of the thread @p handle.
* @sa svcOpenProcess
*/
Result svcGetProcessIdOfThread(u32 *out, Handle handle);
/**
* @brief Checks if a thread handle is valid.
* This requests always return an error when called, it only checks if the handle is a thread or not.
* @return 0xD8E007ED (BAD_ENUM) if the Handle is a Thread Handle
* @return 0xD8E007F7 (BAD_HANDLE) if it isn't.
*/
Result svcGetThreadInfo(s64* out, Handle thread, ThreadInfoType type);
///@}
///@name Synchronization
///@{
Result svcCreateMutex(Handle* mutex, bool initially_locked);
Result svcReleaseMutex(Handle handle);
Result svcCreateSemaphore(Handle* semaphore, s32 initial_count, s32 max_count);
Result svcReleaseSemaphore(s32* count, Handle semaphore, s32 release_count);
Result svcCreateEvent(Handle* event, u8 reset_type);
Result svcSignalEvent(Handle handle);
Result svcClearEvent(Handle handle);
Result svcWaitSynchronization(Handle handle, s64 nanoseconds);
Result svcWaitSynchronizationN(s32* out, Handle* handles, s32 handles_num, bool wait_all, s64 nanoseconds);
Result svcSendSyncRequest(Handle session);
///@}
///@name Time
///@{
Result svcCreateTimer(Handle* timer, u8 reset_type);
Result svcSetTimer(Handle timer, s64 initial, s64 interval);
Result svcCancelTimer(Handle timer);
Result svcClearTimer(Handle timer);
u64 svcGetSystemTick();
///@}
///@name System
///@{
Result svcCloseHandle(Handle handle);
Result svcDuplicateHandle(Handle* out, Handle original);
Result svcGetSystemInfo(s64* out, u32 type, s32 param);
///@}
///@name Debugging
///@{
Result svcOutputDebugString(const char* str, int length);
Result svcDebugActiveProcess(Handle* debug, u32 processId); Result svcDebugActiveProcess(Handle* debug, u32 processId);
Result svcBreakDebugProcess(Handle debug); Result svcBreakDebugProcess(Handle debug);
Result svcTerminateDebugProcess(Handle debug); Result svcTerminateDebugProcess(Handle debug);
Result svcGetProcessDebugEvent(DebugEventInfo* info, Handle debug); Result svcGetProcessDebugEvent(DebugEventInfo* info, Handle debug);
Result svcContinueDebugEvent(Handle debug, u32 flags); Result svcContinueDebugEvent(Handle debug, u32 flags);
Result svcGetProcessList(s32* processCount, u32* processIds, s32 processIdMaxCount); ///@}
Result svcReadProcessMemory(void* buffer, Handle debug, u32 addr, u32 size);
Result svcWriteProcessMemory(Handle debug, const void* buffer, u32 addr, u32 size);
Result svcControlProcessMemory(Handle process, u32 addr0, u32 addr1, u32 size, u32 type, u32 perm);
Result svcMapProcessMemory(Handle process, u32 startAddr, u32 endAddr);
Result svcUnmapProcessMemory(Handle process, u32 startAddr, u32 endAddr);
Result svcBackdoor(s32 (*callback)(void)); Result svcBackdoor(s32 (*callback)(void));
Result svcQueryProcessMemory(MemInfo* info, PageInfo* out, Handle process, u32 addr);