Compare commits

...

19 Commits

Author SHA1 Message Date
TuxSH
44cd3928fb rosalina & pm: properly shutdown when debugger, input redir (but not both) and force connection are enabled 2020-04-28 01:31:29 +01:00
TuxSH
8c54613e44 rosalina/sysconfig: fix handling of disconnected routers in wifi forcing + handle leak 2020-04-28 00:05:55 +01:00
TuxSH
7dfa83b8c0 rosalina: fix gdb/input redir hanging if no internet & fix recovering from failures 2020-04-27 21:58:40 +01:00
TuxSH
b551061264 rosalina/sysconfig: fix wifi forcing, including a regression from v10.1.1 2020-04-27 20:00:41 +01:00
TuxSH
3e228c33c9 here we go again 2020-04-27 18:11:42 +01:00
TuxSH
2b23be8f44 rosalina/cheats: fix v10.1.1 regression where cheats were not working at all. Fixes #1404 2020-04-27 17:59:51 +01:00
TuxSH
ced78cb072 use -wrap for exit 2020-04-27 01:07:57 +01:00
TuxSH
fb17850c3d Update issue template 2020-04-27 01:00:01 +01:00
TuxSH
7f7c4852cc hbloader: raise the maximum time share APT_SetAppCpuTimeLimit can set from 30% to 89%...
... now that we understand both PM and the kernel better.

89% is the maximum value supported for this preemption mode.
2020-04-27 00:57:00 +01:00
TuxSH
f334e3b951 loader/pm: move "force init SD" code to pm. Greatly reduces the number of Arm9 svcBreak with 0xC8804465 2020-04-27 00:47:16 +01:00
TuxSH
9d62995799 rosalina: make the task runner thread actually exit 2020-04-26 21:37:18 +01:00
TuxSH
1d8b793cf7 rosalina: don't keep an ac:u handle. Partially fixes the shutdown issue 2020-04-26 20:55:52 +01:00
TuxSH
33431cb939 pm/kext: make pm terminate Rosalina, removing the need for a dodgy kext hook 2020-04-26 20:33:24 +01:00
TuxSH
e677e0142c rosalina: lower thread prios & make task runner take termination into account 2020-04-26 19:36:59 +01:00
TuxSH
b313a4aa2f rosalina: remove all remaining refs to __syscalls (which we don't init) 2020-04-26 12:07:17 +01:00
TuxSH
37c5c6f049 cheats: don't use rand() 2020-04-26 11:47:15 +01:00
TuxSH
a6d92ed8fe cheats: use pm:dbg new commands to get the application's title ID 2020-04-26 11:27:55 +01:00
TuxSH
eb37ac4142 redefine exit methods for sysmodules. Partially fixes the shutdown issue 2020-04-26 01:50:47 +01:00
TuxSH
a0d4b96915 Fix stack overflow in ProcessListMenu_DumpMemory 2020-04-25 22:48:31 +01:00
43 changed files with 860 additions and 479 deletions

View File

@@ -34,7 +34,7 @@ about: Use this to report bugs you encounter with Luma3DS. Make sure you upload
**Luma3DS version:** **Luma3DS version:**
[e.g. v10.0.1 stable or if using nightly/hourly specify the commit like this https://github.com/AuroraWright/Luma3DS/commit/0543c208fd154e6326ea5da8cbf66ffcbdef010c] [e.g. v10.1.2 stable or if using nightly/hourly specify the commit like this https://github.com/AuroraWright/Luma3DS/commit/0543c208fd154e6326ea5da8cbf66ffcbdef010c]
**Luma3DS configuration/options:** **Luma3DS configuration/options:**

View File

@@ -57,5 +57,4 @@ void SessionInfo_Add(KSession *session, const char *name);
void SessionInfo_Remove(KSession *session); void SessionInfo_Remove(KSession *session);
bool doLangEmu(Result *res, u32 *cmdbuf); bool doLangEmu(Result *res, u32 *cmdbuf);
Result doPublishToProcessHook(Handle handle, u32 *cmdbuf);
bool doErrfThrowHook(u32 *cmdbuf); bool doErrfThrowHook(u32 *cmdbuf);

View File

@@ -235,48 +235,6 @@ bool doLangEmu(Result *res, u32 *cmdbuf)
return skip; return skip;
} }
Result doPublishToProcessHook(Handle handle, u32 *cmdbuf)
{
Result res = 0;
u32 pid;
bool terminateRosalina = cmdbuf[1] == 0x100 && cmdbuf[2] == 0; // cmdbuf[2] to check for well-formed requests
u32 savedCmdbuf[4];
memcpy(savedCmdbuf, cmdbuf, 16);
if(!terminateRosalina || GetProcessId(&pid, cmdbuf[3]) != 0)
terminateRosalina = false;
else
{
KProcessHandleTable *handleTable = handleTableOfProcess(currentCoreContext->objectContext.currentProcess);
KProcess *process = KProcessHandleTable__ToKProcess(handleTable, cmdbuf[3]);
if((strcmp(codeSetOfProcess(process)->processName, "socket") == 0 && (rosalinaState & 2)) ||
strcmp(codeSetOfProcess(process)->processName, "pxi") == 0)
terminateRosalina = true;
else
terminateRosalina = false;
((KAutoObject *)process)->vtable->DecrementReferenceCount((KAutoObject *)process);
}
if(terminateRosalina && nbSection0Modules == 6)
{
Handle rosalinaProcessHandle;
res = OpenProcess(&rosalinaProcessHandle, 5);
if(res == 0)
{
cmdbuf[0] = cmdbuf[0];
cmdbuf[1] = 0x100;
cmdbuf[2] = 0;
cmdbuf[3] = rosalinaProcessHandle;
res = SendSyncRequest(handle);
CloseHandle(rosalinaProcessHandle);
memcpy(cmdbuf, savedCmdbuf, 16);
}
}
return SendSyncRequest(handle);
}
bool doErrfThrowHook(u32 *cmdbuf) bool doErrfThrowHook(u32 *cmdbuf)
{ {
// If fatalErrorInfo->type is "card removed" or "logged", returning from ERRF:Throw is a no-op // If fatalErrorInfo->type is "card removed" or "logged", returning from ERRF:Throw is a no-op

View File

@@ -47,12 +47,7 @@ Result SendSyncRequestHook(Handle handle)
case 0x10042: case 0x10042:
{ {
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession); SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
if(info != NULL && kernelVersion >= SYSTEM_VERSION(2, 39, 4) && strcmp(info->name, "srv:pm") == 0) if(info != NULL && strcmp(info->name, "ndm:u") == 0 && hasStartedRosalinaNetworkFuncsOnce)
{
res = doPublishToProcessHook(handle, cmdbuf);
skip = true;
}
else if(info != NULL && strcmp(info->name, "ndm:u") == 0 && hasStartedRosalinaNetworkFuncsOnce)
{ {
cmdbuf[0] = 0x10040; cmdbuf[0] = 0x10040;
cmdbuf[1] = 0; cmdbuf[1] = 0;
@@ -154,18 +149,6 @@ Result SendSyncRequestHook(Handle handle)
break; break;
} }
case 0x4010042:
{
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
if(info != NULL && kernelVersion < SYSTEM_VERSION(2, 39, 4) && strcmp(info->name, "srv:pm") == 0)
{
res = doPublishToProcessHook(handle, cmdbuf);
skip = true;
}
break;
}
case 0x4010082: case 0x4010082:
{ {
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession); SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);

View File

@@ -37,7 +37,7 @@ CFLAGS := -std=gnu11 $(COMMON_FLAGS)
CXXFLAGS := -fno-rtti -fno-exceptions -std=gnu++17 $(COMMON_FLAGS) CXXFLAGS := -fno-rtti -fno-exceptions -std=gnu++17 $(COMMON_FLAGS)
ASFLAGS := -g $(ARCH) ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map),--section-start,.text=0x14000000 LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map),-wrap,exit,--section-start,.text=0x14000000
LIBS := -lctru LIBS := -lctru

View File

@@ -6,7 +6,7 @@
#include "hbldr.h" #include "hbldr.h"
extern u32 config, multiConfig, bootConfig; extern u32 config, multiConfig, bootConfig;
extern bool isN3DS, needToInitSd, isSdMode; extern bool isN3DS, isSdMode;
static u8 g_ret_buf[sizeof(ExHeader_Info)]; static u8 g_ret_buf[sizeof(ExHeader_Info)];
static u64 g_cached_programHandle; static u64 g_cached_programHandle;

View File

@@ -7,7 +7,7 @@
#include "service_manager.h" #include "service_manager.h"
u32 config, multiConfig, bootConfig; u32 config, multiConfig, bootConfig;
bool isN3DS, needToInitSd, isSdMode; bool isN3DS, isSdMode;
// MAKE SURE fsreg has been init before calling this // MAKE SURE fsreg has been init before calling this
static Result fsldrPatchPermissions(void) static Result fsldrPatchPermissions(void)
@@ -38,18 +38,29 @@ static inline void loadCFWInfo(void)
assertSuccess(svcGetSystemInfo(&out, 0x10000, 0x201)); assertSuccess(svcGetSystemInfo(&out, 0x10000, 0x201));
isN3DS = (bool)out; isN3DS = (bool)out;
assertSuccess(svcGetSystemInfo(&out, 0x10000, 0x202)); //assertSuccess(svcGetSystemInfo(&out, 0x10000, 0x202));
needToInitSd = (bool)out; //needToInitSd = (bool)out;
assertSuccess(svcGetSystemInfo(&out, 0x10000, 0x203)); assertSuccess(svcGetSystemInfo(&out, 0x10000, 0x203));
isSdMode = (bool)out; isSdMode = (bool)out;
IFile file;
if(needToInitSd) fileOpen(&file, ARCHIVE_SDMC, "/", FS_OPEN_READ); //Init SD card if SAFE_MODE is being booted
} }
// this is called before main void __ctru_exit(int rc) { (void)rc; } // needed to avoid linking error
void __appInit()
// this is called after main exits
void __wrap_exit(int rc)
{ {
(void)rc;
// Not supposed to terminate... kernel will clean up the handles if it does happen anyway
svcExitProcess();
}
void __sync_init();
void __libc_init_array(void);
// called before main
void initSystem(void)
{
__sync_init();
loadCFWInfo(); loadCFWInfo();
Result res; Result res;
@@ -71,42 +82,8 @@ void __appInit()
assertSuccess(FSUSER_SetPriority(0)); assertSuccess(FSUSER_SetPriority(0));
assertSuccess(pxiPmInit()); assertSuccess(pxiPmInit());
}
// this is called after main exits //__libc_init_array();
void __appExit()
{
pxiPmExit();
//fsldrExit();
svcCloseHandle(*fsGetSessionHandle());
fsRegExit();
srvExit();
}
// stubs for non-needed pre-main functions
void __sync_init();
void __sync_fini();
void __system_initSyscalls();
void __ctru_exit()
{
void __libc_fini_array(void);
__libc_fini_array();
__appExit();
__sync_fini();
svcExitProcess();
}
void initSystem()
{
void __libc_init_array(void);
__sync_init();
__system_initSyscalls();
__appInit();
__libc_init_array();
} }
static const ServiceManagerServiceEntry services[] = { static const ServiceManagerServiceEntry services[] = {

View File

@@ -39,7 +39,7 @@ enum singleOptions
}; };
extern u32 config, multiConfig, bootConfig; extern u32 config, multiConfig, bootConfig;
extern bool isN3DS, needToInitSd, isSdMode; extern bool isN3DS, isSdMode;
void patchCode(u64 progId, u16 progVer, u8 *code, u32 size, u32 textSize, u32 roSize, u32 dataSize, u32 roAddress, u32 dataAddress); void patchCode(u64 progId, u16 progVer, u8 *code, u32 size, u32 textSize, u32 roSize, u32 dataSize, u32 roAddress, u32 dataAddress);
Result fileOpen(IFile *file, FS_ArchiveID archiveId, const char *path, int flags); Result fileOpen(IFile *file, FS_ArchiveID archiveId, const char *path, int flags);

View File

@@ -37,7 +37,7 @@ CFLAGS += $(INCLUDE)
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH) ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map),-wrap,exit
LIBS := -lctru LIBS := -lctru

View File

@@ -117,7 +117,11 @@ AccessControlInfo:
ServiceAccessControl: ServiceAccessControl:
# Note: pm also uses srv:pm and Loader but doesn't list them here. # Note: pm also uses srv:pm and Loader but doesn't list them here.
- fs:REG - fs:REG
# Custom:
- fs:USER
FileSystemAccess: FileSystemAccess:
# Custom
- DirectSdmc
SystemControlInfo: SystemControlInfo:
SaveDataSize: 0KB # It doesn't use any save data. SaveDataSize: 0KB # It doesn't use any save data.

View File

