#include <3ds/synchronization.h>
#include <3ds/gfx.h>
#include <3ds/console.h>
+#include <3ds/env.h>
#include <3ds/util/utf.h>
#include <3ds/allocator/linear.h>
--- /dev/null
+/**
+ * @file env.h
+ * @brief Homebrew environment information.
+ */
+#pragma once
+
+/// System run-flags.
+enum {
+ RUNFLAG_APTWORKAROUND = BIT(0), ///< Use APT workaround.
+ RUNFLAG_APTREINIT = BIT(1), ///< Reinitialize APT.
+};
+
+/**
+ * @brief Gets whether the application was launched from a homebrew environment.
+ * @return Whether the application was launched from a homebrew environment.
+ */
+static inline bool envIsHomebrew(void) {
+ extern void* __service_ptr;
+ return __service_ptr != NULL;
+}
+
+/**
+ * @brief Retrieves a handle from the environment handle list.
+ * @param name Name of the handle.
+ * @return The retrieved handle.
+ */
+Handle envGetHandle(const char* name);
+
+/**
+ * @brief Gets the environment-recommended app ID to use with APT.
+ * @return The APT app ID.
+ */
+static inline u32 envGetAptAppId(void) {
+ extern u32 __apt_appid;
+ return __apt_appid;
+}
+
+/**
+ * @brief Gets the environment-recommended heap size.
+ * @return The heap size.
+ */
+static inline u32 envGetHeapSize(void) {
+ extern u32 __heap_size;
+ return __heap_size;
+}
+
+/**
+ * @brief Gets the environment-recommended linear heap size.
+ * @return The linear heap size.
+ */
+static inline u32 envGetLinearHeapSize(void) {
+ extern u32 __linear_heap_size;
+ return __linear_heap_size;
+}
+
+/**
+ * @brief Gets the environment argument list.
+ * @return The argument list.
+ */
+static inline const char* envGetSystemArgList(void) {
+ extern const char* __system_arglist;
+ return __system_arglist;
+}
+
+/**
+ * @brief Gets the environment run flags.
+ * @return The run flags.
+ */
+static inline u32 envGetSystemRunFlags(void) {
+ extern u32 __system_runflags;
+ return __system_runflags;
+}
*/
#pragma once
-// TODO: find a better place to put this
-/// APT workaround flag.
-#define RUNFLAG_APTWORKAROUND (BIT(0))
-/// APT reinititalize flag.
-#define RUNFLAG_APTREINIT (BIT(1))
-
/**
* @brief NS Application IDs.
*
Result srvInit(void);
/// Exits the service API.
-Result srvExit(void);
+void srvExit(void);
/**
* @brief Gets the current service API session handle.
Handle *srvGetSessionHandle(void);
/**
- * @brief Retrieves a service handle, retrieving from the launcher handle list if possible.
+ * @brief Retrieves a service handle, retrieving from the environment handle list if possible.
* @param out Pointer to write the handle to.
* @param name Name of the service.
*/
#include "mem_pool.h"
#include "addrmap.h"
-extern u32 __linear_heap, __linear_heap_size;
+extern u32 __ctru_linear_heap;
+extern u32 __ctru_linear_heap_size;
static MemPool sLinearPool;
static bool linearInit()
{
- auto blk = MemBlock::Create((u8*)__linear_heap, __linear_heap_size);
+ auto blk = MemBlock::Create((u8*)__ctru_linear_heap, __ctru_linear_heap_size);
if (blk)
{
sLinearPool.AddBlock(blk);
--- /dev/null
+#include <3ds/types.h>
+#include <3ds/svc.h>
+#include <3ds/env.h>
+
+/*
+ The homebrew loader can choose to supply a list of service handles that have
+ been "stolen" from other processes that have been compromised. This allows us
+ to access services that are normally restricted from the current process.
+
+ For every service requested by the application, we shall first check if the
+ list given to us contains the requested service and if so use it. If we don't
+ find the service in that list, we ask the service manager and hope for the
+ best.
+ */
+
+typedef struct {
+ u32 num;
+
+ struct {
+ char name[8];
+ Handle handle;
+ } services[];
+} service_list_t;
+
+extern void* __service_ptr;
+
+static int __name_cmp(const char* a, const char* b) {
+ u32 i;
+
+ for(i=0; i<8; i++) {
+ if(a[i] != b[i])
+ return 1;
+ if(a[i] == '\0')
+ return 0;
+ }
+
+ return 0;
+}
+
+Handle envGetHandle(const char* name) {
+ if(__service_ptr == NULL)
+ return 0;
+
+ service_list_t* service_list = (service_list_t*) __service_ptr;
+ u32 i, num = service_list->num;
+
+ for(i=0; i<num; i++) {
+ if(__name_cmp(service_list->services[i].name, name) == 0)
+ return service_list->services[i].handle;
+ }
+
+ return 0;
+}
+
+void envDestroyHandles(void) {
+ if(__service_ptr == NULL)
+ return;
+
+ service_list_t* service_list = (service_list_t*) __service_ptr;
+ u32 i, num = service_list->num;
+
+ for(i=0; i<num; i++)
+ svcCloseHandle(service_list->services[i].handle);
+
+ service_list->num = 0;
+}
+
GX_ProcessCommandList(gpuCmdBuf, gpuCmdBufOffset*4, GX_CMDLIST_FLUSH);
}
-extern u32 __linear_heap_size;
-extern u32 __linear_heap;
+extern u32 __ctru_linear_heap;
+extern u32 __ctru_linear_heap_size;
void GPUCMD_FlushAndRun(void)
{
//take advantage of GX_FlushCacheRegions to flush gsp heap
- GX_FlushCacheRegions(gpuCmdBuf, gpuCmdBufOffset*4, (u32 *) __linear_heap, __linear_heap_size, NULL, 0);
+ GX_FlushCacheRegions(gpuCmdBuf, gpuCmdBufOffset*4, (u32 *) __ctru_linear_heap, __ctru_linear_heap_size, NULL, 0);
GX_ProcessCommandList(gpuCmdBuf, gpuCmdBufOffset*4, 0x0);
}
#include "ndsp-internal.h"
#include <3ds/services/cfgu.h>
#include <3ds/services/fs.h>
+#include <3ds/env.h>
#define NDSP_THREAD_STACK_SIZE 0x1000
static bool ndspFindAndLoadComponent(void)
{
- extern Handle __get_handle_from_list(const char* name);
Result rc;
Handle rsrc;
void* bin;
} while (0);
// Try loading the DSP component from hb:ndsp
- rsrc = __get_handle_from_list("hb:ndsp");
+ rsrc = envGetHandle("hb:ndsp");
if (rsrc) do
{
extern u32 fake_heap_end;
#include <3ds/romfs.h>
#include <3ds/services/fs.h>
#include <3ds/util/utf.h>
+#include <3ds/env.h>
static bool romFS_active;
static Handle romFS_file;
static u32 *dirHashTable, *fileHashTable;
static void *dirTable, *fileTable;
-extern u32 __service_ptr;
extern int __system_argc;
extern char** __system_argv;
Result romfsInit(void)
{
if (romFS_active) return 0;
- if (__service_ptr)
+ if (envIsHomebrew())
{
// RomFS appended to a 3DSX file
if (__system_argc == 0 || !__system_argv[0]) return 1;
#include <3ds/services/apt.h>
#include <3ds/services/gspgpu.h>
#include <3ds/ipc.h>
-
+#include <3ds/env.h>
#define APT_HANDLER_STACKSIZE (0x1000)
-//TODO : better place to put this ?
-extern u32 __apt_appid;
-extern u32 __system_runflags;
-
NS_APPID currentAppId;
static const char *__apt_servicestr;
static bool aptIsReinit(void)
{
- return (__system_runflags & RUNFLAG_APTREINIT) != 0;
+ return (envGetSystemRunFlags() & RUNFLAG_APTREINIT) != 0;
}
static bool aptIsCrippled(void)
{
- return (__system_runflags & RUNFLAG_APTWORKAROUND) != 0 && !aptIsReinit();
+ return (envGetSystemRunFlags() & RUNFLAG_APTWORKAROUND) != 0 && !aptIsReinit();
}
static Result __apt_initservicehandle(void)
if(R_FAILED(ret=APT_GetLockHandle(0x0, &aptLockHandle))) goto _fail;
svcCloseHandle(aptuHandle);
- currentAppId = __apt_appid;
+ currentAppId = envGetAptAppId();
svcCreateEvent(&aptStatusEvent, 0);
svcCreateEvent(&aptSleepSync, 0);
#include <3ds/synchronization.h>
#include <3ds/services/fs.h>
#include <3ds/ipc.h>
+#include <3ds/env.h>
static Handle fsuHandle;
static int fsuRefCount;
-// used to determine whether or not we should do FSUSER_Initialize on fsuHandle
-Handle __get_handle_from_list(char* name);
-
Result fsInit(void)
{
Result ret = 0;
if (AtomicPostIncrement(&fsuRefCount)) return 0;
ret = srvGetServiceHandle(&fsuHandle, "fs:USER");
- if (R_SUCCEEDED(ret) && __get_handle_from_list("fs:USER") == 0)
+ if (R_SUCCEEDED(ret) && envGetHandle("fs:USER") == 0)
{
ret = FSUSER_Initialize();
if (R_FAILED(ret)) svcCloseHandle(fsuHandle);
#include <3ds/synchronization.h>
#include <3ds/services/irrst.h>
#include <3ds/ipc.h>
-
-// used to determine whether or not we should do IRRST_Initialize
-Handle __get_handle_from_list(char* name);
+#include <3ds/env.h>
Handle irrstHandle;
Handle irrstMemHandle;
if(R_FAILED(ret=IRRST_GetHandles(&irrstMemHandle, &irrstEvent))) goto cleanup1;
// Initialize ir:rst
- if(__get_handle_from_list("ir:rst")==0)ret=IRRST_Initialize(10, 0);
+ if(envGetHandle("ir:rst") == 0) ret = IRRST_Initialize(10, 0);
// Map ir:rst shared memory.
irrstSharedMem=(vu32*)mappableAlloc(0x98);
goto cleanup1;
}
- if(R_FAILED(ret=svcMapMemoryBlock(irrstMemHandle, (u32)irrstSharedMem, MEMPERM_READ, 0x10000000)))goto cleanup2;
+ if(R_FAILED(ret = svcMapMemoryBlock(irrstMemHandle, (u32)irrstSharedMem, MEMPERM_READ, 0x10000000))) goto cleanup2;
// Reset internal state.
kHeld = 0;
svcCloseHandle(irrstEvent);
// Unmap ir:rst sharedmem and close handles.
svcUnmapMemoryBlock(irrstMemHandle, (u32)irrstSharedMem);
- if(__get_handle_from_list("ir:rst")==0) IRRST_Shutdown();
+ if(envGetHandle("ir:rst") == 0) IRRST_Shutdown();
svcCloseHandle(irrstMemHandle);
svcCloseHandle(irrstHandle);
#include <3ds/srv.h>
#include <3ds/svc.h>
#include <3ds/ipc.h>
-
-
-/*
- The homebrew loader can choose to supply a list of service handles that have
- been "stolen" from other processes that have been compromised. This allows us
- to access services that are normally restricted from the current process.
-
- For every service requested by the application, we shall first check if the
- list given to us contains the requested service and if so use it. If we don't
- find the service in that list, we ask the service manager and hope for the
- best.
- */
-
-typedef struct {
- u32 num;
-
- struct {
- char name[8];
- Handle handle;
- } services[];
-} service_list_t;
-
-extern service_list_t* __service_ptr;
-
-static int __name_cmp(const char* a, const char* b) {
- u32 i;
-
- for(i=0; i<8; i++) {
- if(a[i] != b[i])
- return 1;
- if(a[i] == '\0')
- return 0;
- }
-
- return 0;
-}
-
-Handle __get_handle_from_list(const char* name) {
- if((u32)__service_ptr == 0)
- return 0;
-
- u32 i, num = __service_ptr->num;
-
- for(i=0; i<num; i++) {
- if(__name_cmp(__service_ptr->services[i].name, name) == 0)
- return __service_ptr->services[i].handle;
- }
-
- return 0;
-}
-
-void __destroy_handle_list(void) {
- if((u32)__service_ptr == 0)
- return;
-
- u32 i, num = __service_ptr->num;
-
- for(i=0; i<num; i++)
- svcCloseHandle(__service_ptr->services[i].handle);
-
- __service_ptr->num = 0;
-}
+#include <3ds/synchronization.h>
+#include <3ds/env.h>
static Handle srvHandle;
+static int srvRefCount;
Result srvInit(void)
{
Result rc = 0;
- if(srvHandle != 0) return rc;
+ if (AtomicPostIncrement(&srvRefCount)) return 0;
- if(R_FAILED(rc = svcConnectToPort(&srvHandle, "srv:"))) return rc;
-
- if(R_FAILED(rc = srvRegisterClient())) {
- svcCloseHandle(srvHandle);
- srvHandle = 0;
- }
+ rc = svcConnectToPort(&srvHandle, "srv:");
+ if (R_FAILED(rc)) goto end;
+ rc = srvRegisterClient();
+end:
+ if (R_FAILED(rc)) srvExit();
return rc;
}
-Result srvExit(void)
+void srvExit(void)
{
- if(srvHandle != 0) svcCloseHandle(srvHandle);
+ if (AtomicDecrement(&srvRefCount)) return;
+ if (srvHandle != 0) svcCloseHandle(srvHandle);
srvHandle = 0;
- return 0;
}
Handle *srvGetSessionHandle(void)
{
/* Look in service-list given to us by loader. If we find find a match,
we return it. */
- Handle h = __get_handle_from_list(name);
+ Handle h = envGetHandle(name);
if(h != 0) {
return svcDuplicateHandle(out, h);
#include <3ds/types.h>
#include <3ds/svc.h>
+#include <3ds/env.h>
extern char* fake_heap_start;
extern char* fake_heap_end;
-u32 __linear_heap;
-u32 __heapBase;
-extern u32 __heap_size, __linear_heap_size;
+u32 __ctru_heap;
+u32 __ctru_heap_size;
+u32 __ctru_linear_heap;
+u32 __ctru_linear_heap_size;
void __attribute__((weak)) __system_allocateHeaps() {
u32 tmp=0;
+ // Retrieve heap sizes.
+ __ctru_heap_size = envGetHeapSize();
+ __ctru_linear_heap_size = envGetLinearHeapSize();
+
// Allocate the application heap
- __heapBase = 0x08000000;
- svcControlMemory(&tmp, __heapBase, 0x0, __heap_size, MEMOP_ALLOC, MEMPERM_READ | MEMPERM_WRITE);
+ __ctru_heap = 0x08000000;
+ svcControlMemory(&tmp, __ctru_heap, 0x0, __ctru_heap_size, MEMOP_ALLOC, MEMPERM_READ | MEMPERM_WRITE);
// Allocate the linear heap
- svcControlMemory(&__linear_heap, 0x0, 0x0, __linear_heap_size, MEMOP_ALLOC_LINEAR, MEMPERM_READ | MEMPERM_WRITE);
+ svcControlMemory(&__ctru_linear_heap, 0x0, 0x0, __ctru_linear_heap_size, MEMOP_ALLOC_LINEAR, MEMPERM_READ | MEMPERM_WRITE);
+
// Set up newlib heap
- fake_heap_start = (char*)__heapBase;
- fake_heap_end = fake_heap_start + __heap_size;
+ fake_heap_start = (char*)__ctru_heap;
+ fake_heap_end = fake_heap_start + __ctru_heap_size;
-}
\ No newline at end of file
+}
#include <3ds/types.h>
#include <3ds/svc.h>
+#include <3ds/env.h>
+
+extern u32 __ctru_heap;
+extern u32 __ctru_heap_size;
+extern u32 __ctru_linear_heap;
+extern u32 __ctru_linear_heap_size;
-extern u32 __linear_heap;
-extern u32 __heapBase;
-extern u32 __heap_size, __linear_heap_size;
extern void (*__system_retAddr)(void);
-void __destroy_handle_list(void);
+void envDestroyHandles(void);
+
void __appExit();
void __libc_fini_array(void);
u32 tmp=0;
// Unmap the linear heap
- svcControlMemory(&tmp, __linear_heap, 0x0, __linear_heap_size, MEMOP_FREE, 0x0);
+ svcControlMemory(&tmp, __ctru_linear_heap, 0x0, __ctru_linear_heap_size, MEMOP_FREE, 0x0);
// Unmap the application heap
- svcControlMemory(&tmp, __heapBase, 0x0, __heap_size, MEMOP_FREE, 0x0);
+ svcControlMemory(&tmp, __ctru_heap, 0x0, __ctru_heap_size, MEMOP_FREE, 0x0);
// Close some handles
- __destroy_handle_list();
+ envDestroyHandles();
if (__sync_fini)
__sync_fini();
#include <3ds/types.h>
+#include <3ds/env.h>
#include <string.h>
// System globals we define here
int __system_argc;
char** __system_argv;
-extern const char* __system_arglist;
extern char* fake_heap_start;
extern char* fake_heap_end;
void __system_initArgv()
{
int i;
- const char* temp = __system_arglist;
+ const char* arglist = envGetSystemArgList();
+ const char* temp = arglist;
// Check if the argument list is present
if (!temp)
}
// Reserve heap memory for argv data
- u32 argSize = temp - __system_arglist - sizeof(u32);
+ u32 argSize = temp - 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[4], argSize);
+ memcpy(argCopy, &arglist[4], argSize);
temp = argCopy;
for (i = 0; i < __system_argc; i ++)
{
#include <sys/iosupport.h>
#include <sys/time.h>
-
#include <string.h>
+
#include <3ds/types.h>
#include <3ds/svc.h>
+#include <3ds/env.h>
void (*__system_retAddr)(void);
-// Data from _prm structure
-extern void* __service_ptr; // used to detect if we're run from a homebrew launcher
-
void __system_allocateHeaps();
void __system_initArgv();
void __appInit();
__syscalls.exit = __ctru_exit;
__syscalls.gettod_r = __libctru_gtod;
- __system_retAddr = __service_ptr ? retAddr : NULL;
+ __system_retAddr = envIsHomebrew() ? retAddr : NULL;
if (__sync_init)
__sync_init();