Add client code for new custom pm commands, use them, fix pm race conditions
This commit is contained in:
parent
43b998d37d
commit
22ec031495
@ -128,11 +128,16 @@ Result GetTitleExHeaderFlags(ExHeader_Arm11CoreInfo *outCoreInfo, ExHeader_Syste
|
|||||||
|
|
||||||
Result GetCurrentAppTitleId(u64 *outTitleId)
|
Result GetCurrentAppTitleId(u64 *outTitleId)
|
||||||
{
|
{
|
||||||
|
ProcessList_Lock(&g_manager.processList);
|
||||||
|
Result res;
|
||||||
if (g_manager.runningApplicationData != NULL) {
|
if (g_manager.runningApplicationData != NULL) {
|
||||||
*outTitleId = g_manager.runningApplicationData->titleId;
|
*outTitleId = g_manager.runningApplicationData->titleId;
|
||||||
return 0;
|
res = 0;
|
||||||
} else {
|
} else {
|
||||||
*outTitleId = 0;
|
*outTitleId = 0;
|
||||||
return MAKERESULT(RL_TEMPORARY, RS_NOTFOUND, RM_PM, 0x100);
|
res = MAKERESULT(RL_TEMPORARY, RS_NOTFOUND, RM_PM, 0x100);
|
||||||
}
|
}
|
||||||
|
ProcessList_Unlock(&g_manager.processList);
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -243,6 +243,7 @@ static Result launchTitleImpl(Handle *debug, ProcessData **outProcessData, const
|
|||||||
// note: official pm doesn't terminate the proc. if it fails here either, but will because of the svcCloseHandle and the svcRun codepath
|
// note: official pm doesn't terminate the proc. if it fails here either, but will because of the svcCloseHandle and the svcRun codepath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ProcessList_Lock(&g_manager.processList);
|
||||||
ProcessData *process = *outProcessData;
|
ProcessData *process = *outProcessData;
|
||||||
if (launchFlags & PMLAUNCHFLAG_QUEUE_DEBUG_APPLICATION) {
|
if (launchFlags & PMLAUNCHFLAG_QUEUE_DEBUG_APPLICATION) {
|
||||||
// saved field is different in official pm
|
// saved field is different in official pm
|
||||||
@ -271,6 +272,7 @@ static Result launchTitleImpl(Handle *debug, ProcessData **outProcessData, const
|
|||||||
process->flags |= (launchFlags & PMLAUNCHFLAG_NOTIFY_TERMINATION) ? PROCESSFLAG_NOTIFY_TERMINATION : 0;
|
process->flags |= (launchFlags & PMLAUNCHFLAG_NOTIFY_TERMINATION) ? PROCESSFLAG_NOTIFY_TERMINATION : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ProcessList_Unlock(&g_manager.processList);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -323,11 +325,12 @@ Result LaunchTitle(u32 *outPid, const FS_ProgramInfo *programInfo, u32 launchFla
|
|||||||
panic(4);
|
panic(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ProcessList_Lock(&g_manager.processList);
|
||||||
if (g_manager.runningApplicationData != NULL && (launchFlags & PMLAUNCHFLAG_NORMAL_APPLICATION) != 0) {
|
if (g_manager.runningApplicationData != NULL && (launchFlags & PMLAUNCHFLAG_NORMAL_APPLICATION) != 0) {
|
||||||
|
ProcessList_Unlock(&g_manager.processList);
|
||||||
return 0xC8A05BF0;
|
return 0xC8A05BF0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessList_Lock(&g_manager.processList);
|
|
||||||
FOREACH_PROCESS(&g_manager.processList, process) {
|
FOREACH_PROCESS(&g_manager.processList, process) {
|
||||||
if ((process->titleId & ~0xFFULL) == (programInfo->programId & ~0xFFULL)) {
|
if ((process->titleId & ~0xFFULL) == (programInfo->programId & ~0xFFULL)) {
|
||||||
foundProcess = process;
|
foundProcess = process;
|
||||||
@ -370,15 +373,18 @@ Result LaunchTitle(u32 *outPid, const FS_ProgramInfo *programInfo, u32 launchFla
|
|||||||
|
|
||||||
Result LaunchTitleUpdate(const FS_ProgramInfo *programInfo, const FS_ProgramInfo *programInfoUpdate, u32 launchFlags)
|
Result LaunchTitleUpdate(const FS_ProgramInfo *programInfo, const FS_ProgramInfo *programInfoUpdate, u32 launchFlags)
|
||||||
{
|
{
|
||||||
|
ProcessList_Lock(&g_manager.processList);
|
||||||
if (g_manager.preparingForReboot) {
|
if (g_manager.preparingForReboot) {
|
||||||
return 0xC8A05801;
|
return 0xC8A05801;
|
||||||
}
|
}
|
||||||
if (g_manager.runningApplicationData != NULL) {
|
if (g_manager.runningApplicationData != NULL) {
|
||||||
|
ProcessList_Unlock(&g_manager.processList);
|
||||||
return 0xC8A05BF0;
|
return 0xC8A05BF0;
|
||||||
}
|
}
|
||||||
if (!(launchFlags & ~PMLAUNCHFLAG_NORMAL_APPLICATION)) {
|
if (!(launchFlags & ~PMLAUNCHFLAG_NORMAL_APPLICATION)) {
|
||||||
return 0xD8E05802;
|
return 0xD8E05802;
|
||||||
}
|
}
|
||||||
|
ProcessList_Unlock(&g_manager.processList);
|
||||||
|
|
||||||
bool originallyDebugged = launchFlags & PMLAUNCHFLAG_QUEUE_DEBUG_APPLICATION;
|
bool originallyDebugged = launchFlags & PMLAUNCHFLAG_QUEUE_DEBUG_APPLICATION;
|
||||||
|
|
||||||
@ -408,11 +414,15 @@ Result LaunchTitleUpdate(const FS_ProgramInfo *programInfo, const FS_ProgramInfo
|
|||||||
|
|
||||||
Result LaunchApp(const FS_ProgramInfo *programInfo, u32 launchFlags)
|
Result LaunchApp(const FS_ProgramInfo *programInfo, u32 launchFlags)
|
||||||
{
|
{
|
||||||
|
ProcessList_Lock(&g_manager.processList);
|
||||||
if (g_manager.runningApplicationData != NULL) {
|
if (g_manager.runningApplicationData != NULL) {
|
||||||
|
ProcessList_Unlock(&g_manager.processList);
|
||||||
return 0xC8A05BF0;
|
return 0xC8A05BF0;
|
||||||
}
|
}
|
||||||
|
|
||||||
assertSuccess(setAppCpuTimeLimit(0));
|
assertSuccess(setAppCpuTimeLimit(0));
|
||||||
|
ProcessList_Unlock(&g_manager.processList);
|
||||||
|
|
||||||
return LaunchTitle(NULL, programInfo, launchFlags | PMLAUNCHFLAG_LOAD_DEPENDENCIES | PMLAUNCHFLAG_NORMAL_APPLICATION);
|
return LaunchTitle(NULL, programInfo, launchFlags | PMLAUNCHFLAG_LOAD_DEPENDENCIES | PMLAUNCHFLAG_NORMAL_APPLICATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -421,10 +431,13 @@ Result RunQueuedProcess(Handle *outDebug)
|
|||||||
Result res = 0;
|
Result res = 0;
|
||||||
StartupInfo si = {0};
|
StartupInfo si = {0};
|
||||||
|
|
||||||
|
ProcessList_Lock(&g_manager.processList);
|
||||||
if (g_manager.debugData == NULL) {
|
if (g_manager.debugData == NULL) {
|
||||||
|
ProcessList_Unlock(&g_manager.processList);
|
||||||
return 0xD8A05804;
|
return 0xD8A05804;
|
||||||
} else if ((g_manager.debugData->flags & PROCESSFLAG_NORMAL_APPLICATION) && g_manager.runningApplicationData != NULL) {
|
} else if ((g_manager.debugData->flags & PROCESSFLAG_NORMAL_APPLICATION) && g_manager.runningApplicationData != NULL) {
|
||||||
// Not in official PM
|
// Not in official PM
|
||||||
|
ProcessList_Unlock(&g_manager.processList);
|
||||||
return 0xC8A05BF0;
|
return 0xC8A05BF0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -455,17 +468,21 @@ Result RunQueuedProcess(Handle *outDebug)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ExHeaderInfoHeap_Delete(exheaderInfo);
|
ExHeaderInfoHeap_Delete(exheaderInfo);
|
||||||
|
ProcessList_Unlock(&g_manager.processList);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result LaunchAppDebug(Handle *outDebug, const FS_ProgramInfo *programInfo, u32 launchFlags)
|
Result LaunchAppDebug(Handle *outDebug, const FS_ProgramInfo *programInfo, u32 launchFlags)
|
||||||
{
|
{
|
||||||
|
ProcessList_Lock(&g_manager.processList);
|
||||||
if (g_manager.debugData != NULL) {
|
if (g_manager.debugData != NULL) {
|
||||||
|
ProcessList_Unlock(&g_manager.processList);
|
||||||
return RunQueuedProcess(outDebug);
|
return RunQueuedProcess(outDebug);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_manager.runningApplicationData != NULL) {
|
if (g_manager.runningApplicationData != NULL) {
|
||||||
|
ProcessList_Unlock(&g_manager.processList);
|
||||||
return 0xC8A05BF0;
|
return 0xC8A05BF0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -473,6 +490,8 @@ Result LaunchAppDebug(Handle *outDebug, const FS_ProgramInfo *programInfo, u32 l
|
|||||||
g_debugNextApplication = false;
|
g_debugNextApplication = false;
|
||||||
|
|
||||||
assertSuccess(setAppCpuTimeLimit(0));
|
assertSuccess(setAppCpuTimeLimit(0));
|
||||||
|
ProcessList_Unlock(&g_manager.processList);
|
||||||
|
|
||||||
Result res = launchTitleImplWrapper(outDebug, NULL, programInfo, programInfo,
|
Result res = launchTitleImplWrapper(outDebug, NULL, programInfo, programInfo,
|
||||||
(launchFlags & ~PMLAUNCHFLAG_USE_UPDATE_TITLE) | PMLAUNCHFLAG_NORMAL_APPLICATION);
|
(launchFlags & ~PMLAUNCHFLAG_USE_UPDATE_TITLE) | PMLAUNCHFLAG_NORMAL_APPLICATION);
|
||||||
|
|
||||||
@ -509,9 +528,12 @@ Result LaunchTitleDebug(Handle *outDebug, const FS_ProgramInfo *programInfo, u32
|
|||||||
return LaunchAppDebug(outDebug, programInfo, launchFlags);
|
return LaunchAppDebug(outDebug, programInfo, launchFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ProcessList_Lock(&g_manager.processList);
|
||||||
if (g_manager.debugData != NULL) {
|
if (g_manager.debugData != NULL) {
|
||||||
|
ProcessList_Unlock(&g_manager.processList);
|
||||||
return RunQueuedProcess(outDebug);
|
return RunQueuedProcess(outDebug);
|
||||||
}
|
}
|
||||||
|
ProcessList_Unlock(&g_manager.processList);
|
||||||
|
|
||||||
return launchTitleImplWrapper(outDebug, NULL, programInfo, programInfo, launchFlags & ~PMLAUNCHFLAG_USE_UPDATE_TITLE);
|
return launchTitleImplWrapper(outDebug, NULL, programInfo, programInfo, launchFlags & ~PMLAUNCHFLAG_USE_UPDATE_TITLE);
|
||||||
}
|
}
|
||||||
|
@ -27,16 +27,18 @@ static void cleanupProcess(ProcessData *process)
|
|||||||
LOADER_UnregisterProgram(process->programHandle);
|
LOADER_UnregisterProgram(process->programHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process == g_manager.runningApplicationData) {
|
ProcessList_Lock(&g_manager.processList);
|
||||||
|
if (g_manager.runningApplicationData != NULL && process->handle == g_manager.runningApplicationData->handle) {
|
||||||
if (IS_N3DS && APPMEMTYPE == 6) {
|
if (IS_N3DS && APPMEMTYPE == 6) {
|
||||||
assertSuccess(resetAppMemLimit());
|
assertSuccess(resetAppMemLimit());
|
||||||
}
|
}
|
||||||
g_manager.runningApplicationData = NULL;
|
g_manager.runningApplicationData = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process == g_manager.debugData) {
|
if (g_manager.debugData != NULL && process->handle == g_manager.debugData->handle) {
|
||||||
g_manager.debugData = NULL;
|
g_manager.debugData = NULL;
|
||||||
}
|
}
|
||||||
|
ProcessList_Unlock(&g_manager.processList);
|
||||||
|
|
||||||
if (process->flags & PROCESSFLAG_NOTIFY_TERMINATION) {
|
if (process->flags & PROCESSFLAG_NOTIFY_TERMINATION) {
|
||||||
notifySubscribers(0x110 + process->terminatedNotificationVariation);
|
notifySubscribers(0x110 + process->terminatedNotificationVariation);
|
||||||
|
@ -215,9 +215,11 @@ Result TerminateApplication(s64 timeout)
|
|||||||
assertSuccess(svcClearEvent(g_manager.allNotifiedTerminationEvent));
|
assertSuccess(svcClearEvent(g_manager.allNotifiedTerminationEvent));
|
||||||
g_manager.waitingForTermination = true;
|
g_manager.waitingForTermination = true;
|
||||||
|
|
||||||
|
ProcessList_Lock(&g_manager.processList);
|
||||||
if (g_manager.runningApplicationData != NULL) {
|
if (g_manager.runningApplicationData != NULL) {
|
||||||
terminateProcessImpl(g_manager.runningApplicationData, exheaderInfo);
|
terminateProcessImpl(g_manager.runningApplicationData, exheaderInfo);
|
||||||
}
|
}
|
||||||
|
ProcessList_Unlock(&g_manager.processList);
|
||||||
|
|
||||||
res = commitPendingTerminations(timeout);
|
res = commitPendingTerminations(timeout);
|
||||||
|
|
||||||
@ -266,6 +268,7 @@ ProcessData *terminateAllProcesses(u32 callerPid, s64 timeout)
|
|||||||
ProcessList_Unlock(&g_manager.processList);
|
ProcessList_Unlock(&g_manager.processList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ProcessList_Lock(&g_manager.processList);
|
||||||
// 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;
|
||||||
@ -274,7 +277,6 @@ ProcessData *terminateAllProcesses(u32 callerPid, s64 timeout)
|
|||||||
|
|
||||||
// Send notification 0x100 to anything but the caller deps or the caller; and *increase* the refcount of the latter if autoloaded
|
// Send notification 0x100 to anything but the caller deps or the caller; and *increase* the refcount of the latter if autoloaded
|
||||||
// Ignore KIPs
|
// Ignore KIPs
|
||||||
ProcessList_Lock(&g_manager.processList);
|
|
||||||
FOREACH_PROCESS(&g_manager.processList, process) {
|
FOREACH_PROCESS(&g_manager.processList, process) {
|
||||||
if (process->flags & PROCESSFLAG_KIP) {
|
if (process->flags & PROCESSFLAG_KIP) {
|
||||||
continue;
|
continue;
|
||||||
|
10
sysmodules/rosalina/include/pmdbgext.h
Normal file
10
sysmodules/rosalina/include/pmdbgext.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
// License for this file: ctrulib's license
|
||||||
|
// Copyright AuroraWright, TuxSH 2019
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <3ds/services/pmapp.h>
|
||||||
|
|
||||||
|
Result PMDBG_GetCurrentAppTitleId(u64 *outTitleId);
|
||||||
|
Result PMDBG_DebugNextApplicationByForce(void);
|
||||||
|
Result PMDBG_LaunchTitleDebug(Handle *outDebug, const FS_ProgramInfo *programInfo, u32 launchFlags);
|
@ -84,11 +84,15 @@ void __appInit()
|
|||||||
|
|
||||||
if (R_FAILED(stealFsReg()) || R_FAILED(fsRegSetupPermissions()) || R_FAILED(fsInit()))
|
if (R_FAILED(stealFsReg()) || R_FAILED(fsRegSetupPermissions()) || R_FAILED(fsInit()))
|
||||||
svcBreak(USERBREAK_PANIC);
|
svcBreak(USERBREAK_PANIC);
|
||||||
|
|
||||||
|
if (R_FAILED(pmDbgInit()))
|
||||||
|
svcBreak(USERBREAK_PANIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is called after main exits
|
// this is called after main exits
|
||||||
void __appExit()
|
void __appExit()
|
||||||
{
|
{
|
||||||
|
pmDbgExit();
|
||||||
fsExit();
|
fsExit();
|
||||||
svcCloseHandle(*fsRegGetSessionHandle());
|
svcCloseHandle(*fsRegGetSessionHandle());
|
||||||
srvExit();
|
srvExit();
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "utils.h" // for makeARMBranch
|
#include "utils.h" // for makeARMBranch
|
||||||
#include "minisoc.h"
|
#include "minisoc.h"
|
||||||
#include "ifile.h"
|
#include "ifile.h"
|
||||||
|
#include "pmdbgext.h"
|
||||||
|
|
||||||
Menu miscellaneousMenu = {
|
Menu miscellaneousMenu = {
|
||||||
"Miscellaneous options menu",
|
"Miscellaneous options menu",
|
||||||
@ -54,31 +55,12 @@ void MiscellaneousMenu_SwitchBoot3dsxTargetTitle(void)
|
|||||||
|
|
||||||
if(HBLDR_3DSX_TID == HBLDR_DEFAULT_3DSX_TID)
|
if(HBLDR_3DSX_TID == HBLDR_DEFAULT_3DSX_TID)
|
||||||
{
|
{
|
||||||
u32 pidList[0x40];
|
res = PMDBG_GetCurrentAppTitleId(&titleId);
|
||||||
s32 processAmount;
|
|
||||||
|
|
||||||
res = svcGetProcessList(&processAmount, pidList, 0x40);
|
|
||||||
if(R_SUCCEEDED(res))
|
if(R_SUCCEEDED(res))
|
||||||
{
|
|
||||||
for(s32 i = 0; i < processAmount && (u32)(titleId >> 32) != 0x00040010 && (u32)(titleId >> 32) != 0x00040000; i++)
|
|
||||||
{
|
|
||||||
Handle processHandle;
|
|
||||||
Result res = svcOpenProcess(&processHandle, pidList[i]);
|
|
||||||
if(R_FAILED(res))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
svcGetProcessInfo((s64 *)&titleId, processHandle, 0x10001);
|
|
||||||
svcCloseHandle(processHandle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(R_SUCCEEDED(res) && ((u32)(titleId >> 32) == 0x00040010 || (u32)(titleId >> 32) == 0x00040000))
|
|
||||||
{
|
{
|
||||||
HBLDR_3DSX_TID = titleId;
|
HBLDR_3DSX_TID = titleId;
|
||||||
miscellaneousMenu.items[0].title = "Switch the hb. title to hblauncher_loader";
|
miscellaneousMenu.items[0].title = "Switch the hb. title to hblauncher_loader";
|
||||||
}
|
}
|
||||||
else if(R_FAILED(res))
|
|
||||||
sprintf(failureReason, "%08lx", (u32)res);
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
res = -1;
|
res = -1;
|
||||||
|
47
sysmodules/rosalina/source/pmdbgext.c
Normal file
47
sysmodules/rosalina/source/pmdbgext.c
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
// License for this file: ctrulib's license
|
||||||
|
// Copyright AuroraWright, TuxSH 2019
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <3ds/types.h>
|
||||||
|
#include <3ds/result.h>
|
||||||
|
#include <3ds/svc.h>
|
||||||
|
#include <3ds/srv.h>
|
||||||
|
#include <3ds/synchronization.h>
|
||||||
|
#include <3ds/services/pmdbg.h>
|
||||||
|
#include <3ds/ipc.h>
|
||||||
|
|
||||||
|
Result PMDBG_GetCurrentAppTitleId(u64 *outTitleId)
|
||||||
|
{
|
||||||
|
Result ret = 0;
|
||||||
|
u32 *cmdbuf = getThreadCommandBuffer();
|
||||||
|
cmdbuf[0] = IPC_MakeHeader(0x100, 0, 0);
|
||||||
|
if(R_FAILED(ret = svcSendSyncRequest(*pmDbgGetSessionHandle()))) return ret;
|
||||||
|
|
||||||
|
memcpy(outTitleId, cmdbuf + 2, 8);
|
||||||
|
return cmdbuf[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
Result PMDBG_DebugNextApplicationByForce(void)
|
||||||
|
{
|
||||||
|
Result ret = 0;
|
||||||
|
u32 *cmdbuf = getThreadCommandBuffer();
|
||||||
|
cmdbuf[0] = IPC_MakeHeader(0x101, 0, 0);
|
||||||
|
|
||||||
|
if(R_FAILED(ret = svcSendSyncRequest(*pmDbgGetSessionHandle()))) return ret;
|
||||||
|
return cmdbuf[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
Result PMDBG_LaunchTitleDebug(Handle *outDebug, const FS_ProgramInfo *programInfo, u32 launchFlags)
|
||||||
|
{
|
||||||
|
Result ret = 0;
|
||||||
|
u32 *cmdbuf = getThreadCommandBuffer();
|
||||||
|
|
||||||
|
cmdbuf[0] = IPC_MakeHeader(0x102, 5, 0);
|
||||||
|
memcpy(&cmdbuf[1], programInfo, sizeof(FS_ProgramInfo));
|
||||||
|
cmdbuf[5] = launchFlags;
|
||||||
|
|
||||||
|
if(R_FAILED(ret = svcSendSyncRequest(*pmDbgGetSessionHandle()))) return ret;
|
||||||
|
|
||||||
|
*outDebug = cmdbuf[3];
|
||||||
|
return (Result)cmdbuf[1];
|
||||||
|
}
|
Reference in New Issue
Block a user