2 * System calls are mostly pretty easy as the emulator is tightly bound to
13 #include <sys/times.h>
19 #include <sys/types.h>
20 #include <sys/resource.h>
22 #include <sys/ioctl.h>
30 #define dbprintf(x) db_printf x
35 #define sys_signal elks_signal
36 extern int elks_signal(int bx
,int cx
,int dx
,int di
,int si
);
39 static int elks_termios(int bx
,int cx
,int dx
,int di
,int si
);
40 static int elks_enosys(int bx
,int cx
,int dx
,int di
,int si
);
43 DIR * dirtab
[DIRCOUNT
];
45 static int elks_opendir(char * dname
);
46 static int elks_readdir(int bx
,int cx
,int dx
,int di
,int si
);
47 static int elks_closedir(int bx
);
50 * Compress a host stat into a elks one. Lose upper bits with wild
51 * abandon. For SYS5.3 this isn't a problem, but machines with 32
52 * bit inodes (BSD, SYS5 with veritas, newest SCO) you lose the top
53 * bits which can confuse a few programs which use inode numbers
57 static void squash_stat(struct stat
*s
, int bx
)
59 #if 1 /* Can't use elks_stat, shot in the foot by alignment */
61 ELKS_POKE(short, bx
+0, s
->st_dev
);
62 ELKS_POKE(short, bx
+2, s
->st_ino
^ (s
->st_ino
>>16));
63 ELKS_POKE(short, bx
+4, s
->st_mode
);
64 ELKS_POKE(short, bx
+6, s
->st_nlink
);
65 ELKS_POKE(short, bx
+8, s
->st_uid
);
66 ELKS_POKE(short, bx
+10, s
->st_gid
);
67 ELKS_POKE(short, bx
+12, s
->st_rdev
);
68 ELKS_POKE(long, bx
+14, s
->st_size
);
69 ELKS_POKE(long, bx
+18, s
->st_atime
);
70 ELKS_POKE(long, bx
+22, s
->st_mtime
);
71 ELKS_POKE(long, bx
+26, s
->st_ctime
);
73 struct elks_stat
* ms
= ELKS_PTR(struct elks_stat
, bx
);
74 ms
->est_dev
=s
->st_dev
;
75 ms
->est_inode
=(unsigned short)s
->st_ino
; /* Bits lost */
76 ms
->est_mode
=s
->st_mode
;
77 ms
->est_nlink
=s
->st_nlink
;
78 ms
->est_uid
=s
->st_uid
;
79 ms
->est_gid
=s
->st_gid
;
80 ms
->est_rdev
=s
->st_rdev
;
81 ms
->est_size
=s
->st_size
;
82 ms
->est_atime
=s
->st_atime
;
83 ms
->est_mtime
=s
->st_mtime
;
84 ms
->est_ctime
=s
->st_ctime
;
89 * Implementation of ELKS syscalls.
93 #define sys_exit elks_exit
94 static int elks_exit(int bx
,int cx
,int dx
,int di
,int si
)
96 dbprintf(("exit(%d)\n",bx
));
100 #define sys_vfork elks_fork
101 #define sys_fork elks_fork
102 static int elks_fork(int bx
,int cx
,int dx
,int di
,int si
)
104 dbprintf(("fork()\n"));
105 /* This is fun 8) - fork the emulator (its easier that way) */
109 #define sys_read elks_read
110 static int elks_read(int bx
,int cx
,int dx
,int di
,int si
)
112 dbprintf(("read(%d, %d, %d)\n",
114 if( bx
>= 10000 && bx
< 10000+DIRCOUNT
)
115 return elks_readdir(bx
, cx
, dx
, di
, si
);
116 if( dx
< 0 || dx
> 1024 ) dx
= 1024;
117 return read(bx
, ELKS_PTR(void, cx
), dx
);
120 #define sys_write elks_write
121 static int elks_write(int bx
,int cx
,int dx
,int di
,int si
)
124 if( dx
> 1024 || dx
< 0 )
127 dbprintf(("write(%d, %d, >%d)\n",bx
,cx
,dx
));
132 dbprintf(("write(%d, %d, %d)\n",bx
,cx
,dx
));
134 return write(bx
,ELKS_PTR(void, cx
),dx
);
137 #define sys_open elks_open
138 static int elks_open(int bx
,int cx
,int dx
,int di
,int si
)
142 /* Assumes _all_ flags are the same */
143 char *dp
=ELKS_PTR(char, bx
);
144 dbprintf(("open(%s, %d, %d)\n",
147 /* Nasty hack so /lib/liberror.txt doesn't exist on the host.
149 if (strcmp(dp
, "/lib/liberror.txt") == 0 ) {
150 int fd
= open("/var/run/elks-liberror.txt", O_CREAT
|O_EXCL
|O_RDWR
, 0666);
151 if (fd
< 0) return fd
;
152 unlink("/var/run/elks-liberror.txt");
153 write(fd
, efile
, sizeof(efile
));
162 if( S_ISDIR(s
.st_mode
) )
163 return elks_opendir(dp
);
166 return open(dp
,cx
,dx
);
169 #define sys_close elks_close
170 static int elks_close(int bx
,int cx
,int dx
,int di
,int si
)
172 dbprintf(("close(%d)\n",bx
));
173 if( bx
>= 10000 && bx
< 10000+DIRCOUNT
)
174 return elks_closedir(bx
);
178 #define sys_wait4 elks_wait4
179 static int elks_wait4(int bx
,int cx
,int dx
,int di
,int si
)
182 unsigned short *tp
=ELKS_PTR(unsigned short, cx
);
186 dbprintf(("wait4(%d, %d, %d, %d)\n", bx
, cx
, dx
, di
));
187 r
=wait4((int)(short)bx
, &status
, dx
, &use
);
190 if( di
) memcpy(ELKS_PTR(void, di
), &use
, sizeof(use
));
194 #define sys_link elks_link
195 static int elks_link(int bx
,int cx
,int dx
,int di
,int si
)
197 dbprintf(("link(%s,%s)\n", ELKS_PTR(char, bx
), ELKS_PTR(char, cx
)));
198 return link(ELKS_PTR(char, bx
),ELKS_PTR(char, cx
));
201 #define sys_unlink elks_unlink
202 static int elks_unlink(int bx
,int cx
,int dx
,int di
,int si
)
204 dbprintf(("unlink(%s)\n",ELKS_PTR(char, bx
)));
205 return unlink(ELKS_PTR(char, bx
));
208 #define sys_chdir elks_chdir
209 static int elks_chdir(int bx
,int cx
,int dx
,int di
,int si
)
211 dbprintf(("chdir(%s)\n",ELKS_PTR(char, bx
)));
212 return chdir(ELKS_PTR(char, bx
));
215 #define sys_fchdir elks_fchdir
216 static int elks_fchdir(int bx
,int cx
,int dx
,int di
,int si
)
218 dbprintf(("fchdir(%s)\n",bx
));
223 #define sys_mknod elks_mknod
224 static int elks_mknod(int bx
,int cx
,int dx
,int di
,int si
)
226 dbprintf(("mknod(%s,%d,%d)\n", ELKS_PTR(char, bx
),cx
,dx
));
227 return mknod(ELKS_PTR(char, bx
),cx
,dx
);
230 #define sys_chmod elks_chmod
231 static int elks_chmod(int bx
,int cx
,int dx
,int di
,int si
)
233 dbprintf(("chmod(%s,%d)\n", ELKS_PTR(char, bx
),cx
));
234 return chmod(ELKS_PTR(char, bx
), cx
);
237 #define sys_chown elks_chown
238 static int elks_chown(int bx
,int cx
,int dx
,int di
,int si
)
240 dbprintf(("chown(%s,%d,%d)\n", ELKS_PTR(char, bx
),cx
,dx
));
241 return chown(ELKS_PTR(char, bx
),cx
,dx
);
244 #define sys_brk elks_brk
245 static int elks_brk(int bx
,int cx
,int dx
,int di
,int si
)
247 dbprintf(("brk(%d)\n",bx
));
248 if(bx
>=elks_cpu
.regs
.esp
)
250 errno
= 1; /* Really return -1 */
253 return 0; /* Can't return bx, 0xBAD1 is an error */
256 #define sys_stat elks_stat
257 static int elks_stat(int bx
,int cx
,int dx
,int di
,int si
)
260 dbprintf(("stat(%s,%d)\n", ELKS_PTR(char, bx
), cx
));
261 if(stat(ELKS_PTR(char, bx
),&s
)==-1)
267 #define sys_lstat elks_lstat
268 static int elks_lstat(int bx
,int cx
,int dx
,int di
,int si
)
271 dbprintf(("lstat(%s,%d)\n", ELKS_PTR(char, bx
), cx
));
272 if(lstat(ELKS_PTR(char, bx
),&s
)==-1)
278 #define sys_lseek elks_lseek
279 static int elks_lseek(int bx
,int cx
,int dx
,int di
,int si
)
281 long l
=ELKS_PEEK(long, cx
);
283 dbprintf(("lseek(%d,%ld,%d)\n",bx
,l
,dx
));
285 if( l
< 0 ) return -1;
286 ELKS_POKE(long, cx
, l
);
290 #define sys_getpid elks_getpid
291 static int elks_getpid(int bx
,int cx
,int dx
,int di
,int si
)
293 dbprintf(("getpid/getppid()\n"));
294 ELKS_POKE(unsigned short, bx
, getppid());
298 #define sys_setuid elks_setuid
299 static int elks_setuid(int bx
,int cx
,int dx
,int di
,int si
)
301 dbprintf(("setuid(%d)\n",bx
));
305 #define sys_getuid elks_getuid
306 static int elks_getuid(int bx
,int cx
,int dx
,int di
,int si
)
308 dbprintf(("get[e]uid()\n"));
309 ELKS_POKE(unsigned short, bx
, geteuid());
313 #define sys_alarm elks_alarm
314 static int elks_alarm(int bx
,int cx
,int dx
,int di
,int si
)
316 dbprintf(("alarm(%d)\n",bx
&0xFFFF));
317 return alarm(bx
&0xFFFF);
320 #define sys_fstat elks_fstat
321 static int elks_fstat(int bx
,int cx
,int dx
,int di
,int si
)
325 dbprintf(("fstat(%d,%d)\n",bx
,cx
));
331 #define sys_pause elks_pause
332 static int elks_pause(int bx
,int cx
,int dx
,int di
,int si
)
334 dbprintf(("pause()\n"));
338 #define sys_utime elks_utime
339 static int elks_utime(int bx
,int cx
,int dx
,int di
,int si
)
341 unsigned long *up
=ELKS_PTR(long, cx
);
345 return utime(ELKS_PTR(char, bx
), &u
);
348 #define sys_access elks_access
349 static int elks_access(int bx
,int cx
,int dx
,int di
,int si
)
351 dbprintf(("access(%s,%d)\n",ELKS_PTR(char, bx
),cx
));
352 return access(ELKS_PTR(char, bx
),cx
);
355 #define sys_sync elks_sync
356 static int elks_sync(int bx
,int cx
,int dx
,int di
,int si
)
358 dbprintf(("sync()\n"));
363 #define sys_kill elks_kill
364 static int elks_kill(int bx
,int cx
,int dx
,int di
,int si
)
366 dbprintf(("kill(%d,%d)\n",bx
,cx
));
370 #define sys_pipe elks_pipe
371 static int elks_pipe(int bx
,int cx
,int dx
,int di
,int si
)
373 unsigned short *dp
=ELKS_PTR(unsigned short, bx
);
383 #define sys_times elks_times
384 static int elks_times(int bx
,int cx
,int dx
,int di
,int si
)
387 long clock_ticks
=times(&t
);
388 long *tp
=ELKS_PTR(long, bx
);
389 long *clkt
=ELKS_PTR(long, cx
);
395 return 0; /* Should be clock_ticks */
398 #define sys_setgid elks_setgid
399 static int elks_setgid(int bx
,int cx
,int dx
,int di
,int si
)
404 #define sys_getgid elks_getgid
405 static int elks_getgid(int bx
,int cx
,int dx
,int di
,int si
)
407 ELKS_POKE(unsigned short, bx
, getegid());
412 * Exec is fun. The Minix user library builds a complete elks stack image.
413 * Great except that we need to unpack it all again and do a real exec. If
414 * its another elks image then our kernel side binary loader will load
415 * elksemu again and we'll take the Unix args and turn them back into a
418 * For now we run elksemu ourselves and do token attempts at binary checking.
420 * Of course if the kernel misc module is confiured we could just run the exe.
422 #define sys_execve elks_execve
423 static int elks_execve(int bx
,int cx
,int dx
,int di
,int si
)
432 struct elks_exec_hdr mh
;
435 dbprintf(("exec(%s,%d,%d)\n",ELKS_PTR(char, bx
), cx
, dx
));
437 base
=ELKS_PTR(unsigned char, cx
);
438 bp
=ELKS_PTR(unsigned short, cx
+2);
441 fd
=open(ELKS_PTR(char, bx
),O_RDONLY
);
443 { errno
= ENOENT
; return -1; }
444 if(read(fd
, &mh
, sizeof(mh
))!=sizeof(mh
))
451 if(mh
.hlen
!=EXEC_HEADER_SIZE
452 || (mh
.type
!=ELKS_COMBID
&& mh
.type
!=ELKS_SPLITID
))
460 arg_ct
+=2; /* elksemu-path progname arg0...argn */
461 argp
=malloc(sizeof(char *)*(arg_ct
+1));
462 envp
=malloc(sizeof(char *)*(env_ct
+1));
463 if(!argp
||!envp
) { errno
= ENOMEM
; return -1; }
467 argp
[0]="/usr/bin/elksemu";
468 /* argp[1]=ELKS_PTR(char, bx); */
472 argp
[ct
++]=ELKS_PTR(char, cx
+ *bp
++);
477 envp
[ct
++]=ELKS_PTR(char, cx
+ *bp
++);
481 argp
[1]=ELKS_PTR(char, bx
);
482 execve(argp
[0],argp
,envp
);
485 execve(ELKS_PTR(char, bx
),argp
,envp
);
486 if( errno
== ENOEXEC
|| errno
== EACCES
) return -1;
491 #define sys_umask elks_umask
492 static int elks_umask(int bx
,int cx
,int dx
,int di
,int si
)
497 #define sys_chroot elks_chroot
498 static int elks_chroot(int bx
,int cx
,int dx
,int di
,int si
)
500 dbprintf(("chroot(%s)\n", ELKS_PTR(char, bx
)));
501 return chroot(ELKS_PTR(char, bx
));
505 #define sys_fcntl elks_fcntl
506 static int elks_fcntl(int bx
,int cx
,int dx
,int di
,int si
)
508 dbprintf(("fcntl(%d,%d,%d)\n", bx
,cx
,dx
));
512 return fcntl(bx
,F_GETFD
,0);
514 return fcntl(bx
,F_GETFL
,0);
516 return fcntl(bx
,F_DUPFD
,dx
);
518 return fcntl(bx
,F_SETFD
,dx
);
520 return fcntl(bx
,F_SETFL
,dx
);
522 * Fixme: Unpack and process elks file locks
534 #define sys_dup elks_dup
535 static int elks_dup(int bx
,int cx
,int dx
,int di
,int si
)
540 #define sys_dup2 elks_dup2
541 static int elks_dup2(int bx
,int cx
,int dx
,int di
,int si
)
546 #define sys_rename elks_rename
547 static int elks_rename(int bx
,int cx
,int dx
,int di
,int si
)
549 dbprintf(("rename(%s,%s)\n", ELKS_PTR(char, bx
), ELKS_PTR(char, cx
)));
550 return rename(ELKS_PTR(char, bx
), ELKS_PTR(char, cx
));
553 #define sys_mkdir elks_mkdir
554 static int elks_mkdir(int bx
,int cx
,int dx
,int di
,int si
)
556 dbprintf(("mkdir(%s,%d)\n", ELKS_PTR(char, bx
),cx
));
557 return mkdir(ELKS_PTR(char, bx
),cx
);
560 #define sys_rmdir elks_rmdir
561 static int elks_rmdir(int bx
,int cx
,int dx
,int di
,int si
)
563 dbprintf(("rmdir(%s)\n", ELKS_PTR(char, bx
)));
564 return rmdir(ELKS_PTR(char, bx
));
567 #define sys_gettimeofday elks_gettimeofday
568 static int elks_gettimeofday(int bx
,int cx
,int dx
,int di
,int si
)
573 dbprintf(("gettimeofday(%d,%d)\n",bx
,cx
));
575 ax
= gettimeofday(&tv
, &tz
);
579 ELKS_POKE(long, bx
, tv
.tv_sec
);
580 ELKS_POKE(long, bx
+4, tv
.tv_usec
);
584 ELKS_POKE(short, cx
, tz
.tz_minuteswest
);
585 ELKS_POKE(short, cx
+2, tz
.tz_dsttime
);
590 #define sys_settimeofday elks_settimeofday
591 static int elks_settimeofday(int bx
,int cx
,int dx
,int di
,int si
)
593 struct timeval tv
, *pv
= 0;
594 struct timezone tz
, *pz
= 0;
596 dbprintf(("settimeofday(%d,%d)\n",bx
,cx
));
601 tv
.tv_sec
= ELKS_PEEK(long, bx
);
602 tv
.tv_usec
= ELKS_PEEK(long, bx
+4);
607 tz
.tz_minuteswest
= ELKS_PEEK(short, cx
);
608 tz
.tz_dsttime
= ELKS_PEEK(short, cx
+2);
611 ax
= settimeofday(pv
, pz
);
615 #define sys_nice elks_nice
616 static int elks_nice(int bx
,int cx
,int dx
,int di
,int si
)
618 dbprintf(("nice(%d)\n",bx
));
622 #define sys_symlink elks_symlink
623 static int elks_symlink(int bx
,int cx
,int dx
,int di
,int si
)
625 dbprintf(("symlink(%s,%s)\n", ELKS_PTR(char, bx
), ELKS_PTR(char, cx
)));
626 return symlink(ELKS_PTR(char, bx
), ELKS_PTR(char, cx
));
629 #define sys_readlink elks_readlink
630 static int elks_readlink(int bx
,int cx
,int dx
,int di
,int si
)
632 dbprintf(("readlink(%s,%s,%d)\n",
636 return readlink(ELKS_PTR(char, bx
), ELKS_PTR(char, cx
), dx
);
639 #define sys_ioctl elks_ioctl
640 static int elks_ioctl(int bx
,int cx
,int dx
,int di
,int si
)
642 dbprintf(("ioctl(%d,0x%04x,0x%04x)\n", bx
,cx
,dx
));
645 case 'T': return elks_termios(bx
,cx
,dx
,di
,si
);
646 default: return elks_enosys(bx
,cx
,dx
,di
,si
);
650 #define sys_reboot elks_reboot
651 static int elks_reboot(int bx
,int cx
,int dx
,int di
,int si
)
654 if( bx
!= 0xfee1 || cx
!= 0xdead ) return -1;
658 /* graceful shutdown, C-A-D off, kill -? 1 */
659 case 0: return reboot(0xfee1dead, 672274793, 0);
661 case 0xCAD: return reboot(0xfee1dead, 672274793, 0x89abcdef);
663 case 0xD1E: return reboot(0xfee1dead, 672274793, 0x1234567);
668 /****************************************************************************/
671 elks_opendir(char * dname
)
675 for(rv
=0; rv
<DIRCOUNT
; rv
++)
676 if( dirtab
[rv
] == 0 )
678 if( rv
>= DIRCOUNT
) { errno
=ENOMEM
; return -1; }
680 if( d
== 0 ) return -1;
685 #define sys_readdir elks_readdir
686 static int elks_readdir(int bx
,int cx
,int dx
,int di
,int si
)
690 /* Only read _ONE_ _WHOLE_ dirent at a time */
691 if( dx
!= 266 && dx
!= 1 )
693 errno
=EINVAL
; return -1;
696 ent
= readdir(dirtab
[bx
-10000]);
697 if( ent
== 0 ) { if( errno
) { return -1; } else return 0; }
699 memcpy(ELKS_PTR(char, cx
+10), ent
->d_name
, ent
->d_reclen
+1);
700 ELKS_POKE(long, cx
, ent
->d_ino
);
701 ELKS_POKE(short, cx
+8, ent
->d_reclen
);
706 elks_closedir(int bx
)
709 if( dirtab
[bx
] ) closedir(dirtab
[bx
]);
714 /****************************************************************************/
716 static int elks_termios(int bx
,int cx
,int dx
,int di
,int si
)
721 case 0x01: rv
= ioctl(bx
, TCGETS
, ELKS_PTR(void, dx
)); break;
722 case 0x02: rv
= ioctl(bx
, TCSETS
, ELKS_PTR(void, dx
)); break;
723 case 0x03: rv
= ioctl(bx
, TCSETSW
, ELKS_PTR(void, dx
)); break;
724 case 0x04: rv
= ioctl(bx
, TCSETSF
, ELKS_PTR(void, dx
)); break;
726 case 0x09: rv
= ioctl(bx
, TCSBRK
, dx
); break;
727 case 0x0A: rv
= ioctl(bx
, TCXONC
, dx
); break;
728 case 0x0B: rv
= ioctl(bx
, TCFLSH
, dx
); break;
730 case 0x11: rv
= ioctl(bx
, TIOCOUTQ
, ELKS_PTR(void, dx
)); break;
731 case 0x1B: rv
= ioctl(bx
, TIOCINQ
, ELKS_PTR(void, dx
)); break;
733 default: rv
= -1; errno
= EINVAL
; break;
738 /****************************************************************************/
740 /****************************************************************************/
741 #define sys_enosys elks_enosys
742 static int elks_enosys(int bx
,int cx
,int dx
,int di
,int si
)
744 fprintf(stderr
, "Function number %d called (%d,%d,%d)\n",
745 (int)(0xFFFF&elks_cpu
.regs
.eax
),
751 #include "defn_tab.v"
754 typedef int (*funcp
)(int, int, int, int, int);
756 static funcp jump_tbl
[] = {
757 #include "call_tab.v"
761 int elks_syscall(void)
764 int bx
=elks_cpu
.regs
.ebx
&0xFFFF;
765 int cx
=elks_cpu
.regs
.ecx
&0xFFFF;
766 int dx
=elks_cpu
.regs
.edx
&0xFFFF;
767 int di
=elks_cpu
.regs
.edi
&0xFFFF;
768 int si
=elks_cpu
.regs
.esi
&0xFFFF;
771 n
= (elks_cpu
.regs
.eax
&0xFFFF);
772 if( n
>= 0 && n
< sizeof(jump_tbl
)/sizeof(funcp
) )
773 r
= (*(jump_tbl
[n
]))(bx
, cx
, dx
, di
, si
);