1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <mach.h>
5 #define EXTERN
6 #include "arm.h"
7
8 #define ODIRLEN 116 /* compatibility; used in _stat etc. */
9 #define OERRLEN 64 /* compatibility; used in _stat etc. */
10
11 char errbuf[ERRMAX];
12 ulong nofunc;
13
14 #include "/sys/src/libc/9syscall/sys.h"
15
16
17 char* sysctab[] =
18 {
19 [SYSR1] "Running",
20 [_ERRSTR] "_errstr",
21 [BIND] "Bind",
22 [CHDIR] "Chdir",
23 [CLOSE] "Close",
24 [DUP] "Dup",
25 [ALARM] "Alarm",
26 [EXEC] "Exec",
27 [EXITS] "Exits",
28 [_FSESSION] "_Fsession",
29 [FAUTH] "Fauth",
30 [_FSTAT] "_fstat",
31 [SEGBRK] "Segbrk",
32 [MOUNT] "Mount",
33 [OPEN] "Open",
34 [_READ] "_Read",
35 [OSEEK] "Oseek",
36 [SLEEP] "Sleep",
37 [_STAT] "_Stat",
38 [RFORK] "Rfork",
39 [_WRITE] "_Write",
40 [PIPE] "Pipe",
41 [CREATE] "Create",
42 [FD2PATH] "Fd2path",
43 [BRK_] "Brk_",
44 [REMOVE] "Remove",
45 [_WSTAT] "_Wstat",
46 [_FWSTAT] "_Fwstat",
47 [NOTIFY] "Notify",
48 [NOTED] "Noted",
49 [SEGATTACH] "Segattach",
50 [SEGDETACH] "Segdetach",
51 [SEGFREE] "Segfree",
52 [SEGFLUSH] "Segflush",
53 [RENDEZVOUS] "Rendezvous",
54 [UNMOUNT] "Unmount",
55 [_WAIT] "_Wait",
56 [SEEK] "Seek",
57 [FVERSION] "Fversion",
58 [ERRSTR] "Errstr",
59 [STAT] "Stat",
60 [FSTAT] "Fstat",
61 [WSTAT] "Wstat",
62 [FWSTAT] "Fwstat",
63 [PREAD] "Pread",
64 [PWRITE] "Pwrite",
65 [AWAIT] "Await",
66 };
67
68 void
sys1(void)69 sys1(void)
70 {
71 Bprint(bioout, "no system call %s\n", sysctab[reg.r[1]]);
72 exits(0);
73 }
74
75 void
sys_errstr(void)76 sys_errstr(void)
77 {
78 ulong str;
79
80 str = getmem_w(reg.r[13]+4);
81 if(sysdbg)
82 itrace("errstr(0x%lux)", str);
83
84 memio(errbuf, str, OERRLEN, MemWrite);
85 strcpy(errbuf, "no error");
86 reg.r[REGRET] = 0;
87
88 }
89
90 void
syserrstr(void)91 syserrstr(void)
92 {
93 ulong str;
94 int n;
95
96 str = getmem_w(reg.r[13]+4);
97 n = getmem_w(reg.r[13]+8);
98 if(sysdbg)
99 itrace("errstr(0x%lux, 0x%lux)", str, n);
100
101 if(n > strlen(errbuf)+1)
102 n = strlen(errbuf)+1;
103 memio(errbuf, str, n, MemWrite);
104 strcpy(errbuf, "no error");
105 reg.r[REGRET] = n;
106
107 }
108 void
sysbind(void)109 sysbind(void)
110 {
111 ulong pname, pold, flags;
112 char name[1024], old[1024];
113 int n;
114
115 pname = getmem_w(reg.r[13]+4);
116 pold = getmem_w(reg.r[13]+8);
117 flags = getmem_w(reg.r[13]+12);
118 memio(name, pname, sizeof(name), MemReadstring);
119 memio(old, pold, sizeof(old), MemReadstring);
120 if(sysdbg)
121 itrace("bind(0x%lux='%s', 0x%lux='%s', 0x%lux)", name, name, old, old, flags);
122
123 n = bind(name, old, flags);
124 if(n < 0)
125 errstr(errbuf, sizeof errbuf);
126
127 reg.r[REGRET] = n;
128 }
129
130 void
sysfd2path(void)131 sysfd2path(void)
132 {
133 int n;
134 uint fd;
135 ulong str;
136 char buf[1024];
137
138 fd = getmem_w(reg.r[13]+4);
139 str = getmem_w(reg.r[13]+8);
140 n = getmem_w(reg.r[13]+12);
141 if(sysdbg)
142 itrace("fd2path(0x%lux, 0x%lux, 0x%lux)", fd, str, n);
143 reg.r[1] = -1;
144 if(n > sizeof buf){
145 strcpy(errbuf, "buffer too big");
146 return;
147 }
148 n = fd2path(fd, buf, sizeof buf);
149 if(n < 0)
150 errstr(buf, sizeof buf);
151 else
152 memio(errbuf, str, n, MemWrite);
153 reg.r[REGRET] = n;
154
155 }
156
157 void
syschdir(void)158 syschdir(void)
159 {
160 char file[1024];
161 int n;
162 ulong name;
163
164 name = getmem_w(reg.r[13]+4);
165 memio(file, name, sizeof(file), MemReadstring);
166 if(sysdbg)
167 itrace("chdir(0x%lux='%s', 0x%lux)", name, file);
168
169 n = chdir(file);
170 if(n < 0)
171 errstr(errbuf, sizeof errbuf);
172
173 reg.r[REGRET] = n;
174 }
175
176 void
sysclose(void)177 sysclose(void)
178 {
179 int n;
180 ulong fd;
181
182 fd = getmem_w(reg.r[13]+4);
183 if(sysdbg)
184 itrace("close(%d)", fd);
185
186 n = close(fd);
187 if(n < 0)
188 errstr(errbuf, sizeof errbuf);
189 reg.r[REGRET] = n;
190 }
191
192 void
sysdup(void)193 sysdup(void)
194 {
195 int oldfd, newfd;
196 int n;
197
198 oldfd = getmem_w(reg.r[13]+4);
199 newfd = getmem_w(reg.r[13]+8);
200 if(sysdbg)
201 itrace("dup(%d, %d)", oldfd, newfd);
202
203 n = dup(oldfd, newfd);
204 if(n < 0)
205 errstr(errbuf, sizeof errbuf);
206 reg.r[REGRET] = n;
207 }
208
209 void
sysexits(void)210 sysexits(void)
211 {
212 char buf[OERRLEN];
213 ulong str;
214
215 str = getmem_w(reg.r[13]+4);
216 if(sysdbg)
217 itrace("exits(0x%lux)", str);
218
219 count = 1;
220 if(str != 0) {
221 memio(buf, str, sizeof buf, MemRead);
222 Bprint(bioout, "exits(%s)\n", buf);
223 }
224 else
225 Bprint(bioout, "exits(0)\n");
226 }
227
228 void
sysopen(void)229 sysopen(void)
230 {
231 char file[1024];
232 int n;
233 ulong mode, name;
234
235 name = getmem_w(reg.r[13]+4);
236 mode = getmem_w(reg.r[13]+8);
237 memio(file, name, sizeof(file), MemReadstring);
238
239 n = open(file, mode);
240 if(n < 0)
241 errstr(errbuf, sizeof errbuf);
242
243 if(sysdbg)
244 itrace("open(0x%lux='%s', 0x%lux) = %d", name, file, mode, n);
245
246 reg.r[REGRET] = n;
247 };
248
249
250 void
sysread(vlong offset)251 sysread(vlong offset)
252 {
253 int fd;
254 ulong size, a;
255 char *buf, *p;
256 int n, cnt, c;
257
258 fd = getmem_w(reg.r[13]+4);
259 a = getmem_w(reg.r[13]+8);
260 size = getmem_w(reg.r[13]+12);
261
262 buf = emalloc(size);
263 if(fd == 0) {
264 print("\nstdin>>");
265 p = buf;
266 n = 0;
267 cnt = size;
268 while(cnt) {
269 c = Bgetc(bin);
270 if(c <= 0)
271 break;
272 *p++ = c;
273 n++;
274 cnt--;
275 if(c == '\n')
276 break;
277 }
278 }
279 else
280 n = pread(fd, buf, size, offset);
281
282 if(n < 0)
283 errstr(errbuf, sizeof errbuf);
284 else
285 memio(buf, a, n, MemWrite);
286
287 if(sysdbg)
288 itrace("read(%d, 0x%lux, %d, 0x%llx) = %d", fd, a, size, offset, n);
289
290 free(buf);
291 reg.r[REGRET] = n;
292 }
293
294 void
sys_read(void)295 sys_read(void)
296 {
297 sysread(-1LL);
298 }
299
300 void
syspread(void)301 syspread(void)
302 {
303 sysread(getmem_v(reg.r[13]+16));
304 }
305
306 void
sysseek(void)307 sysseek(void)
308 {
309 int fd;
310 ulong mode;
311 ulong retp;
312 vlong v;
313
314 retp = getmem_w(reg.r[13]+4);
315 fd = getmem_w(reg.r[13]+8);
316 v = getmem_v(reg.r[13]+16);
317 mode = getmem_w(reg.r[13]+20);
318 if(sysdbg)
319 itrace("seek(%d, %lld, %d)", fd, v, mode);
320
321 v = seek(fd, v, mode);
322 if(v < 0)
323 errstr(errbuf, sizeof errbuf);
324
325 putmem_v(retp, v);
326 }
327
328 void
sysoseek(void)329 sysoseek(void)
330 {
331 int fd, n;
332 ulong off, mode;
333
334 fd = getmem_w(reg.r[13]+4);
335 off = getmem_w(reg.r[13]+8);
336 mode = getmem_w(reg.r[13]+12);
337 if(sysdbg)
338 itrace("seek(%d, %lud, %d)", fd, off, mode);
339
340 n = seek(fd, off, mode);
341 if(n < 0)
342 errstr(errbuf, sizeof errbuf);
343
344 reg.r[REGRET] = n;
345 }
346
347 void
syssleep(void)348 syssleep(void)
349 {
350 ulong len;
351 int n;
352
353 len = getmem_w(reg.r[13]+4);
354 if(sysdbg)
355 itrace("sleep(%d)", len);
356
357 n = sleep(len);
358 if(n < 0)
359 errstr(errbuf, sizeof errbuf);
360
361 reg.r[REGRET] = n;
362 }
363
364 void
sys_stat(void)365 sys_stat(void)
366 {
367 char nambuf[1024];
368 char buf[ODIRLEN];
369 ulong edir, name;
370 extern int _stat(char*, char*); /* old system call */
371 int n;
372
373 name = getmem_w(reg.r[13]+4);
374 edir = getmem_w(reg.r[13]+8);
375 memio(nambuf, name, sizeof(nambuf), MemReadstring);
376 if(sysdbg)
377 itrace("stat(0x%lux='%s', 0x%lux)", name, nambuf, edir);
378
379 n = _stat(nambuf, buf);
380 if(n < 0)
381 errstr(errbuf, sizeof errbuf);
382 else
383 memio(buf, edir, ODIRLEN, MemWrite);
384
385 reg.r[REGRET] = n;
386 }
387
388 void
sysstat(void)389 sysstat(void)
390 {
391 char nambuf[1024];
392 uchar buf[STATMAX];
393 ulong edir, name;
394 int n;
395
396 name = getmem_w(reg.r[13]+4);
397 edir = getmem_w(reg.r[13]+8);
398 n = getmem_w(reg.r[13]+12);
399 memio(nambuf, name, sizeof(nambuf), MemReadstring);
400 if(sysdbg)
401 itrace("stat(0x%lux='%s', 0x%lux, 0x%lux)", name, nambuf, edir, n);
402 if(n > sizeof buf)
403 errstr(errbuf, sizeof errbuf);
404 else{
405 n = stat(nambuf, buf, n);
406 if(n < 0)
407 errstr(errbuf, sizeof errbuf);
408 else
409 memio((char*)buf, edir, n, MemWrite);
410 }
411 reg.r[REGRET] = n;
412 }
413
414 void
sys_fstat(void)415 sys_fstat(void)
416 {
417 char buf[ODIRLEN];
418 extern int _fstat(int, char*); /* old system call */
419 ulong edir;
420 int n, fd;
421
422 fd = getmem_w(reg.r[13]+4);
423 edir = getmem_w(reg.r[13]+8);
424 if(sysdbg)
425 itrace("fstat(%d, 0x%lux)", fd, edir);
426
427 n = _fstat(fd, buf);
428 if(n < 0)
429 errstr(errbuf, sizeof errbuf);
430 else
431 memio(buf, edir, ODIRLEN, MemWrite);
432
433 reg.r[REGRET] = n;
434 }
435
436 void
sysfstat(void)437 sysfstat(void)
438 {
439 uchar buf[STATMAX];
440 ulong edir;
441 int n, fd;
442
443 fd = getmem_w(reg.r[13]+4);
444 edir = getmem_w(reg.r[13]+8);
445 n = getmem_w(reg.r[13]+12);
446 if(sysdbg)
447 itrace("fstat(%d, 0x%lux, 0x%lux)", fd, edir, n);
448
449 reg.r[REGRET] = -1;
450 if(n > sizeof buf){
451 strcpy(errbuf, "stat buffer too big");
452 return;
453 }
454 n = fstat(fd, buf, n);
455 if(n < 0)
456 errstr(errbuf, sizeof errbuf);
457 else
458 memio((char*)buf, edir, n, MemWrite);
459 reg.r[REGRET] = n;
460 }
461
462 void
syswrite(vlong offset)463 syswrite(vlong offset)
464 {
465 int fd;
466 ulong size, a;
467 char *buf;
468 int n;
469
470 fd = getmem_w(reg.r[13]+4);
471 a = getmem_w(reg.r[13]+8);
472 size = getmem_w(reg.r[13]+12);
473
474 Bflush(bioout);
475 buf = memio(0, a, size, MemRead);
476 n = pwrite(fd, buf, size, offset);
477 if(n < 0)
478 errstr(errbuf, sizeof errbuf);
479
480 if(sysdbg)
481 itrace("write(%d, %lux, %d, 0x%llx) = %d", fd, a, size, offset, n);
482
483 free(buf);
484
485 reg.r[REGRET] = n;
486 }
487
488 void
sys_write(void)489 sys_write(void)
490 {
491 syswrite(-1LL);
492 }
493
494 void
syspwrite(void)495 syspwrite(void)
496 {
497 syswrite(getmem_v(reg.r[13]+16));
498 }
499
500 void
syspipe(void)501 syspipe(void)
502 {
503 int n, p[2];
504 ulong fd;
505
506 fd = getmem_w(reg.r[13]+4);
507 if(sysdbg)
508 itrace("pipe(%lux)", fd);
509
510 n = pipe(p);
511 if(n < 0)
512 errstr(errbuf, sizeof errbuf);
513 else {
514 putmem_w(fd, p[0]);
515 putmem_w(fd+4, p[1]);
516 }
517 reg.r[REGRET] = n;
518 }
519
520 void
syscreate(void)521 syscreate(void)
522 {
523 char file[1024];
524 int n;
525 ulong mode, name, perm;
526
527 name = getmem_w(reg.r[13]+4);
528 mode = getmem_w(reg.r[13]+8);
529 perm = getmem_w(reg.r[13]+12);
530 memio(file, name, sizeof(file), MemReadstring);
531 if(sysdbg)
532 itrace("create(0x%lux='%s', 0x%lux, 0x%lux)", name, file, mode, perm);
533
534 n = create(file, mode, perm);
535 if(n < 0)
536 errstr(errbuf, sizeof errbuf);
537
538 reg.r[REGRET] = n;
539 }
540
541 void
sysbrk_(void)542 sysbrk_(void)
543 {
544 ulong addr, osize, nsize;
545 Segment *s;
546
547 addr = getmem_w(reg.r[13]+4);
548 if(sysdbg)
549 itrace("brk_(0x%lux)", addr);
550
551 reg.r[REGRET] = -1;
552 if(addr < memory.seg[Data].base+datasize) {
553 strcpy(errbuf, "address below segment");
554 return;
555 }
556 if(addr > memory.seg[Stack].base) {
557 strcpy(errbuf, "segment too big");
558 return;
559 }
560 s = &memory.seg[Bss];
561 if(addr > s->end) {
562 osize = ((s->end-s->base)/BY2PG)*sizeof(uchar*);
563 addr = ((addr)+(BY2PG-1))&~(BY2PG-1);
564 s->end = addr;
565 nsize = ((s->end-s->base)/BY2PG)*sizeof(uchar*);
566 s->table = erealloc(s->table, osize, nsize);
567 }
568
569 reg.r[REGRET] = 0;
570 }
571
572 void
sysremove(void)573 sysremove(void)
574 {
575 char nambuf[1024];
576 ulong name;
577 int n;
578
579 name = getmem_w(reg.r[13]+4);
580 memio(nambuf, name, sizeof(nambuf), MemReadstring);
581 if(sysdbg)
582 itrace("remove(0x%lux='%s')", name, nambuf);
583
584 n = remove(nambuf);
585 if(n < 0)
586 errstr(errbuf, sizeof errbuf);
587 reg.r[REGRET] = n;
588 }
589
590 void
sysnotify(void)591 sysnotify(void)
592 {
593 nofunc = getmem_w(reg.r[13]+4);
594 if(sysdbg)
595 itrace("notify(0x%lux)\n", nofunc);
596
597 reg.r[REGRET] = 0;
598 }
599
600 void
sys_wait(void)601 sys_wait(void)
602 {
603 Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]);
604 exits(0);
605 }
606 void
sysawait(void)607 sysawait(void)
608 {
609 Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]);
610 exits(0);
611 }
612 void
sysrfork(void)613 sysrfork(void)
614 {
615 Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]);
616 exits(0);
617 }
618 void
syswstat(void)619 syswstat(void)
620 {
621 Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]);
622 exits(0);
623 }
624 void
sys_wstat(void)625 sys_wstat(void)
626 {
627 Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]);
628 exits(0);
629 }
630 void
sysfwstat(void)631 sysfwstat(void)
632 {
633 Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]);
634 exits(0);
635 }
636 void
sys_fwstat(void)637 sys_fwstat(void)
638 {
639 Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]);
640 exits(0);
641 }
642 void
sysnoted(void)643 sysnoted(void)
644 {
645 Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]);
646 exits(0);
647 }
648 void
syssegattach(void)649 syssegattach(void)
650 {
651 Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]);
652 exits(0);
653 }
654 void
syssegdetach(void)655 syssegdetach(void)
656 {
657 Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]);
658 exits(0);
659 }
660 void
syssegfree(void)661 syssegfree(void)
662 {
663 Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]);
664 exits(0);
665 }
666 void
syssegflush(void)667 syssegflush(void)
668 {
669 Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]);
670 exits(0);
671 }
672 void
sysrendezvous(void)673 sysrendezvous(void)
674 {
675 Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]);
676 exits(0);
677 }
678 void
sysunmount(void)679 sysunmount(void)
680 {
681 Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]);
682 exits(0);
683 }
684 void
sysfork(void)685 sysfork(void)
686 {
687 Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]);
688 exits(0);
689 }
690 void
sysforkpgrp(void)691 sysforkpgrp(void)
692 {
693 Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]);
694 exits(0);
695 }
696 void
syssegbrk(void)697 syssegbrk(void)
698 {
699 Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]);
700 exits(0);
701 }
702 void
sysmount(void)703 sysmount(void)
704 {
705 Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]);
706 exits(0);
707 }
708 void
sysalarm(void)709 sysalarm(void)
710 {
711 Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]);
712 exits(0);
713 }
714 void
sysexec(void)715 sysexec(void)
716 {
717 Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]);
718 exits(0);
719 }
720 void
sys_fsession(void)721 sys_fsession(void)
722 {
723 Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]);
724 exits(0);
725 }
726 void
sysfauth(void)727 sysfauth(void)
728 {
729 Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]);
730 exits(0);
731 }
732 void
sysfversion(void)733 sysfversion(void)
734 {
735 Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGARG]]);
736 exits(0);
737 }
738
739 void (*systab[])(void) =
740 {
741 [SYSR1] sys1,
742 [_ERRSTR] sys_errstr,
743 [BIND] sysbind,
744 [CHDIR] syschdir,
745 [CLOSE] sysclose,
746 [DUP] sysdup,
747 [ALARM] sysalarm,
748 [EXEC] sysexec,
749 [EXITS] sysexits,
750 [_FSESSION] sys_fsession,
751 [FAUTH] sysfauth,
752 [_FSTAT] sys_fstat,
753 [SEGBRK] syssegbrk,
754 [MOUNT] sysmount,
755 [OPEN] sysopen,
756 [_READ] sys_read,
757 [OSEEK] sysoseek,
758 [SLEEP] syssleep,
759 [_STAT] sys_stat,
760 [RFORK] sysrfork,
761 [_WRITE] sys_write,
762 [PIPE] syspipe,
763 [CREATE] syscreate,
764 [FD2PATH] sysfd2path,
765 [BRK_] sysbrk_,
766 [REMOVE] sysremove,
767 [_WSTAT] sys_wstat,
768 [_FWSTAT] sys_fwstat,
769 [NOTIFY] sysnotify,
770 [NOTED] sysnoted,
771 [SEGATTACH] syssegattach,
772 [SEGDETACH] syssegdetach,
773 [SEGFREE] syssegfree,
774 [SEGFLUSH] syssegflush,
775 [RENDEZVOUS] sysrendezvous,
776 [UNMOUNT] sysunmount,
777 [_WAIT] sys_wait,
778 [SEEK] sysseek,
779 [FVERSION] sysfversion,
780 [ERRSTR] syserrstr,
781 [STAT] sysstat,
782 [FSTAT] sysfstat,
783 [WSTAT] syswstat,
784 [FWSTAT] sysfwstat,
785 [PREAD] syspread,
786 [PWRITE] syspwrite,
787 [AWAIT] sysawait,
788 };
789
790 void
Ssyscall(ulong)791 Ssyscall(ulong)
792 {
793 int call;
794
795 call = reg.r[REGARG];
796 if(call < 0 || call >= nelem(systab) || systab[call] == nil) {
797 Bprint(bioout, "bad system call %d (%#ux)\n", call, call);
798 dumpreg();
799 Bflush(bioout);
800 return;
801 }
802
803 if(trace)
804 itrace("SWI\t%s", sysctab[call]);
805 (*systab[call])();
806 Bflush(bioout);
807 }
808