Manually merge files
This commit is contained in:
215
k11_extension/source/svc/ControlProcess.c
Normal file
215
k11_extension/source/svc/ControlProcess.c
Normal file
@@ -0,0 +1,215 @@
|
||||
#include "svc/ControlProcess.h"
|
||||
#include "memory.h"
|
||||
#include "mmu.h"
|
||||
#include "synchronization.h"
|
||||
|
||||
typedef bool (*ThreadPredicate)(KThread *thread);
|
||||
|
||||
void rosalinaLockThread(KThread *thread);
|
||||
void rosalinaRescheduleThread(KThread *thread, bool lock);
|
||||
|
||||
Result ControlProcess(Handle processHandle, ProcessOp op, u32 varg2, u32 varg3)
|
||||
{
|
||||
Result res = 0;
|
||||
KProcess *process;
|
||||
KProcessHandleTable *handleTable = handleTableOfProcess(currentCoreContext->objectContext.currentProcess);
|
||||
|
||||
if(processHandle == CUR_PROCESS_HANDLE)
|
||||
{
|
||||
process = currentCoreContext->objectContext.currentProcess;
|
||||
KAutoObject__AddReference((KAutoObject *)process);
|
||||
}
|
||||
else
|
||||
process = KProcessHandleTable__ToKProcess(handleTable, processHandle);
|
||||
|
||||
if(process == NULL)
|
||||
return 0xD8E007F7; // invalid handle
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case PROCESSOP_GET_ALL_HANDLES:
|
||||
{
|
||||
KProcessHandleTable *table = handleTableOfProcess(process);
|
||||
u32 *originalHandleList = (u32 *)varg2;
|
||||
u32 count = 0;
|
||||
u32 searchForToken = varg3;
|
||||
HandleDescriptor *handleDesc = table->handleTable == NULL ? table->internalTable : table->handleTable;
|
||||
|
||||
for (u32 idx = 0; idx < (u32)table->maxHandleCount; ++idx, ++handleDesc)
|
||||
{
|
||||
if (handleDesc->pointer == NULL)
|
||||
continue;
|
||||
|
||||
if (searchForToken)
|
||||
{
|
||||
KClassToken token;
|
||||
|
||||
handleDesc->pointer->vtable->GetClassToken(&token, handleDesc->pointer);
|
||||
if (searchForToken != token.flags)
|
||||
continue;
|
||||
}
|
||||
|
||||
*originalHandleList++ = idx | ((handleDesc->info << 16) >> 1);
|
||||
++count;
|
||||
}
|
||||
res = count;
|
||||
break;
|
||||
}
|
||||
|
||||
case PROCESSOP_SET_MMU_TO_RWX:
|
||||
{
|
||||
KProcessHwInfo *hwInfo = hwInfoOfProcess(process);
|
||||
|
||||
*KPROCESS_GET_PTR(process, customFlags) |= ForceRWXPages;
|
||||
KProcessHwInfo__SetMMUTableToRWX(hwInfo);
|
||||
break;
|
||||
}
|
||||
case PROCESSOP_GET_ON_MEMORY_CHANGE_EVENT:
|
||||
{
|
||||
// Only accept current process for this command
|
||||
if (process != currentCoreContext->objectContext.currentProcess)
|
||||
{
|
||||
res = 0xD8E007F7; // invalid handle
|
||||
break;
|
||||
}
|
||||
|
||||
Handle *onMemoryLayoutChangeEvent = KPROCESS_GET_PTR(process, onMemoryLayoutChangeEvent);
|
||||
|
||||
if (*onMemoryLayoutChangeEvent == 0)
|
||||
res = CreateEvent(onMemoryLayoutChangeEvent, RESET_ONESHOT);
|
||||
|
||||
if (res >= 0)
|
||||
{
|
||||
*KPROCESS_GET_PTR(process, customFlags) |= SignalOnMemLayoutChanges;
|
||||
KAutoObject * event = KProcessHandleTable__ToKAutoObject(handleTable, *onMemoryLayoutChangeEvent);
|
||||
|
||||
createHandleForThisProcess((Handle *)varg2, event);
|
||||
((KAutoObject *)event)->vtable->DecrementReferenceCount((KAutoObject *)event); ///< This avoid an extra operation on process exit
|
||||
///< Closing the handle in the handle table will destroy the event
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PROCESSOP_GET_ON_EXIT_EVENT:
|
||||
{
|
||||
// Only accept current process for this command
|
||||
if (process != currentCoreContext->objectContext.currentProcess)
|
||||
{
|
||||
res = 0xD8E007F7; // invalid handle
|
||||
break;
|
||||
}
|
||||
|
||||
Handle *onProcessExitEvent = KPROCESS_GET_PTR(process, onProcessExitEvent);
|
||||
Handle *resumeProcessExitEvent = KPROCESS_GET_PTR(process, resumeProcessExitEvent);
|
||||
|
||||
if (*onProcessExitEvent == 0)
|
||||
res = CreateEvent(onProcessExitEvent, RESET_ONESHOT);
|
||||
if (*resumeProcessExitEvent == 0)
|
||||
res |= CreateEvent(resumeProcessExitEvent, RESET_ONESHOT);
|
||||
|
||||
if (res >= 0)
|
||||
{
|
||||
*KPROCESS_GET_PTR(process, customFlags) |= SignalOnExit;
|
||||
KAutoObject * event = KProcessHandleTable__ToKAutoObject(handleTable, *onProcessExitEvent);
|
||||
|
||||
createHandleForThisProcess((Handle *)varg2, event);
|
||||
((KAutoObject *)event)->vtable->DecrementReferenceCount((KAutoObject *)event); ///< See higher
|
||||
|
||||
event = KProcessHandleTable__ToKAutoObject(handleTable, *resumeProcessExitEvent);
|
||||
|
||||
createHandleForThisProcess((Handle *)varg3, event);
|
||||
((KAutoObject *)event)->vtable->DecrementReferenceCount((KAutoObject *)event); ///< See higher
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case PROCESSOP_GET_PA_FROM_VA:
|
||||
{
|
||||
KProcessHwInfo *hwInfo = hwInfoOfProcess(process);
|
||||
|
||||
u32 pa = KProcessHwInfo__GetPAFromVA(hwInfo, varg3);
|
||||
*(u32 *)varg2 = pa;
|
||||
|
||||
if (pa == 0)
|
||||
res = 0xE0E01BF5; ///< Invalid address
|
||||
|
||||
break;
|
||||
}
|
||||
case PROCESSOP_SCHEDULE_THREADS:
|
||||
{
|
||||
ThreadPredicate threadPredicate = (ThreadPredicate)varg3;
|
||||
|
||||
KRecursiveLock__Lock(criticalSectionLock);
|
||||
|
||||
if (varg2 == 0) // Unlock
|
||||
{
|
||||
for(KLinkedListNode *node = threadList->list.nodes.first; node != (KLinkedListNode *)&threadList->list.nodes; node = node->next)
|
||||
{
|
||||
KThread *thread = (KThread *)node->key;
|
||||
|
||||
if((thread->schedulingMask & 0xF) == 2) // thread is terminating
|
||||
continue;
|
||||
|
||||
if(thread->schedulingMask & 0x40)
|
||||
rosalinaRescheduleThread(thread, false);
|
||||
}
|
||||
}
|
||||
else // Lock
|
||||
{
|
||||
bool currentThreadsFound = false;
|
||||
|
||||
for(KLinkedListNode *node = threadList->list.nodes.first; node != (KLinkedListNode *)&threadList->list.nodes; node = node->next)
|
||||
{
|
||||
KThread *thread = (KThread *)node->key;
|
||||
|
||||
if(thread->ownerProcess != process
|
||||
|| (threadPredicate != NULL && !threadPredicate(thread)))
|
||||
continue;
|
||||
|
||||
if(thread == coreCtxs[thread->coreId].objectContext.currentThread)
|
||||
currentThreadsFound = true;
|
||||
else
|
||||
rosalinaLockThread(thread);
|
||||
}
|
||||
|
||||
if(currentThreadsFound)
|
||||
{
|
||||
for(KLinkedListNode *node = threadList->list.nodes.first; node != (KLinkedListNode *)&threadList->list.nodes; node = node->next)
|
||||
{
|
||||
KThread *thread = (KThread *)node->key;
|
||||
|
||||
if(thread->ownerProcess != process
|
||||
|| (threadPredicate != NULL && !threadPredicate(thread)))
|
||||
continue;
|
||||
|
||||
if(!(thread->schedulingMask & 0x40))
|
||||
{
|
||||
rosalinaLockThread(thread);
|
||||
KRecursiveLock__Lock(criticalSectionLock);
|
||||
if(thread->coreId != getCurrentCoreID())
|
||||
{
|
||||
u32 cpsr = __get_cpsr();
|
||||
__disable_irq();
|
||||
coreCtxs[thread->coreId].objectContext.currentScheduler->triggerCrossCoreInterrupt = true;
|
||||
currentCoreContext->objectContext.currentScheduler->triggerCrossCoreInterrupt = true;
|
||||
__set_cpsr_cx(cpsr);
|
||||
}
|
||||
KRecursiveLock__Unlock(criticalSectionLock);
|
||||
}
|
||||
}
|
||||
KScheduler__TriggerCrossCoreInterrupt(currentCoreContext->objectContext.currentScheduler);
|
||||
}
|
||||
}
|
||||
|
||||
KRecursiveLock__Unlock(criticalSectionLock);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
res = 0xF8C007F4;
|
||||
}
|
||||
|
||||
((KAutoObject *)process)->vtable->DecrementReferenceCount((KAutoObject *)process);
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -29,11 +29,14 @@
|
||||
|
||||
Result GetHandleInfoHook(s64 *out, Handle handle, u32 type)
|
||||
{
|
||||
if(type == 0x10000) // KDebug and KProcess: get context ID
|
||||
Result res = 0;
|
||||
|
||||
if(type >= 0x10000)
|
||||
{
|
||||
KProcessHwInfo *hwInfo;
|
||||
KProcessHwInfo *hwInfo;
|
||||
KProcessHandleTable *handleTable = handleTableOfProcess(currentCoreContext->objectContext.currentProcess);
|
||||
KAutoObject *obj;
|
||||
KAutoObject *obj;
|
||||
|
||||
if(handle == CUR_PROCESS_HANDLE)
|
||||
{
|
||||
obj = (KAutoObject *)(currentCoreContext->objectContext.currentProcess);
|
||||
@@ -45,18 +48,82 @@ Result GetHandleInfoHook(s64 *out, Handle handle, u32 type)
|
||||
if(obj == NULL)
|
||||
return 0xD8E007F7;
|
||||
|
||||
if(strcmp(classNameOfAutoObject(obj), "KDebug") == 0)
|
||||
hwInfo = hwInfoOfProcess(((KDebug *)obj)->owner);
|
||||
else if(strcmp(classNameOfAutoObject(obj), "KProcess") == 0)
|
||||
hwInfo = hwInfoOfProcess((KProcess *)obj);
|
||||
else
|
||||
hwInfo = NULL;
|
||||
switch (type)
|
||||
{
|
||||
case 0x10000: ///< Get ctx id (should probably move it to GetProcessInfo)
|
||||
{
|
||||
if(strcmp(classNameOfAutoObject(obj), "KDebug") == 0)
|
||||
hwInfo = hwInfoOfProcess(((KDebug *)obj)->owner);
|
||||
else if(strcmp(classNameOfAutoObject(obj), "KProcess") == 0)
|
||||
hwInfo = hwInfoOfProcess((KProcess *)obj);
|
||||
else
|
||||
hwInfo = NULL;
|
||||
|
||||
*out = hwInfo != NULL ? KPROCESSHWINFO_GET_RVALUE(hwInfo, contextId) : -1;
|
||||
*out = hwInfo != NULL ? KPROCESSHWINFO_GET_RVALUE(hwInfo, contextId) : -1;
|
||||
break;
|
||||
}
|
||||
case 0x10001: ///< Get referenced object flags (token)
|
||||
{
|
||||
KClassToken token;
|
||||
|
||||
obj->vtable->GetClassToken(&token, obj);
|
||||
*out = token.flags;
|
||||
break;
|
||||
}
|
||||
case 0x10002: ///< Get object owner
|
||||
{
|
||||
Handle hOut;
|
||||
KClassToken token;
|
||||
KProcess * owner = NULL;
|
||||
|
||||
obj->vtable->GetClassToken(&token, obj);
|
||||
switch(token.flags)
|
||||
{
|
||||
case TOKEN_KEVENT:
|
||||
owner = ((KEvent *)obj)->owner;
|
||||
break;
|
||||
case TOKEN_KSEMAPHORE:
|
||||
owner = ((KSemaphore *)obj)->owner;
|
||||
break;
|
||||
case TOKEN_KTIMER:
|
||||
owner = ((KTimer *)obj)->owner;
|
||||
break;
|
||||
case TOKEN_KMUTEX:
|
||||
owner = ((KMutex *)obj)->owner;
|
||||
break;
|
||||
case TOKEN_KDEBUG:
|
||||
owner = ((KDebug *)obj)->owner;
|
||||
break;
|
||||
case TOKEN_KTHREAD:
|
||||
owner = ((KThread *)obj)->ownerProcess;
|
||||
break;
|
||||
case TOKEN_KADDRESSARBITER:
|
||||
owner = ((KAddressArbiter *)obj)->owner;
|
||||
break;
|
||||
case TOKEN_KSHAREDMEMORY:
|
||||
owner = ((KSharedMemory *)obj)->owner;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (owner == NULL)
|
||||
res = 0xD8E007F7;
|
||||
|
||||
res = createHandleForThisProcess(&hOut, (KAutoObject *)owner);
|
||||
*out = hOut;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
res = 0xF8C007F4;
|
||||
break;
|
||||
}
|
||||
|
||||
obj->vtable->DecrementReferenceCount(obj);
|
||||
return 0;
|
||||
return res;
|
||||
}
|
||||
else
|
||||
return GetHandleInfo(out, handle, type);
|
||||
|
||||
return GetHandleInfo(out, handle, type);
|
||||
}
|
||||
|
||||
@@ -79,6 +79,14 @@ Result GetProcessInfoHook(s64 *out, Handle processHandle, u32 type)
|
||||
*out = ttb & ~((1 << (14 - TTBCR)) - 1);
|
||||
break;
|
||||
}
|
||||
case 0x10009:
|
||||
{
|
||||
KProcessHwInfo *hwInfo = hwInfoOfProcess(process);
|
||||
u32 mmusize = KPROCESSHWINFO_GET_RVALUE(hwInfo, mmuTableSize);
|
||||
u32 mmupa = (u32)PA_FROM_VA_PTR(KPROCESSHWINFO_GET_RVALUE(hwInfo, mmuTableVA));
|
||||
*out = (s64)(mmusize | ((s64)mmupa << 32));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
res = 0xD8E007ED; // invalid enum value
|
||||
break;
|
||||
|
||||
@@ -64,6 +64,9 @@ Result GetSystemInfoHook(s64 *out, s32 type, s32 param)
|
||||
case 0x101:
|
||||
*out = cfwInfo.rosalinaMenuCombo;
|
||||
break;
|
||||
case 0x102:
|
||||
*out = cfwInfo.rosalinaFlags;
|
||||
break;
|
||||
|
||||
case 0x200: // isRelease
|
||||
*out = cfwInfo.flags & 1;
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
static u32 nbEnabled = 0;
|
||||
static u32 maskedPids[MAX_DEBUG];
|
||||
static u32 masks[MAX_DEBUG][8] = {0};
|
||||
static u32 *homeBtnPressed = NULL;
|
||||
|
||||
bool shouldSignalSyscallDebugEvent(KProcess *process, u8 svcId)
|
||||
{
|
||||
@@ -178,6 +179,15 @@ Result KernelSetStateHook(u32 type, u32 varg1, u32 varg2, u32 varg3)
|
||||
KRecursiveLock__Unlock(&dbgParamsLock);
|
||||
break;
|
||||
}
|
||||
case 0x10007:
|
||||
{
|
||||
// A bit crude but do the job for a simple notification + reboot, nothing sensitive here
|
||||
if (varg1 > 255 && homeBtnPressed == NULL)
|
||||
homeBtnPressed = PA_FROM_VA_PTR((u32 *)varg1);
|
||||
else if (homeBtnPressed != NULL && *homeBtnPressed == 0)
|
||||
*homeBtnPressed = varg1;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
res = KernelSetState(type, varg1, varg2, varg3);
|
||||
|
||||
@@ -26,19 +26,61 @@
|
||||
|
||||
#include "svc/MapProcessMemoryEx.h"
|
||||
|
||||
Result MapProcessMemoryEx(Handle processHandle, void *dst, void *src, u32 size)
|
||||
Result MapProcessMemoryEx(Handle dstProcessHandle, u32 vaDst, Handle srcProcessHandle, u32 vaSrc, u32 size)
|
||||
{
|
||||
Result res = 0;
|
||||
u32 sizeInPage = size >> 12;
|
||||
KLinkedList list;
|
||||
KProcess *srcProcess;
|
||||
KProcess *dstProcess;
|
||||
KProcessHandleTable *handleTable = handleTableOfProcess(currentCoreContext->objectContext.currentProcess);
|
||||
KProcessHwInfo *currentHwInfo = hwInfoOfProcess(currentCoreContext->objectContext.currentProcess);
|
||||
KProcess *process = KProcessHandleTable__ToKProcess(handleTable, processHandle);
|
||||
|
||||
if(process == NULL)
|
||||
if (dstProcessHandle == CUR_PROCESS_HANDLE)
|
||||
{
|
||||
dstProcess = currentCoreContext->objectContext.currentProcess;
|
||||
KAutoObject__AddReference((KAutoObject *)dstProcess);
|
||||
}
|
||||
else
|
||||
dstProcess = KProcessHandleTable__ToKProcess(handleTable, dstProcessHandle);
|
||||
|
||||
if (dstProcess == NULL)
|
||||
return 0xD8E007F7;
|
||||
|
||||
Result res = KProcessHwInfo__MapProcessMemory(currentHwInfo, hwInfoOfProcess(process), dst, src, size >> 12);
|
||||
if (srcProcessHandle == CUR_PROCESS_HANDLE)
|
||||
{
|
||||
srcProcess = currentCoreContext->objectContext.currentProcess;
|
||||
KAutoObject__AddReference((KAutoObject *)srcProcess);
|
||||
}
|
||||
else
|
||||
srcProcess = KProcessHandleTable__ToKProcess(handleTable, srcProcessHandle);
|
||||
|
||||
KAutoObject *obj = (KAutoObject *)process;
|
||||
obj->vtable->DecrementReferenceCount(obj);
|
||||
if (srcProcess == NULL)
|
||||
{
|
||||
res = 0xD8E007F7;
|
||||
goto exit1;
|
||||
}
|
||||
|
||||
KLinkedList__Initialize(&list);
|
||||
|
||||
res = KProcessHwInfo__GetListOfKBlockInfoForVA(hwInfoOfProcess(srcProcess), &list, vaSrc, sizeInPage);
|
||||
|
||||
if (res >= 0)
|
||||
{
|
||||
// Check if the destination address is free and large enough
|
||||
res = KProcessHwInfo__CheckVaState(hwInfoOfProcess(dstProcess), vaDst, size, 0, 0);
|
||||
if (res == 0)
|
||||
res = KProcessHwInfo__MapListOfKBlockInfo(hwInfoOfProcess(dstProcess), vaDst, &list, 0x5806, MEMPERM_RW | 0x18, 0);
|
||||
}
|
||||
|
||||
KLinkedList_KBlockInfo__Clear(&list);
|
||||
|
||||
((KAutoObject *)srcProcess)->vtable->DecrementReferenceCount((KAutoObject *)srcProcess);
|
||||
|
||||
exit1:
|
||||
((KAutoObject *)dstProcess)->vtable->DecrementReferenceCount((KAutoObject *)dstProcess);
|
||||
|
||||
invalidateEntireInstructionCache();
|
||||
flushEntireDataCache();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -29,12 +29,42 @@
|
||||
|
||||
Result UnmapProcessMemoryEx(Handle processHandle, void *dst, u32 size)
|
||||
{
|
||||
if(kernelVersion < SYSTEM_VERSION(2, 37, 0)) // < 6.x
|
||||
return UnmapProcessMemory(processHandle, dst, size); // equivalent when size <= 64MB
|
||||
Result res = 0;
|
||||
u32 sizeInPage = size >> 12;
|
||||
KLinkedList list;
|
||||
KProcess *process;
|
||||
KProcessHwInfo *hwInfo;
|
||||
KProcessHandleTable *handleTable = handleTableOfProcess(currentCoreContext->objectContext.currentProcess);
|
||||
|
||||
KProcessHwInfo *currentHwInfo = hwInfoOfProcess(currentCoreContext->objectContext.currentProcess);
|
||||
if (processHandle == CUR_PROCESS_HANDLE)
|
||||
{
|
||||
process = currentCoreContext->objectContext.currentProcess;
|
||||
KAutoObject__AddReference((KAutoObject *)process);
|
||||
}
|
||||
else
|
||||
process = KProcessHandleTable__ToKProcess(handleTable, processHandle);
|
||||
|
||||
Result res = KProcessHwInfo__UnmapProcessMemory(currentHwInfo, dst, size >> 12);
|
||||
if (process == NULL)
|
||||
return 0xD8E007F7;
|
||||
|
||||
hwInfo = hwInfoOfProcess(process);
|
||||
|
||||
KLinkedList__Initialize(&list);
|
||||
|
||||
res = KProcessHwInfo__GetListOfKBlockInfoForVA(hwInfo, &list, (u32)dst, sizeInPage);
|
||||
|
||||
if (res >= 0)
|
||||
{
|
||||
// Check for dst address to be in the right state (0x5806 as we set it with svcMapProcessMemoryEx)
|
||||
res = KProcessHwInfo__CheckVaState(hwInfo, (u32)dst, size, 0x5806, 0);
|
||||
if (res == 0)
|
||||
res = KProcessHwInfo__MapListOfKBlockInfo(hwInfo, (u32)dst, &list, 0, 0, 0);
|
||||
}
|
||||
|
||||
KLinkedList_KBlockInfo__Clear(&list);
|
||||
|
||||
|
||||
((KAutoObject *)process)->vtable->DecrementReferenceCount((KAutoObject *)process);
|
||||
|
||||
invalidateEntireInstructionCache();
|
||||
flushEntireDataCache();
|
||||
|
||||
@@ -84,3 +84,12 @@ ControlMemoryEx:
|
||||
ldr r1, [sp, #12]
|
||||
add sp, #20
|
||||
pop {pc}
|
||||
|
||||
.global MapProcessMemoryExWrapper
|
||||
.type MapProcessMemoryExWrapper, %function
|
||||
MapProcessMemoryExWrapper:
|
||||
push {lr}
|
||||
str r4, [sp, #-4]!
|
||||
bl MapProcessMemoryEx
|
||||
add sp, #4
|
||||
pop {pc}
|
||||
|
||||
Reference in New Issue
Block a user