@@ -14,10 +14,27 @@
#include "service_manager.h" #include "service_manager.h"
static MyThread processMonitorThread, taskRunnerThread; static MyThread processMonitorThread, taskRunnerThread;
static u8 ALIGN(8) processDataBuffer[0x40 * sizeof(ProcessData)] = {0};
static u8 ALIGN(8) exheaderInfoBuffer[6 * sizeof(ExHeader_Info)] = {0};
static u8 ALIGN(8) threadStacks[2][THREAD_STACK_SIZE] = {0};
// this is called before main // this is called after main exits
void __appInit() void __wrap_exit(int rc)
{ {
(void)rc;
// Not supposed to terminate... kernel will clean up the handles if it does happen anyway
svcExitProcess();
}
Result __sync_init(void);
//void __libc_init_array(void);
// Called before main
void initSystem()
{
__sync_init();
//__libc_init_array();
// Wait for sm // Wait for sm
for(Result res = 0xD88007FA; res == (Result)0xD88007FA; svcSleepThread(500 * 1000LL)) { for(Result res = 0xD88007FA; res == (Result)0xD88007FA; svcSleepThread(500 * 1000LL)) {
res = srvPmInit(); res = srvPmInit();
@@ -28,56 +45,10 @@ void __appInit()
loaderInit(); loaderInit();
fsRegInit(); fsRegInit();
static u8 ALIGN(8) processDataBuffer[0x40 * sizeof(ProcessData)] = {0};
static u8 ALIGN(8) exheaderInfoBuffer[6 * sizeof(ExHeader_Info)] = {0};
static u8 ALIGN(8) threadStacks[2][THREAD_STACK_SIZE] = {0};
// Init objects // Init objects
Manager_Init(processDataBuffer, 0x40); Manager_Init(processDataBuffer, 0x40);
ExHeaderInfoHeap_Init(exheaderInfoBuffer, 6); ExHeaderInfoHeap_Init(exheaderInfoBuffer, 6);
TaskRunner_Init(); TaskRunner_Init();
// Init the reslimits, register the KIPs and map the firmlaunch parameters
initializeReslimits();
Manager_RegisterKips();
mapFirmlaunchParameters();
// Create the threads
assertSuccess(MyThread_Create(&processMonitorThread, processMonitor, NULL, threadStacks[0], THREAD_STACK_SIZE, 0x17, -2));
assertSuccess(MyThread_Create(&taskRunnerThread, TaskRunner_HandleTasks, NULL, threadStacks[1], THREAD_STACK_SIZE, 0x17, -2));
// Launch NS, etc.
autolaunchSysmodules();
}
// this is called after main exits
void __appExit()
{
// We don't clean up g_manager's handles because it could hang the process monitor thread, etc.
fsRegExit();
loaderExit();
srvPmExit();
}
Result __sync_init(void);
Result __sync_fini(void);
void __libc_init_array(void);
void __libc_fini_array(void);
void __ctru_exit()
{
__libc_fini_array();
__appExit();
__sync_fini();
svcExitProcess();
}
void initSystem()
{
__sync_init();
__appInit();
__libc_init_array();
} }
static const ServiceManagerServiceEntry services[] = { static const ServiceManagerServiceEntry services[] = {
@@ -90,9 +61,24 @@ static const ServiceManagerNotificationEntry notifications[] = {
{ 0x000, NULL }, { 0x000, NULL },
}; };
void __ctru_exit(int rc) { (void)rc; } // needed to avoid linking error
int main(void) int main(void)
{ {
Result res = 0; Result res = 0;
// Init the reslimits, register the KIPs and map the firmlaunch parameters
initializeReslimits();
Manager_RegisterKips();
mapFirmlaunchParameters();
// Create the threads
assertSuccess(MyThread_Create(&processMonitorThread, processMonitor, NULL, threadStacks[0], THREAD_STACK_SIZE, 0x17, -2));
assertSuccess(MyThread_Create(&taskRunnerThread, TaskRunner_HandleTasks, NULL, threadStacks[1], THREAD_STACK_SIZE, 0x17, -2));
// Launch NS, etc.
autolaunchSysmodules();
if (R_FAILED(res = ServiceManager_Run(services, notifications, NULL))) { if (R_FAILED(res = ServiceManager_Run(services, notifications, NULL))) {
panic(res); panic(res);
} }

View File

@@ -4,6 +4,11 @@
TaskRunner g_taskRunner; TaskRunner g_taskRunner;
static void taskRunnerNoOpFunction(void *args)
{
(void)args;
}
void TaskRunner_Init(void) void TaskRunner_Init(void)
{ {
memset(&g_taskRunner, 0, sizeof(TaskRunner)); memset(&g_taskRunner, 0, sizeof(TaskRunner));
@@ -20,12 +25,23 @@ void TaskRunner_RunTask(void (*task)(void *argdata), void *argdata, size_t argsi
LightEvent_Signal(&g_taskRunner.parametersSetEvent); LightEvent_Signal(&g_taskRunner.parametersSetEvent);
} }
void TaskRunner_Terminate(void)
{
g_taskRunner.shouldTerminate = true;
TaskRunner_RunTask(taskRunnerNoOpFunction, NULL, 0);
}
void TaskRunner_HandleTasks(void *p) void TaskRunner_HandleTasks(void *p)
{ {
(void)p; (void)p;
for (;;) { while (!g_taskRunner.shouldTerminate) {
LightEvent_Signal(&g_taskRunner.readyEvent); LightEvent_Signal(&g_taskRunner.readyEvent);
LightEvent_Wait(&g_taskRunner.parametersSetEvent); LightEvent_Wait(&g_taskRunner.parametersSetEvent);
g_taskRunner.task(g_taskRunner.argStorage); g_taskRunner.task(g_taskRunner.argStorage);
} }
} }
void TaskRunner_WaitReady(void)
{
LightEvent_Wait(&g_taskRunner.readyEvent);
}

View File

@@ -8,11 +8,15 @@ typedef struct TaskRunner {
LightEvent parametersSetEvent; LightEvent parametersSetEvent;
void (*task)(void *argdata); void (*task)(void *argdata);
u8 argStorage[0x40]; u8 argStorage[0x40];
bool shouldTerminate;
} TaskRunner; } TaskRunner;
extern TaskRunner g_taskRunner; extern TaskRunner g_taskRunner;
void TaskRunner_Init(void); void TaskRunner_Init(void);
void TaskRunner_RunTask(void (*task)(void *argdata), void *argdata, size_t argsize); void TaskRunner_RunTask(void (*task)(void *argdata), void *argdata, size_t argsize);
void TaskRunner_Terminate(void);
/// Thread function /// Thread function
void TaskRunner_HandleTasks(void *p); void TaskRunner_HandleTasks(void *p);
void TaskRunner_WaitReady(void);

View File

@@ -6,6 +6,35 @@
#include "exheader_info_heap.h" #include "exheader_info_heap.h"
#include "task_runner.h" #include "task_runner.h"
static Result fsRegSetupPermissions(void)
{
u32 pid;
Result res;
FS_ProgramInfo info;
ExHeader_Arm11StorageInfo storageInfo = {
.fs_access_info = FSACCESS_SDMC_RW,
};
info.programId = 0x0004013000001202LL; // PM's TID
info.mediaType = MEDIATYPE_NAND;
if(R_SUCCEEDED(res = svcGetProcessId(&pid, CUR_PROCESS_HANDLE)))
res = FSREG_Register(pid, 0xFFFF000000000000LL, &info, &storageInfo);
return res;
}
void forceMountSdCard(void)
{
FS_Archive sdmcArchive;
assertSuccess(fsRegSetupPermissions());
assertSuccess(fsInit());
assertSuccess(FSUSER_OpenArchive(&sdmcArchive, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, "")));
// No need to clean up things as we will firmlaunch straight away
}
static Result terminateUnusedDependencies(const u64 *dependencies, u32 numDeps) static Result terminateUnusedDependencies(const u64 *dependencies, u32 numDeps)
{ {
ProcessData *process; ProcessData *process;
@@ -65,6 +94,16 @@ static Result terminateProcessImpl(ProcessData *process, ExHeader_Info *exheader
} }
} }
static void terminateProcessByIdChecked(u32 pid)
{
ProcessData *process = ProcessList_FindProcessById(&g_manager.processList, pid);
if (process != NULL) {
ProcessData_SendTerminationNotification(process);
} else {
panic(0LL);
}
}
static Result commitPendingTerminations(s64 timeout) static Result commitPendingTerminations(s64 timeout)
{ {
// Wait for all of the processes that have received notification 0x100 to terminate // Wait for all of the processes that have received notification 0x100 to terminate
@@ -247,6 +286,8 @@ ProcessData *terminateAllProcesses(u32 callerPid, s64 timeout)
u64 dependencies[48]; u64 dependencies[48];
u32 numDeps = 0; u32 numDeps = 0;
s64 numKips = 0;
svcGetSystemInfo(&numKips, 26, 0);
ExHeader_Info *exheaderInfo = ExHeaderInfoHeap_New(); ExHeader_Info *exheaderInfo = ExHeaderInfoHeap_New();
@@ -269,6 +310,12 @@ ProcessData *terminateAllProcesses(u32 callerPid, s64 timeout)
} }
ProcessList_Lock(&g_manager.processList); ProcessList_Lock(&g_manager.processList);
// Send custom notification to at least Rosalina to make it relinquish some non-KIP services handles, stop the debugger, etc.
if (numKips >= 6) {
notifySubscribers(0x1001);
}
// Send notification 0x100 to the currently running application // Send notification 0x100 to the currently running application
if (g_manager.runningApplicationData != NULL) { if (g_manager.runningApplicationData != NULL) {
g_manager.runningApplicationData->flags &= ~PROCESSFLAG_DEPENDENCIES_LOADED; g_manager.runningApplicationData->flags &= ~PROCESSFLAG_DEPENDENCIES_LOADED;
@@ -302,20 +349,29 @@ ProcessData *terminateAllProcesses(u32 callerPid, s64 timeout)
commitPendingTerminations(timeoutTicks >= 0 ? ticksToNs(timeoutTicks) : 0LL); commitPendingTerminations(timeoutTicks >= 0 ? ticksToNs(timeoutTicks) : 0LL);
g_manager.waitingForTermination = false; g_manager.waitingForTermination = false;
// Now, send termination notification to PXI (PID 4) if (callerPid == (u32)-1) {
// On firmlaunch, try to force Process9 to mount the SD card to allow the Process9 firmlaunch patch to load boot.firm if needed
// Need to do that before we tell PXI to terminate
s64 out;
if(R_SUCCEEDED(svcGetSystemInfo(&out, 0x10000, 0x203)) && out != 0) {
// If boot.firm is on the SD card, then...
forceMountSdCard();
}
}
// Now, send termination notification to PXI (PID 4). Also do the same for Rosalina.
assertSuccess(svcClearEvent(g_manager.allNotifiedTerminationEvent)); assertSuccess(svcClearEvent(g_manager.allNotifiedTerminationEvent));
g_manager.waitingForTermination = true; g_manager.waitingForTermination = true;
ProcessList_Lock(&g_manager.processList); ProcessList_Lock(&g_manager.processList);
process = ProcessList_FindProcessById(&g_manager.processList, 4);
if (process != NULL) { if (numKips >= 6) {
ProcessData_SendTerminationNotification(process); terminateProcessByIdChecked(5); // Rosalina
} else {
panic(0LL);
} }
terminateProcessByIdChecked(4); // PXI
ProcessList_Unlock(&g_manager.processList); ProcessList_Unlock(&g_manager.processList);
// Allow 1.5 extra seconds for PXI (approx 402167783 ticks) // Allow 1.5 extra seconds for PXI and Rosalina (approx 402167783 ticks)
timeoutTicks = dstTimePoint - svcGetSystemTick(); timeoutTicks = dstTimePoint - svcGetSystemTick();
commitPendingTerminations(1500 * 1000 * 1000LL + (timeoutTicks >= 0 ? ticksToNs(timeoutTicks) : 0LL)); commitPendingTerminations(1500 * 1000 * 1000LL + (timeoutTicks >= 0 ? ticksToNs(timeoutTicks) : 0LL));
g_manager.waitingForTermination = false; g_manager.waitingForTermination = false;

View File

@@ -37,7 +37,7 @@ CFLAGS += $(INCLUDE)
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH) ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map),-wrap,exit
LIBS := -lctru LIBS := -lctru

View File

@@ -7,7 +7,6 @@ This is part of 3ds_pxi, which is licensed under the MIT license (see LICENSE fo
*/ */
#include <string.h> #include <string.h>
#include "PXI.h" #include "PXI.h"
#include "common.h" #include "common.h"
#include "MyThread.h" #include "MyThread.h"
@@ -100,9 +99,38 @@ static u8 ALIGN(8) receiverStack[THREAD_STACK_SIZE];
static u8 ALIGN(8) senderStack[THREAD_STACK_SIZE]; static u8 ALIGN(8) senderStack[THREAD_STACK_SIZE];
static u8 ALIGN(8) PXISRV11HandlerStack[THREAD_STACK_SIZE]; static u8 ALIGN(8) PXISRV11HandlerStack[THREAD_STACK_SIZE];
// this is called before main Result __sync_init(void);
void __appInit() Result __sync_fini(void);
void __libc_fini_array(void);
void __libc_init_array(void);
void __ctru_exit(int rc) { (void)rc; } // needed to avoid linking error
// this is called after main exits
void __wrap_exit(int rc)
{ {
(void)rc;
srvExit();
exitPXI();
svcCloseHandle(terminationRequestedEvent);
svcCloseHandle(sessionManager.sendAllBuffersToArm9Event);
svcCloseHandle(sessionManager.replySemaphore);
svcCloseHandle(sessionManager.PXISRV11CommandReceivedEvent);
svcCloseHandle(sessionManager.PXISRV11ReplySentEvent);
//__libc_fini_array();
__sync_fini();
svcExitProcess();
}
// this is called before main
void initSystem(void)
{
__sync_init();
assertSuccess(svcCreateEvent(&terminationRequestedEvent, RESET_STICKY)); assertSuccess(svcCreateEvent(&terminationRequestedEvent, RESET_STICKY));
assertSuccess(svcCreateEvent(&sessionManager.sendAllBuffersToArm9Event, RESET_ONESHOT)); assertSuccess(svcCreateEvent(&sessionManager.sendAllBuffersToArm9Event, RESET_ONESHOT));
@@ -117,46 +145,8 @@ void __appInit()
if(R_FAILED(res) && res != (Result)0xD88007FA) if(R_FAILED(res) && res != (Result)0xD88007FA)
svcBreak(USERBREAK_PANIC); svcBreak(USERBREAK_PANIC);
} }
}
// this is called after main exits //__libc_init_array();
void __appExit()
{
srvExit();
exitPXI();
svcCloseHandle(terminationRequestedEvent);
svcCloseHandle(sessionManager.sendAllBuffersToArm9Event);
svcCloseHandle(sessionManager.replySemaphore);
svcCloseHandle(sessionManager.PXISRV11CommandReceivedEvent);
svcCloseHandle(sessionManager.PXISRV11ReplySentEvent);
}
// stubs for non-needed pre-main functions
void __system_initSyscalls(){}
Result __sync_init(void);
Result __sync_fini(void);
void __ctru_exit()
{
void __libc_fini_array(void);
__libc_fini_array();
__appExit();
__sync_fini();
svcExitProcess();
}
void initSystem()
{
void __libc_init_array(void);
__sync_init();
__system_initSyscalls();
__appInit();
__libc_init_array();
} }
int main(void) int main(void)

View File

@@ -37,7 +37,7 @@ CFLAGS += $(INCLUDE)
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH) ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map),--section-start,.text=0x14000000 LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map),-wrap,exit,--section-start,.text=0x14000000
LIBS := -lctru LIBS := -lctru

