From 3926969ebc2924f9902982b381c76b065912dfa0 Mon Sep 17 00:00:00 2001 From: plutoo Date: Sat, 7 Oct 2017 15:32:08 +0200 Subject: [PATCH] Minor changes * Refactored system/* * Implemented all of tmem * Introduced virtmem --- crt0/switch_crt0.s | 6 +- nx/include/switch.h | 1 + nx/include/switch/kernel/tmem.h | 20 ++++--- nx/include/switch/kernel/virtmem.h | 2 + nx/include/switch/result.h | 6 +- nx/include/switch/svc.h | 11 ++-- nx/include/switch/types.h | 12 ++++ nx/source/kernel/svc.s | 10 ++++ nx/source/kernel/tmem.c | 95 +++++++++++++++++++++++++++--- nx/source/kernel/virtmem.c | 21 +++++++ nx/source/services/fatal.c | 2 +- nx/source/services/sm.c | 12 ++-- nx/source/system/appExit.c | 7 --- nx/source/system/appInit.c | 7 --- nx/source/system/dynamic.c | 2 +- nx/source/system/init.c | 62 +++++++++++++++++++ nx/source/system/initSystem.c | 18 ------ nx/source/system/nx_exit.c | 7 --- nx/source/system/syscalls.c | 46 --------------- nx/source/system/sysinit.s | 19 ------ 20 files changed, 225 insertions(+), 141 deletions(-) create mode 100644 nx/include/switch/kernel/virtmem.h create mode 100644 nx/source/kernel/virtmem.c delete mode 100644 nx/source/system/appExit.c delete mode 100644 nx/source/system/appInit.c create mode 100644 nx/source/system/init.c delete mode 100644 nx/source/system/initSystem.c delete mode 100644 nx/source/system/nx_exit.c delete mode 100644 nx/source/system/syscalls.c delete mode 100644 nx/source/system/sysinit.s diff --git a/crt0/switch_crt0.s b/crt0/switch_crt0.s index ced5c18f..e90897b6 100644 --- a/crt0/switch_crt0.s +++ b/crt0/switch_crt0.s @@ -31,11 +31,11 @@ bss_loop: // initialize system mov x0, x28 - bl __nx_init + bl __libnx_init // call entrypoint mov x0, #0 // argc mov x1, #0 // argv - adrp x30, __nx_exit - add x30, x30, #:lo12:__nx_exit + adrp x30, __libnx_exit + add x30, x30, #:lo12:__libnx_exit b main diff --git a/nx/include/switch.h b/nx/include/switch.h index 21cc17d3..c6826efa 100644 --- a/nx/include/switch.h +++ b/nx/include/switch.h @@ -16,6 +16,7 @@ extern "C" { #include #include +#include #include #include diff --git a/nx/include/switch/kernel/tmem.h b/nx/include/switch/kernel/tmem.h index 49822696..0f571059 100644 --- a/nx/include/switch/kernel/tmem.h +++ b/nx/include/switch/kernel/tmem.h @@ -1,14 +1,16 @@ typedef struct { - Handle MemHandle; - size_t Size; + Handle MemHandle; + size_t Size; + Permission Perm; + void* SourceAddr; + void* MappedAddr; } TransferMemory; -typedef enum { - PERM_NONE = 0, - PERM_R = 1, - PERM_RW = 3 -} Permission; - Result tmemCreate(TransferMemory* t, size_t size, Permission perm); -Result tmemClose(TransferMemory* t); +void tmemLoadRemote(TransferMemory* t, Handle handle, size_t size, Permission perm); +Result tmemMap(TransferMemory* t); +Result tmemUnmap(TransferMemory* t); +void* tmemGetAddr(TransferMemory* t); + +Result tmemClose(TransferMemory* t); diff --git a/nx/include/switch/kernel/virtmem.h b/nx/include/switch/kernel/virtmem.h new file mode 100644 index 00000000..b7745e33 --- /dev/null +++ b/nx/include/switch/kernel/virtmem.h @@ -0,0 +1,2 @@ +void* virtmemReserve(size_t size); +void virtmemFree(void* addr, size_t size); diff --git a/nx/include/switch/result.h b/nx/include/switch/result.h index b9bd081a..ea7b475f 100644 --- a/nx/include/switch/result.h +++ b/nx/include/switch/result.h @@ -18,5 +18,7 @@ #define MAKERESULT(module,description) \ ((((module)&0x1FF)) | ((description)&0x1FFF)<<9) -#define MODULE_LIBNX 345 -#define MODULE_BADRELOC 1 +#define MODULE_LIBNX 345 +#define LIBNX_BADRELOC 1 +#define LIBNX_OUTOFMEM 2 +#define LIBNX_ALREADYMAPPED 3 diff --git a/nx/include/switch/svc.h b/nx/include/switch/svc.h index 785e6235..a8439775 100644 --- a/nx/include/switch/svc.h +++ b/nx/include/switch/svc.h @@ -29,8 +29,7 @@ typedef struct { u32 padding; } MemInfo; -typedef struct _regs_t -{ +typedef struct { u64 X0; u64 X1; u64 X2; @@ -39,11 +38,11 @@ typedef struct _regs_t u64 X5; u64 X6; u64 X7; -} __attribute__((packed)) regs_t; +} __attribute__((packed)) SecmonArgs; Result svcSetHeapSize(void** out_addr, u64 size); Result svcQueryMemory(MemInfo* meminfo_ptr, u32 *pageinfo, u64 addr); -void svcExitProcess() __attribute__((noreturn)); +void NORETURN svcExitProcess(); Result svcSleepThread(u64 nano); Result svcCloseHandle(Handle handle); Result svcCreateTransferMemory(Handle* out, void* addr, size_t size, u32 perm); @@ -57,6 +56,8 @@ Result svcGetInfo(u64* out, u64 id0, Handle handle, u64 id1); Result svcCreateSession(Handle *server_handle, Handle *client_handle, u32 unk0, u64 unk1);//unk* are normally 0? Result svcAcceptSession(Handle *session_handle, Handle port_handle); Result svcReplyAndReceive(s32* index, const Handle* handles, s32 handleCount, Handle replyTarget, u64 timeout); +Result svcMapTransferMemory(Handle tmem_handle, void* addr, size_t size, u32 perm); +Result svcUnmapTransferMemory(Handle tmem_handle, void* addr, size_t size); Result svcQueryPhysicalAddress(u64 out[3], u64 virtaddr); Result svcQueryIoMapping(u64* virtaddr, u64 physaddr, u64 size); Result svcCreateDeviceAddressSpace(Handle *handle, u64 dev_addr, u64 dev_size); @@ -69,4 +70,4 @@ Result svcContinueDebugEvent(Handle debug, u32 flags, u64 unk); Result svcQueryDebugProcessMemory(MemInfo* meminfo_ptr, u32* pageinfo, Handle debug, u64 addr); Result svcReadDebugProcessMemory(void* buffer, Handle debug, u64 addr, u64 size); Result svcManageNamedPort(Handle* portServer, const char* name, s32 maxSessions); -u64 svcCallSecureMonitor(regs_t *regs); +u64 svcCallSecureMonitor(SecmonArgs* regs); diff --git a/nx/include/switch/types.h b/nx/include/switch/types.h index 91c5c4b6..b31bfa38 100644 --- a/nx/include/switch/types.h +++ b/nx/include/switch/types.h @@ -43,6 +43,14 @@ typedef u32 Result; ///< Function result. typedef void (*ThreadFunc)(void *); ///< Thread entrypoint function. typedef void (*voidfn)(void); +typedef enum { + PERM_NONE = 0, + PERM_R = 1, + PERM_W = 2, + PERM_RW = PERM_R | PERM_W, + PERM_DONTCARE = 0x10000000 +} Permission; + /// Creates a bitmask from a bit number. #define BIT(n) (1U<<(n)) @@ -51,6 +59,9 @@ typedef void (*voidfn)(void); /// Packs a struct (and other types?) so it won't include padding bytes. #define PACKED __attribute__((packed)) +#define NORETURN __attribute__((noreturn)) +#define IGNORE_ARG(x) (void)(x) + #ifndef LIBCTRU_NO_DEPRECATION /// Flags a function as deprecated. #define DEPRECATED __attribute__ ((deprecated)) @@ -59,3 +70,4 @@ typedef void (*voidfn)(void); #define DEPRECATED #endif +#define INVALID_HANDLE ((Handle) -1) diff --git a/nx/source/kernel/svc.s b/nx/source/kernel/svc.s index 90aa21c6..a0bd10e7 100644 --- a/nx/source/kernel/svc.s +++ b/nx/source/kernel/svc.s @@ -118,6 +118,16 @@ SVC_BEGIN svcReplyAndReceive ret SVC_END +SVC_BEGIN svcMapTransferMemory + svc 0x51 + ret +SVC_END + +SVC_BEGIN svcUnmapTransferMemory + svc 0x52 + ret +SVC_END + SVC_BEGIN svcQueryPhysicalAddress str x0, [sp, #-16]! svc 0x54 diff --git a/nx/source/kernel/tmem.c b/nx/source/kernel/tmem.c index 3a8aca08..e2c05b5e 100644 --- a/nx/source/kernel/tmem.c +++ b/nx/source/kernel/tmem.c @@ -1,21 +1,98 @@ +// Copyright 2017 plutoo #include -Result tmemCreate(TransferMemory* t, size_t size, Permission perm) { - t->Size = size; - +Result tmemCreate(TransferMemory* t, size_t size, Permission perm) +{ Result rc = 0; - void* addr = heapAllocPages(size); - if (addr == NULL) - rc = -1; + t->MemHandle = INVALID_HANDLE; + t->Size = size; + t->Perm = perm; + t->MappedAddr = NULL; + t->SourceAddr = heapAllocPages(size); + + if (t->SourceAddr == NULL) { + rc = MAKERESULT(MODULE_LIBNX, LIBNX_OUTOFMEM); + } if (R_SUCCEEDED(rc)) { - rc = svcCreateTransferMemory(&t->MemHandle, addr, size, perm); + rc = svcCreateTransferMemory(&t->MemHandle, t->SourceAddr, size, perm); } return rc; } -Result tmemClose(TransferMemory* t) { - return svcCloseHandle(t->MemHandle); +void tmemLoadRemote(TransferMemory* t, Handle handle, size_t size, Permission perm) +{ + t->MemHandle = handle; + t->Size = size; + t->Perm = perm; + t->MappedAddr = NULL; + t->SourceAddr = NULL; +} + +Result tmemMap(TransferMemory* t) +{ + Result rc = 0; + + if (t->MappedAddr == NULL) + { + void* addr = virtmemReserve(t->Size); + + rc = svcMapTransferMemory(t->MemHandle, addr, t->Size, t->Perm); + + if (R_SUCCEEDED(rc)) { + t->MappedAddr = addr; + } + else { + virtmemFree(addr, t->Size); + } + } + else { + rc = LIBNX_ALREADYMAPPED; + } + + return rc; +} + +Result tmemUnmap(TransferMemory* t) +{ + Result rc; + + rc = svcUnmapTransferMemory(t->MemHandle, t->MappedAddr, t->Size); + + if (R_SUCCEEDED(rc)) { + t->MappedAddr = NULL; + } + + return rc; +} + +void* tmemGetAddr(TransferMemory* t) { + return t->MappedAddr; +} + +Result tmemClose(TransferMemory* t) +{ + Result rc = 0; + + if (t->SourceAddr != NULL) { + // todo: Free is currently broken for page-aligned allocs. + //heapFree(t->SourceAddr); + } + + if (t->MappedAddr != NULL) { + rc = tmemUnmap(t); + } + + if (R_SUCCEEDED(rc)) { + if (t->MemHandle != INVALID_HANDLE) { + rc = svcCloseHandle(t->MemHandle); + } + + t->SourceAddr = NULL; + t->MemHandle = INVALID_HANDLE; + } + + return rc; } diff --git a/nx/source/kernel/virtmem.c b/nx/source/kernel/virtmem.c new file mode 100644 index 00000000..426eef03 --- /dev/null +++ b/nx/source/kernel/virtmem.c @@ -0,0 +1,21 @@ +#include + +static u8* g_VirtBase; + +void virtmemSetup() { + // TODO: Implement this. +} + +void* virtmemReserve(size_t size) { + void* ret = g_VirtBase; + + size = (size + 0xFFF) &~ 0xFFF; + g_VirtBase += size + 0x1000; + + return ret; +} + +void virtmemFree(void* addr, size_t size) { + (void) addr; + (void) size; +} diff --git a/nx/source/services/fatal.c b/nx/source/services/fatal.c index d99e23ff..2e5f8e73 100644 --- a/nx/source/services/fatal.c +++ b/nx/source/services/fatal.c @@ -27,7 +27,7 @@ void fatalSimple(Result err) { raw = ipcPrepareHeader(&c, sizeof(*raw)); raw->magic = SFCI_MAGIC; - raw->cmd_id = 1; + raw->cmd_id = 0; raw->result = err; raw->unknown = 0; diff --git a/nx/source/services/sm.c b/nx/source/services/sm.c index 4f2284da..095979e0 100644 --- a/nx/source/services/sm.c +++ b/nx/source/services/sm.c @@ -49,13 +49,11 @@ Result smInitialize() { return rc; } -void smExit(void) -{ - if(smHasInitialized()) - { - svcCloseHandle(g_smHandle); - g_smHandle = -1; - } +void smExit(void) { + if(smHasInitialized()) { + svcCloseHandle(g_smHandle); + g_smHandle = -1; + } } static u64 _EncodeName(const char* name) { diff --git a/nx/source/system/appExit.c b/nx/source/system/appExit.c deleted file mode 100644 index 3b4d1db2..00000000 --- a/nx/source/system/appExit.c +++ /dev/null @@ -1,7 +0,0 @@ -#include -#include - -void __attribute__((weak)) __appExit(void) { - // Initialize services - smExit(); -} diff --git a/nx/source/system/appInit.c b/nx/source/system/appInit.c deleted file mode 100644 index d018eeb5..00000000 --- a/nx/source/system/appInit.c +++ /dev/null @@ -1,7 +0,0 @@ -#include -#include - -void __attribute__((weak)) __appInit(void) { - // Initialize services - smInitialize(); -} diff --git a/nx/source/system/dynamic.c b/nx/source/system/dynamic.c index e693cffa..5f27a662 100644 --- a/nx/source/system/dynamic.c +++ b/nx/source/system/dynamic.c @@ -20,7 +20,7 @@ void __nx_dynamic(uintptr_t base, const Elf64_Dyn* dyn) } if (rela == NULL) - fatalSimple(MAKERESULT(MODULE_LIBNX, MODULE_BADRELOC)); + fatalSimple(MAKERESULT(MODULE_LIBNX, LIBNX_BADRELOC)); for (; relasz--; rela++) { diff --git a/nx/source/system/init.c b/nx/source/system/init.c new file mode 100644 index 00000000..01e8dd37 --- /dev/null +++ b/nx/source/system/init.c @@ -0,0 +1,62 @@ +#include + +#include +#include +#include +#include +#include + +void __nx_exit(int rc); + +void virtmemSetup(); +void heapSetup(); + +void __attribute__((weak)) __appInit(void) +{ + // Initialize default services. + smInitialize(); +} + +void __attribute__((weak)) __appExit(void) +{ + // Cleanup default services. + smExit(); +} + +void __attribute__((weak)) __libnx_init(void) +{ + // Called by crt0. + + // Newlib initialization goes here. + void exitImpl(int rc); + __syscalls.exit = exitImpl; + + // Libnx initialization goes here. + virtmemSetup(); + heapSetup(); + + // Initialize services. + __appInit(); + + // Call constructors. + void __libc_init_array(void); + __libc_init_array(); +} + +void __attribute__((weak)) NORETURN __libnx_exit(void) +{ + // Call destructors. + void __libc_fini_array(void); + __libc_fini_array(); + + // Clean up services. + __appExit(); + + svcExitProcess(); + while(1); +} + +void NORETURN exitImpl(int rc) +{ + __libnx_exit(); +} diff --git a/nx/source/system/initSystem.c b/nx/source/system/initSystem.c deleted file mode 100644 index f8f76847..00000000 --- a/nx/source/system/initSystem.c +++ /dev/null @@ -1,18 +0,0 @@ -#include -#include -#include - -#include -#include - -void __system_initSyscalls(void); - -void heapSetup(); - -void __attribute__((weak)) __libnx_init(void) -{ - // Initialize newlib support system calls - __system_initSyscalls(); - - heapSetup(); -} diff --git a/nx/source/system/nx_exit.c b/nx/source/system/nx_exit.c deleted file mode 100644 index 68fadb7a..00000000 --- a/nx/source/system/nx_exit.c +++ /dev/null @@ -1,7 +0,0 @@ -#include -#include - -void __attribute__((weak)) __attribute__((noreturn)) __libnx_exit(int rc) -{ - svcExitProcess(); -} diff --git a/nx/source/system/syscalls.c b/nx/source/system/syscalls.c deleted file mode 100644 index 99ede0a1..00000000 --- a/nx/source/system/syscalls.c +++ /dev/null @@ -1,46 +0,0 @@ -#include -#include -#include -#include -#include - -#include -#include - -void __nx_exit(int rc); - -//TODO -/*extern const u8 __tdata_lma[]; -extern const u8 __tdata_lma_end[]; -extern u8 __tls_start[]; - -static struct _reent* __nx_get_reent() -{ - ThreadVars* tv = getThreadVars(); - if (tv->magic != THREADVARS_MAGIC) - { - svcBreak(USERBREAK_PANIC); - for (;;); - } - return tv->reent; -} -*/ - -void __system_initSyscalls(void) -{ - // Register newlib syscalls - __syscalls.exit = __nx_exit; - //__syscalls.getreent = __nx_get_reent; - - // Initialize thread vars for the main thread (TODO) - /*ThreadVars* tv = getThreadVars(); - tv->magic = THREADVARS_MAGIC; - tv->reent = _impure_ptr; - tv->thread_ptr = NULL; - tv->tls_tp = __tls_start-8; // ARM ELF TLS ABI mandates an 8-byte header - - u32 tls_size = __tdata_lma_end - __tdata_lma; - if (tls_size) - memcpy(__tls_start, __tdata_lma, tls_size);*/ -} - diff --git a/nx/source/system/sysinit.s b/nx/source/system/sysinit.s deleted file mode 100644 index 200c0fb1..00000000 --- a/nx/source/system/sysinit.s +++ /dev/null @@ -1,19 +0,0 @@ - .text - .global __nx_init - .type __nx_init, %function - -__nx_init: - stp x29, x30, [sp, #-16]! - bl __libnx_init - bl __appInit - bl __libc_init_array - ldp x29, x30, [sp], #16 - ret - - .global __nx_exit - .type __nx_exit, %function - -__nx_exit: - bl __libc_fini_array - bl __appExit - b __libnx_exit