aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.HLE/HOS/Ipc
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2018-08-16 20:47:36 -0300
committerGitHub <noreply@github.com>2018-08-16 20:47:36 -0300
commit521751795a1c97c0d97f6f8904a3be69b13d3a9d (patch)
tree942a05899c40e2de6d92a38b93a494bd96ee64b8 /Ryujinx.HLE/HOS/Ipc
parent182d716867ae477c2b15a5332430dc2641fa1cc3 (diff)
Code style fixes and nits on the HLE project (#355)
* Some style fixes and nits on ITimeZoneService * Remove some unneeded usings * Remove the Ryujinx.HLE.OsHle.Handles namespace * Remove hbmenu automatic load on process exit * Rename Ns to Device, rename Os to System, rename SystemState to State * Move Exceptions and Utilities out of OsHle * Rename OsHle to HOS * Rename OsHle folder to HOS * IManagerDisplayService and ISystemDisplayService style fixes * BsdError shouldn't be public * Add a empty new line before using static * Remove unused file * Some style fixes on NPDM * Exit gracefully when the application is closed * Code style fixes on IGeneralService * Add 0x prefix on values printed as hex * Small improvements on finalization code * Move ProcessId and ThreadId out of AThreadState * Rename VFs to FileSystem * FsAccessHeader shouldn't be public. Also fix file names casing * More case changes on NPDM * Remove unused files * Move using to the correct place on NPDM * Use properties on KernelAccessControlMmio * Address PR feedback
Diffstat (limited to 'Ryujinx.HLE/HOS/Ipc')
-rw-r--r--Ryujinx.HLE/HOS/Ipc/IpcBuffDesc.cs27
-rw-r--r--Ryujinx.HLE/HOS/Ipc/IpcHandleDesc.cs92
-rw-r--r--Ryujinx.HLE/HOS/Ipc/IpcHandler.cs140
-rw-r--r--Ryujinx.HLE/HOS/Ipc/IpcMagic.cs8
-rw-r--r--Ryujinx.HLE/HOS/Ipc/IpcMessage.cs215
-rw-r--r--Ryujinx.HLE/HOS/Ipc/IpcMessageType.cs12
-rw-r--r--Ryujinx.HLE/HOS/Ipc/IpcPtrBuffDesc.cs26
-rw-r--r--Ryujinx.HLE/HOS/Ipc/IpcRecvListBuffDesc.cs19
-rw-r--r--Ryujinx.HLE/HOS/Ipc/ServiceProcessRequest.cs4
9 files changed, 543 insertions, 0 deletions
diff --git a/Ryujinx.HLE/HOS/Ipc/IpcBuffDesc.cs b/Ryujinx.HLE/HOS/Ipc/IpcBuffDesc.cs
new file mode 100644
index 00000000..346d696e
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Ipc/IpcBuffDesc.cs
@@ -0,0 +1,27 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Ipc
+{
+ struct IpcBuffDesc
+ {
+ public long Position { get; private set; }
+ public long Size { get; private set; }
+ public int Flags { get; private set; }
+
+ public IpcBuffDesc(BinaryReader Reader)
+ {
+ long Word0 = Reader.ReadUInt32();
+ long Word1 = Reader.ReadUInt32();
+ long Word2 = Reader.ReadUInt32();
+
+ Position = Word1;
+ Position |= (Word2 << 4) & 0x0f00000000;
+ Position |= (Word2 << 34) & 0x7000000000;
+
+ Size = Word0;
+ Size |= (Word2 << 8) & 0xf00000000;
+
+ Flags = (int)Word2 & 3;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Ipc/IpcHandleDesc.cs b/Ryujinx.HLE/HOS/Ipc/IpcHandleDesc.cs
new file mode 100644
index 00000000..081b5695
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Ipc/IpcHandleDesc.cs
@@ -0,0 +1,92 @@
+using System;
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Ipc
+{
+ class IpcHandleDesc
+ {
+ public bool HasPId { get; private set; }
+
+ public long PId { get; private set; }
+
+ public int[] ToCopy { get; private set; }
+ public int[] ToMove { get; private set; }
+
+ public IpcHandleDesc(BinaryReader Reader)
+ {
+ int Word = Reader.ReadInt32();
+
+ HasPId = (Word & 1) != 0;
+
+ ToCopy = new int[(Word >> 1) & 0xf];
+ ToMove = new int[(Word >> 5) & 0xf];
+
+ PId = HasPId ? Reader.ReadInt64() : 0;
+
+ for (int Index = 0; Index < ToCopy.Length; Index++)
+ {
+ ToCopy[Index] = Reader.ReadInt32();
+ }
+
+ for (int Index = 0; Index < ToMove.Length; Index++)
+ {
+ ToMove[Index] = Reader.ReadInt32();
+ }
+ }
+
+ public IpcHandleDesc(int[] Copy, int[] Move)
+ {
+ ToCopy = Copy ?? throw new ArgumentNullException(nameof(Copy));
+ ToMove = Move ?? throw new ArgumentNullException(nameof(Move));
+ }
+
+ public IpcHandleDesc(int[] Copy, int[] Move, long PId) : this(Copy, Move)
+ {
+ this.PId = PId;
+
+ HasPId = true;
+ }
+
+ public static IpcHandleDesc MakeCopy(params int[] Handles)
+ {
+ return new IpcHandleDesc(Handles, new int[0]);
+ }
+
+ public static IpcHandleDesc MakeMove(params int[] Handles)
+ {
+ return new IpcHandleDesc(new int[0], Handles);
+ }
+
+ public byte[] GetBytes()
+ {
+ using (MemoryStream MS = new MemoryStream())
+ {
+ BinaryWriter Writer = new BinaryWriter(MS);
+
+ int Word = HasPId ? 1 : 0;
+
+ Word |= (ToCopy.Length & 0xf) << 1;
+ Word |= (ToMove.Length & 0xf) << 5;
+
+ Writer.Write(Word);
+
+ if (HasPId)
+ {
+ Writer.Write((long)PId);
+ }
+
+ foreach (int Handle in ToCopy)
+ {
+ Writer.Write(Handle);
+ }
+
+ foreach (int Handle in ToMove)
+ {
+ Writer.Write(Handle);
+ }
+
+ return MS.ToArray();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Ipc/IpcHandler.cs b/Ryujinx.HLE/HOS/Ipc/IpcHandler.cs
new file mode 100644
index 00000000..08a4cdb5
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Ipc/IpcHandler.cs
@@ -0,0 +1,140 @@
+using ChocolArm64.Memory;
+using Ryujinx.HLE.HOS.Kernel;
+using System;
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Ipc
+{
+ static class IpcHandler
+ {
+ public static long IpcCall(
+ Switch Ns,
+ Process Process,
+ AMemory Memory,
+ KSession Session,
+ IpcMessage Request,
+ long CmdPtr)
+ {
+ IpcMessage Response = new IpcMessage();
+
+ using (MemoryStream Raw = new MemoryStream(Request.RawData))
+ {
+ BinaryReader ReqReader = new BinaryReader(Raw);
+
+ if (Request.Type == IpcMessageType.Request ||
+ Request.Type == IpcMessageType.RequestWithContext)
+ {
+ Response.Type = IpcMessageType.Response;
+
+ using (MemoryStream ResMS = new MemoryStream())
+ {
+ BinaryWriter ResWriter = new BinaryWriter(ResMS);
+
+ ServiceCtx Context = new ServiceCtx(
+ Ns,
+ Process,
+ Memory,
+ Session,
+ Request,
+ Response,
+ ReqReader,
+ ResWriter);
+
+ Session.Service.CallMethod(Context);
+
+ Response.RawData = ResMS.ToArray();
+ }
+ }
+ else if (Request.Type == IpcMessageType.Control ||
+ Request.Type == IpcMessageType.ControlWithContext)
+ {
+ long Magic = ReqReader.ReadInt64();
+ long CmdId = ReqReader.ReadInt64();
+
+ switch (CmdId)
+ {
+ case 0:
+ {
+ Request = FillResponse(Response, 0, Session.Service.ConvertToDomain());
+
+ break;
+ }
+
+ case 3:
+ {
+ Request = FillResponse(Response, 0, 0x500);
+
+ break;
+ }
+
+ //TODO: Whats the difference between IpcDuplicateSession/Ex?
+ case 2:
+ case 4:
+ {
+ int Unknown = ReqReader.ReadInt32();
+
+ int Handle = Process.HandleTable.OpenHandle(Session);
+
+ Response.HandleDesc = IpcHandleDesc.MakeMove(Handle);
+
+ Request = FillResponse(Response, 0);
+
+ break;
+ }
+
+ default: throw new NotImplementedException(CmdId.ToString());
+ }
+ }
+ else if (Request.Type == IpcMessageType.CloseSession)
+ {
+ //TODO
+ }
+ else
+ {
+ throw new NotImplementedException(Request.Type.ToString());
+ }
+
+ Memory.WriteBytes(CmdPtr, Response.GetBytes(CmdPtr));
+ }
+
+ return 0;
+ }
+
+ private static IpcMessage FillResponse(IpcMessage Response, long Result, params int[] Values)
+ {
+ using (MemoryStream MS = new MemoryStream())
+ {
+ BinaryWriter Writer = new BinaryWriter(MS);
+
+ foreach (int Value in Values)
+ {
+ Writer.Write(Value);
+ }
+
+ return FillResponse(Response, Result, MS.ToArray());
+ }
+ }
+
+ private static IpcMessage FillResponse(IpcMessage Response, long Result, byte[] Data = null)
+ {
+ Response.Type = IpcMessageType.Response;
+
+ using (MemoryStream MS = new MemoryStream())
+ {
+ BinaryWriter Writer = new BinaryWriter(MS);
+
+ Writer.Write(IpcMagic.Sfco);
+ Writer.Write(Result);
+
+ if (Data != null)
+ {
+ Writer.Write(Data);
+ }
+
+ Response.RawData = MS.ToArray();
+ }
+
+ return Response;
+ }
+ }
+}
diff --git a/Ryujinx.HLE/HOS/Ipc/IpcMagic.cs b/Ryujinx.HLE/HOS/Ipc/IpcMagic.cs
new file mode 100644
index 00000000..72770b90
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Ipc/IpcMagic.cs
@@ -0,0 +1,8 @@
+namespace Ryujinx.HLE.HOS.Ipc
+{
+ abstract class IpcMagic
+ {
+ public const long Sfci = 'S' << 0 | 'F' << 8 | 'C' << 16 | 'I' << 24;
+ public const long Sfco = 'S' << 0 | 'F' << 8 | 'C' << 16 | 'O' << 24;
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Ipc/IpcMessage.cs b/Ryujinx.HLE/HOS/Ipc/IpcMessage.cs
new file mode 100644
index 00000000..c8153fdb
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Ipc/IpcMessage.cs
@@ -0,0 +1,215 @@
+using System.Collections.Generic;
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Ipc
+{
+ class IpcMessage
+ {
+ public IpcMessageType Type { get; set; }
+
+ public IpcHandleDesc HandleDesc { get; set; }
+
+ public List<IpcPtrBuffDesc> PtrBuff { get; private set; }
+ public List<IpcBuffDesc> SendBuff { get; private set; }
+ public List<IpcBuffDesc> ReceiveBuff { get; private set; }
+ public List<IpcBuffDesc> ExchangeBuff { get; private set; }
+ public List<IpcRecvListBuffDesc> RecvListBuff { get; private set; }
+
+ public List<int> ObjectIds { get; private set; }
+
+ public byte[] RawData { get; set; }
+
+ public IpcMessage()
+ {
+ PtrBuff = new List<IpcPtrBuffDesc>();
+ SendBuff = new List<IpcBuffDesc>();
+ ReceiveBuff = new List<IpcBuffDesc>();
+ ExchangeBuff = new List<IpcBuffDesc>();
+ RecvListBuff = new List<IpcRecvListBuffDesc>();
+
+ ObjectIds = new List<int>();
+ }
+
+ public IpcMessage(byte[] Data, long CmdPtr) : this()
+ {
+ using (MemoryStream MS = new MemoryStream(Data))
+ {
+ BinaryReader Reader = new BinaryReader(MS);
+
+ Initialize(Reader, CmdPtr);
+ }
+ }
+
+ private void Initialize(BinaryReader Reader, long CmdPtr)
+ {
+ int Word0 = Reader.ReadInt32();
+ int Word1 = Reader.ReadInt32();
+
+ Type = (IpcMessageType)(Word0 & 0xffff);
+
+ int PtrBuffCount = (Word0 >> 16) & 0xf;
+ int SendBuffCount = (Word0 >> 20) & 0xf;
+ int RecvBuffCount = (Word0 >> 24) & 0xf;
+ int XchgBuffCount = (Word0 >> 28) & 0xf;
+
+ int RawDataSize = (Word1 >> 0) & 0x3ff;
+ int RecvListFlags = (Word1 >> 10) & 0xf;
+ bool HndDescEnable = ((Word1 >> 31) & 0x1) != 0;
+
+ if (HndDescEnable)
+ {
+ HandleDesc = new IpcHandleDesc(Reader);
+ }
+
+ for (int Index = 0; Index < PtrBuffCount; Index++)
+ {
+ PtrBuff.Add(new IpcPtrBuffDesc(Reader));
+ }
+
+ void ReadBuff(List<IpcBuffDesc> Buff, int Count)
+ {
+ for (int Index = 0; Index < Count; Index++)
+ {
+ Buff.Add(new IpcBuffDesc(Reader));
+ }
+ }
+
+ ReadBuff(SendBuff, SendBuffCount);
+ ReadBuff(ReceiveBuff, RecvBuffCount);
+ ReadBuff(ExchangeBuff, XchgBuffCount);
+
+ RawDataSize *= 4;
+
+ long RecvListPos = Reader.BaseStream.Position + RawDataSize;
+
+ long Pad0 = GetPadSize16(Reader.BaseStream.Position + CmdPtr);
+
+ Reader.BaseStream.Seek(Pad0, SeekOrigin.Current);
+
+ int RecvListCount = RecvListFlags - 2;
+
+ if (RecvListCount == 0)
+ {
+ RecvListCount = 1;
+ }
+ else if (RecvListCount < 0)
+ {
+ RecvListCount = 0;
+ }
+
+ RawData = Reader.ReadBytes(RawDataSize);
+
+ Reader.BaseStream.Seek(RecvListPos, SeekOrigin.Begin);
+
+ for (int Index = 0; Index < RecvListCount; Index++)
+ {
+ RecvListBuff.Add(new IpcRecvListBuffDesc(Reader));
+ }
+ }
+
+ public byte[] GetBytes(long CmdPtr)
+ {
+ using (MemoryStream MS = new MemoryStream())
+ {
+ BinaryWriter Writer = new BinaryWriter(MS);
+
+ int Word0;
+ int Word1;
+
+ Word0 = (int)Type;
+ Word0 |= (PtrBuff.Count & 0xf) << 16;
+ Word0 |= (SendBuff.Count & 0xf) << 20;
+ Word0 |= (ReceiveBuff.Count & 0xf) << 24;
+ Word0 |= (ExchangeBuff.Count & 0xf) << 28;
+
+ byte[] HandleData = new byte[0];
+
+ if (HandleDesc != null)
+ {
+ HandleData = HandleDesc.GetBytes();
+ }
+
+ int DataLength = RawData?.Length ?? 0;
+
+ int Pad0 = (int)GetPadSize16(CmdPtr + 8 + HandleData.Length);
+
+ //Apparently, padding after Raw Data is 16 bytes, however when there is
+ //padding before Raw Data too, we need to subtract the size of this padding.
+ //This is the weirdest padding I've seen so far...
+ int Pad1 = 0x10 - Pad0;
+
+ DataLength = (DataLength + Pad0 + Pad1) / 4;
+
+ Word1 = DataLength & 0x3ff;
+
+ if (HandleDesc != null)
+ {
+ Word1 |= 1 << 31;
+ }
+
+ Writer.Write(Word0);
+ Writer.Write(Word1);
+ Writer.Write(HandleData);
+
+ MS.Seek(Pad0, SeekOrigin.Current);
+
+ if (RawData != null)
+ {
+ Writer.Write(RawData);
+ }
+
+ Writer.Write(new byte[Pad1]);
+
+ return MS.ToArray();
+ }
+ }
+
+ private long GetPadSize16(long Position)
+ {
+ if ((Position & 0xf) != 0)
+ {
+ return 0x10 - (Position & 0xf);
+ }
+
+ return 0;
+ }
+
+ public (long Position, long Size) GetBufferType0x21()
+ {
+ if (PtrBuff.Count != 0 &&
+ PtrBuff[0].Position != 0 &&
+ PtrBuff[0].Size != 0)
+ {
+ return (PtrBuff[0].Position, PtrBuff[0].Size);
+ }
+
+ if (SendBuff.Count != 0 &&
+ SendBuff[0].Position != 0 &&
+ SendBuff[0].Size != 0)
+ {
+ return (SendBuff[0].Position, SendBuff[0].Size);
+ }
+
+ return (0, 0);
+ }
+
+ public (long Position, long Size) GetBufferType0x22()
+ {
+ if (RecvListBuff.Count != 0 &&
+ RecvListBuff[0].Position != 0 &&
+ RecvListBuff[0].Size != 0)
+ {
+ return (RecvListBuff[0].Position, RecvListBuff[0].Size);
+ }
+
+ if (ReceiveBuff.Count != 0 &&
+ ReceiveBuff[0].Position != 0 &&
+ ReceiveBuff[0].Size != 0)
+ {
+ return (ReceiveBuff[0].Position, ReceiveBuff[0].Size);
+ }
+
+ return (0, 0);
+ }
+ }
+}
diff --git a/Ryujinx.HLE/HOS/Ipc/IpcMessageType.cs b/Ryujinx.HLE/HOS/Ipc/IpcMessageType.cs
new file mode 100644
index 00000000..e258accc
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Ipc/IpcMessageType.cs
@@ -0,0 +1,12 @@
+namespace Ryujinx.HLE.HOS.Ipc
+{
+ enum IpcMessageType
+ {
+ Response = 0,
+ CloseSession = 2,
+ Request = 4,
+ Control = 5,
+ RequestWithContext = 6,
+ ControlWithContext = 7
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Ipc/IpcPtrBuffDesc.cs b/Ryujinx.HLE/HOS/Ipc/IpcPtrBuffDesc.cs
new file mode 100644
index 00000000..21f5d3bc
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Ipc/IpcPtrBuffDesc.cs
@@ -0,0 +1,26 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Ipc
+{
+ struct IpcPtrBuffDesc
+ {
+ public long Position { get; private set; }
+ public int Index { get; private set; }
+ public long Size { get; private set; }
+
+ public IpcPtrBuffDesc(BinaryReader Reader)
+ {
+ long Word0 = Reader.ReadUInt32();
+ long Word1 = Reader.ReadUInt32();
+
+ Position = Word1;
+ Position |= (Word0 << 20) & 0x0f00000000;
+ Position |= (Word0 << 30) & 0x7000000000;
+
+ Index = ((int)Word0 >> 0) & 0x03f;
+ Index |= ((int)Word0 >> 3) & 0x1c0;
+
+ Size = (ushort)(Word0 >> 16);
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Ipc/IpcRecvListBuffDesc.cs b/Ryujinx.HLE/HOS/Ipc/IpcRecvListBuffDesc.cs
new file mode 100644
index 00000000..1d0a8c80
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Ipc/IpcRecvListBuffDesc.cs
@@ -0,0 +1,19 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Ipc
+{
+ struct IpcRecvListBuffDesc
+ {
+ public long Position { get; private set; }
+ public long Size { get; private set; }
+
+ public IpcRecvListBuffDesc(BinaryReader Reader)
+ {
+ long Value = Reader.ReadInt64();
+
+ Position = Value & 0xffffffffffff;
+
+ Size = (ushort)(Value >> 48);
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Ipc/ServiceProcessRequest.cs b/Ryujinx.HLE/HOS/Ipc/ServiceProcessRequest.cs
new file mode 100644
index 00000000..da4a7e75
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Ipc/ServiceProcessRequest.cs
@@ -0,0 +1,4 @@
+namespace Ryujinx.HLE.HOS.Ipc
+{
+ delegate long ServiceProcessRequest(ServiceCtx Context);
+} \ No newline at end of file