Implement PM GetProcessInfo atmosphere extension (partially) (#2966)

This commit is contained in:
gdkchan 2022-05-03 18:28:32 -03:00 committed by GitHub
parent 1cbca5eecb
commit 556be08c4e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 63 additions and 15 deletions

View file

@ -571,8 +571,12 @@ namespace Ryujinx.HLE.HOS
Ptc.Initialize(TitleIdText, DisplayVersion, usePtc, memoryManagerMode); Ptc.Initialize(TitleIdText, DisplayVersion, usePtc, memoryManagerMode);
// We allow it for nx-hbloader because it can be used to launch homebrew.
bool allowCodeMemoryForJit = TitleId == 0x010000000000100DUL;
metaData.GetNpdm(out Npdm npdm).ThrowIfFailure(); metaData.GetNpdm(out Npdm npdm).ThrowIfFailure();
ProgramLoader.LoadNsos(_device.System.KernelContext, out ProcessTamperInfo tamperInfo, metaData, new ProgramInfo(in npdm), executables: programs); ProgramInfo programInfo = new ProgramInfo(in npdm, allowCodeMemoryForJit);
ProgramLoader.LoadNsos(_device.System.KernelContext, out ProcessTamperInfo tamperInfo, metaData, programInfo, executables: programs);
_device.Configuration.VirtualFileSystem.ModLoader.LoadCheats(TitleId, tamperInfo, _device.TamperMachine); _device.Configuration.VirtualFileSystem.ModLoader.LoadCheats(TitleId, tamperInfo, _device.TamperMachine);
} }
@ -581,7 +585,7 @@ namespace Ryujinx.HLE.HOS
{ {
MetaLoader metaData = GetDefaultNpdm(); MetaLoader metaData = GetDefaultNpdm();
metaData.GetNpdm(out Npdm npdm).ThrowIfFailure(); metaData.GetNpdm(out Npdm npdm).ThrowIfFailure();
ProgramInfo programInfo = new ProgramInfo(in npdm); ProgramInfo programInfo = new ProgramInfo(in npdm, allowCodeMemoryForJit: true);
bool isNro = Path.GetExtension(filePath).ToLower() == ".nro"; bool isNro = Path.GetExtension(filePath).ToLower() == ".nro";

View file

@ -59,5 +59,15 @@ namespace Ryujinx.HLE.HOS.Kernel
{ {
return GetCurrentThread().Owner; return GetCurrentThread().Owner;
} }
internal static KProcess GetProcessByPid(ulong pid)
{
if (Context.Processes.TryGetValue(pid, out KProcess process))
{
return process;
}
return null;
}
} }
} }

View file