View File

@@ -36,4 +36,5 @@ extern int inputRedirectionStartResult;
MyThread *inputRedirectionCreateThread(void); MyThread *inputRedirectionCreateThread(void);
void inputRedirectionThreadMain(void); void inputRedirectionThreadMain(void);
Result InputRedirection_Disable(s64 timeout);
Result InputRedirection_DoOrUndoPatches(void); Result InputRedirection_DoOrUndoPatches(void);

View File

@@ -33,4 +33,5 @@
#define CHEATS_PER_MENU_PAGE 18 #define CHEATS_PER_MENU_PAGE 18
void RosalinaMenu_Cheats(void); void RosalinaMenu_Cheats(void);
void Cheat_ApplyCheats(); void Cheat_SeedRng(u64 seed);
void Cheat_ApplyCheats(void);

View File

@@ -32,6 +32,8 @@
extern Menu debuggerMenu; extern Menu debuggerMenu;
void debuggerFetchAndSetNextApplicationDebugHandleTask(void *argdata); void debuggerFetchAndSetNextApplicationDebugHandleTask(void *argdata);
Result debuggerDisable(s64 timeout);
void DebuggerMenu_EnableDebugger(void); void DebuggerMenu_EnableDebugger(void);
void DebuggerMenu_DisableDebugger(void); void DebuggerMenu_DisableDebugger(void);
void DebuggerMenu_DebugNextApplicationByForce(void); void DebuggerMenu_DebugNextApplicationByForce(void);

View File

@@ -30,8 +30,12 @@
#include "menu.h" #include "menu.h"
extern Menu sysconfigMenu; extern Menu sysconfigMenu;
extern bool isConnectionForced;
void SysConfigMenu_UpdateStatus(bool control);
void SysConfigMenu_ToggleLEDs(void); void SysConfigMenu_ToggleLEDs(void);
void SysConfigMenu_ToggleWireless(void); void SysConfigMenu_ToggleWireless(void);
void SysConfigMenu_TogglePowerButton(void); void SysConfigMenu_TogglePowerButton(void);
void SysConfigMenu_ControlWifi(void); void SysConfigMenu_ControlWifi(void);
void SysConfigMenu_DisableForcedWifiConnection(void);

View File

@@ -18,13 +18,10 @@
#include <errno.h> #include <errno.h>
#define SYNC_ERROR ENODEV #define SYNC_ERROR ENODEV
extern Handle SOCU_handle;
extern Handle socMemhandle;
extern bool miniSocEnabled; extern bool miniSocEnabled;
Result miniSocInit(); Result miniSocInit(void);
Result miniSocExitDirect(void);
Result miniSocExit(void); Result miniSocExit(void);
s32 _net_convert_error(s32 sock_retval); s32 _net_convert_error(s32 sock_retval);
@@ -37,10 +34,17 @@ int socConnect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
int socPoll(struct pollfd *fds, nfds_t nfds, int timeout); int socPoll(struct pollfd *fds, nfds_t nfds, int timeout);
int socSetsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen); int socSetsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
int socClose(int sockfd); int socClose(int sockfd);
long socGethostid(void);
ssize_t soc_recv(int sockfd, void *buf, size_t len, int flags); ssize_t socRecvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
ssize_t soc_send(int sockfd, const void *buf, size_t len, int flags); ssize_t socSendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
// actually provided by ctrulib static inline ssize_t socRecv(int sockfd, void *buf, size_t len, int flags)
ssize_t soc_recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen); {
ssize_t soc_sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen); return socRecvfrom(sockfd, buf, len, flags, NULL, 0);
}
static inline ssize_t socSend(int sockfd, const void *buf, size_t len, int flags)
{
return socSendto(sockfd, buf, len, flags, NULL, 0);
}

View File

@@ -68,10 +68,11 @@ typedef struct sock_server
sock_free_func free; sock_free_func free;
Handle shall_terminate_event; Handle shall_terminate_event;
Result init_result;
} sock_server; } sock_server;
Result server_init(struct sock_server *serv); Result server_init(struct sock_server *serv);
void server_bind(struct sock_server *serv, u16 port); Result server_bind(struct sock_server *serv, u16 port);
void server_run(struct sock_server *serv); void server_run(struct sock_server *serv);
void server_kill_connections(struct sock_server *serv); void server_kill_connections(struct sock_server *serv);
void server_set_should_close_all(struct sock_server *serv); void server_set_should_close_all(struct sock_server *serv);

View File

@@ -9,6 +9,7 @@ typedef struct TaskRunner {
LightEvent parametersSetEvent; LightEvent parametersSetEvent;
void (*task)(void *argdata); void (*task)(void *argdata);
u8 argStorage[0x40]; u8 argStorage[0x40];
bool shouldTerminate;
} TaskRunner; } TaskRunner;
extern TaskRunner g_taskRunner; extern TaskRunner g_taskRunner;
@@ -17,6 +18,8 @@ MyThread *taskRunnerCreateThread(void);
void TaskRunner_Init(void); void TaskRunner_Init(void);
void TaskRunner_RunTask(void (*task)(void *argdata), void *argdata, size_t argsize); void TaskRunner_RunTask(void (*task)(void *argdata), void *argdata, size_t argsize);
void TaskRunner_Terminate(void);
/// Thread function /// Thread function
void TaskRunner_HandleTasks(void); void TaskRunner_HandleTasks(void);
void TaskRunner_WaitReady(void); void TaskRunner_WaitReady(void);

View File

@@ -21,7 +21,7 @@ AccessControlInfo:
IdealProcessor : 1 IdealProcessor : 1
AffinityMask : 3 AffinityMask : 3
Priority : 20 Priority : 25 # 55
DisableDebug : false DisableDebug : false
EnableForceDebug : true EnableForceDebug : true

View File

@@ -48,7 +48,7 @@ static char staticBuf[0x100 + 1] = {0};
MyThread *errDispCreateThread(void) MyThread *errDispCreateThread(void)
{ {
if(R_FAILED(MyThread_Create(&errDispThread, errDispThreadMain, errDispThreadStack, 0xD00, 0x18, CORE_SYSTEM))) if(R_FAILED(MyThread_Create(&errDispThread, errDispThreadMain, errDispThreadStack, 0xD00, 55, CORE_SYSTEM)))
svcBreak(USERBREAK_PANIC); svcBreak(USERBREAK_PANIC);
return &errDispThread; return &errDispThread;
} }

View File

