rosalina: implement dirty hb chainload

This commit is contained in:
TuxSH
2020-05-10 02:58:21 +01:00
parent 04bd881cfa
commit d3e62df769
16 changed files with 130 additions and 24 deletions

View File

@@ -129,16 +129,21 @@ Result GetTitleExHeaderFlags(ExHeader_Arm11CoreInfo *outCoreInfo, ExHeader_Syste
return res;
}
Result GetCurrentAppTitleIdAndPid(u64 *outTitleId, u32 *outPid)
Result GetCurrentAppInfo(FS_ProgramInfo *outProgramInfo, u32 *outPid, u32 *outLaunchFlags)
{
ProcessList_Lock(&g_manager.processList);
Result res;
memset(outProgramInfo, 0, sizeof(FS_ProgramInfo));
if (g_manager.runningApplicationData != NULL) {
*outTitleId = g_manager.runningApplicationData->titleId;
*outPid = g_manager.runningApplicationData->pid;
ProcessData *app = g_manager.runningApplicationData;
outProgramInfo->programId = app->titleId;
outProgramInfo->mediaType = app->mediaType;
*outPid = app->pid;
*outLaunchFlags = app->launchFlags;
res = 0;
} else {
*outTitleId = 0;
*outPid = 0;
res = MAKERESULT(RL_TEMPORARY, RS_NOTFOUND, RM_PM, 0x100);
}
ProcessList_Unlock(&g_manager.processList);

View File

@@ -12,4 +12,4 @@ Result listMergeUniqueDependencies(ProcessData **procs, u64 *dependencies, u32 *
Result GetTitleExHeaderFlags(ExHeader_Arm11CoreInfo *outCoreInfo, ExHeader_SystemInfoFlags *outSiFlags, const FS_ProgramInfo *programInfo);
// Custom
Result GetCurrentAppTitleIdAndPid(u64 *outTitleId, u32 *outPid);
Result GetCurrentAppInfo(FS_ProgramInfo *outProgramInfo, u32 *outPid, u32 *outLaunchFlags);

View File

@@ -56,10 +56,12 @@ static Result loadWithoutDependencies(Handle *outDebug, ProcessData **outProcess
process->pid = pid;
process->titleId = exheaderInfo->aci.local_caps.title_id;;
process->programHandle = programHandle;
process->launchFlags = launchFlags; // not in official PM
process->flags = 0; // will be filled later
process->terminatedNotificationVariation = (launchFlags & 0xF0) >> 4;
process->terminationStatus = TERMSTATUS_RUNNING;
process->refcount = 1;
process->mediaType = programInfo->mediaType; // not in official PM
ProcessList_Unlock(&g_manager.processList);
svcSignalEvent(g_manager.newProcessEvent);
@@ -135,6 +137,11 @@ static Result loadWithDependencies(Handle *outDebug, ProcessData **outProcessDat
process->flags |= PROCESSFLAG_DEPENDENCIES_LOADED;
}
if (launchFlags & PMLAUNCHFLAGEXT_FAKE_DEPENDENCY_LOADING) {
// See no evil
numUnique = 0;
}
/*
Official pm does this:
for each dependency:

View File

@@ -4,6 +4,11 @@
#include <3ds/services/fs.h>
#include "process_data.h"
/// Custom launch flags for PM launch commands.
enum {
PMLAUNCHFLAGEXT_FAKE_DEPENDENCY_LOADING = BIT(24),
};
Result LaunchTitle(u32 *outPid, const FS_ProgramInfo *programInfo, u32 launchFlags);
Result LaunchTitleUpdate(const FS_ProgramInfo *programInfo, const FS_ProgramInfo *programInfoUpdate, u32 launchFlags);
Result LaunchApp(const FS_ProgramInfo *programInfo, u32 launchFlags);

View File

@@ -52,7 +52,7 @@ void initSystem()
}
static const ServiceManagerServiceEntry services[] = {
{ "pm:app", 3, pmAppHandleCommands, false },
{ "pm:app", 4, pmAppHandleCommands, false },
{ "pm:dbg", 2, pmDbgHandleCommands, false },
{ NULL },
};

View File

@@ -69,3 +69,27 @@ Result UnregisterProcess(u64 titleId)
ProcessList_Unlock(&g_manager.processList);
return 0;
}
Result PrepareToChainloadHomebrew(u64 titleId)
{
// Note: I'm allowing this command to be called for non-applications, maybe that'll be useful
// in the future...
ProcessData *foundProcess = NULL;
Result res;
ProcessList_Lock(&g_manager.processList);
foundProcess = ProcessList_FindProcessByTitleId(&g_manager.processList, titleId & ~N3DS_TID_MASK);
if (foundProcess != NULL) {
// Clear the "notify on termination, don't cleanup" flag, so that for ex. APT isn't notified & no need for UnregisterProcess,
// and the "dependencies loaded" flag, so that the dependencies aren't killed (for ex. when
// booting hbmenu instead of Home Menu, in which case the same title is going to be launched...)
foundProcess->flags &= ~(PROCESSFLAG_DEPENDENCIES_LOADED | PROCESSFLAG_NOTIFY_TERMINATION);
res = 0;
} else {
res = MAKERESULT(RL_TEMPORARY, RS_NOTFOUND, RM_PM, 0x100);
}
ProcessList_Unlock(&g_manager.processList);
return res;
}

View File

@@ -21,3 +21,4 @@ extern Manager g_manager;
void Manager_Init(void *procBuf, size_t numProc);
void Manager_RegisterKips(void);
Result UnregisterProcess(u64 titleId);
Result PrepareToChainloadHomebrew(u64 titleId);

View File

@@ -3,6 +3,7 @@
#include "launch.h"
#include "info.h"
#include "util.h"
#include "manager.h"
void pmDbgHandleCommands(void *ctx)
{
@@ -11,10 +12,10 @@ void pmDbgHandleCommands(void *ctx)
u32 cmdhdr = cmdbuf[0];
FS_ProgramInfo programInfo;
Handle debug;
u64 titleId;
Handle debug;
u32 pid;
u32 launchFlags;
switch (cmdhdr >> 16) {
case 1:
@@ -40,12 +41,11 @@ void pmDbgHandleCommands(void *ctx)
// Custom
case 0x100:
titleId = 0;
pid = 0xFFFFFFFF;
cmdbuf[1] = GetCurrentAppTitleIdAndPid(&titleId, &pid);
cmdbuf[0] = IPC_MakeHeader(0x100, 4, 0);
memcpy(cmdbuf + 2, &titleId, 8);
cmdbuf[4] = pid;
cmdbuf[1] = GetCurrentAppInfo(&programInfo, &pid, &launchFlags);
cmdbuf[0] = IPC_MakeHeader(0x100, 7, 0);
memcpy(cmdbuf + 2, &programInfo, sizeof(FS_ProgramInfo));
cmdbuf[6] = pid;
cmdbuf[7] = launchFlags;
break;
case 0x101:
cmdbuf[1] = DebugNextApplicationByForce(cmdbuf[1] != 0);
@@ -59,7 +59,11 @@ void pmDbgHandleCommands(void *ctx)
cmdbuf[2] = IPC_Desc_MoveHandles(1);
cmdbuf[3] = debug;
break;
case 0x103:
memcpy(&titleId, cmdbuf + 1, 8);
cmdbuf[1] = PrepareToChainloadHomebrew(titleId);
cmdbuf[0] = IPC_MakeHeader(0x103, 1, 0);
break;
default:
cmdbuf[0] = IPC_MakeHeader(0, 1, 0);
cmdbuf[1] = 0xD900182F;

View File

@@ -29,10 +29,12 @@ typedef struct ProcessData {
u32 pid;
u64 titleId;
u64 programHandle;
u32 launchFlags;
u8 flags;
u8 terminatedNotificationVariation;
TerminationStatus terminationStatus;
u8 refcount;
FS_MediaType mediaType;
} ProcessData;
typedef struct ProcessList {