@ -60,6 +60,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
public KProcessCapabilities Capabilities { get; private set; } public KProcessCapabilities Capabilities { get; private set; }
public bool AllowCodeMemoryForJit { get; private set; }
public ulong TitleId { get; private set; } public ulong TitleId { get; private set; }
public bool IsApplication { get; private set; } public bool IsApplication { get; private set; }
public ulong Pid { get; private set; } public ulong Pid { get; private set; }
@ -90,7 +92,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
public HleProcessDebugger Debugger { get; private set; } public HleProcessDebugger Debugger { get; private set; }
public KProcess(KernelContext context) : base(context) public KProcess(KernelContext context, bool allowCodeMemoryForJit = false) : base(context)
{ {
_processLock = new object(); _processLock = new object();
_threadingLock = new object(); _threadingLock = new object();
@ -102,6 +104,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
Capabilities = new KProcessCapabilities(); Capabilities = new KProcessCapabilities();
AllowCodeMemoryForJit = allowCodeMemoryForJit;
RandomEntropy = new ulong[KScheduler.CpuCoresCount]; RandomEntropy = new ulong[KScheduler.CpuCoresCount];
PinnedThreads = new KThread[KScheduler.CpuCoresCount]; PinnedThreads = new KThread[KScheduler.CpuCoresCount];

View file

@ -7,7 +7,6 @@ using Ryujinx.HLE.HOS.Kernel.Ipc;
using Ryujinx.HLE.HOS.Kernel.Memory; using Ryujinx.HLE.HOS.Kernel.Memory;
using Ryujinx.HLE.HOS.Kernel.Process; using Ryujinx.HLE.HOS.Kernel.Process;
using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.HLE.HOS.Kernel.Threading;
using Ryujinx.Memory;
using System; using System;
using System.Threading; using System.Threading;
@ -1363,10 +1362,10 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
KCodeMemory codeMemory = currentProcess.HandleTable.GetObject<KCodeMemory>(handle); KCodeMemory codeMemory = currentProcess.HandleTable.GetObject<KCodeMemory>(handle);
// Newer versions of the return also returns an error here if the owner and process // Newer versions of the kernel also returns an error here if the owner and process
// where the operation will happen are the same. We do not return an error here // where the operation will happen are the same. We do not return an error here
// because some homebrew requires this to be patched out to work (for JIT). // for homebrew because some of them requires this to be patched out to work (for JIT).
if (codeMemory == null /* || codeMemory.Owner == currentProcess */) if (codeMemory == null || (!currentProcess.AllowCodeMemoryForJit && codeMemory.Owner == currentProcess))
{ {
return KernelResult.InvalidHandle; return KernelResult.InvalidHandle;
} }

View file

@ -20,11 +20,13 @@ namespace Ryujinx.HLE.HOS
{ {
public string Name; public string Name;
public ulong ProgramId; public ulong ProgramId;
public bool AllowCodeMemoryForJit;
public ProgramInfo(in Npdm npdm) public ProgramInfo(in Npdm npdm, bool allowCodeMemoryForJit)
{ {
Name = StringUtils.Utf8ZToString(npdm.Meta.Value.ProgramName); Name = StringUtils.Utf8ZToString(npdm.Meta.Value.ProgramName);
ProgramId = npdm.Aci.Value.ProgramId.Value; ProgramId = npdm.Aci.Value.ProgramId.Value;
AllowCodeMemoryForJit = allowCodeMemoryForJit;
} }
} }
@ -141,7 +143,13 @@ namespace Ryujinx.HLE.HOS
return true; return true;
} }
public static bool LoadNsos(KernelContext context, out ProcessTamperInfo tamperInfo, MetaLoader metaData, ProgramInfo programInfo, byte[] arguments = null, params IExecutable[] executables) public static bool LoadNsos(
KernelContext context,
out ProcessTamperInfo tamperInfo,
MetaLoader metaData,
ProgramInfo programInfo,
byte[] arguments = null,
params IExecutable[] executables)
{ {
LibHac.Result rc = metaData.GetNpdm(out var npdm); LibHac.Result rc = metaData.GetNpdm(out var npdm);
@ -243,7 +251,7 @@ namespace Ryujinx.HLE.HOS
return false; return false;
} }
KProcess process = new KProcess(context); KProcess process = new KProcess(context, programInfo.AllowCodeMemoryForJit);
MemoryRegion memoryRegion = (MemoryRegion)((npdm.Acid.Value.Flags >> 2) & 0xf); MemoryRegion memoryRegion = (MemoryRegion)((npdm.Acid.Value.Flags >> 2) & 0xf);

View file

@ -1,8 +1,31 @@
namespace Ryujinx.HLE.HOS.Services.Pm using Ryujinx.HLE.HOS.Ipc;
using Ryujinx.HLE.HOS.Kernel;
using Ryujinx.HLE.HOS.Kernel.Common;
using Ryujinx.HLE.HOS.Kernel.Process;
namespace Ryujinx.HLE.HOS.Services.Pm
{ {
[Service("pm:dmnt")] [Service("pm:dmnt")]
class IDebugMonitorInterface : IpcService class IDebugMonitorInterface : IpcService
{ {
public IDebugMonitorInterface(ServiceCtx context) { } public IDebugMonitorInterface(ServiceCtx context) { }
[CommandHipc(65000)]
// AtmosphereGetProcessInfo(os::ProcessId process_id) -> sf::OutCopyHandle out_process_handle, sf::Out<ncm::ProgramLocation> out_loc, sf::Out<cfg::OverrideStatus> out_status
public ResultCode GetProcessInfo(ServiceCtx context)
{
ulong pid = context.RequestData.ReadUInt64();
KProcess process = KernelStatic.GetProcessByPid(pid);
if (context.Process.HandleTable.GenerateHandle(process, out int processHandle) != KernelResult.Success)
{
throw new System.Exception("Out of handles!");
}
context.Response.HandleDesc = IpcHandleDesc.MakeCopy(processHandle);
return ResultCode.Success;
}
} }
} }