From: fincs Date: Wed, 20 Aug 2014 20:01:50 +0000 (+0200) Subject: Implement initSystem(), __ctru_exit() and __system_argc/argv X-Git-Tag: v0.2.0~134 X-Git-Url: https://chaos.moe/g/?a=commitdiff_plain;h=a90ee009f835837e988e9a4b1565be316e6fa102;p=corbenik%2Fctrulib.git Implement initSystem(), __ctru_exit() and __system_argc/argv --- diff --git a/libctru/source/initSystem.c b/libctru/source/initSystem.c new file mode 100644 index 0000000..1f51c03 --- /dev/null +++ b/libctru/source/initSystem.c @@ -0,0 +1,99 @@ +#include +#include <3ds/types.h> +#include <3ds/svc.h> +#include + +// System globals we define here +int __system_argc; +char** __system_argv; +void (*__system_retAddr)(void); + +// Data from _prm structure +extern void* __service_ptr; // used to detect if we're run from a homebrew launcher +extern u32 __heap_size; +extern const char* __system_arglist; + +// newlib definitions we need +void __libc_fini_array(); +extern char* fake_heap_start; +extern char* fake_heap_end; + +static void initArgv(); + +void __ctru_exit(int rc) +{ + // Run the global destructors + __libc_fini_array(); + + // TODO: APT exit goes here + + // Unmap the heap + u32 blockAddr; + svcControlMemory(&blockAddr, 0x08000000, 0x0, __heap_size, MEMOP_FREE, 0x0); + + // Jump to the loader if it provided a callback + if (__system_retAddr) + __system_retAddr(); + + // Since above did not jump: hang + for (;;); +} + +void initSystem(void (*retAddr)(void)) +{ + // Register newlib exit() syscall + __syscalls.exit = __ctru_exit; + __system_retAddr = __service_ptr ? retAddr : NULL; + + // Allocate the application heap + u32 blockAddr; + svcControlMemory(&blockAddr, 0x08000000, 0x0, __heap_size, MEMOP_ALLOC, 0x3); + + // Set up newlib heap + fake_heap_start = (char*)0x08000000; + fake_heap_end = fake_heap_start + __heap_size; + + // Build argc/argv if present + initArgv(); + + // TODO: APT init goes here +} + +void initArgv() +{ + int i; + const char* temp = __system_arglist; + + // Check if the argument list is present + if (!temp) + return; + + // Retrieve argc + __system_argc = *(u32*)temp; + temp += sizeof(u32); + + // Find the end of the argument data + for (i = 0; i < __system_argc; i ++) + { + for (; *temp; temp ++); + temp ++; + } + + // Reserve heap memory for argv data + u32 argSize = temp - __system_arglist - sizeof(u32); + __system_argv = (char**)fake_heap_start; + fake_heap_start += sizeof(char**)*(__system_argc + 1); + char* argCopy = fake_heap_start; + fake_heap_start += argSize; + + // Fill argv array + memcpy(argCopy, __system_arglist, argSize); + temp = argCopy; + for (i = 0; i < __system_argc; i ++) + { + __system_argv[i] = (char*)temp; + for (; *temp; temp ++); + temp ++; + } + __system_argv[__system_argc] = NULL; +}