@@ -177,7 +177,7 @@ int GDB_ReceivePacket(GDBContext *ctx)
memcpy(backupbuf, ctx->buffer, ctx->latestSentPacketSize); memcpy(backupbuf, ctx->buffer, ctx->latestSentPacketSize);
memset(ctx->buffer, 0, sizeof(ctx->buffer)); memset(ctx->buffer, 0, sizeof(ctx->buffer));
int r = soc_recv(ctx->super.sockfd, ctx->buffer, sizeof(ctx->buffer), MSG_PEEK); int r = socRecv(ctx->super.sockfd, ctx->buffer, sizeof(ctx->buffer), MSG_PEEK);
if(r < 1) if(r < 1)
return -1; return -1;
if(ctx->buffer[0] == '+') // GDB sometimes acknowleges TCP acknowledgment packets (yes...). IDA does it properly if(ctx->buffer[0] == '+') // GDB sometimes acknowleges TCP acknowledgment packets (yes...). IDA does it properly
@@ -186,20 +186,20 @@ int GDB_ReceivePacket(GDBContext *ctx)
return -1; return -1;
// Consume it // Consume it
r = soc_recv(ctx->super.sockfd, ctx->buffer, 1, 0); r = socRecv(ctx->super.sockfd, ctx->buffer, 1, 0);
if(r != 1) if(r != 1)
return -1; return -1;
ctx->buffer[0] = 0; ctx->buffer[0] = 0;
r = soc_recv(ctx->super.sockfd, ctx->buffer, sizeof(ctx->buffer), MSG_PEEK); r = socRecv(ctx->super.sockfd, ctx->buffer, sizeof(ctx->buffer), MSG_PEEK);
if(r == -1) if(r == -1)
goto packet_error; goto packet_error;
} }
else if(ctx->buffer[0] == '-') else if(ctx->buffer[0] == '-')
{ {
soc_send(ctx->super.sockfd, backupbuf, ctx->latestSentPacketSize, 0); socSend(ctx->super.sockfd, backupbuf, ctx->latestSentPacketSize, 0);
return 0; return 0;
} }
int maxlen = r > (int)sizeof(ctx->buffer) ? (int)sizeof(ctx->buffer) : r; int maxlen = r > (int)sizeof(ctx->buffer) ? (int)sizeof(ctx->buffer) : r;
@@ -215,7 +215,7 @@ int GDB_ReceivePacket(GDBContext *ctx)
else else
{ {
u8 checksum; u8 checksum;
r = soc_recv(ctx->super.sockfd, ctx->buffer, 3 + pos - ctx->buffer, 0); r = socRecv(ctx->super.sockfd, ctx->buffer, 3 + pos - ctx->buffer, 0);
if(r != 3 + pos - ctx->buffer || GDB_DecodeHex(&checksum, pos + 1, 1) != 1) if(r != 3 + pos - ctx->buffer || GDB_DecodeHex(&checksum, pos + 1, 1) != 1)
goto packet_error; goto packet_error;
else if(GDB_ComputeChecksum(ctx->buffer + 1, pos - ctx->buffer - 1) != checksum) else if(GDB_ComputeChecksum(ctx->buffer + 1, pos - ctx->buffer - 1) != checksum)
@@ -227,7 +227,7 @@ int GDB_ReceivePacket(GDBContext *ctx)
} }
else if(ctx->buffer[0] == '\x03') else if(ctx->buffer[0] == '\x03')
{ {
r = soc_recv(ctx->super.sockfd, ctx->buffer, 1, 0); r = socRecv(ctx->super.sockfd, ctx->buffer, 1, 0);
if(r != 1) if(r != 1)
goto packet_error; goto packet_error;
@@ -236,7 +236,7 @@ int GDB_ReceivePacket(GDBContext *ctx)
if(!(ctx->flags & GDB_FLAG_NOACK)) if(!(ctx->flags & GDB_FLAG_NOACK))
{ {
int r2 = soc_send(ctx->super.sockfd, "+", 1, 0); int r2 = socSend(ctx->super.sockfd, "+", 1, 0);
if(r2 != 1) if(r2 != 1)
return -1; return -1;
} }
@@ -252,7 +252,7 @@ int GDB_ReceivePacket(GDBContext *ctx)
packet_error: packet_error:
if(!(ctx->flags & GDB_FLAG_NOACK)) if(!(ctx->flags & GDB_FLAG_NOACK))
{ {
r = soc_send(ctx->super.sockfd, "-", 1, 0); r = socSend(ctx->super.sockfd, "-", 1, 0);
if(r != 1) if(r != 1)
return -1; return -1;
else else
@@ -264,7 +264,7 @@ packet_error:
static int GDB_DoSendPacket(GDBContext *ctx, u32 len) static int GDB_DoSendPacket(GDBContext *ctx, u32 len)
{ {
int r = soc_send(ctx->super.sockfd, ctx->buffer, len, 0); int r = socSend(ctx->super.sockfd, ctx->buffer, len, 0);
if(r > 0) if(r > 0)
ctx->latestSentPacketSize = r; ctx->latestSentPacketSize = r;

View File

@@ -74,13 +74,14 @@ void GDB_DecrementServerReferenceCount(GDBServer *server)
void GDB_RunServer(GDBServer *server) void GDB_RunServer(GDBServer *server)
{ {
server_bind(&server->super, GDB_PORT_BASE); Result res = server_bind(&server->super, GDB_PORT_BASE);
server_bind(&server->super, GDB_PORT_BASE + 1); if(R_SUCCEEDED(res)) res = server_bind(&server->super, GDB_PORT_BASE + 1);
server_bind(&server->super, GDB_PORT_BASE + 2); if(R_SUCCEEDED(res)) res = server_bind(&server->super, GDB_PORT_BASE + 2);
server_bind(&server->super, GDB_PORT_BASE + 3); // next application if(R_SUCCEEDED(res)) res = server_bind(&server->super, GDB_PORT_BASE + 3); // next application
server_run(&server->super); if(R_SUCCEEDED(res))
server_run(&server->super);
} }
void GDB_LockAllContexts(GDBServer *server) void GDB_LockAllContexts(GDBServer *server)

View File

@@ -279,7 +279,9 @@ void HBLDR_HandleCommands(void *ctx)
memset(localcaps0->reslimits, 0, sizeof(localcaps0->reslimits)); memset(localcaps0->reslimits, 0, sizeof(localcaps0->reslimits));
localcaps0->reslimits[0] = 0x9E; // Stuff needed to run stuff on core1 // Set mode1 preemption mode for core1, max. 89% of CPU time (default 0, requires a APT_SetAppCpuTimeLimit call)
// See the big comment in sysmodules/pm/source/reslimit.c for technical details.
localcaps0->reslimits[0] = BIT(7) | 89;
localcaps0->storage_info.fs_access_info = 0xFFFFFFFF; // Give access to everything localcaps0->storage_info.fs_access_info = 0xFFFFFFFF; // Give access to everything
localcaps0->storage_info.no_romfs = true; localcaps0->storage_info.no_romfs = true;

View File

@@ -55,27 +55,51 @@ int inputRedirectionStartResult;
void inputRedirectionThreadMain(void) void inputRedirectionThreadMain(void)
{ {
Result res = 0; Result res = 0;
inputRedirectionStartResult = 0;
res = miniSocInit(); res = miniSocInit();
if(R_FAILED(res)) if(R_FAILED(res))
{
// Socket services broken
inputRedirectionStartResult = res;
miniSocExit();
// Still signal the event
svcSignalEvent(inputRedirectionThreadStartedEvent);
return; return;
}
int sock = socSocket(AF_INET, SOCK_DGRAM, 0); int sock = socSocket(AF_INET, SOCK_DGRAM, 0);
while(sock == -1) u32 tries = 15;
while(sock == -1 && --tries > 0)
{ {
svcSleepThread(1000 * 0000 * 0000LL); svcSleepThread(100 * 1000 * 1000LL);
sock = socSocket(AF_INET, SOCK_DGRAM, 0); sock = socSocket(AF_INET, SOCK_DGRAM, 0);
} }
if (sock < -10000 || tries == 0) {
// Socket services broken
inputRedirectionStartResult = -1;
miniSocExit();
// Still signal the event
svcSignalEvent(inputRedirectionThreadStartedEvent);
return;
}
struct sockaddr_in saddr; struct sockaddr_in saddr;
saddr.sin_family = AF_INET; saddr.sin_family = AF_INET;
saddr.sin_port = htons(4950); saddr.sin_port = htons(4950);
saddr.sin_addr.s_addr = gethostid(); saddr.sin_addr.s_addr = socGethostid();
res = socBind(sock, (struct sockaddr*)&saddr, sizeof(struct sockaddr_in)); res = socBind(sock, (struct sockaddr*)&saddr, sizeof(struct sockaddr_in));
if(res != 0) if(res != 0)
{ {
socClose(sock); socClose(sock);
miniSocExit(); miniSocExit();
inputRedirectionStartResult = res; inputRedirectionStartResult = res;
// Still signal the event
svcSignalEvent(inputRedirectionThreadStartedEvent);
return; return;
} }
@@ -99,7 +123,7 @@ void inputRedirectionThreadMain(void)
int pollres = socPoll(&pfd, 1, 10); int pollres = socPoll(&pfd, 1, 10);
if(pollres > 0 && (pfd.revents & POLLIN)) if(pollres > 0 && (pfd.revents & POLLIN))
{ {
int n = soc_recvfrom(sock, buf, 20, 0, NULL, 0); int n = socRecvfrom(sock, buf, 20, 0, NULL, 0);
if(n < 0) if(n < 0)
break; break;
else if(n < 12) else if(n < 12)
@@ -125,21 +149,40 @@ void inputRedirectionThreadMain(void)
srvPublishToSubscriber(0x203, 0); srvPublishToSubscriber(0x203, 0);
} }
} }
else if(pollres < -10000)
break;
} }
inputRedirectionEnabled = false;
struct linger linger; struct linger linger;
linger.l_onoff = 1; linger.l_onoff = 1;
linger.l_linger = 0; linger.l_linger = 0;
socSetsockopt(sock, SOL_SOCKET, SO_LINGER, &linger, sizeof(struct linger)); socSetsockopt(sock, SOL_SOCKET, SO_LINGER, &linger, sizeof(struct linger));
socClose(sock); socClose(sock);
miniSocExit(); miniSocExit();
} }
void hidCodePatchFunc(void); void hidCodePatchFunc(void);
void irCodePatchFunc(void); void irCodePatchFunc(void);
Result InputRedirection_Disable(s64 timeout)
{
if(!inputRedirectionEnabled)
return 0;
Result res = InputRedirection_DoOrUndoPatches();
if(R_FAILED(res))
return res;
inputRedirectionEnabled = false;
res = MyThread_Join(&inputRedirectionThread, timeout);
svcCloseHandle(inputRedirectionThreadStartedEvent);
return res;
}
Result InputRedirection_DoOrUndoPatches(void) Result InputRedirection_DoOrUndoPatches(void)
{ {
s64 startAddress, textTotalRoundedSize, rodataTotalRoundedSize, dataTotalRoundedSize; s64 startAddress, textTotalRoundedSize, rodataTotalRoundedSize, dataTotalRoundedSize;
@@ -147,6 +190,8 @@ Result InputRedirection_DoOrUndoPatches(void)
Handle processHandle; Handle processHandle;
Result res = OpenProcessByName("hid", &processHandle); Result res = OpenProcessByName("hid", &processHandle);
static bool hidPatched = false;
static bool irPatched = false;
if(R_SUCCEEDED(res)) if(R_SUCCEEDED(res))
{ {
@@ -173,11 +218,12 @@ Result InputRedirection_DoOrUndoPatches(void)
static u32 *hidRegPatchOffsets[2]; static u32 *hidRegPatchOffsets[2];
static u32 *hidPatchJumpLoc; static u32 *hidPatchJumpLoc;
if(inputRedirectionEnabled) if(hidPatched)
{ {
memcpy(hidRegPatchOffsets[0], &hidOrigRegisterAndValue, sizeof(hidOrigRegisterAndValue)); memcpy(hidRegPatchOffsets[0], &hidOrigRegisterAndValue, sizeof(hidOrigRegisterAndValue));
memcpy(hidRegPatchOffsets[1], &hidOrigRegisterAndValue, sizeof(hidOrigRegisterAndValue)); memcpy(hidRegPatchOffsets[1], &hidOrigRegisterAndValue, sizeof(hidOrigRegisterAndValue));
memcpy(hidPatchJumpLoc, &hidOrigCode, sizeof(hidOrigCode)); memcpy(hidPatchJumpLoc, &hidOrigCode, sizeof(hidOrigCode));
hidPatched = false;
} }
else else
{ {
@@ -218,6 +264,7 @@ Result InputRedirection_DoOrUndoPatches(void)
*off = *off2 = hidDataPhys; *off = *off2 = hidDataPhys;
memcpy(off3, &hidHook, sizeof(hidHook)); memcpy(off3, &hidHook, sizeof(hidHook));
hidPatched = true;
} }
} }
@@ -264,7 +311,7 @@ Result InputRedirection_DoOrUndoPatches(void)
static u32 *irHookLoc, *irWaitSyncLoc, *irCppFlagLoc; static u32 *irHookLoc, *irWaitSyncLoc, *irCppFlagLoc;
if(inputRedirectionEnabled) if(irPatched)
{ {
memcpy(irHookLoc, &irOrigReadingCode, sizeof(irOrigReadingCode)); memcpy(irHookLoc, &irOrigReadingCode, sizeof(irOrigReadingCode));
if(useOldSyncCode) if(useOldSyncCode)
@@ -272,6 +319,8 @@ Result InputRedirection_DoOrUndoPatches(void)
else else
memcpy(irWaitSyncLoc, &irOrigWaitSyncCode, sizeof(irOrigWaitSyncCode)); memcpy(irWaitSyncLoc, &irOrigWaitSyncCode, sizeof(irOrigWaitSyncCode));
memcpy(irCppFlagLoc, &irOrigCppFlagCode, sizeof(irOrigCppFlagCode)); memcpy(irCppFlagLoc, &irOrigCppFlagCode, sizeof(irOrigCppFlagCode));
irPatched = false;
} }
else else
{ {
@@ -331,6 +380,8 @@ Result InputRedirection_DoOrUndoPatches(void)
// This NOPs out a flag check in ir:user's CPP emulation // This NOPs out a flag check in ir:user's CPP emulation
*irCppFlagLoc = 0xE3150000; // tst r5, #0 *irCppFlagLoc = 0xE3150000; // tst r5, #0
irPatched = true;
} }
} }

View File

@@ -37,9 +37,15 @@
#include "menus/miscellaneous.h" #include "menus/miscellaneous.h"
#include "menus/debugger.h" #include "menus/debugger.h"
#include "menus/screen_filters.h" #include "menus/screen_filters.h"
#include "menus/cheats.h"
#include "menus/sysconfig.h"
#include "input_redirection.h"
#include "minisoc.h"
#include "task_runner.h" #include "task_runner.h"
bool isN3DS;
static Result stealFsReg(void) static Result stealFsReg(void)
{ {
Result ret = 0; Result ret = 0;
@@ -73,11 +79,51 @@ static Result fsRegSetupPermissions(void)
return res; return res;
} }
// this is called before main Result __sync_init(void);
bool isN3DS; Result __sync_fini(void);
void __appInit() void __libc_init_array(void);
void __libc_fini_array(void);
void __ctru_exit(int rc) { (void)rc; } // needed to avoid linking error
// this is called after main exits
void __wrap_exit(int rc)
{ {
(void)rc;
// TODO: make pm terminate rosalina
__libc_fini_array();
// Kernel will take care of it all
/*
pmDbgExit();
fsExit();
svcCloseHandle(*fsRegGetSessionHandle());
srvExit();
__sync_fini();*/
svcExitProcess();
}
// this is called before main
void initSystem(void)
{
s64 out;
Result res; Result res;
__sync_init();
isN3DS = svcGetSystemInfo(&out, 0x10001, 0) == 0;
svcGetSystemInfo(&out, 0x10000, 0x100);
HBLDR_3DSX_TID = out == 0 ? HBLDR_DEFAULT_3DSX_TID : (u64)out;
svcGetSystemInfo(&out, 0x10000, 0x101);
menuCombo = out == 0 ? DEFAULT_MENU_COMBO : (u32)out;
miscellaneousMenu.items[0].title = HBLDR_3DSX_TID == HBLDR_DEFAULT_3DSX_TID ? "Switch the hb. title to the current app." :
"Switch the hb. title to hblauncher_loader";
ProcessPatchesMenu_PatchUnpatchFSDirectly();
for(res = 0xD88007FA; res == (Result)0xD88007FA; svcSleepThread(500 * 1000LL)) for(res = 0xD88007FA; res == (Result)0xD88007FA; svcSleepThread(500 * 1000LL))
{ {
res = srvInit(); res = srvInit();
@@ -91,52 +137,9 @@ void __appInit()
if (R_FAILED(pmDbgInit())) if (R_FAILED(pmDbgInit()))
svcBreak(USERBREAK_PANIC); svcBreak(USERBREAK_PANIC);
if (R_FAILED(acInit())) // **** DO NOT init services that don't come from KIPs here ****
svcBreak(USERBREAK_PANIC); // Instead, init the service only where it's actually init (then deinit it).
}
// this is called after main exits
void __appExit()
{
acExit();
pmDbgExit();
fsExit();
svcCloseHandle(*fsRegGetSessionHandle());
srvExit();
}
Result __sync_init(void);
Result __sync_fini(void);
void __libc_init_array(void);
void __libc_fini_array(void);
void __ctru_exit()
{
__libc_fini_array();
__appExit();
__sync_fini();
svcExitProcess();
}
void initSystem()
{
s64 out;
isN3DS = svcGetSystemInfo(&out, 0x10001, 0) == 0;
svcGetSystemInfo(&out, 0x10000, 0x100);
HBLDR_3DSX_TID = out == 0 ? HBLDR_DEFAULT_3DSX_TID : (u64)out;
svcGetSystemInfo(&out, 0x10000, 0x101);
menuCombo = out == 0 ? DEFAULT_MENU_COMBO : (u32)out;
miscellaneousMenu.items[0].title = HBLDR_3DSX_TID == HBLDR_DEFAULT_3DSX_TID ? "Switch the hb. title to the current app." :
"Switch the hb. title to hblauncher_loader";
ProcessPatchesMenu_PatchUnpatchFSDirectly();
__sync_init();
__appInit();
__libc_init_array(); __libc_init_array();
// ROSALINA HACKJOB BEGIN // ROSALINA HACKJOB BEGIN
@@ -161,12 +164,31 @@ static void handleTermNotification(u32 notificationId)
svcSignalEvent(terminationRequestEvent); svcSignalEvent(terminationRequestEvent);
} }
static void relinquishConnectionSessions(u32 notificationId)
{
(void)notificationId;
// Might be subject to a race condition, but heh.
// Disable input redirection
InputRedirection_Disable(100 * 1000 * 1000LL);
// Ask the debugger to terminate in approx 2 * 100ms
debuggerDisable(100 * 1000 * 1000LL);
// Kill the ac session if needed
if(isConnectionForced)
{
acExit();
isConnectionForced = false;
SysConfigMenu_UpdateStatus(true);
}
}
static void handleNextApplicationDebuggedByForce(u32 notificationId) static void handleNextApplicationDebuggedByForce(u32 notificationId)
{ {
int dummy;
(void)notificationId; (void)notificationId;
// Following call needs to be async because pm -> Loader depends on rosalina hb:ldr, handled in this very thread. // Following call needs to be async because pm -> Loader depends on rosalina hb:ldr, handled in this very thread.
TaskRunner_RunTask(debuggerFetchAndSetNextApplicationDebugHandleTask, &dummy, 0); TaskRunner_RunTask(debuggerFetchAndSetNextApplicationDebugHandleTask, NULL, 0);
} }
static const ServiceManagerServiceEntry services[] = { static const ServiceManagerServiceEntry services[] = {
@@ -176,7 +198,9 @@ static const ServiceManagerServiceEntry services[] = {
static const ServiceManagerNotificationEntry notifications[] = { static const ServiceManagerNotificationEntry notifications[] = {
{ 0x100 , handleTermNotification }, { 0x100 , handleTermNotification },
//{ 0x103 , relinquishConnectionSessions }, // Sleep mode entry <=== causes issues
{ 0x1000, handleNextApplicationDebuggedByForce }, { 0x1000, handleNextApplicationDebuggedByForce },
{ 0x1001, relinquishConnectionSessions },
{ 0x000, NULL }, { 0x000, NULL },
}; };
@@ -195,6 +219,8 @@ int main(void)
if(R_FAILED(svcCreateEvent(&terminationRequestEvent, RESET_STICKY))) if(R_FAILED(svcCreateEvent(&terminationRequestEvent, RESET_STICKY)))
svcBreak(USERBREAK_ASSERT); svcBreak(USERBREAK_ASSERT);
Cheat_SeedRng(svcGetSystemTick());
MyThread *menuThread = menuCreateThread(); MyThread *menuThread = menuCreateThread();
MyThread *taskRunnerThread = taskRunnerCreateThread(); MyThread *taskRunnerThread = taskRunnerCreateThread();
MyThread *errDispThread = errDispCreateThread(); MyThread *errDispThread = errDispCreateThread();
@@ -202,6 +228,8 @@ int main(void)
if (R_FAILED(ServiceManager_Run(services, notifications, NULL))) if (R_FAILED(ServiceManager_Run(services, notifications, NULL)))
svcBreak(USERBREAK_PANIC); svcBreak(USERBREAK_PANIC);
TaskRunner_Terminate();
MyThread_Join(menuThread, -1LL); MyThread_Join(menuThread, -1LL);
MyThread_Join(taskRunnerThread, -1LL); MyThread_Join(taskRunnerThread, -1LL);
MyThread_Join(errDispThread, -1LL); MyThread_Join(errDispThread, -1LL);

View File

@@ -245,7 +245,7 @@ static void menuDraw(Menu *menu, u32 selected)
if(miniSocEnabled) if(miniSocEnabled)
{ {
char ipBuffer[17]; char ipBuffer[17];
u32 ip = gethostid(); u32 ip = socGethostid();
u8 *addr = (u8 *)&ip; u8 *addr = (u8 *)&ip;
int n = sprintf(ipBuffer, "%hhu.%hhu.%hhu.%hhu", addr[0], addr[1], addr[2], addr[3]); int n = sprintf(ipBuffer, "%hhu.%hhu.%hhu.%hhu", addr[0], addr[1], addr[2], addr[3]);
Draw_DrawString(SCREEN_BOT_WIDTH - 10 - SPACING_X * n, 10, COLOR_WHITE, ipBuffer); Draw_DrawString(SCREEN_BOT_WIDTH - 10 - SPACING_X * n, 10, COLOR_WHITE, ipBuffer);

View File

@@ -33,16 +33,11 @@
#include "utils.h" #include "utils.h"
#include "fmt.h" #include "fmt.h"
#include "ifile.h" #include "ifile.h"
#include "pmdbgext.h"
#define MAKE_QWORD(hi,low) \ #define MAKE_QWORD(hi,low) \
((u64) ((((u64)(hi)) << 32) | (low))) ((u64) ((((u64)(hi)) << 32) | (low)))
typedef struct CheatProcessInfo
{
u32 pid;
u64 titleId;
} CheatProcessInfo;
typedef struct CheatDescription typedef struct CheatDescription
{ {
struct { struct {
@@ -70,36 +65,6 @@ CheatDescription* cheats[1024] = { 0 };
u8 cheatBuffer[32768] = { 0 }; u8 cheatBuffer[32768] = { 0 };
u8 cheatPage[0x1000] = { 0 }; u8 cheatPage[0x1000] = { 0 };
static CheatProcessInfo cheatinfo[0x40] = { 0 };
static s32 Cheats_FetchProcessInfo(void)
{
u32 pidList[0x40];
s32 processAmount;
s64 sa, textTotalRoundedSize, rodataTotalRoundedSize, dataTotalRoundedSize;
svcGetProcessList(&processAmount, pidList, 0x40);
for (s32 i = 0; i < processAmount; i++)
{
Handle processHandle;
Result res = svcOpenProcess(&processHandle, pidList[i]);
if (R_FAILED(res)) continue;
cheatinfo[i].pid = pidList[i];
svcGetProcessInfo((s64 *) &cheatinfo[i].titleId, processHandle, 0x10001);
svcGetProcessInfo(&textTotalRoundedSize, processHandle, 0x10002);
svcGetProcessInfo(&rodataTotalRoundedSize, processHandle, 0x10003);
svcGetProcessInfo(&dataTotalRoundedSize, processHandle, 0x10004);
svcGetProcessInfo(&sa, processHandle, 0x10005);
svcCloseHandle(processHandle);
}
return processAmount;
}
typedef struct CheatState typedef struct CheatState
{ {
u32 index; u32 index;
@@ -131,6 +96,7 @@ typedef struct CheatState
CheatState cheat_state = { 0 }; CheatState cheat_state = { 0 };
u8 cheatCount = 0; u8 cheatCount = 0;
u64 cheatTitleInfo = -1ULL; u64 cheatTitleInfo = -1ULL;
u64 cheatRngState = 0;
static inline u32* activeOffset() static inline u32* activeOffset()
{ {
@@ -149,6 +115,12 @@ static inline u32* activeStorage(CheatDescription* desc)
char failureReason[64]; char failureReason[64];
static u32 Cheat_GetRandomNumber(void)
{
cheatRngState = 0x5D588B656C078965ULL * cheatRngState + 0x0000000000269EC3ULL;
return (u32)(cheatRngState >> 32);
}
static bool Cheat_IsValidAddress(const Handle processHandle, u32 address, u32 size) static bool Cheat_IsValidAddress(const Handle processHandle, u32 address, u32 size)
{ {
MemInfo info; MemInfo info;
@@ -1512,7 +1484,7 @@ static u32 Cheat_ApplyCheat(const Handle processHandle, CheatDescription* const
case 0xF: case 0xF:
{ {
u32 range = arg1 - (arg0 & 0xFFFFFF); u32 range = arg1 - (arg0 & 0xFFFFFF);
u32 number = rand() % range; u32 number = Cheat_GetRandomNumber() % range;
*activeData() = (arg0 & 0xFFFFFF) + number; *activeData() = (arg0 & 0xFFFFFF) + number;
} }
break; break;
@@ -1886,33 +1858,20 @@ static void Cheat_LoadCheatsIntoMemory(u64 titleId)
memset(cheatPage, 0, 0x1000); memset(cheatPage, 0, 0x1000);
} }
static u32 Cheat_GetCurrentPID(u64* titleId) static u32 Cheat_GetCurrentProcessAndTitleId(u64* titleId)
{ {
s32 processAmount = Cheats_FetchProcessInfo(); u32 pid;
Result res = PMDBG_GetCurrentAppTitleIdAndPid(titleId, &pid);
s32 index = -1; if (R_FAILED(res)) {
for (s32 i = 0; i < processAmount; i++)
{
if (((u32) (cheatinfo[i].titleId >> 32)) == 0x00040010 || ((u32) (cheatinfo[i].titleId >> 32) == 0x00040000))
{
index = i;
break;
}
}
if (index != -1)
{
*titleId = cheatinfo[index].titleId;
return cheatinfo[index].pid;
}
else
{
*titleId = 0; *titleId = 0;
return 0xFFFFFFFF; return 0xFFFFFFFF;
} }
return pid;
}
void Cheat_SeedRng(u64 seed)
{
cheatRngState = seed;
} }
void Cheat_ApplyCheats(void) void Cheat_ApplyCheats(void)
@@ -1923,7 +1882,7 @@ void Cheat_ApplyCheats(void)
} }
u64 titleId = 0; u64 titleId = 0;
u32 pid = Cheat_GetCurrentPID(&titleId); u32 pid = Cheat_GetCurrentProcessAndTitleId(&titleId);
if (!titleId) if (!titleId)
{ {
@@ -1949,7 +1908,7 @@ void Cheat_ApplyCheats(void)
void RosalinaMenu_Cheats(void) void RosalinaMenu_Cheats(void)
{ {
u64 titleId = 0; u64 titleId = 0;
u32 pid = Cheat_GetCurrentPID(&titleId); u32 pid = Cheat_GetCurrentProcessAndTitleId(&titleId);
if (titleId != 0) if (titleId != 0)
{ {

View File

@@ -84,6 +84,30 @@ void debuggerFetchAndSetNextApplicationDebugHandleTask(void *argdata)
GDB_UnlockAllContexts(&gdbServer); GDB_UnlockAllContexts(&gdbServer);
} }
Result debuggerDisable(s64 timeout)
{
Result res = 0;
bool initialized = gdbServer.referenceCount != 0;
if(initialized)
{
svcSignalEvent(gdbServer.super.shall_terminate_event);
server_kill_connections(&gdbServer.super);
res = MyThread_Join(&debuggerDebugThread, timeout);
if(res == 0)
res = MyThread_Join(&debuggerSocketThread, timeout);
Handle dummy = 0;
PMDBG_RunQueuedProcess(&dummy);
svcCloseHandle(dummy);
PMDBG_DebugNextApplicationByForce(false);
nextApplicationGdbCtx = NULL;
svcKernelSetState(0x10000, 2);
}
return res;
}
void DebuggerMenu_EnableDebugger(void) void DebuggerMenu_EnableDebugger(void)
{ {
bool done = false, alreadyEnabled = gdbServer.super.running; bool done = false, alreadyEnabled = gdbServer.super.running;
@@ -115,16 +139,18 @@ void DebuggerMenu_EnableDebugger(void)
if(!done) if(!done)
{ {
res = GDB_InitializeServer(&gdbServer); res = GDB_InitializeServer(&gdbServer);
Handle handles[3] = { gdbServer.super.started_event, gdbServer.super.shall_terminate_event, terminationRequestEvent };
s32 idx;
if(R_SUCCEEDED(res)) if(R_SUCCEEDED(res))
{ {
debuggerCreateSocketThread(); debuggerCreateSocketThread();
debuggerCreateDebugThread(); debuggerCreateDebugThread();
res = svcWaitSynchronization(gdbServer.super.started_event, 10 * 1000 * 1000 * 1000LL); res = svcWaitSynchronizationN(&idx, handles, 3, false, 10 * 1000 * 1000 * 1000LL);
if(res == 0) res = gdbServer.super.init_result;
} }
if(res != 0) if(res != 0)
sprintf(buf, "Starting debugger... failed (0x%08lx).", (u32)res); sprintf(buf, "Starting debugger... failed (0x%08lx).", (u32)res);
done = true; done = true;
} }
if(res == 0) if(res == 0)
@@ -142,27 +168,10 @@ void DebuggerMenu_EnableDebugger(void)
void DebuggerMenu_DisableDebugger(void) void DebuggerMenu_DisableDebugger(void)
{ {
bool initialized = gdbServer.referenceCount != 0; bool initialized = gdbServer.referenceCount != 0;
Result res = 0;
Result res = initialized ? debuggerDisable(2 * 1000 * 1000 * 1000LL) : 0;
char buf[65]; char buf[65];
if(initialized)
{
svcSignalEvent(gdbServer.super.shall_terminate_event);
server_kill_connections(&gdbServer.super);
//server_set_should_close_all(&gdbServer.super);
res = MyThread_Join(&debuggerDebugThread, 2 * 1000 * 1000 * 1000LL);
if(res == 0)
res = MyThread_Join(&debuggerSocketThread, 2 * 1000 * 1000 * 1000LL);
Handle dummy = 0;
PMDBG_RunQueuedProcess(&dummy);
svcCloseHandle(dummy);
PMDBG_DebugNextApplicationByForce(false);
nextApplicationGdbCtx = NULL;
svcKernelSetState(0x10000, 2);
}
if(res != 0) if(res != 0)
sprintf(buf, "Failed to disable debugger (0x%08lx).", (u32)res); sprintf(buf, "Failed to disable debugger (0x%08lx).", (u32)res);

View File

@@ -221,7 +221,6 @@ void MiscellaneousMenu_SaveSettings(void)
void MiscellaneousMenu_InputRedirection(void) void MiscellaneousMenu_InputRedirection(void)
{ {
static MyThread *inputRedirectionThread = NULL;
bool done = false; bool done = false;
Result res; Result res;
@@ -231,11 +230,7 @@ void MiscellaneousMenu_InputRedirection(void)
if(wasEnabled) if(wasEnabled)
{ {
res = InputRedirection_DoOrUndoPatches(); res = InputRedirection_Disable(5 * 1000 * 1000 * 1000LL);
inputRedirectionEnabled = false;
res = MyThread_Join(inputRedirectionThread, 5 * 1000 * 1000 * 1000LL);
svcCloseHandle(inputRedirectionThreadStartedEvent);
if(res != 0) if(res != 0)
sprintf(buf, "Failed to stop InputRedirection (0x%08lx).", (u32)res); sprintf(buf, "Failed to stop InputRedirection (0x%08lx).", (u32)res);
else else
@@ -282,13 +277,18 @@ void MiscellaneousMenu_InputRedirection(void)
res = svcCreateEvent(&inputRedirectionThreadStartedEvent, RESET_STICKY); res = svcCreateEvent(&inputRedirectionThreadStartedEvent, RESET_STICKY);
if(R_SUCCEEDED(res)) if(R_SUCCEEDED(res))
{ {
inputRedirectionThread = inputRedirectionCreateThread(); inputRedirectionCreateThread();
res = svcWaitSynchronization(inputRedirectionThreadStartedEvent, 10 * 1000 * 1000 * 1000LL); res = svcWaitSynchronization(inputRedirectionThreadStartedEvent, 10 * 1000 * 1000 * 1000LL);
if(res == 0) if(res == 0)
res = (Result)inputRedirectionStartResult; res = (Result)inputRedirectionStartResult;
if(res != 0) if(res != 0)
{
svcCloseHandle(inputRedirectionThreadStartedEvent);
InputRedirection_DoOrUndoPatches(); InputRedirection_DoOrUndoPatches();
inputRedirectionEnabled = false;
}
inputRedirectionStartResult = 0;
} }
} }

View File

@@ -104,7 +104,7 @@ static void ProcessListMenu_DumpMemory(const char *name, void *start, u32 size)
IFile file; IFile file;
Result res; Result res;
char filename[64] = {0}; char filename[100] = {0};
FS_Archive archive; FS_Archive archive;
FS_ArchiveID archiveId; FS_ArchiveID archiveId;
@@ -666,7 +666,7 @@ void RosalinaMenu_ProcessList(void)
if(gdbServer.super.running) if(gdbServer.super.running)
{ {
char ipBuffer[17]; char ipBuffer[17];
u32 ip = gethostid(); u32 ip = socGethostid();
u8 *addr = (u8 *)&ip; u8 *addr = (u8 *)&ip;
int n = sprintf(ipBuffer, "%hhu.%hhu.%hhu.%hhu", addr[0], addr[1], addr[2], addr[3]); int n = sprintf(ipBuffer, "%hhu.%hhu.%hhu.%hhu", addr[0], addr[1], addr[2], addr[3]);
Draw_DrawString(SCREEN_BOT_WIDTH - 10 - SPACING_X * n, 10, COLOR_WHITE, ipBuffer); Draw_DrawString(SCREEN_BOT_WIDTH - 10 - SPACING_X * n, 10, COLOR_WHITE, ipBuffer);

View File

@@ -43,6 +43,8 @@ Menu sysconfigMenu = {
} }
}; };
bool isConnectionForced = false;
void SysConfigMenu_ToggleLEDs(void) void SysConfigMenu_ToggleLEDs(void)
{ {
Draw_Lock(); Draw_Lock();
@@ -149,9 +151,29 @@ void SysConfigMenu_ToggleWireless(void)
while(!terminationRequest); while(!terminationRequest);
} }
static void SysConfigMenu_ForceWifiConnection(int slot) void SysConfigMenu_UpdateStatus(bool control)
{
MenuItem *item = &sysconfigMenu.items[3];
if(control)
{
item->title = "Control Wireless connection";
item->method = &SysConfigMenu_ControlWifi;
}
else
{
item->title = "Disable forced wireless connection";
item->method = &SysConfigMenu_DisableForcedWifiConnection;
}
}
static bool SysConfigMenu_ForceWifiConnection(int slot)
{ {
char ssid[0x20 + 1] = {0}; char ssid[0x20 + 1] = {0};
isConnectionForced = false;
if(R_FAILED(acInit()))
return false;
acuConfig config = {0}; acuConfig config = {0};
ACU_CreateDefaultConfig(&config); ACU_CreateDefaultConfig(&config);
@@ -165,14 +187,19 @@ static void SysConfigMenu_ForceWifiConnection(int slot)
bool forcedConnection = false; bool forcedConnection = false;
if(R_SUCCEEDED(ACU_ConnectAsync(&config, connectEvent))) if(R_SUCCEEDED(ACU_ConnectAsync(&config, connectEvent)))
{ {
if(R_SUCCEEDED(svcWaitSynchronization(connectEvent, -1))) if(R_SUCCEEDED(svcWaitSynchronization(connectEvent, -1)) && R_SUCCEEDED(ACU_GetSSID(ssid)))
{
ACU_GetSSID(ssid);
forcedConnection = true; forcedConnection = true;
}
} }
svcCloseHandle(connectEvent); svcCloseHandle(connectEvent);
if(forcedConnection)
{
isConnectionForced = true;
SysConfigMenu_UpdateStatus(false);
}
else
acExit();
char infoString[80] = {0}; char infoString[80] = {0};
u32 infoStringColor = forcedConnection ? COLOR_GREEN : COLOR_RED; u32 infoStringColor = forcedConnection ? COLOR_GREEN : COLOR_RED;
if(forcedConnection) if(forcedConnection)
@@ -198,9 +225,11 @@ static void SysConfigMenu_ForceWifiConnection(int slot)
u32 pressed = waitInputWithTimeout(1000); u32 pressed = waitInputWithTimeout(1000);
if(pressed & BUTTON_B) if(pressed & BUTTON_B)
return; break;
} }
while(!terminationRequest); while(!terminationRequest);
return forcedConnection;
} }
void SysConfigMenu_TogglePowerButton(void) void SysConfigMenu_TogglePowerButton(void)
@@ -269,7 +298,11 @@ void SysConfigMenu_ControlWifi(void)
if(pressed & BUTTON_A) if(pressed & BUTTON_A)
{ {
SysConfigMenu_ForceWifiConnection(slot); if(SysConfigMenu_ForceWifiConnection(slot))
{
// Connection successfully forced, return from this menu to prevent ac handle refcount leakage.
break;
}
Draw_Lock(); Draw_Lock();
Draw_ClearFramebuffer(); Draw_ClearFramebuffer();
@@ -301,3 +334,26 @@ void SysConfigMenu_ControlWifi(void)
} }
while(!terminationRequest); while(!terminationRequest);
} }
void SysConfigMenu_DisableForcedWifiConnection(void)
{
Draw_Lock();
Draw_ClearFramebuffer();
Draw_FlushFramebuffer();
Draw_Unlock();
acExit();
SysConfigMenu_UpdateStatus(true);
do
{
Draw_Lock();
Draw_DrawString(10, 10, COLOR_TITLE, "System configuration menu");
Draw_DrawString(10, 30, COLOR_WHITE, "Forced connection successfully disabled.\nNote: auto-connection may remain broken.");
u32 pressed = waitInputWithTimeout(1000);
if(pressed & BUTTON_B)
return;
}
while(!terminationRequest);
}

View File

@@ -10,7 +10,16 @@
#include <3ds/ipc.h> #include <3ds/ipc.h>
#include <3ds/os.h> #include <3ds/os.h>
#include <3ds/synchronization.h> #include <3ds/synchronization.h>
#include "memory.h" #include <3ds/result.h>
#include <string.h>
s32 miniSocRefCount = 0;
static u32 socContextAddr = 0x08000000;
static u32 socContextSize = 0x60000;
static Handle miniSocHandle;
static Handle miniSocMemHandle;
bool miniSocEnabled = false;
s32 _net_convert_error(s32 sock_retval); s32 _net_convert_error(s32 sock_retval);
@@ -25,7 +34,7 @@ static Result SOCU_Initialize(Handle memhandle, u32 memsize)
cmdbuf[4] = IPC_Desc_SharedHandles(1); cmdbuf[4] = IPC_Desc_SharedHandles(1);
cmdbuf[5] = memhandle; cmdbuf[5] = memhandle;
ret = svcSendSyncRequest(SOCU_handle); ret = svcSendSyncRequest(miniSocHandle);
if(ret != 0) if(ret != 0)
return ret; return ret;
@@ -39,22 +48,14 @@ static Result SOCU_Shutdown(void)
cmdbuf[0] = IPC_MakeHeader(0x19,0,0); // 0x190000 cmdbuf[0] = IPC_MakeHeader(0x19,0,0); // 0x190000
ret = svcSendSyncRequest(SOCU_handle); ret = svcSendSyncRequest(miniSocHandle);
if(ret != 0) if(ret != 0)
return ret; return ret;
return cmdbuf[1]; return cmdbuf[1];
} }
static s32 miniSocRefCount = 0; Result miniSocInit(void)
static u32 socContextAddr = 0x08000000;
static u32 socContextSize = 0x60000;
// SOCU_handle from ctrulib
// socMemhandle from ctrulib
bool miniSocEnabled = false;
Result miniSocInit()
{ {
if(AtomicPostIncrement(&miniSocRefCount)) if(AtomicPostIncrement(&miniSocRefCount))
return 0; return 0;
@@ -71,7 +72,7 @@ Result miniSocInit()
goto cleanup; goto cleanup;
} }
ret = srvGetServiceHandle(&SOCU_handle, "soc:U"); ret = srvGetServiceHandle(&miniSocHandle, "soc:U");
if(ret != 0) goto cleanup; if(ret != 0) goto cleanup;
ret = svcControlMemory(&tmp, socContextAddr, 0, socContextSize, MEMOP_ALLOC, MEMPERM_READ | MEMPERM_WRITE); ret = svcControlMemory(&tmp, socContextAddr, 0, socContextSize, MEMOP_ALLOC, MEMPERM_READ | MEMPERM_WRITE);
@@ -79,12 +80,12 @@ Result miniSocInit()
socContextAddr = tmp; socContextAddr = tmp;
ret = svcCreateMemoryBlock(&socMemhandle, (u32)socContextAddr, socContextSize, 0, 3); ret = svcCreateMemoryBlock(&miniSocMemHandle, (u32)socContextAddr, socContextSize, 0, 3);
if(ret != 0) goto cleanup; if(ret != 0) goto cleanup;
ret = SOCU_Initialize(socMemhandle, socContextSize); ret = SOCU_Initialize(miniSocMemHandle, socContextSize);
if(ret != 0) goto cleanup; if(ret != 0) goto cleanup;
svcKernelSetState(0x10000, 2); svcKernelSetState(0x10000, 2);
@@ -94,17 +95,17 @@ Result miniSocInit()
cleanup: cleanup:
AtomicDecrement(&miniSocRefCount); AtomicDecrement(&miniSocRefCount);
if(socMemhandle != 0) if(miniSocMemHandle != 0)
{ {
svcCloseHandle(socMemhandle); svcCloseHandle(miniSocMemHandle);
socMemhandle = 0; miniSocMemHandle = 0;
} }
if(SOCU_handle != 0) if(miniSocHandle != 0)
{ {
SOCU_Shutdown(); SOCU_Shutdown();
svcCloseHandle(SOCU_handle); svcCloseHandle(miniSocHandle);
SOCU_handle = 0; miniSocHandle = 0;
} }
if(tmp != 0) if(tmp != 0)
@@ -113,21 +114,19 @@ cleanup:
return ret; return ret;
} }
Result miniSocExit(void) Result miniSocExitDirect(void)
{ {
if(AtomicDecrement(&miniSocRefCount)) //if (miniSocRefCount != 0) __builtin_trap();
return 0;
Result ret = 0; Result ret = 0;
u32 tmp; u32 tmp;
svcCloseHandle(socMemhandle); svcCloseHandle(miniSocMemHandle);
socMemhandle = 0; miniSocMemHandle = 0;
ret = SOCU_Shutdown(); ret = SOCU_Shutdown();
svcCloseHandle(SOCU_handle); svcCloseHandle(miniSocHandle);
SOCU_handle = 0; miniSocHandle = 0;
svcControlMemory(&tmp, socContextAddr, socContextAddr, socContextSize, MEMOP_FREE, MEMPERM_DONTCARE); svcControlMemory(&tmp, socContextAddr, socContextAddr, socContextSize, MEMOP_FREE, MEMPERM_DONTCARE);
if(ret == 0) if(ret == 0)
@@ -138,6 +137,14 @@ Result miniSocExit(void)
return ret; return ret;
} }
Result miniSocExit(void)
{
if(!miniSocEnabled || AtomicDecrement(&miniSocRefCount))
return 0;
return miniSocExitDirect();
}
int socSocket(int domain, int type, int protocol) int socSocket(int domain, int type, int protocol)
{ {
int ret = 0; int ret = 0;
@@ -163,11 +170,11 @@ int socSocket(int domain, int type, int protocol)
cmdbuf[3] = protocol; cmdbuf[3] = protocol;
cmdbuf[4] = IPC_Desc_CurProcessId(); cmdbuf[4] = IPC_Desc_CurProcessId();
ret = svcSendSyncRequest(SOCU_handle); ret = svcSendSyncRequest(miniSocHandle);
if(ret != 0) if(ret != 0)
{ {
//errno = SYNC_ERROR; //errno = SYNC_ERROR;
return ret; return R_FAILED(ret) ? ret : -1;
} }
ret = (int)cmdbuf[1]; ret = (int)cmdbuf[1];
@@ -213,7 +220,7 @@ int socBind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
cmdbuf[5] = IPC_Desc_StaticBuffer(tmp_addrlen,0); cmdbuf[5] = IPC_Desc_StaticBuffer(tmp_addrlen,0);
cmdbuf[6] = (u32)tmpaddr; cmdbuf[6] = (u32)tmpaddr;
ret = svcSendSyncRequest(SOCU_handle); ret = svcSendSyncRequest(miniSocHandle);
if(ret != 0) { if(ret != 0) {
//errno = SYNC_ERROR; //errno = SYNC_ERROR;
return ret; return ret;
@@ -241,7 +248,7 @@ int socListen(int sockfd, int max_connections)
cmdbuf[2] = (u32)max_connections; cmdbuf[2] = (u32)max_connections;
cmdbuf[3] = IPC_Desc_CurProcessId(); cmdbuf[3] = IPC_Desc_CurProcessId();
ret = svcSendSyncRequest(SOCU_handle); ret = svcSendSyncRequest(miniSocHandle);
if(ret != 0) if(ret != 0)
{ {
//errno = SYNC_ERROR; //errno = SYNC_ERROR;
@@ -283,7 +290,7 @@ int socAccept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
staticbufs[0] = IPC_Desc_StaticBuffer(tmp_addrlen,0); staticbufs[0] = IPC_Desc_StaticBuffer(tmp_addrlen,0);
staticbufs[1] = (u32)tmpaddr; staticbufs[1] = (u32)tmpaddr;
ret = svcSendSyncRequest(SOCU_handle); ret = svcSendSyncRequest(miniSocHandle);
staticbufs[0] = saved_threadstorage[0]; staticbufs[0] = saved_threadstorage[0];
staticbufs[1] = saved_threadstorage[1]; staticbufs[1] = saved_threadstorage[1];
@@ -340,7 +347,7 @@ int socConnect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
cmdbuf[5] = IPC_Desc_StaticBuffer(tmp_addrlen,0); cmdbuf[5] = IPC_Desc_StaticBuffer(tmp_addrlen,0);
cmdbuf[6] = (u32)tmpaddr; cmdbuf[6] = (u32)tmpaddr;
ret = svcSendSyncRequest(SOCU_handle); ret = svcSendSyncRequest(miniSocHandle);
if(ret != 0) return -1; if(ret != 0) return -1;
ret = (int)cmdbuf[1]; ret = (int)cmdbuf[1];
@@ -383,13 +390,13 @@ int socPoll(struct pollfd *fds, nfds_t nfds, int timeout)
staticbufs[0] = IPC_Desc_StaticBuffer(size,0); staticbufs[0] = IPC_Desc_StaticBuffer(size,0);
staticbufs[1] = (u32)fds; staticbufs[1] = (u32)fds;
ret = svcSendSyncRequest(SOCU_handle); ret = svcSendSyncRequest(miniSocHandle);
staticbufs[0] = saved_threadstorage[0]; staticbufs[0] = saved_threadstorage[0];
staticbufs[1] = saved_threadstorage[1]; staticbufs[1] = saved_threadstorage[1];
if(ret != 0) { if(ret != 0) {
return ret; return R_FAILED(ret) ? ret : -1;
} }
ret = (int)cmdbuf[1]; ret = (int)cmdbuf[1];
@@ -408,7 +415,7 @@ int socClose(int sockfd)
cmdbuf[1] = (u32)sockfd; cmdbuf[1] = (u32)sockfd;
cmdbuf[2] = IPC_Desc_CurProcessId(); cmdbuf[2] = IPC_Desc_CurProcessId();
ret = svcSendSyncRequest(SOCU_handle); ret = svcSendSyncRequest(miniSocHandle);
if(ret != 0) { if(ret != 0) {
//errno = SYNC_ERROR; //errno = SYNC_ERROR;
return ret; return ret;
@@ -440,7 +447,7 @@ int socSetsockopt(int sockfd, int level, int optname, const void *optval, sockle
cmdbuf[7] = IPC_Desc_StaticBuffer(optlen,9); cmdbuf[7] = IPC_Desc_StaticBuffer(optlen,9);
cmdbuf[8] = (u32)optval; cmdbuf[8] = (u32)optval;
ret = svcSendSyncRequest(SOCU_handle); ret = svcSendSyncRequest(miniSocHandle);
if(ret != 0) { if(ret != 0) {
return ret; return ret;
} }
@@ -457,12 +464,262 @@ int socSetsockopt(int sockfd, int level, int optname, const void *optval, sockle
return ret; return ret;
} }
ssize_t soc_recv(int sockfd, void *buf, size_t len, int flags) long socGethostid(void)
{ {
return soc_recvfrom(sockfd, buf, len, flags, NULL, 0); int ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x16,0,0); // 0x160000
ret = svcSendSyncRequest(miniSocHandle);
if(ret != 0) {
//errno = SYNC_ERROR;
return -1;
}
ret = (int)cmdbuf[1];
if(ret == 0)
ret = cmdbuf[2];
return ret;
} }
ssize_t soc_send(int sockfd, const void *buf, size_t len, int flags) static ssize_t _socuipc_cmd7(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen)
{ {
return soc_sendto(sockfd, buf, len, flags, NULL, 0); int ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
u32 tmp_addrlen = 0;
u8 tmpaddr[0x1c];
u32 saved_threadstorage[2];
memset(tmpaddr, 0, 0x1c);
if(src_addr)
tmp_addrlen = 0x1c;
cmdbuf[0] = IPC_MakeHeader(0x7,4,4); // 0x70104
cmdbuf[1] = (u32)sockfd;
cmdbuf[2] = (u32)len;
cmdbuf[3] = (u32)flags;
cmdbuf[4] = (u32)tmp_addrlen;
cmdbuf[5] = IPC_Desc_CurProcessId();
cmdbuf[7] = IPC_Desc_Buffer(len,IPC_BUFFER_W);
cmdbuf[8] = (u32)buf;
u32 * staticbufs = getThreadStaticBuffers();
saved_threadstorage[0] = staticbufs[0];
saved_threadstorage[1] = staticbufs[1];
staticbufs[0] = IPC_Desc_StaticBuffer(tmp_addrlen,0);
staticbufs[1] = (u32)tmpaddr;
ret = svcSendSyncRequest(miniSocHandle);
staticbufs[0] = saved_threadstorage[0];
staticbufs[1] = saved_threadstorage[1];
if(ret != 0) {
//errno = SYNC_ERROR;
return -1;
}
ret = (int)cmdbuf[1];
if(ret == 0)
ret = _net_convert_error(cmdbuf[2]);
if(ret < 0) {
//errno = -ret;
return -1;
}
if(src_addr != NULL) {
src_addr->sa_family = tmpaddr[1];
if(*addrlen > tmpaddr[0])
*addrlen = tmpaddr[0];
memcpy(src_addr->sa_data, &tmpaddr[2], *addrlen - 2);
}
return ret;
}
static ssize_t _socuipc_cmd8(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen)
{
int ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
u32 tmp_addrlen = 0;
u8 tmpaddr[0x1c];
u32 saved_threadstorage[4];
if(src_addr)
tmp_addrlen = 0x1c;
memset(tmpaddr, 0, 0x1c);
cmdbuf[0] = 0x00080102;
cmdbuf[1] = (u32)sockfd;
cmdbuf[2] = (u32)len;
cmdbuf[3] = (u32)flags;
cmdbuf[4] = (u32)tmp_addrlen;
cmdbuf[5] = 0x20;
saved_threadstorage[0] = cmdbuf[0x100>>2];
saved_threadstorage[1] = cmdbuf[0x104>>2];
saved_threadstorage[2] = cmdbuf[0x108>>2];
saved_threadstorage[3] = cmdbuf[0x10c>>2];
cmdbuf[0x100>>2] = (((u32)len)<<14) | 2;
cmdbuf[0x104>>2] = (u32)buf;
cmdbuf[0x108>>2] = (tmp_addrlen<<14) | 2;
cmdbuf[0x10c>>2] = (u32)tmpaddr;
ret = svcSendSyncRequest(miniSocHandle);
if(ret != 0) {
//errno = SYNC_ERROR;
return ret;
}
cmdbuf[0x100>>2] = saved_threadstorage[0];
cmdbuf[0x104>>2] = saved_threadstorage[1];
cmdbuf[0x108>>2] = saved_threadstorage[2];
cmdbuf[0x10c>>2] = saved_threadstorage[3];
ret = (int)cmdbuf[1];
if(ret == 0)
ret = _net_convert_error(cmdbuf[2]);
if(ret < 0) {
//errno = -ret;
return -1;
}
if(src_addr != NULL) {
src_addr->sa_family = tmpaddr[1];
if(*addrlen > tmpaddr[0])
*addrlen = tmpaddr[0];
memcpy(src_addr->sa_data, &tmpaddr[2], *addrlen - 2);
}
return ret;
}
static ssize_t _socuipc_cmd9(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen)
{
int ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
u32 tmp_addrlen = 0;
u8 tmpaddr[0x1c];
memset(tmpaddr, 0, 0x1c);
if(dest_addr) {
if(dest_addr->sa_family == AF_INET)
tmp_addrlen = 8;
else
tmp_addrlen = 0x1c;
if(addrlen < tmp_addrlen) {
//errno = EINVAL;
return -1;
}
tmpaddr[0] = tmp_addrlen;
tmpaddr[1] = dest_addr->sa_family;
memcpy(&tmpaddr[2], &dest_addr->sa_data, tmp_addrlen-2);
}
cmdbuf[0] = IPC_MakeHeader(0x9,4,6); // 0x90106
cmdbuf[1] = (u32)sockfd;
cmdbuf[2] = (u32)len;
cmdbuf[3] = (u32)flags;
cmdbuf[4] = (u32)tmp_addrlen;
cmdbuf[5] = IPC_Desc_CurProcessId();
cmdbuf[7] = IPC_Desc_StaticBuffer(tmp_addrlen,1);
cmdbuf[8] = (u32)tmpaddr;
cmdbuf[9] = IPC_Desc_Buffer(len,IPC_BUFFER_R);
cmdbuf[10] = (u32)buf;
ret = svcSendSyncRequest(miniSocHandle);
if(ret != 0) {
//errno = SYNC_ERROR;
return ret;
}
ret = (int)cmdbuf[1];
if(ret == 0)
ret = _net_convert_error(cmdbuf[2]);
if(ret < 0) {
//errno = -ret;
return -1;
}
return ret;
}
static ssize_t _socuipc_cmda(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen)
{
int ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
u32 tmp_addrlen = 0;
u8 tmpaddr[0x1c];
memset(tmpaddr, 0, 0x1c);
if(dest_addr) {
if(dest_addr->sa_family == AF_INET)
tmp_addrlen = 8;
else
tmp_addrlen = 0x1c;
if(addrlen < tmp_addrlen) {
//errno = EINVAL;
return -1;
}
tmpaddr[0] = tmp_addrlen;
tmpaddr[1] = dest_addr->sa_family;
memcpy(&tmpaddr[2], &dest_addr->sa_data, tmp_addrlen-2);
}
cmdbuf[0] = IPC_MakeHeader(0xA,4,6); // 0xA0106
cmdbuf[1] = (u32)sockfd;
cmdbuf[2] = (u32)len;
cmdbuf[3] = (u32)flags;
cmdbuf[4] = (u32)tmp_addrlen;
cmdbuf[5] = IPC_Desc_CurProcessId();
cmdbuf[7] = IPC_Desc_StaticBuffer(len,2);
cmdbuf[8] = (u32)buf;
cmdbuf[9] = IPC_Desc_StaticBuffer(tmp_addrlen,1);
cmdbuf[10] = (u32)tmpaddr;
ret = svcSendSyncRequest(miniSocHandle);
if(ret != 0) {
//errno = SYNC_ERROR;
return ret;
}
ret = (int)cmdbuf[1];
if(ret == 0)
ret = _net_convert_error(cmdbuf[2]);
if(ret < 0) {
//errno = -ret;
return -1;
}
return ret;
}
ssize_t socRecvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen)
{
if(len < 0x2000)
return _socuipc_cmd8(sockfd, buf, len, flags, src_addr, addrlen);
return _socuipc_cmd7(sockfd, buf, len, flags, src_addr, addrlen);
}
ssize_t socSendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen)
{
if(len < 0x2000)
return _socuipc_cmda(sockfd, buf, len, flags, dest_addr, addrlen);
return _socuipc_cmd9(sockfd, buf, len, flags, dest_addr, addrlen);
} }

View File

@@ -104,6 +104,11 @@ Result ntpGetTimeStamp(time_t *outTimestamp)
return res; return res;
int sock = socSocket(AF_INET, SOCK_DGRAM, 0); int sock = socSocket(AF_INET, SOCK_DGRAM, 0);
if (sock < -10000) {
// Socket services broken
return sock;
}
struct sockaddr_in servAddr = {0}; // Server address data structure. struct sockaddr_in servAddr = {0}; // Server address data structure.
NtpPacket packet = {0}; NtpPacket packet = {0};
@@ -125,10 +130,10 @@ Result ntpGetTimeStamp(time_t *outTimestamp)
if(socConnect(sock, (struct sockaddr *)&servAddr, sizeof(struct sockaddr_in)) < 0) if(socConnect(sock, (struct sockaddr *)&servAddr, sizeof(struct sockaddr_in)) < 0)
goto cleanup; goto cleanup;
if(soc_send(sock, &packet, sizeof(NtpPacket), 0) < 0) if(socSend(sock, &packet, sizeof(NtpPacket), 0) < 0)
goto cleanup; goto cleanup;
if(soc_recv(sock, &packet, sizeof(NtpPacket), 0) < 0) if(socRecv(sock, &packet, sizeof(NtpPacket), 0) < 0)
goto cleanup; goto cleanup;
res = 0; res = 0;

View File

@@ -101,29 +101,36 @@ Result server_init(struct sock_server *serv)
return svcCreateEvent(&serv->shall_terminate_event, RESET_STICKY); return svcCreateEvent(&serv->shall_terminate_event, RESET_STICKY);
} }
void server_bind(struct sock_server *serv, u16 port) Result server_bind(struct sock_server *serv, u16 port)
{ {
int server_sockfd; int server_sockfd;
Handle handles[2] = { terminationRequestEvent, serv->shall_terminate_event }; Handle handles[2] = { terminationRequestEvent, serv->shall_terminate_event };
s32 idx = -1; s32 idx = -1;
server_sockfd = socSocket(AF_INET, SOCK_STREAM, 0); server_sockfd = socSocket(AF_INET, SOCK_STREAM, 0);
int res;
while(server_sockfd == -1) int res;
u32 tries = 15;
while(server_sockfd == -1 && --tries > 0)
{ {
if(svcWaitSynchronizationN(&idx, handles, 2, false, 100 * 1000 * 1000LL) == 0) if(svcWaitSynchronizationN(&idx, handles, 2, false, 100 * 1000 * 1000LL) == 0)
return; return -1;
server_sockfd = socSocket(AF_INET, SOCK_STREAM, 0); server_sockfd = socSocket(AF_INET, SOCK_STREAM, 0);
} }
if (server_sockfd < -10000 || tries == 0) {
// Socket services broken
serv->init_result = -1;
svcSignalEvent(serv->shall_terminate_event);
return -1;
}
struct sockaddr_in saddr; struct sockaddr_in saddr;
saddr.sin_family = AF_INET; saddr.sin_family = AF_INET;
saddr.sin_port = htons(port); saddr.sin_port = htons(port);
saddr.sin_addr.s_addr = gethostid(); saddr.sin_addr.s_addr = socGethostid();
res = socBind(server_sockfd, (struct sockaddr*)&saddr, sizeof(struct sockaddr_in)); res = socBind(server_sockfd, (struct sockaddr*)&saddr, sizeof(struct sockaddr_in));
if(res == 0) if(res == 0)
{ {
res = socListen(server_sockfd, 2); res = socListen(server_sockfd, 2);
@@ -143,6 +150,15 @@ void server_bind(struct sock_server *serv, u16 port)
serv->ctx_ptrs[idx] = new_ctx; serv->ctx_ptrs[idx] = new_ctx;
} }
} }
if (res != 0) {
// Socket services broken
serv->init_result = res;
svcSignalEvent(serv->shall_terminate_event);
return res;
}
return 0;
} }
static bool server_should_exit(struct sock_server *serv) static bool server_should_exit(struct sock_server *serv)
@@ -171,7 +187,7 @@ void server_run(struct sock_server *serv)
fds[i].revents = 0; fds[i].revents = 0;
int pollres = socPoll(fds, serv->nfds, 50); int pollres = socPoll(fds, serv->nfds, 50);
if(server_should_exit(serv)) if(server_should_exit(serv) || pollres < -10000)
goto abort_connections; goto abort_connections;
for(nfds_t i = 0; pollres > 0 && i < serv->nfds; i++) for(nfds_t i = 0; pollres > 0 && i < serv->nfds; i++)
@@ -256,6 +272,7 @@ abort_connections:
server_kill_connections(serv); server_kill_connections(serv);
serv->running = false; serv->running = false;
svcClearEvent(serv->started_event); svcClearEvent(serv->started_event);
svcSignalEvent(serv->shall_terminate_event);
} }
void server_set_should_close_all(struct sock_server *serv) void server_set_should_close_all(struct sock_server *serv)
@@ -284,7 +301,8 @@ void server_kill_connections(struct sock_server *serv)
socClose(fds[i].fd); socClose(fds[i].fd);
fds[i].fd = -1; fds[i].fd = -1;
serv->ctx_ptrs[i]->should_close = true; if(serv->ctx_ptrs[i] != NULL)
serv->ctx_ptrs[i]->should_close = true;
} }
} }

View File

@@ -7,10 +7,15 @@ TaskRunner g_taskRunner;
static MyThread taskRunnerThread; static MyThread taskRunnerThread;
static u8 ALIGN(8) taskRunnerThreadStack[0x1000]; static u8 ALIGN(8) taskRunnerThreadStack[0x1000];
static void taskRunnerNoOpFunction(void *args)
{
(void)args;
}
MyThread *taskRunnerCreateThread(void) MyThread *taskRunnerCreateThread(void)
{ {
TaskRunner_Init(); TaskRunner_Init();
MyThread_Create(&taskRunnerThread, TaskRunner_HandleTasks, taskRunnerThreadStack, THREAD_STACK_SIZE, 0x20, 1); MyThread_Create(&taskRunnerThread, TaskRunner_HandleTasks, taskRunnerThreadStack, THREAD_STACK_SIZE, 58, 1);
return &taskRunnerThread; return &taskRunnerThread;
} }
@@ -30,9 +35,15 @@ void TaskRunner_RunTask(void (*task)(void *argdata), void *argdata, size_t argsi
LightEvent_Signal(&g_taskRunner.parametersSetEvent); LightEvent_Signal(&g_taskRunner.parametersSetEvent);
} }
void TaskRunner_Terminate(void)
{
g_taskRunner.shouldTerminate = true;
TaskRunner_RunTask(taskRunnerNoOpFunction, NULL, 0);
}
void TaskRunner_HandleTasks(void) void TaskRunner_HandleTasks(void)
{ {
for (;;) { while (!g_taskRunner.shouldTerminate) {
LightEvent_Signal(&g_taskRunner.readyEvent); LightEvent_Signal(&g_taskRunner.readyEvent);
LightEvent_Wait(&g_taskRunner.parametersSetEvent); LightEvent_Wait(&g_taskRunner.parametersSetEvent);
g_taskRunner.task(g_taskRunner.argStorage); g_taskRunner.task(g_taskRunner.argStorage);
@@ -42,4 +53,4 @@ void TaskRunner_HandleTasks(void)
void TaskRunner_WaitReady(void) void TaskRunner_WaitReady(void)
{ {
LightEvent_Wait(&g_taskRunner.readyEvent); LightEvent_Wait(&g_taskRunner.readyEvent);
} }

View File

@@ -37,7 +37,7 @@ CFLAGS += $(INCLUDE)
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH) ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map),-wrap,exit
LIBS := -lctru LIBS := -lctru

View File

@@ -24,10 +24,27 @@ static ProcessData processDataPool[64];
static u8 ALIGN(4) serviceAccessListStaticBuffer[0x110]; static u8 ALIGN(4) serviceAccessListStaticBuffer[0x110];
void __appInit(void) void __ctru_exit(int rc) { (void)rc; } // needed to avoid linking error
{
s64 out;
// this is called after main exits
void __wrap_exit(int rc)
{
(void)rc;
// Not supposed to terminate... kernel will clean up the handles if it does happen anyway
svcExitProcess();
}
void __sync_init();
// void __libc_init_array(void);
// Called before main
void initSystem(void)
{
__sync_init();
//__libc_init_array();
s64 out;
u32 *staticBuffers = getThreadStaticBuffers(); u32 *staticBuffers = getThreadStaticBuffers();
staticBuffers[0] = IPC_Desc_StaticBuffer(0x110, 0); staticBuffers[0] = IPC_Desc_StaticBuffer(0x110, 0);
staticBuffers[1] = (u32)serviceAccessListStaticBuffer; staticBuffers[1] = (u32)serviceAccessListStaticBuffer;
@@ -40,28 +57,6 @@ void __appInit(void)
buildList(&freeProcessDataList, processDataPool, sizeof(processDataPool) / sizeof(ProcessData), sizeof(ProcessData)); buildList(&freeProcessDataList, processDataPool, sizeof(processDataPool) / sizeof(ProcessData), sizeof(ProcessData));
} }
// this is called after main exits
void __appExit(void){}
void __system_allocateHeaps(void){}
void __system_initSyscalls(void){}
Result __sync_init(void);
Result __sync_fini(void);
void __ctru_exit(void){}
void initSystem(void)
{
void __libc_init_array(void);
__sync_init();
__system_allocateHeaps();
__appInit();
__libc_init_array();
}
int main(void) int main(void)
{ {
Result res; Result res;