SvcSystem.cs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. using ChocolArm64.Memory;
  2. using ChocolArm64.State;
  3. using Ryujinx.OsHle.Exceptions;
  4. using Ryujinx.OsHle.Handles;
  5. using Ryujinx.OsHle.Ipc;
  6. using System;
  7. namespace Ryujinx.OsHle.Svc
  8. {
  9. partial class SvcHandler
  10. {
  11. private void SvcExitProcess(ARegisters Registers) => Ns.Os.ExitProcess(Registers.ProcessId);
  12. private void SvcCloseHandle(ARegisters Registers)
  13. {
  14. int Handle = (int)Registers.X0;
  15. Ns.Os.CloseHandle(Handle);
  16. Registers.X0 = (int)SvcResult.Success;
  17. }
  18. private void SvcResetSignal(ARegisters Registers)
  19. {
  20. int Handle = (int)Registers.X0;
  21. //TODO: Implement events.
  22. Registers.X0 = (int)SvcResult.Success;
  23. }
  24. private void SvcWaitSynchronization(ARegisters Registers)
  25. {
  26. long HandlesPtr = (long)Registers.X0;
  27. int HandlesCount = (int)Registers.X2;
  28. long Timeout = (long)Registers.X3;
  29. //TODO: Implement events.
  30. //Logging.Info($"SvcWaitSynchronization Thread {Registers.ThreadId}");
  31. if (Process.TryGetThread(Registers.Tpidr, out HThread Thread))
  32. {
  33. Process.Scheduler.Yield(Thread);
  34. }
  35. else
  36. {
  37. Logging.Error($"Thread with TPIDR_EL0 0x{Registers.Tpidr:x16} not found!");
  38. }
  39. Registers.X0 = (int)SvcResult.Success;
  40. }
  41. private void SvcGetSystemTick(ARegisters Registers)
  42. {
  43. Registers.X0 = (ulong)Registers.CntpctEl0;
  44. }
  45. private void SvcConnectToNamedPort(ARegisters Registers)
  46. {
  47. long StackPtr = (long)Registers.X0;
  48. long NamePtr = (long)Registers.X1;
  49. string Name = AMemoryHelper.ReadAsciiString(Memory, NamePtr, 8);
  50. //TODO: Validate that app has perms to access the service, and that the service
  51. //actually exists, return error codes otherwise.
  52. HSession Session = new HSession(Name);
  53. Registers.X1 = (ulong)Ns.Os.Handles.GenerateId(Session);
  54. Registers.X0 = (int)SvcResult.Success;
  55. }
  56. private void SvcSendSyncRequest(ARegisters Registers)
  57. {
  58. SendSyncRequest(Registers, false);
  59. }
  60. private void SvcSendSyncRequestWithUserBuffer(ARegisters Registers)
  61. {
  62. SendSyncRequest(Registers, true);
  63. }
  64. private void SendSyncRequest(ARegisters Registers, bool UserBuffer)
  65. {
  66. long CmdPtr = Registers.Tpidr;
  67. long Size = 0x100;
  68. int Handle = 0;
  69. if (UserBuffer)
  70. {
  71. CmdPtr = (long)Registers.X0;
  72. Size = (long)Registers.X1;
  73. Handle = (int)Registers.X2;
  74. }
  75. else
  76. {
  77. Handle = (int)Registers.X0;
  78. }
  79. byte[] CmdData = AMemoryHelper.ReadBytes(Memory, CmdPtr, (int)Size);
  80. HSession Session = Ns.Os.Handles.GetData<HSession>(Handle);
  81. IpcMessage Cmd = new IpcMessage(CmdData, CmdPtr, Session is HDomain);
  82. if (Session != null)
  83. {
  84. IpcHandler.IpcCall(Ns, Memory, Session, Cmd, CmdPtr, Handle);
  85. byte[] Response = AMemoryHelper.ReadBytes(Memory, CmdPtr, (int)Size);
  86. Registers.X0 = (int)SvcResult.Success;
  87. }
  88. else
  89. {
  90. Registers.X0 = (int)SvcResult.ErrBadIpcReq;
  91. }
  92. }
  93. private void SvcBreak(ARegisters Registers)
  94. {
  95. long Reason = (long)Registers.X0;
  96. long Unknown = (long)Registers.X1;
  97. long Info = (long)Registers.X2;
  98. throw new GuestBrokeExecutionException();
  99. }
  100. private void SvcOutputDebugString(ARegisters Registers)
  101. {
  102. long Position = (long)Registers.X0;
  103. long Size = (long)Registers.X1;
  104. string Str = AMemoryHelper.ReadAsciiString(Memory, Position, (int)Size);
  105. Logging.Info($"SvcOutputDebugString: {Str}");
  106. Registers.X0 = (int)SvcResult.Success;
  107. }
  108. private void SvcGetInfo(ARegisters Registers)
  109. {
  110. long StackPtr = (long)Registers.X0;
  111. int InfoType = (int)Registers.X1;
  112. long Handle = (long)Registers.X2;
  113. int InfoId = (int)Registers.X3;
  114. //Fail for info not available on older Kernel versions.
  115. if (InfoType == 18 ||
  116. InfoType == 19)
  117. {
  118. Registers.X0 = (int)SvcResult.ErrBadInfo;
  119. return;
  120. }
  121. switch (InfoType)
  122. {
  123. case 2: Registers.X1 = GetMapRegionBaseAddr(); break;
  124. case 3: Registers.X1 = GetMapRegionSize(); break;
  125. case 4: Registers.X1 = GetHeapRegionBaseAddr(); break;
  126. case 5: Registers.X1 = GetHeapRegionSize(); break;
  127. case 6: Registers.X1 = GetTotalMem(); break;
  128. case 7: Registers.X1 = GetUsedMem(); break;
  129. case 11: Registers.X1 = GetRnd64(); break;
  130. case 12: Registers.X1 = GetAddrSpaceBaseAddr(); break;
  131. case 13: Registers.X1 = GetAddrSpaceSize(); break;
  132. case 14: Registers.X1 = GetMapRegionBaseAddr(); break;
  133. case 15: Registers.X1 = GetMapRegionSize(); break;
  134. default: throw new NotImplementedException($"SvcGetInfo: {InfoType} {Handle} {InfoId}");
  135. }
  136. Registers.X0 = (int)SvcResult.Success;
  137. }
  138. private ulong GetTotalMem()
  139. {
  140. return (ulong)Memory.Manager.GetTotalMemorySize();
  141. }
  142. private ulong GetUsedMem()
  143. {
  144. return (ulong)Memory.Manager.GetUsedMemorySize();
  145. }
  146. private ulong GetRnd64()
  147. {
  148. return (ulong)Rng.Next() + ((ulong)Rng.Next() << 32);
  149. }
  150. private ulong GetAddrSpaceBaseAddr()
  151. {
  152. return 0x08000000;
  153. }
  154. private ulong GetAddrSpaceSize()
  155. {
  156. return AMemoryMgr.AddrSize - GetAddrSpaceBaseAddr();
  157. }
  158. private ulong GetMapRegionBaseAddr()
  159. {
  160. return 0x80000000;
  161. }
  162. private ulong GetMapRegionSize()
  163. {
  164. return 0x40000000;
  165. }
  166. private ulong GetHeapRegionBaseAddr()
  167. {
  168. return GetMapRegionBaseAddr() + GetMapRegionSize();
  169. }
  170. private ulong GetHeapRegionSize()
  171. {
  172. return 0x40000000;
  173. }
  174. }
  175. }