Prepo: Fix SaveSystemReport* IPC definitions (#4278)

* Prepo: Fix SaveSystemReport IPC definitions

* Follow original code

* Fix args index in HipcGenerator

* Addresses feedback

* oops
This commit is contained in:
Ac_K 2023-01-13 01:50:14 +01:00 committed by GitHub
parent 8fa248ceb4
commit 4d2c8e2a44
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 78 additions and 17 deletions

View file

@ -267,6 +267,8 @@ namespace Ryujinx.Horizon.Generators.Hipc
} }
int index = 0; int index = 0;
int inArgIndex = 0;
int outArgIndex = 0;
int inCopyHandleIndex = 0; int inCopyHandleIndex = 0;
int inMoveHandleIndex = 0; int inMoveHandleIndex = 0;
int inObjectIndex = 0; int inObjectIndex = 0;
@ -284,7 +286,7 @@ namespace Ryujinx.Horizon.Generators.Hipc
{ {
if (IsNonSpanOutBuffer(compilation, parameter)) if (IsNonSpanOutBuffer(compilation, parameter))
{ {
generator.AppendLine($"using var {argName} = CommandSerialization.GetWritableRegion(processor.GetBufferRange({index}));"); generator.AppendLine($"using var {argName} = CommandSerialization.GetWritableRegion(processor.GetBufferRange({outArgIndex++}));");
argName = $"out {GenerateSpanCastElement0(canonicalTypeName, $"{argName}.Memory.Span")}"; argName = $"out {GenerateSpanCastElement0(canonicalTypeName, $"{argName}.Memory.Span")}";
} }
@ -302,7 +304,7 @@ namespace Ryujinx.Horizon.Generators.Hipc
switch (argType) switch (argType)
{ {
case CommandArgType.InArgument: case CommandArgType.InArgument:
value = $"CommandSerialization.DeserializeArg<{canonicalTypeName}>(inRawData, processor.GetInArgOffset({index}))"; value = $"CommandSerialization.DeserializeArg<{canonicalTypeName}>(inRawData, processor.GetInArgOffset({inArgIndex++}))";
break; break;
case CommandArgType.InCopyHandle: case CommandArgType.InCopyHandle:
value = $"CommandSerialization.DeserializeCopyHandle(ref context, {inCopyHandleIndex++})"; value = $"CommandSerialization.DeserializeCopyHandle(ref context, {inCopyHandleIndex++})";

View file

@ -42,7 +42,7 @@ namespace Ryujinx.Horizon.Prepo.Ipc
return PrepoResult.PermissionDenied; return PrepoResult.PermissionDenied;
} }
ProcessPlayReport(PlayReportKind.Normal, pid, gameRoomBuffer, reportBuffer, Uid.Null); ProcessPlayReport(PlayReportKind.Normal, gameRoomBuffer, reportBuffer, pid, Uid.Null);
return Result.Success; return Result.Success;
} }
@ -57,7 +57,7 @@ namespace Ryujinx.Horizon.Prepo.Ipc
return PrepoResult.PermissionDenied; return PrepoResult.PermissionDenied;
} }
ProcessPlayReport(PlayReportKind.Normal, pid, gameRoomBuffer, reportBuffer, userId, true); ProcessPlayReport(PlayReportKind.Normal, gameRoomBuffer, reportBuffer, pid, userId, true);
return Result.Success; return Result.Success;
} }
@ -107,25 +107,25 @@ namespace Ryujinx.Horizon.Prepo.Ipc
} }
[CmifCommand(20100)] [CmifCommand(20100)]
public Result SaveSystemReport([Buffer(HipcBufferFlags.In | HipcBufferFlags.Pointer)] ReadOnlySpan<byte> gameRoomBuffer, [Buffer(HipcBufferFlags.In | HipcBufferFlags.MapAlias)] ReadOnlySpan<byte> reportBuffer, [ClientProcessId] ulong pid) public Result SaveSystemReport([Buffer(HipcBufferFlags.In | HipcBufferFlags.Pointer)] ReadOnlySpan<byte> gameRoomBuffer, Sdk.Ncm.ApplicationId applicationId, [Buffer(HipcBufferFlags.In | HipcBufferFlags.MapAlias)] ReadOnlySpan<byte> reportBuffer)
{ {
if ((_permissionLevel & PrepoServicePermissionLevel.System) != 0) if ((_permissionLevel & PrepoServicePermissionLevel.System) != 0)
{ {
return PrepoResult.PermissionDenied; return PrepoResult.PermissionDenied;
} }
return ProcessPlayReport(PlayReportKind.System, pid, gameRoomBuffer, reportBuffer, Uid.Null); return ProcessPlayReport(PlayReportKind.System, gameRoomBuffer, reportBuffer, 0, Uid.Null, false, applicationId);
} }
[CmifCommand(20101)] [CmifCommand(20101)]
public Result SaveSystemReportWithUser(Uid userId, [Buffer(HipcBufferFlags.In | HipcBufferFlags.Pointer)] ReadOnlySpan<byte> gameRoomBuffer, [Buffer(HipcBufferFlags.In | HipcBufferFlags.MapAlias)] ReadOnlySpan<byte> reportBuffer, [ClientProcessId] ulong pid) public Result SaveSystemReportWithUser(Uid userId, [Buffer(HipcBufferFlags.In | HipcBufferFlags.Pointer)] ReadOnlySpan<byte> gameRoomBuffer, Sdk.Ncm.ApplicationId applicationId, [Buffer(HipcBufferFlags.In | HipcBufferFlags.MapAlias)] ReadOnlySpan<byte> reportBuffer)
{ {
if ((_permissionLevel & PrepoServicePermissionLevel.System) != 0) if ((_permissionLevel & PrepoServicePermissionLevel.System) != 0)
{ {
return PrepoResult.PermissionDenied; return PrepoResult.PermissionDenied;
} }
return ProcessPlayReport(PlayReportKind.System, pid, gameRoomBuffer, reportBuffer, userId, true); return ProcessPlayReport(PlayReportKind.System, gameRoomBuffer, reportBuffer, 0, userId, true, applicationId);
} }
[CmifCommand(40100)] // 2.0.0+ [CmifCommand(40100)] // 2.0.0+
@ -164,7 +164,7 @@ namespace Ryujinx.Horizon.Prepo.Ipc
return PrepoResult.PermissionDenied; return PrepoResult.PermissionDenied;
} }
private static Result ProcessPlayReport(PlayReportKind playReportKind, ulong pid, ReadOnlySpan<byte> gameRoomBuffer, ReadOnlySpan<byte> reportBuffer, Uid userId, bool withUserId = false) private static Result ProcessPlayReport(PlayReportKind playReportKind, ReadOnlySpan<byte> gameRoomBuffer, ReadOnlySpan<byte> reportBuffer, ulong pid, Uid userId, bool withUserId = false, Sdk.Ncm.ApplicationId applicationId = default)
{ {
if (withUserId) if (withUserId)
{ {
@ -191,16 +191,23 @@ namespace Ryujinx.Horizon.Prepo.Ipc
return PrepoResult.InvalidBufferSize; return PrepoResult.InvalidBufferSize;
} }
// NOTE: The service calls arp:r using the pid to get the application id, if it fails PrepoResult.InvalidPid is returned.
// Reports are stored internally and an event is signaled to transmit them.
StringBuilder builder = new(); StringBuilder builder = new();
MessagePackObject deserializedReport = MessagePackSerializer.UnpackMessagePackObject(reportBuffer.ToArray()); MessagePackObject deserializedReport = MessagePackSerializer.UnpackMessagePackObject(reportBuffer.ToArray());
builder.AppendLine(); builder.AppendLine();
builder.AppendLine("PlayReport log:"); builder.AppendLine("PlayReport log:");
builder.AppendLine($" Kind: {playReportKind}"); builder.AppendLine($" Kind: {playReportKind}");
// NOTE: The service calls arp:r using the pid to get the application id, if it fails PrepoResult.InvalidPid is returned.
// Reports are stored internally and an event is signaled to transmit them.
if (pid != 0)
{
builder.AppendLine($" Pid: {pid}"); builder.AppendLine($" Pid: {pid}");
}
else
{
builder.AppendLine($" ApplicationId: {applicationId}");
}
if (!userId.IsNull) if (!userId.IsNull)
{ {

View file

@ -6,7 +6,7 @@ using System.Runtime.InteropServices;
namespace Ryujinx.Horizon.Sdk.Account namespace Ryujinx.Horizon.Sdk.Account
{ {
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public readonly record struct Uid readonly record struct Uid
{ {
public readonly long High; public readonly long High;
public readonly long Low; public readonly long Low;

View file

@ -0,0 +1,52 @@
namespace Ryujinx.Horizon.Sdk.Ncm
{
readonly struct ApplicationId
{
public readonly ulong Id;
public static int Length => sizeof(ulong);
public static ApplicationId First => new(0x0100000000010000);
public static ApplicationId Last => new(0x01FFFFFFFFFFFFFF);
public static ApplicationId Invalid => new(0);
public bool IsValid => Id >= First.Id && Id <= Last.Id;
public ApplicationId(ulong id)
{
Id = id;
}
public override bool Equals(object obj)
{
return obj is ApplicationId applicationId && applicationId.Equals(this);
}
public bool Equals(ApplicationId other)
{
return other.Id == Id;
}
public override int GetHashCode()
{
return Id.GetHashCode();
}
public static bool operator ==(ApplicationId lhs, ApplicationId rhs)
{
return lhs.Equals(rhs);
}
public static bool operator !=(ApplicationId lhs, ApplicationId rhs)
{
return !lhs.Equals(rhs);
}
public override string ToString()
{
return $"0x{Id:x}";
}
}
}

View file

@ -12,8 +12,8 @@ namespace Ryujinx.Horizon.Sdk.Prepo
Result RequestImmediateTransmission(); Result RequestImmediateTransmission();
Result GetTransmissionStatus(out int status); Result GetTransmissionStatus(out int status);
Result GetSystemSessionId(out ulong systemSessionId); Result GetSystemSessionId(out ulong systemSessionId);
Result SaveSystemReport(ReadOnlySpan<byte> gameRoomBuffer, ReadOnlySpan<byte> reportBuffer, ulong pid); Result SaveSystemReport(ReadOnlySpan<byte> gameRoomBuffer, Ncm.ApplicationId applicationId, ReadOnlySpan<byte> reportBuffer);
Result SaveSystemReportWithUser(Uid userId, ReadOnlySpan<byte> gameRoomBuffer, ReadOnlySpan<byte> reportBuffer, ulong pid); Result SaveSystemReportWithUser(Uid userId, ReadOnlySpan<byte> gameRoomBuffer, Ncm.ApplicationId applicationId, ReadOnlySpan<byte> reportBuffer);
Result IsUserAgreementCheckEnabled(out bool enabled); Result IsUserAgreementCheckEnabled(out bool enabled);
Result SetUserAgreementCheckEnabled(bool enabled); Result SetUserAgreementCheckEnabled(bool enabled);
} }

View file

@ -8,7 +8,7 @@ namespace Ryujinx.Horizon.Sdk.Sm
{ {
public static ServiceName Invalid { get; } = new ServiceName(0); public static ServiceName Invalid { get; } = new ServiceName(0);
public bool IsInvalid => Packed == 0; public bool IsValid => Packed != 0;
public int Length => sizeof(ulong); public int Length => sizeof(ulong);