pm/kext: make pm terminate Rosalina, removing the need for a dodgy kext hook

This commit is contained in:
TuxSH 2020-04-26 20:33:24 +01:00
parent e677e0142c
commit 33431cb939
4 changed files with 21 additions and 69 deletions

View File

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

View File

@ -235,48 +235,6 @@ bool doLangEmu(Result *res, u32 *cmdbuf)
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)
{
// 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:
{
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;
}
else if(info != NULL && strcmp(info->name, "ndm:u") == 0 && hasStartedRosalinaNetworkFuncsOnce)
if(info != NULL && strcmp(info->name, "ndm:u") == 0 && hasStartedRosalinaNetworkFuncsOnce)
{
cmdbuf[0] = 0x10040;
cmdbuf[1] = 0;
@ -154,18 +149,6 @@ Result SendSyncRequestHook(Handle handle)
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:
{
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);

View File

@ -65,6 +65,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)
{
// Wait for all of the processes that have received notification 0x100 to terminate
@ -247,6 +257,8 @@ ProcessData *terminateAllProcesses(u32 callerPid, s64 timeout)
u64 dependencies[48];
u32 numDeps = 0;
s64 numKips = 0;
svcGetSystemInfo(&numKips, 26, 0);
ExHeader_Info *exheaderInfo = ExHeaderInfoHeap_New();
@ -269,6 +281,7 @@ ProcessData *terminateAllProcesses(u32 callerPid, s64 timeout)
}
ProcessList_Lock(&g_manager.processList);
// Send notification 0x100 to the currently running application
if (g_manager.runningApplicationData != NULL) {
g_manager.runningApplicationData->flags &= ~PROCESSFLAG_DEPENDENCIES_LOADED;
@ -302,20 +315,19 @@ ProcessData *terminateAllProcesses(u32 callerPid, s64 timeout)
commitPendingTerminations(timeoutTicks >= 0 ? ticksToNs(timeoutTicks) : 0LL);
g_manager.waitingForTermination = false;
// Now, send termination notification to PXI (PID 4)
// Now, send termination notification to PXI (PID 4). Also do the same for Rosalina.
assertSuccess(svcClearEvent(g_manager.allNotifiedTerminationEvent));
g_manager.waitingForTermination = true;
ProcessList_Lock(&g_manager.processList);
process = ProcessList_FindProcessById(&g_manager.processList, 4);
if (process != NULL) {
ProcessData_SendTerminationNotification(process);
} else {
panic(0LL);
if (numKips >= 6) {
terminateProcessByIdChecked(5); // Rosalina
}
terminateProcessByIdChecked(4); // PXI
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();
commitPendingTerminations(1500 * 1000 * 1000LL + (timeoutTicks >= 0 ? ticksToNs(timeoutTicks) : 0LL));
g_manager.waitingForTermination = false;