diff --git a/crt0/switch_crt0.s b/crt0/switch_crt0.s index ea16ae9a..8a942ee0 100644 --- a/crt0/switch_crt0.s +++ b/crt0/switch_crt0.s @@ -1,5 +1,5 @@ .section ".crt0","ax" -.global _start, _sysexit, main +.global _start _start: bl startup @@ -40,7 +40,8 @@ got_loop: subs x1, x1, #8 bne got_loop - ldr x3, =heapSetup + mov x0, x28 + ldr x3, =initSystem add x3, x3, x28 blr x3 @@ -49,7 +50,8 @@ got_loop: ldr x3, =main add x3, x3, x28 - blr x3 + ldr x2, =__nx_exit + add x2, x2, x28 + mov x30, x2 + br x3 -_sysexit: - svc 0x7 diff --git a/nx/Makefile b/nx/Makefile index 3fd2b632..93569f36 100644 --- a/nx/Makefile +++ b/nx/Makefile @@ -24,7 +24,7 @@ VERSION := $(LIBNX_MAJOR).$(LIBNX_MINOR).$(LIBNX_PATCH) #--------------------------------------------------------------------------------- TARGET := nx #BUILD := build -SOURCES := source/kernel source/services source/heap +SOURCES := source/system source/kernel source/services source/heap DATA := data INCLUDES := include diff --git a/nx/include/switch/svc.h b/nx/include/switch/svc.h index 03cc803f..e1e0ccce 100644 --- a/nx/include/switch/svc.h +++ b/nx/include/switch/svc.h @@ -18,16 +18,37 @@ static inline void* armGetTls(void) { return ret; } +typedef struct _regs_t +{ + u64 X0; + u64 X1; + u64 X2; + u64 X3; + u64 X4; + u64 X5; + u64 X6; + u64 X7; +} __attribute__((packed)) regs_t; + Result svcSetHeapSize(void** out_addr, u64 size); Result svcQueryMemory(u32 *meminfo_ptr, u32 *pageinfo, u64 addr); +void svcExitProcess() __attribute__((noreturn)); +Result svcSleepThread(u64 nano); Result svcCloseHandle(Handle handle); Result svcCreateTransferMemory(Handle* out, void* addr, size_t size, u32 perm); Result svcWaitSynchronization(s32* index, const Handle* handles, s32 handleCount, u64 timeout); Result svcConnectToNamedPort(Handle* session, const char* name); Result svcSendSyncRequest(Handle session); Result svcBreak(u32 breakReason, u64 inval1, u64 inval2); +Result svcGetInfo(u64* out, u64 id0, Handle handle, u64 id1); Result svcAcceptSession(Handle *session_handle, Handle port_handle); Result svcReplyAndReceive(s32* index, const Handle* handles, s32 handleCount, Handle replyTarget, u64 timeout); 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); +Result svcAttachDeviceAddressSpace(u64 device, Handle handle); +Result svcDetachDeviceAddressSpace(u64 device, Handle handle); +Result svcMapDeviceAddressSpaceAligned(Handle handle, Handle proc_handle, u64 dev_addr, u64 dev_size, u64 map_addr, u64 perm); +Result svcUnmapDeviceAddressSpace(Handle handle, Handle proc_handle, u64 map_addr, u64 map_size, u64 perm); +u64 svcCallSecureMonitor(regs_t *regs); Result svcManageNamedPort(Handle* portServer, const char* name, s32 maxSessions); diff --git a/nx/source/heap/heap.c b/nx/source/heap/heap.c index b165251e..f0558256 100644 --- a/nx/source/heap/heap.c +++ b/nx/source/heap/heap.c @@ -32,16 +32,18 @@ void heapInit(void* base, size_t size) { void heapSetup() { // Called by crt0. + #define INNER_HEAP_SIZE 0x20000 + #define OUTER_HEAP_SIZE (0x2000000*4) + void* addr; - Result rc = svcSetHeapSize(&addr, 0x2000000); + Result rc = svcSetHeapSize(&addr, OUTER_HEAP_SIZE); if (R_SUCCEEDED(rc)) { - heapInit(addr, 0x2000000); + heapInit(addr, OUTER_HEAP_SIZE); } else { - #define HEAP_SIZE 0x20000 - static u8 g_Heap[HEAP_SIZE]; - heapInit(&g_Heap[0], HEAP_SIZE); + static u8 g_Heap[INNER_HEAP_SIZE]; + heapInit(&g_Heap[0], INNER_HEAP_SIZE); } } diff --git a/nx/source/kernel/svc.s b/nx/source/kernel/svc.s index 7476efd7..564765d4 100644 --- a/nx/source/kernel/svc.s +++ b/nx/source/kernel/svc.s @@ -13,7 +13,7 @@ SVC_BEGIN svcSetHeapSize str x0, [sp, #-16]! - svc 1 + svc 0x1 ldr x2, [sp], #16 str x1, [x2] ret @@ -27,6 +27,16 @@ SVC_BEGIN svcQueryMemory ret SVC_END +SVC_BEGIN svcExitProcess + svc 0x7 + ret +SVC_END + +SVC_BEGIN svcSleepThread + svc 0xB + ret +SVC_END + SVC_BEGIN svcCloseHandle svc 0x16 ret @@ -50,7 +60,7 @@ SVC_END SVC_BEGIN svcConnectToNamedPort str x0, [sp, #-16]! - svc 0x1f + svc 0x1F ldr x2, [sp], #16 str w1, [x2] ret @@ -66,6 +76,14 @@ SVC_BEGIN svcBreak ret SVC_END +SVC_BEGIN svcGetInfo + str x0, [sp, #-16]! + svc 0x29 + ldr x2, [sp], #16 + str x1, [x2] + ret +SVC_END + SVC_BEGIN svcAcceptSession str x0, [sp, #-16]! svc 0x41 @@ -100,6 +118,35 @@ SVC_BEGIN svcQueryIoMapping ret SVC_END +SVC_BEGIN svcCreateDeviceAddressSpace + str x0, [sp, #-16]! + svc 0x56 + ldr x2, [sp] + str w1, [x2] + add sp, sp, #0x10 + ret +SVC_END + +SVC_BEGIN svcAttachDeviceAddressSpace + svc 0x57 + ret +SVC_END + +SVC_BEGIN svcDetachDeviceAddressSpace + svc 0x58 + ret +SVC_END + +SVC_BEGIN svcMapDeviceAddressSpaceAligned + svc 0x5A + ret +SVC_END + +SVC_BEGIN svcUnmapDeviceAddressSpace + svc 0x5C + ret +SVC_END + SVC_BEGIN svcManageNamedPort str x0, [sp, #-16]! svc 0x71 @@ -107,3 +154,21 @@ SVC_BEGIN svcManageNamedPort str w1, [x2] ret SVC_END + +SVC_BEGIN svcCallSecureMonitor + str x0, [sp, #-16]! + mov x8, x0 + ldp x0, x1, [x8] + ldp x2, x3, [x8, #0x10] + ldp x4, x5, [x8, #0x20] + ldp x6, x7, [x8, #0x30] + svc 0x7F + ldr x8, [SP] + stp x0, x1, [x8] + stp x2, x3, [x8, #0x10] + stp x4, x5, [x8, #0x20] + stp x6, x7, [x8, #0x30] + add sp, sp, #0x10 + ret +SVC_END + diff --git a/nx/source/system/appExit.c b/nx/source/system/appExit.c new file mode 100644 index 00000000..8ecf701a --- /dev/null +++ b/nx/source/system/appExit.c @@ -0,0 +1,5 @@ +#include + +void __attribute__((weak)) __appExit(void) { + // Initialize services +} diff --git a/nx/source/system/appInit.c b/nx/source/system/appInit.c new file mode 100644 index 00000000..2d1d1bcb --- /dev/null +++ b/nx/source/system/appInit.c @@ -0,0 +1,5 @@ +#include + +void __attribute__((weak)) __appInit(void) { + // Initialize services +} diff --git a/nx/source/system/initSystem.c b/nx/source/system/initSystem.c new file mode 100644 index 00000000..f8f76847 --- /dev/null +++ b/nx/source/system/initSystem.c @@ -0,0 +1,18 @@ +#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 new file mode 100644 index 00000000..68fadb7a --- /dev/null +++ b/nx/source/system/nx_exit.c @@ -0,0 +1,7 @@ +#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 new file mode 100644 index 00000000..99ede0a1 --- /dev/null +++ b/nx/source/system/syscalls.c @@ -0,0 +1,46 @@ +#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 new file mode 100644 index 00000000..72a6f833 --- /dev/null +++ b/nx/source/system/sysinit.s @@ -0,0 +1,99 @@ + .text + .global initSystem + .type initSystem, %function + +initSystem: + stp x29, x30, [sp, #-16]! + adr x1, __nx_binarybase + str x0, [x1] + bl __libnx_init + + bl __appInit + bl __nx_libc_init_array + ldp x29, x30, [sp], #16 + ret + + .global __nx_exit + .type __nx_exit, %function + +__nx_exit: + bl __nx_libc_fini_array + bl __appExit + + b __libnx_exit + +__nx_libc_init_array: + stp x29, x30, [sp, #-16]! + stp x21, x22, [sp, #-16]! + stp x19, x20, [sp, #-16]! + adr x3, __nx_binarybase + ldr x20, [x3] + + ldr x0, =__preinit_array_start + ldr x1, =__preinit_array_end + sub x1, x1, x0 + add x21, x0, x20 + lsr x19, x1, #3 + cbz x19, __nx_libc_init_array_end0 + + __nx_libc_init_array_lp0: + ldr x3, [x21], #8 + sub x19, x19, #1 + add x3, x3, x20 + blr x3 + cbnz x19, __nx_libc_init_array_lp0 + +__nx_libc_init_array_end0: + bl _init + + ldr x0, =__init_array_start + ldr x1, =__init_array_end + sub x1, x1, x0 + add x21, x0, x20 + lsr x19, x1, #3 + cbz x19, __nx_libc_init_array_end1 + + __nx_libc_init_array_lp1: + ldr x3, [x21], #8 + sub x19, x19, #1 + add x3, x3, x20 + blr x3 + cbnz x19, __nx_libc_init_array_lp1 + +__nx_libc_init_array_end1: + ldp x19, x20, [sp], #16 + ldp x21, x22, [sp], #16 + ldp x29, x30, [sp], #16 + ret + +__nx_libc_fini_array: + stp x29, x30, [sp, #-16]! + stp x21, x22, [sp, #-16]! + stp x19, x20, [sp, #-16]! + adr x3, __nx_binarybase + ldr x20, [x3] + + ldr x0, =__fini_array_start + ldr x1, =__fini_array_end + sub x1, x1, x0 + add x21, x0, x20 + lsr x19, x1, #3 + cbz x19, __nx_libc_fini_array_end + + __nx_libc_fini_array_lp: + sub x19, x19, #1 + ldr x3, [x21, x19, lsl #3] + add x3, x3, x20 + blr x3 + cbnz x19, __nx_libc_fini_array_lp + +__nx_libc_fini_array_end: + ldp x19, x20, [sp], #16 + ldp x21, x22, [sp], #16 + ldp x29, x30, [sp], #16 + ret + + .data +__nx_binarybase: + .dword 0 +