SvcSystem.cs 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. using ChocolArm64.Memory;
  2. using ChocolArm64.State;
  3. using Ryujinx.Core.OsHle.Exceptions;
  4. using Ryujinx.Core.OsHle.Handles;
  5. using Ryujinx.Core.OsHle.Ipc;
  6. using Ryujinx.Core.OsHle.Services;
  7. using System;
  8. using System.Threading;
  9. using static Ryujinx.Core.OsHle.ErrorCode;
  10. namespace Ryujinx.Core.OsHle.Kernel
  11. {
  12. partial class SvcHandler
  13. {
  14. private const int AllowedCpuIdBitmask = 0b1111;
  15. private const bool EnableProcessDebugging = false;
  16. private void SvcExitProcess(AThreadState ThreadState)
  17. {
  18. Ns.Os.ExitProcess(ThreadState.ProcessId);
  19. }
  20. private void SvcClearEvent(AThreadState ThreadState)
  21. {
  22. int Handle = (int)ThreadState.X0;
  23. //TODO: Implement events.
  24. ThreadState.X0 = 0;
  25. }
  26. private void SvcCloseHandle(AThreadState ThreadState)
  27. {
  28. int Handle = (int)ThreadState.X0;
  29. object Obj = Process.HandleTable.CloseHandle(Handle);
  30. if (Obj == null)
  31. {
  32. Logging.Warn(LogClass.KernelSvc, $"Tried to CloseHandle on invalid handle 0x{Handle:x8}!");
  33. ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
  34. return;
  35. }
  36. if (Obj is KSession Session)
  37. {
  38. Session.Dispose();
  39. }
  40. else if (Obj is HTransferMem TMem)
  41. {
  42. TMem.Memory.Manager.Reprotect(
  43. TMem.Position,
  44. TMem.Size,
  45. TMem.Perm);
  46. }
  47. ThreadState.X0 = 0;
  48. }
  49. private void SvcResetSignal(AThreadState ThreadState)
  50. {
  51. int Handle = (int)ThreadState.X0;
  52. KEvent Event = Process.HandleTable.GetData<KEvent>(Handle);
  53. if (Event != null)
  54. {
  55. Event.WaitEvent.Reset();
  56. ThreadState.X0 = 0;
  57. }
  58. else
  59. {
  60. Logging.Warn(LogClass.KernelSvc, $"Tried to ResetSignal on invalid event handle 0x{Handle:x8}!");
  61. ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
  62. }
  63. }
  64. private void SvcWaitSynchronization(AThreadState ThreadState)
  65. {
  66. long HandlesPtr = (long)ThreadState.X1;
  67. int HandlesCount = (int)ThreadState.X2;
  68. long Timeout = (long)ThreadState.X3;
  69. KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
  70. WaitHandle[] Handles = new WaitHandle[HandlesCount];
  71. for (int Index = 0; Index < HandlesCount; Index++)
  72. {
  73. int Handle = Memory.ReadInt32(HandlesPtr + Index * 4);
  74. KSynchronizationObject SyncObj = Process.HandleTable.GetData<KSynchronizationObject>(Handle);
  75. if (SyncObj == null)
  76. {
  77. Logging.Warn(LogClass.KernelSvc, $"Tried to WaitSynchronization on invalid handle 0x{Handle:x8}!");
  78. ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
  79. return;
  80. }
  81. Handles[Index] = SyncObj.WaitEvent;
  82. }
  83. Process.Scheduler.Suspend(CurrThread.ProcessorId);
  84. int HandleIndex;
  85. ulong Result = 0;
  86. if (Timeout != -1)
  87. {
  88. HandleIndex = WaitHandle.WaitAny(Handles, (int)(Timeout / 1000000));
  89. if (HandleIndex == WaitHandle.WaitTimeout)
  90. {
  91. Result = MakeError(ErrorModule.Kernel, KernelErr.Timeout);
  92. }
  93. }
  94. else
  95. {
  96. HandleIndex = WaitHandle.WaitAny(Handles);
  97. }
  98. Process.Scheduler.Resume(CurrThread);
  99. ThreadState.X0 = Result;
  100. if (Result == 0)
  101. {
  102. ThreadState.X1 = (ulong)HandleIndex;
  103. }
  104. }
  105. private void SvcGetSystemTick(AThreadState ThreadState)
  106. {
  107. ThreadState.X0 = ThreadState.CntpctEl0;
  108. }
  109. private void SvcConnectToNamedPort(AThreadState ThreadState)
  110. {
  111. long StackPtr = (long)ThreadState.X0;
  112. long NamePtr = (long)ThreadState.X1;
  113. string Name = AMemoryHelper.ReadAsciiString(Memory, NamePtr, 8);
  114. //TODO: Validate that app has perms to access the service, and that the service
  115. //actually exists, return error codes otherwise.
  116. KSession Session = new KSession(ServiceFactory.MakeService(Name), Name);
  117. ulong Handle = (ulong)Process.HandleTable.OpenHandle(Session);
  118. ThreadState.X0 = 0;
  119. ThreadState.X1 = Handle;
  120. }
  121. private void SvcSendSyncRequest(AThreadState ThreadState)
  122. {
  123. SendSyncRequest(ThreadState, ThreadState.Tpidr, 0x100, (int)ThreadState.X0);
  124. }
  125. private void SvcSendSyncRequestWithUserBuffer(AThreadState ThreadState)
  126. {
  127. SendSyncRequest(
  128. ThreadState,
  129. (long)ThreadState.X0,
  130. (long)ThreadState.X1,
  131. (int)ThreadState.X2);
  132. }
  133. private void SendSyncRequest(AThreadState ThreadState, long CmdPtr, long Size, int Handle)
  134. {
  135. KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
  136. byte[] CmdData = AMemoryHelper.ReadBytes(Memory, CmdPtr, Size);
  137. KSession Session = Process.HandleTable.GetData<KSession>(Handle);
  138. if (Session != null)
  139. {
  140. Process.Scheduler.Suspend(CurrThread.ProcessorId);
  141. IpcMessage Cmd = new IpcMessage(CmdData, CmdPtr);
  142. IpcHandler.IpcCall(Ns, Process, Memory, Session, Cmd, CmdPtr);
  143. Thread.Yield();
  144. Process.Scheduler.Resume(CurrThread);
  145. ThreadState.X0 = 0;
  146. }
  147. else
  148. {
  149. Logging.Warn(LogClass.KernelSvc, $"Tried to SendSyncRequest on invalid session handle 0x{Handle:x8}!");
  150. ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
  151. }
  152. }
  153. private void SvcBreak(AThreadState ThreadState)
  154. {
  155. long Reason = (long)ThreadState.X0;
  156. long Unknown = (long)ThreadState.X1;
  157. long Info = (long)ThreadState.X2;
  158. throw new GuestBrokeExecutionException();
  159. }
  160. private void SvcOutputDebugString(AThreadState ThreadState)
  161. {
  162. long Position = (long)ThreadState.X0;
  163. long Size = (long)ThreadState.X1;
  164. string Str = AMemoryHelper.ReadAsciiString(Memory, Position, Size);
  165. Logging.Info(LogClass.KernelSvc, Str);
  166. ThreadState.X0 = 0;
  167. }
  168. private void SvcGetInfo(AThreadState ThreadState)
  169. {
  170. long StackPtr = (long)ThreadState.X0;
  171. int InfoType = (int)ThreadState.X1;
  172. long Handle = (long)ThreadState.X2;
  173. int InfoId = (int)ThreadState.X3;
  174. //Fail for info not available on older Kernel versions.
  175. if (InfoType == 18 ||
  176. InfoType == 19 ||
  177. InfoType == 20)
  178. {
  179. ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidInfo);
  180. return;
  181. }
  182. switch (InfoType)
  183. {
  184. case 0:
  185. ThreadState.X1 = AllowedCpuIdBitmask;
  186. break;
  187. case 2:
  188. ThreadState.X1 = MemoryRegions.MapRegionAddress;
  189. break;
  190. case 3:
  191. ThreadState.X1 = MemoryRegions.MapRegionSize;
  192. break;
  193. case 4:
  194. ThreadState.X1 = MemoryRegions.HeapRegionAddress;
  195. break;
  196. case 5:
  197. ThreadState.X1 = MemoryRegions.HeapRegionSize;
  198. break;
  199. case 6:
  200. ThreadState.X1 = MemoryRegions.TotalMemoryAvailable;
  201. break;
  202. case 7:
  203. ThreadState.X1 = MemoryRegions.TotalMemoryUsed + CurrentHeapSize;
  204. break;
  205. case 8:
  206. ThreadState.X1 = EnableProcessDebugging ? 1 : 0;
  207. break;
  208. case 11:
  209. ThreadState.X1 = (ulong)Rng.Next() + ((ulong)Rng.Next() << 32);
  210. break;
  211. case 12:
  212. ThreadState.X1 = MemoryRegions.AddrSpaceStart;
  213. break;
  214. case 13:
  215. ThreadState.X1 = MemoryRegions.AddrSpaceSize;
  216. break;
  217. case 14:
  218. ThreadState.X1 = MemoryRegions.MapRegionAddress;
  219. break;
  220. case 15:
  221. ThreadState.X1 = MemoryRegions.MapRegionSize;
  222. break;
  223. default: throw new NotImplementedException($"SvcGetInfo: {InfoType} {Handle} {InfoId}");
  224. }
  225. ThreadState.X0 = 0;
  226. }
  227. }
  228. }