1 using System;
2 using cmsx.machine;
3
4 namespace cmsx.kernel
5 {
6 public const byte sys_exit = 0u;
7 public const byte sys_wait = 1u;
8 public const byte sys_fork = 2u;
9 public const byte sys_exec = 3u;
10 public const byte sys_kill = 4u;
11 public const byte sys_create = 5u;
12 public const byte sys_open = 6u;
13 public const byte sys_close = 7u;
14 public const byte sys_read = 8u;
15 public const byte sys_write = 9u;
16 public const byte sys_seek = 10u;
17 public const byte sys_tell = 11u;
18 public const byte sys_pool_end = 12u;
19 public const byte sys_set_pool_end = 13u;
20 public const byte sys_debug_break = 14u;
21 public const byte sys_stack_trace = 15u;
22 public const byte sys_throw = 16u;
23 public const byte sys_catch = 17u;
24 public const byte sys_resume = 18u;
25 public const byte sys_get_system_error = 19u;
26 public const byte sys_get_current_time_point = 20u;
27 public const byte sys_sleep = 21u;
28 public const byte sys_get_current_date = 22u;
29 public const byte sys_get_current_date_time = 23u;
30 public const byte sys_pow = 24u;
31 public const byte sys_get_random_seed = 25u;
32 public const byte sys_link = 26u;
33 public const byte sys_unlink = 27u;
34 public const byte sys_rename = 28u;
35 public const byte sys_mkdir = 29u;
36 public const byte sys_opendir = 30u;
37 public const byte sys_readdir = 31u;
38 public const byte sys_closedir = 32u;
39 public const byte sys_getcwd = 33u;
40 public const byte sys_chdir = 34u;
41 public const byte sys_stat = 35u;
42 public const byte sys_umask = 36u;
43 public const byte sys_ioctl = 37u;
44 public const byte sys_chmod = 38u;
45 public const byte sys_chown = 39u;
46 public const byte sys_utime = 40u;
47 public const byte sys_getuid = 41u;
48 public const byte sys_setuid = 42u;
49 public const byte sys_getgid = 43u;
50 public const byte sys_setgid = 44u;
51 public const byte sys_getpid = 45u;
52 public const byte sys_getpgid = 46u;
53 public const byte sys_setpgid = 47u;
54 public const byte sys_getfgpid = 48u;
55 public const byte sys_setfgpid = 49u;
56 public const byte sys_sync = 50u;
57 public const byte sys_times = 51u;
58 public const byte sys_get_host_name = 52u;
59 public const byte sys_dup = 53u;
60 public const byte sys_pipe = 54u;
61 public const byte sys_log = 55u;
62 public const byte sys_log_message = 56u;
63
64 public const byte numSystemCalls = sys_log_message + 1u;
65
66 public nothrow string SystemCallName(byte systemCall)
67 {
68 switch (systemCall)
69 {
70 case sys_exit: return "sys_exit";
71 case sys_wait: return "sys_wait";
72 case sys_fork: return "sys_fork";
73 case sys_exec: return "sys_exec";
74 case sys_kill: return "sys_kill";
75 case sys_create: return "sys_create";
76 case sys_open: return "sys_open";
77 case sys_close: return "sys_close";
78 case sys_read: return "sys_read";
79 case sys_write: return "sys_write";
80 case sys_seek: return "sys_seek";
81 case sys_tell: return "sys_tell";
82 case sys_pool_end: return "sys_pool_end";
83 case sys_set_pool_end: return "sys_set_pool_end";
84 case sys_debug_break: return "sys_debug_break";
85 case sys_stack_trace: return "sys_stack_trace";
86 case sys_throw: return "sys_throw";
87 case sys_catch: return "sys_catch";
88 case sys_resume: return "sys_resume";
89 case sys_get_system_error: return "sys_get_system_error";
90 case sys_get_current_time_point: return "sys_get_current_time_point";
91 case sys_sleep: return "sys_sleep";
92 case sys_get_current_date: return "sys_get_current_date";
93 case sys_get_current_date_time: return "sys_get_current_date_time";
94 case sys_pow: return "sys_pow";
95 case sys_get_random_seed: return "sys_get_random_seed";
96 case sys_link: return "sys_link";
97 case sys_unlink: return "sys_unlink";
98 case sys_rename: return "sys_rename";
99 case sys_mkdir: return "sys_mkdir";
100 case sys_opendir: return "sys_opendir";
101 case sys_readdir: return "sys_readdir";
102 case sys_closedir: return "sys_closedir";
103 case sys_getcwd: return "sys_getcwd";
104 case sys_chdir: return "sys_chdir";
105 case sys_stat: return "sys_stat";
106 case sys_umask: return "sys_umask";
107 case sys_ioctl: return "sys_ioctl";
108 case sys_chmod: return "sys_chmod";
109 case sys_chown: return "sys_chown";
110 case sys_utime: return "sys_utime";
111 case sys_getuid: return "sys_getuid";
112 case sys_setuid: return "sys_setuid";
113 case sys_getgid: return "sys_getgid";
114 case sys_setgid: return "sys_setgid";
115 case sys_getpid: return "sys_getpid";
116 case sys_getpgid: return "sys_getpgid";
117 case sys_setpgid: return "sys_setpgid";
118 case sys_getfgpid: return "sys_getfgpid";
119 case sys_setfgpid: return "sys_setfgpid";
120 case sys_sync: return "sys_sync";
121 case sys_times: return "sys_times";
122 case sys_get_host_name: return "sys_get_host_name";
123 case sys_dup: return "sys_dup";
124 case sys_pipe: return "sys_pipe";
125 case sys_log: return "sys_log";
126 case sys_log_message: return "sys_log_message";
127 }
128 return string();
129 }
130
131 public const uint debugBreakInst = (TRAP << 24u) | (0u << 16u) | (sys_debug_break << 8u) | (0u << 0u);
132
133 public inline nothrow ulong MakeSystemCallPtrAddress(int systemCall)
134 {
135 return trapTableBaseAddress + cast<ulong>(systemCall) * 8u;
136 }
137
138 public class SystemCall
139 {
140 public nothrow SystemCall(Machine* machine_, Kernel* kernel_, ProcessTable* processTable_, Process* process_,
141 SystemCallHandler handler_, byte x_, byte y_, byte z_, ulong ax_, ulong bx_, ulong cx_, ulong dx_, ulong ex_) :
142 machine(machine_), kernel(kernel_), processTable(processTable_), process(process_),
143 handler(handler_), x(x_), y(y_), z(z_), ax(ax_), bx(bx_), cx(cx_), dx(dx_), ex(ex_), result(0)
144 {
145 }
146 public nothrow string ToString() const
147 {
148 string s;
149 s.Append(SystemCallName(y)).Append(".ax=").Append(ToHexString(ax)).Append(".bx=").Append(ToHexString(bx)).Append(".cx=").Append(ToHexString(cx)).Append(".dx=");
150 s.Append(ToHexString(dx)).Append(".ex=").Append(ToHexString(ex)).Append(".result=").Append(ToHexString(result));
151 return s;
152 }
153 public nothrow bool IsDebugBreak() const
154 {
155 return x == 0u && y == sys_debug_break && z == 0u;
156 }
157 public Machine* machine;
158 public Kernel* kernel;
159 public ProcessTable* processTable;
160 public Process* process;
161 public SystemCallHandler handler;
162 public byte x;
163 public byte y;
164 public byte z;
165 public ulong ax;
166 public ulong bx;
167 public ulong cx;
168 public ulong dx;
169 public ulong ex;
170 public long result;
171 }
172
173 public delegate void SystemCallHandler(SystemCall& sc);
174
175 public void SystemCallFiber(void* processParam)
176 {
177 Process* process = cast<Process*>(processParam);
178 while (true)
179 {
180 try
181 {
182 process->systemCallReady = false;
183 const SystemCall& sc = process->systemCall;
184 if (Log())
185 {
186 LogMessage("sc.begin", sc.ToString());
187 }
188 SystemCallHandler handler = sc.handler;
189 process->kernelStart = Now();
190 handler(sc);
191 }
192 catch (const SystemError& systemError)
193 {
194 process->lastError = systemError;
195 process->systemCall.result = -1;
196 string s = SystemCallName(process->systemCall.y);
197 s.Append(" failed\n");
198 Kernel& kernel = GetKernel();
199 Debugger* debugger = kernel.GetDebugger();
200 debugger->WriteOutput(cast<byte*>(cast<void*>(s.Chars())), s.Length());
201 }
202 catch (const Exception& ex)
203 {
204 process->lastError = SystemError(EFAIL, "system call failed: " + ex.ToString());
205 process->systemCall.result = -1;
206 }
207 if (Log())
208 {
209 string msg = process->systemCall.ToString();
210 if (process->systemCall.result == -1)
211 {
212 msg.Append(".error=").Append(process->lastError.ToString());
213 }
214 LogMessage("sc.end", msg);
215 }
216 process->systemCallReady = true;
217 process->mode = Process.Mode.runningUser;
218 process->kernelTime = process->kernelTime + Now() - process->kernelStart;
219 OsSwitchToFiber(mainFiber);
220 }
221 }
222
223 public void Exit(SystemCall& sc)
224 {
225 if (sc.x != 0u || sc.y != sys_exit || sc.z != 0u)
226 {
227 Panic("invalid exit parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
228 }
229 ushort exitCode = MakeProcessExitCode(0u, cast<byte>(sc.ax));
230 Debugger* debugger = sc.kernel->GetDebugger();
231 Processor& processor = sc.machine->GetProcessor();
232 Process* process = sc.process;
233 ExitProcess(*sc.machine, *sc.processTable, process, exitCode);
234 if (process->pid == sc.kernel->GetProgramPID())
235 {
236 processor.Exit();
237 }
238 debugger->Exit(process);
239 }
240
241 public void Wait(SystemCall& sc)
242 {
243 if (sc.x != 0u || sc.y != sys_wait || sc.z != 0u)
244 {
245 Panic("invalid wait parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
246 }
247 int retval = WaitProcess(*sc.machine, *sc.processTable, sc.process, sc.ax);
248 sc.result = retval;
249 }
250
251 public void Fork(SystemCall& sc)
252 {
253 if (sc.x != 0u || sc.y != sys_fork || sc.z != 0u)
254 {
255 Panic("invalid fork parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
256 }
257 int retval = ForkProcess(*sc.machine, *sc.processTable, sc.process);
258 sc.result = retval;
259 }
260
261 public void Exec(SystemCall& sc)
262 {
263 if (sc.x != 0u || sc.y != sys_exec || sc.z != 0u)
264 {
265 Panic("invalid exec parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
266 }
267 Exec(*sc.machine, *sc.processTable, sc.process, cast<int>(sc.ax), cast<int>(sc.bx), sc.cx, cast<long>(sc.dx));
268 sc.result = cast<int>(sc.ax);
269 }
270
271 public void Kill(SystemCall& sc)
272 {
273 if (sc.x != 0u || sc.y != sys_kill || sc.z != 0u)
274 {
275 Panic("invalid kill parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
276 }
277 SendSignalProcess(*sc.machine, *sc.processTable, sc.process, cast<int>(sc.ax), cast<int>(sc.bx));
278 sc.result = 0;
279 }
280
281 public void Create(SystemCall& sc)
282 {
283 if (sc.x != 0u || sc.y != sys_create || sc.z != 0u)
284 {
285 Panic("invalid create parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
286 }
287 sc.result = Create(*sc.machine, sc.process, cast<ulong>(sc.ax), cast<int>(sc.bx));
288 }
289
290 public void Open(SystemCall& sc)
291 {
292 if (sc.x != 0u || sc.y != sys_open || sc.z != 0u)
293 {
294 Panic("invalid open parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
295 }
296 sc.result = Open(*sc.machine, sc.process, cast<ulong>(sc.ax), cast<OpenFlags>(cast<int>(sc.bx)), cast<int>(sc.cx));
297 }
298
299 public void Close(SystemCall& sc)
300 {
301 if (sc.x != 0u || sc.y != sys_close || sc.z != 0u)
302 {
303 Panic("invalid close parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
304 }
305 Close(*sc.machine, sc.process, cast<int>(sc.ax));
306 sc.result = 0;
307 }
308
309 public void Read(SystemCall& sc)
310 {
311 if (sc.x != 0u || sc.y != sys_read || sc.z != 0u)
312 {
313 Panic("invalid read parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
314 }
315 long retval = Read(*sc.machine, sc.process, cast<int>(sc.ax), sc.bx, cast<long>(sc.cx));
316 sc.result = retval;
317 }
318
319 public void Write(SystemCall& sc)
320 {
321 if (sc.x != 0u || sc.y != sys_write || sc.z != 0u)
322 {
323 Panic("invalid write parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
324 }
325 long retval = Write(*sc.machine, sc.process, cast<int>(sc.ax), sc.bx, cast<long>(sc.cx));
326 sc.result = retval;
327 }
328
329 public void Seek(SystemCall& sc)
330 {
331 if (sc.x != 0u || sc.y != sys_seek || sc.z != 0u)
332 {
333 Panic("invalid seek parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
334 }
335 int fd = cast<int>(sc.ax);
336 long pos = cast<long>(sc.bx);
337 Origin origin = cast<Origin>(cast<byte>(sc.cx));
338 long retval = Seek(*sc.machine, sc.process, fd, pos, origin);
339 sc.result = retval;
340 }
341
342 public void Tell(SystemCall& sc)
343 {
344 if (sc.x != 0u || sc.y != sys_seek || sc.z != 0u)
345 {
346 Panic("invalid tell parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
347 }
348 int fd = cast<int>(sc.ax);
349 long retval = Tell(*sc.machine, sc.process, fd);
350 sc.result = retval;
351 }
352
353 public void PoolEnd(SystemCall& sc)
354 {
355 if (sc.x != 0u || sc.y != sys_pool_end || sc.z != 0u)
356 {
357 Panic("invalid pool_end parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
358 }
359 long retval = cast<long>(sc.process->poolEnd);
360 sc.result = retval;
361 }
362
363 public void SetPoolEnd(SystemCall& sc)
364 {
365 if (sc.x != 0u || sc.y != sys_set_pool_end || sc.z != 0u)
366 {
367 Panic("invalid set_pool_end parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
368 }
369 sc.result = SetPoolEndProcess(*sc.machine, sc.process, sc.ax);
370 }
371
372 public void DebugBreak(SystemCall& sc)
373 {
374 if (sc.x != 0u || sc.y != sys_debug_break || sc.z != 0u)
375 {
376 Panic("invalid debug break parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
377 }
378 Debugger* debugger = sc.kernel->GetDebugger();
379 debugger->Run(sc.process);
380 }
381
382 public void StackTrace(SystemCall& sc)
383 {
384 if (sc.x != 0u || sc.y != sys_stack_trace || sc.z != 0u)
385 {
386 Panic("invalid stack trace parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
387 }
388 ulong fp = sc.machine->GetRegisters().Get(regFP);
389 ulong buffer = sc.ax;
390 long count = cast<long>(sc.bx);
391 GetProcessStackTrace(*sc.machine, sc.process, fp, buffer, count);
392 sc.result = 0;
393 }
394
395 public void Throw(SystemCall& sc)
396 {
397 if (sc.x != 0u || sc.y != sys_throw || sc.z != 0u)
398 {
399 Panic("invalid throw parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
400 }
401 ulong exceptionAddress = sc.ax;
402 ulong exceptionClassId = sc.bx;
403 ulong fp = sc.machine->GetRegisters().Get(regFP);
404 sc.process->currentExceptionAddress = exceptionAddress;
405 sc.process->currentExceptionClassId = exceptionClassId;
406 DispatchException(*sc.machine, sc.process, fp);
407 sc.result = 0;
408 }
409
410 public void Catch(SystemCall& sc)
411 {
412 if (sc.x != 0u || sc.y != sys_catch || sc.z != 0u)
413 {
414 Panic("invalid catch parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
415 }
416 ulong exceptionAddress = sc.process->currentExceptionAddress;
417 sc.result = cast<long>(exceptionAddress);
418 }
419
420 public void Resume(SystemCall& sc)
421 {
422 if (sc.x != 0u || sc.y != sys_resume || sc.z != 0u)
423 {
424 Panic("invalid resume parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
425 }
426 ulong fp = sc.machine->GetRegisters().Get(regFP);
427 ContinueExceptionDispatch(*sc.machine, sc.process, fp);
428 sc.result = 0;
429 }
430
431 public void GetSystemError(SystemCall& sc)
432 {
433 if (sc.x != 0u || sc.y != sys_get_system_error || sc.z != 0u)
434 {
435 Panic("invalid get_system_error parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
436 }
437 ulong errorCodeAddress = sc.ax;
438 ulong bufferAddress = sc.bx;
439 long count = cast<long>(sc.cx);
440 GetProcessSystemError(*sc.machine, sc.process, errorCodeAddress, bufferAddress, count);
441 sc.result = 0;
442 }
443
444 public void GetCurrentTimePoint(SystemCall& sc)
445 {
446 if (sc.x != 0u || sc.y != sys_get_current_time_point || sc.z != 0u)
447 {
448 Panic("invalid get_current_time_point parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
449 }
450 long currentTimePoint = System.Now().Rep();
451 sc.result = currentTimePoint;
452 }
453
454 public void Sleep(SystemCall& sc)
455 {
456 if (sc.x != 0u || sc.y != sys_sleep || sc.z != 0u)
457 {
458 Panic("invalid sleep parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
459 }
460 Duration sleepDuration(cast<long>(sc.ax));
461 if (sleepDuration.Rep() < 0)
462 {
463 throw SystemError(EINVAL, "invalid sleep duration");
464 }
465 TimePoint dueTime = System.Now() + sleepDuration;
466 SleepProcess(sc.process, wakeupEvent, cast<ulong>(dueTime.Rep()), 0u);
467 SleepingProcessQueue.Instance().AddProcess(sc.process);
468 sc.result = 0;
469 }
470
471 public void GetCurrentDate(SystemCall& sc)
472 {
473 if (sc.x != 0u || sc.y != sys_get_current_date || sc.z != 0u)
474 {
475 Panic("invalid get_current_date parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
476 }
477 ulong yearAddress = sc.ax;
478 ulong monthAddress = sc.bx;
479 ulong dayAddress = sc.cx;
480 if (yearAddress == 0u)
481 {
482 throw SystemError(EINVAL, "year pointer is null");
483 }
484 else if (monthAddress == 0u)
485 {
486 throw SystemError(EINVAL, "month pointer is null");
487 }
488 else if (dayAddress == 0u)
489 {
490 throw SystemError(EINVAL, "day pointer is null");
491 }
492 Date date = System.GetCurrentDate();
493 short year = date.Year();
494 sbyte month = date.GetMonth();
495 sbyte day = date.Day();
496 WriteProcessMemory(*sc.machine, sc.process, yearAddress, cast<ulong>(year), 2u, Protection.write);
497 WriteProcessMemory(*sc.machine, sc.process, monthAddress, cast<ulong>(month), 1u, Protection.write);
498 WriteProcessMemory(*sc.machine, sc.process, dayAddress, cast<ulong>(day), 1u, Protection.write);
499 }
500
501 public void GetCurrentDateTime(SystemCall& sc)
502 {
503 if (sc.x != 0u || sc.y != sys_get_current_date_time || sc.z != 0u)
504 {
505 Panic("invalid get_current_date_time parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
506 }
507 ulong yearAddress = sc.ax;
508 ulong monthAddress = sc.bx;
509 ulong dayAddress = sc.cx;
510 ulong secsAddress = sc.dx;
511 if (yearAddress == 0u)
512 {
513 throw SystemError(EINVAL, "year pointer is null");
514 }
515 else if (monthAddress == 0u)
516 {
517 throw SystemError(EINVAL, "month pointer is null");
518 }
519 else if (dayAddress == 0u)
520 {
521 throw SystemError(EINVAL, "day pointer is null");
522 }
523 else if (secsAddress == 0u)
524 {
525 throw SystemError(EINVAL, "secs pointer is null");
526 }
527 DateTime dateTime = GetCurrentDateTime();
528 Date date = dateTime.GetDate();
529 short year = date.Year();
530 sbyte month = date.GetMonth();
531 sbyte day = date.Day();
532 int secs = dateTime.Seconds();
533 WriteProcessMemory(*sc.machine, sc.process, yearAddress, cast<ulong>(year), 2u, Protection.write);
534 WriteProcessMemory(*sc.machine, sc.process, monthAddress, cast<ulong>(month), 1u, Protection.write);
535 WriteProcessMemory(*sc.machine, sc.process, dayAddress, cast<ulong>(day), 1u, Protection.write);
536 WriteProcessMemory(*sc.machine, sc.process, secsAddress, cast<ulong>(secs), 4u, Protection.write);
537 }
538
539 public void Pow(SystemCall& sc)
540 {
541 if (sc.x != 0u || sc.y != sys_pow || sc.z != 0u)
542 {
543 Panic("invalid pow parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
544 }
545 double x = *cast<double*>(cast<void*>(&sc.ax));
546 double y = *cast<double*>(cast<void*>(&sc.bx));
547 double r = Pow(x, y);
548 sc.result = *cast<long*>(cast<void*>(&r));
549 }
550
551 public void GetRandomSeed(SystemCall& sc)
552 {
553 if (sc.x != 0u || sc.y != sys_get_random_seed || sc.z != 0u)
554 {
555 Panic("invalid get_random_seed parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
556 }
557 sc.result = RtGetRandomSeed();
558 }
559
560 public void Link(SystemCall& sc)
561 {
562 if (sc.x != 0u || sc.y != sys_link || sc.z != 0u)
563 {
564 Panic("invalid link parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
565 }
566 Link(*sc.machine, sc.process, sc.ax, sc.bx);
567 }
568
569 public void Unlink(SystemCall& sc)
570 {
571 if (sc.x != 0u || sc.y != sys_unlink || sc.z != 0u)
572 {
573 Panic("invalid unlink parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
574 }
575 Unlink(*sc.machine, sc.process, sc.ax);
576 sc.result = 0;
577 }
578
579 public void Rename(SystemCall& sc)
580 {
581 if (sc.x != 0u || sc.y != sys_rename || sc.z != 0u)
582 {
583 Panic("invalid rename parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
584 }
585 Rename(*sc.machine, sc.process, sc.ax, sc.bx);
586 sc.result = 0;
587 }
588
589 public void Mkdir(SystemCall& sc)
590 {
591 if (sc.x != 0u || sc.y != sys_mkdir || sc.z != 0u)
592 {
593 Panic("invalid mkdir parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
594 }
595 Mkdir(*sc.machine, sc.process, sc.ax, cast<int>(sc.bx));
596 }
597
598 public void OpenDir(SystemCall& sc)
599 {
600 if (sc.x != 0u || sc.y != sys_opendir || sc.z != 0u)
601 {
602 Panic("invalid opendir parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
603 }
604 sc.result = OpenDir(*sc.machine, sc.process, sc.ax);
605 }
606
607 public void ReadDir(SystemCall& sc)
608 {
609 if (sc.x != 0u || sc.y != sys_readdir || sc.z != 0u)
610 {
611 Panic("invalid readdir parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
612 }
613 sc.result = ReadDir(*sc.machine, sc.process, cast<int>(sc.ax), sc.bx, sc.cx);
614 }
615
616 public void CloseDir(SystemCall& sc)
617 {
618 if (sc.x != 0u || sc.y != sys_closedir || sc.z != 0u)
619 {
620 Panic("invalid closedir parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
621 }
622 CloseDir(*sc.machine, sc.process, cast<int>(sc.ax));
623 sc.result = 0;
624 }
625
626 public void GetCWD(SystemCall& sc)
627 {
628 if (sc.x != 0u || sc.y != sys_getcwd || sc.z != 0u)
629 {
630 Panic("invalid getcwd parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
631 }
632 GetCWD(*sc.machine, sc.process, sc.ax, cast<long>(sc.bx));
633 sc.result = 0;
634 }
635
636 public void ChDir(SystemCall& sc)
637 {
638 if (sc.x != 0u || sc.y != sys_chdir || sc.z != 0u)
639 {
640 Panic("invalid chdir parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
641 }
642 ChDir(*sc.machine, sc.process, sc.ax);
643 sc.result = 0;
644 }
645
646 public void Stat(SystemCall& sc)
647 {
648 if (sc.x != 0u || sc.y != sys_stat || sc.z != 0u)
649 {
650 Panic("invalid stat parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
651 }
652 Stat(*sc.machine, sc.process, sc.ax, sc.bx);
653 sc.result = 0;
654 }
655
656 public void UMask(SystemCall& sc)
657 {
658 if (sc.x != 0u || sc.y != sys_umask || sc.z != 0u)
659 {
660 Panic("invalid umask parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
661 }
662 sc.result = UMask(*sc.machine, sc.process, cast<int>(sc.ax));
663 }
664
665 public void IOCtl(SystemCall& sc)
666 {
667 if (sc.x != 0u || sc.y != sys_ioctl || sc.z != 0u)
668 {
669 Panic("invalid ioctl parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
670 }
671 IOCtl(*sc.machine, sc.process, cast<int>(sc.ax), cast<int>(sc.bx), sc.cx, cast<long>(sc.dx));
672 sc.result = 0;
673 }
674
675 public void Chmod(SystemCall& sc)
676 {
677 if (sc.x != 0u || sc.y != sys_chmod || sc.z != 0u)
678 {
679 Panic("invalid chmod parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
680 }
681 Chmod(*sc.machine, sc.process, sc.ax, cast<int>(sc.bx));
682 sc.result = 0;
683 }
684
685 public void Chown(SystemCall& sc)
686 {
687 if (sc.x != 0u || sc.y != sys_chown || sc.z != 0u)
688 {
689 Panic("invalid chmod parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
690 }
691 Chown(*sc.machine, sc.process, sc.ax, cast<int>(sc.bx), cast<int>(sc.cx));
692 sc.result = 0;
693 }
694
695 public void UTime(SystemCall& sc)
696 {
697 if (sc.x != 0u || sc.y != sys_utime || sc.z != 0u)
698 {
699 Panic("invalid utime parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
700 }
701 UTime(*sc.machine, sc.process, sc.ax, sc.bx);
702 }
703
704 public void GetUID(SystemCall& sc)
705 {
706 if (sc.x != 0u || sc.y != sys_getuid || sc.z != 0u)
707 {
708 Panic("invalid getuid parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
709 }
710 sc.result = sc.process->uid;
711 }
712
713 public void SetUID(SystemCall& sc)
714 {
715 if (sc.x != 0u || sc.y != sys_setuid || sc.z != 0u)
716 {
717 Panic("invalid setuid parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
718 }
719 SetUIDProcess(sc.process, cast<int>(sc.ax));
720 sc.result = 0;
721 }
722
723 public void GetGID(SystemCall& sc)
724 {
725 if (sc.x != 0u || sc.y != sys_getgid || sc.z != 0u)
726 {
727 Panic("invalid getgid parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
728 }
729 sc.result = sc.process->gid;
730 }
731
732 public void SetGID(SystemCall& sc)
733 {
734 if (sc.x != 0u || sc.y != sys_setgid || sc.z != 0u)
735 {
736 Panic("invalid setgid parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
737 }
738 SetGIDProcess(sc.process, cast<int>(sc.ax));
739 sc.result = 0;
740 }
741
742 public void GetPID(SystemCall& sc)
743 {
744 if (sc.x != 0u || sc.y != sys_getpid || sc.z != 0u)
745 {
746 Panic("invalid getpid parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
747 }
748 sc.result = sc.process->pid;
749 }
750
751 public void GetPGID(SystemCall& sc)
752 {
753 if (sc.x != 0u || sc.y != sys_getpgid || sc.z != 0u)
754 {
755 Panic("invalid getpgid parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
756 }
757 sc.result = sc.process->pgid;
758 }
759
760 public void SetPGID(SystemCall& sc)
761 {
762 if (sc.x != 0u || sc.y != sys_setpgid || sc.z != 0u)
763 {
764 Panic("invalid setpgid parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
765 }
766 Process* process = sc.process;
767 process->pgid = cast<int>(sc.ax);
768 sc.result = 0;
769 }
770
771 public void GetFGPID(SystemCall& sc)
772 {
773 if (sc.x != 0u || sc.y != sys_getfgpid || sc.z != 0u)
774 {
775 Panic("invalid getfgpid parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
776 }
777 int fd = cast<int>(sc.ax);
778 sc.result = GetFGPID(sc.process, fd);
779 }
780
781 public void SetFGPID(SystemCall& sc)
782 {
783 if (sc.x != 0u || sc.y != sys_setfgpid || sc.z != 0u)
784 {
785 Panic("invalid setfgpid parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
786 }
787 int fd = cast<int>(sc.ax);
788 int pid = cast<int>(sc.bx);
789 SetFGPID(sc.process, fd, pid);
790 sc.result = 0;
791 }
792
793 public void Sync(SystemCall& sc)
794 {
795 if (sc.x != 0u || sc.y != sys_sync || sc.z != 0u)
796 {
797 Panic("invalid sync parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
798 }
799 GetMountTable().Flush();
800 sc.result = 0;
801 }
802
803 public void Times(SystemCall& sc)
804 {
805 if (sc.x != 0u || sc.y != sys_times || sc.z != 0u)
806 {
807 Panic("invalid times parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
808 }
809 Times(*sc.machine, sc.process, sc.ax, sc.bx, sc.cx, sc.dx);
810 sc.result = 0;
811 }
812
813 public void GetHostName(SystemCall& sc)
814 {
815 if (sc.x != 0u || sc.y != sys_get_host_name || sc.z != 0u)
816 {
817 Panic("invalid get_host_name parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
818 }
819 ulong bufferAddress = sc.ax;
820 int size = cast<int>(sc.bx);
821 const string& host = sc.kernel->Host();
822 if (size <= host.Length())
823 {
824 throw SystemError(ERANGE, "get_host_name: buffer too small");
825 }
826 WriteProcessMemory(*sc.machine, sc.process, bufferAddress, cast<byte*>(cast<void*>(host.Chars())), cast<ulong>(host.Length() + 1), Protection.write);
827 sc.result = 0;
828 }
829
830 public void Dup(SystemCall& sc)
831 {
832 if (sc.x != 0u || sc.y != sys_dup || sc.z != 0u)
833 {
834 Panic("invalid dup parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
835 }
836 sc.result = Dup(sc.process, cast<int>(sc.ax));
837 }
838
839 public void Pipe(SystemCall& sc)
840 {
841 if (sc.x != 0u || sc.y != sys_pipe || sc.z != 0u)
842 {
843 Panic("invalid pipe parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
844 }
845 Pipe(*sc.machine, sc.process, sc.ax, sc.bx);
846 sc.result = 0;
847 }
848
849 public void Log(SystemCall& sc)
850 {
851 if (sc.x != 0u || sc.y != sys_log || sc.z != 0u)
852 {
853 Panic("invalid log parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
854 }
855 if (cmsx.kernel.Log())
856 {
857 sc.result = 1;
858 }
859 else
860 {
861 sc.result = 0;
862 }
863 }
864
865 public void LogMessage(SystemCall& sc)
866 {
867 if (sc.x != 0u || sc.y != sys_log_message || sc.z != 0u)
868 {
869 Panic("invalid log_message parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
870 }
871 ulong methodAddress = sc.ax;
872 if (methodAddress == 0u)
873 {
874 throw SystemError(EINVAL, "method address is null");
875 }
876 ulong msgAddress = sc.bx;
877 if (msgAddress == 0u)
878 {
879 throw SystemError(EINVAL, "msg address is null");
880 }
881 string method;
882 ReadStringFromProcessMemory(*sc.machine, sc.process, methodAddress, method);
883 string msg;
884 ReadStringFromProcessMemory(*sc.machine, sc.process, msgAddress, msg);
885 LogMessage(method, msg);
886 }
887 }