Cleanup in elf.c with .bss section clean; adm command mounts cdrom instead of floppy...
[ZeXOS.git] / kernel / arch / i386 / syscall.c
blob3bf76937ee936e9fd6b8b04331de304cedd3e096
1 /*
2 * ZeX/OS
3 * Copyright (C) 2007 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
4 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
5 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
6 * Copyright (C) 2009 Martin 'povik' Poviser (martin.povik@gmail.com)
7 * Copyright (C) 2010 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include <system.h>
25 #include <arch/io.h>
26 #include <string.h>
27 #include <tty.h>
28 #include <proc.h>
29 #include <net/socket.h>
30 #include <file.h>
31 #include <signal.h>
32 #include <module.h>
33 #include <rs232.h>
34 #include <ioctl.h>
35 #include <fd.h>
36 #include <paging.h>
37 #include <pipe.h>
38 #include <errno.h>
39 #include <sound/audio.h>
40 #include <syscall.h>
42 void sys_exit (struct regs *r)
44 task_t *taskc = task_find (0);
46 if (!taskc)
47 return;
49 page_dir_switch (taskc->page_cover->page_dir);
51 proc_t *proc = proc_find (_curr_task);
53 if (!proc)
54 return;
56 task_t *task = proc->tty->task;
58 proc->pid = 0;
60 if (int_disable ())
61 longjmp (task->state, 1);
62 else
63 for (;;)
64 schedule ();
67 void sys_getch (struct regs *r)
69 proc_t *proc = proc_find (_curr_task);
71 if (!proc)
72 return;
74 if (proc->tty != currtty)
75 return;
77 unsigned char c = (unsigned char) getkey ();
79 if (c)
80 setkey (0);
82 *SYSV_GETCH = (unsigned) c;
86 void sys_sleep (struct regs *r)
88 unsigned long timer_start = timer_ticks + ((unsigned) r->ebx * 1000);
90 while (timer_start > timer_ticks)
91 schedule ();
94 void sys_putch (struct regs *r)
96 //page_dir_switch (taskc->page_cover->page_dir);
98 proc_t *proc = proc_find (_curr_task);
100 if (!proc)
101 return;
103 int c = r->ebx;
105 tty_putnch (proc->tty, c);
107 //page_dir_switch (proc->task->page_cover->page_dir);
110 void sys_color (struct regs *r)
112 video_color (r->ebx, r->ecx);
116 void sys_cls (struct regs *r)
118 proc_t *proc = proc_find (_curr_task);
120 if (!proc)
121 return;
123 if (proc->tty != currtty)
124 return;
126 /* NOTE: Why we should disable interrupts ? Nobody know, but works better */
127 if (int_disable ()) {
128 tty_cls (proc->tty);
129 int_enable ();
133 void sys_getkey (struct regs *r)
135 proc_t *proc = proc_find (_curr_task);
137 if (!proc)
138 return;
140 if (proc->tty != currtty)
141 return;
143 *SYSV_GETKEY = (unsigned) scancode;
145 scancode = 0;
148 void sys_gotoxy (struct regs *r)
150 proc_t *proc = proc_find (_curr_task);
152 if (!proc)
153 return;
155 tty_gotoxy (proc->tty, r->ebx, r->ecx);
158 void sys_fork (struct regs *r)
160 *SYSV_FORK = fork ();
163 void sys_schedule (struct regs *r)
165 schedule ();
168 void sys_write (struct regs *r)
170 unsigned len = r->ecx;
171 unsigned fd = r->edx;
173 unsigned char *buf = (unsigned char *) r->ebx;
175 if (!buf)
176 return;
178 int ret = 0;
180 proc_t *proc = 0;
181 char *mem = 0;
183 switch (fd) {
184 case 0:
185 proc = proc_find (_curr_task);
187 if (!proc) {
188 ret = -1;
189 break;
192 mem = (char *) buf;
194 //printf ("data: %s | 0x%x | %d\n", mem, proc->data, len);
196 tty_write (proc->tty, (char *) mem, len);
198 ret = len;
200 break;
201 case 1:
202 proc = proc_find (_curr_task);
204 if (!proc) {
205 ret = -1;
206 break;
209 if (len > KBD_MAX_QUAUE)
210 len = KBD_MAX_QUAUE;
212 mem = (char *) buf;
214 int i = 0;
215 for (i = len; i >= 0; i --)
216 setkey (buf[i]);
218 //mem[len] = '\0';
220 ret = len;
221 break;
222 default:
223 mem = (char *) buf;
225 ret = write (fd, (char *) mem, len);
226 break;
229 *SYSV_WRITE = ret;
232 void sys_socket (struct regs *r)
234 *SYSV_SOCKET = socket (r->ebx, r->ecx, r->edx);
237 void sys_connect (struct regs *r)
239 sockaddr *addr = (sockaddr *) r->ebx;
241 *SYSV_CONNECT = connect (r->ecx, addr, r->edx);
244 void sys_malloc (struct regs *r)
246 proc_t *proc = proc_find (_curr_task);
248 paging_disable ();
249 r->eax = (unsigned) umalloc (proc, (int) r->ebx);
250 paging_enable ();
252 DPRINT (DBG_SYSCALL, "malloc (): 0x%x", r->eax);
255 void sys_send (struct regs *r)
257 *SYSV_SEND = send ((int) r->ecx, (char *) r->ebx, (unsigned) r->edx, 0);
260 void sys_recv (struct regs *r)
262 unsigned char *msg = (unsigned char *) r->ebx;
263 unsigned size = (unsigned) r->edx;
264 int fd = (int) r->ecx;
266 *SYSV_RECV = recv (fd, (char *) msg, size, 0);
269 void sys_close (struct regs *r)
271 close (r->ebx);
274 void sys_open (struct regs *r)
276 *SYSV_OPEN = open ((char *) r->ebx, (unsigned) r->ecx);
279 void sys_pcspk (struct regs *r)
281 dev_t *dev = dev_find ("/dev/pcspk");
283 if (dev)
284 dev->handler (DEV_ACT_PLAY, (unsigned) r->ebx);
287 void sys_usleep (struct regs *r)
289 //unsigned long timer_start = timer_ticks + ((unsigned) r->ebx);
291 //while (timer_start > timer_ticks)
292 // schedule ();
293 usleep ((unsigned) r->ebx);
296 void sys_read (struct regs *r)
298 unsigned fd = r->ecx;
299 unsigned len = r->edx;
301 unsigned char *buf = (unsigned char *) r->ebx;
303 int ret = 0;
305 proc_t *proc = 0;
307 switch (fd) {
308 case 0:
309 break;
310 case 1:
311 proc = proc_find (_curr_task);
313 if (!proc)
314 break;
316 //if (proc->tty != currtty)
317 // return;
319 ret = tty_read (proc->tty, (char *) buf, len);
320 break;
321 default:
322 ret = read (fd, (char *) buf, len);
323 break;
326 *SYSV_READ = ret;
329 void sys_time (struct regs *r)
331 time_t *memptr = (time_t *) SYSV_TIME;
333 tm *t = rtc_getcurrtime ();
335 if (t)
336 *memptr = (time_t) t->__tm_gmtoff;
339 void sys_system (struct regs *r)
341 proc_t *proc = proc_find (_curr_task);
343 if (!proc)
344 return;
346 task_t *oldtask = _curr_task;
348 unsigned char *cmd = (unsigned char *) r->ebx;
350 /*paging_disable ();
351 page_dir_switch (task->page_cover->page_dir);
352 paging_enable ();
354 _curr_task = task;
355 schedule ();*/
357 command_parser ((char *) cmd, strlen (cmd));
359 page_dir_switch (oldtask->page_cover->page_dir);
361 /* needed for correct scheduling (when you execute new process, _curr_task is tasj of current tty) */
362 _curr_task = oldtask;
364 schedule ();
368 void sys_chdir (struct regs *r)
370 char *dir = (unsigned char *) r->ebx;
372 *SYSV_CHDIR = vfs_cd (dir, strlen (dir)) ? 0 : -1;
375 void sys_getdir (struct regs *r)
377 r->eax = (unsigned) vfs_dirent ();
380 void sys_procarg (struct regs *r)
382 proc_t *proc = proc_find (_curr_task);
384 if (!proc)
385 return;
387 switch (r->ecx) {
388 case 0:
389 r->eax = (unsigned) proc->argv;
390 break;
391 case 1:
392 r->eax = (unsigned) proc->argc;
393 break;
394 default:
395 r->eax = 0;
399 void sys_signal (struct regs *r)
401 signal (r->ebx, (sighandler_t) r->ecx);
404 void sys_mount (struct regs *r)
406 partition_t *p = partition_find ((char *) r->ebx);
408 if (p) {
409 mount (p, "", (char *) r->ecx);
410 r->eax = 1;
411 } else
412 r->eax = 0;
415 void sys_kputs (struct regs *r)
417 int_disable ();
419 module_t *kmod = module_find (_curr_task);
421 if (!kmod)
422 return;
424 if (kmod->task != _curr_task)
425 return;
427 unsigned char *buf = (unsigned char *) r->ebx;
428 kprintf (buf);
430 //kprintf ("yeah, sys_kputs: '%s' '0x%x'\n", buf, buf);
432 int_enable ();
435 void sys_bind (struct regs *r)
437 *SYSV_BIND = bind (r->ecx, (sockaddr *) r->ebx, r->edx);
440 void sys_listen (struct regs *r)
442 *SYSV_LISTEN = listen (r->ebx, r->ecx);
445 void sys_accept (struct regs *r)
447 *SYSV_ACCEPT = accept (r->ecx, r->ebx, r->edx);
450 void sys_fcntl (struct regs *r)
452 *SYSV_FCNTL = fcntl (r->ebx, r->ecx, r->edx);
455 void sys_gvgafb (struct regs *r)
457 proc_t *proc = proc_find (_curr_task);
459 if (!proc)
460 return;
462 if (vgagui != 2) {
463 printf ("Please start this program in graphical VESA mode\n");
464 sys_exit (r);
465 return;
468 *SYSV_GVGAFB = (unsigned) init_vgafb ();
471 void sys_gcls (struct regs *r)
473 //gcls (r->ebx);
476 void sys_gfbswap (struct regs *r)
478 proc_t *proc = proc_find (_curr_task);
480 if (!proc)
481 return;
483 if (proc->tty == currtty)
484 video_gfx_fbswap ();
486 schedule ();
489 void sys_rs232read (struct regs *r)
491 *SYSV_RS232READ = (int) rs232_read ();
494 void sys_rs232write (struct regs *r)
496 rs232_write ((char) r->ebx);
499 void sys_gttyexit (struct regs *r)
501 proc_t *proc = proc_find (_curr_task);
503 if (!proc)
504 return;
506 tty_change (proc->tty);
509 void sys_gexit (struct regs *r)
511 video_gfx_exit ();
514 void sys_gttyinit (struct regs *r)
516 tty_t *tty = gtty_init ();
518 if (!tty)
519 return;
521 r->eax = (unsigned) &tty->screen;
524 void sys_getenv (struct regs *r)
526 char *name = (char *) r->ebx;
528 char *val = (char *) env_get (name);
530 r->eax = (unsigned) val;
533 void sys_free (struct regs *r)
535 proc_t *proc = proc_find (_curr_task);
537 paging_disable ();
539 ufree (proc, (void *) r->ebx);
541 DPRINT (DBG_SYSCALL, "free (): 0x%x", r->ebx);
543 paging_enable ();
546 void sys_realloc (struct regs *r)
548 proc_t *proc = proc_find (_curr_task);
550 paging_disable ();
552 r->eax = (unsigned) urealloc (proc, (void *) r->ebx, (size_t) r->ecx);
554 DPRINT (DBG_SYSCALL, "realloc (): 0x%x", r->eax);
556 paging_enable ();
559 void sys_gethostbyname (struct regs *r)
561 char *buf = (char *) r->ebx;
563 if (!buf) {
564 r->eax = 0;
565 return;
568 r->eax = (unsigned) gethostbyname (buf);
571 void sys_vfsent (struct regs *r)
573 char *pathname = (char *) r->ebx;
575 r->eax = (unsigned) vfs_find (pathname, strlen (pathname));
578 void sys_sendto (struct regs *r)
580 /* HACK: bleeh, there is problem with fourth argument,
581 so we need to use another way to getting address */
582 sockaddr_in *to = (sockaddr_in *) *SYSV_SENDTO;
584 *SYSV_SENDTO = sendto ((int) r->ecx, (char *) r->ebx, (unsigned) r->edx, 0, to, 0);
587 void sys_recvfrom (struct regs *r)
589 unsigned char *msg = (unsigned char *) r->ebx;
591 /* HACK: bleeh, there is problem with fourth argument,
592 so we need to use another way to getting address */
593 sockaddr_in *from = (sockaddr_in *) *SYSV_RECVFROM;
595 *SYSV_RECVFROM = recvfrom ((int) r->ecx, (char *) msg, (unsigned) r->edx, 0, from, 0);
598 void sys_getchar (struct regs *r)
600 proc_t *proc = proc_find (_curr_task);
602 int i = 1;
603 unsigned char s = '\n';
605 int *memptr = SYSV_GETCHAR;
607 /* non-blocking mode */
608 if (stdin->flags & O_NONBLOCK) {
609 if (!proc)
610 return;
612 if (proc->tty != currtty)
613 return;
615 unsigned char c = getkey ();
617 if (!c) {
618 *memptr = -1;
619 return;
622 tty_putnch (proc->tty, c);
624 *memptr = c;
626 return;
629 /* blocking - clasical mode */
630 for (;;) {
631 if (!proc)
632 return;
634 if (proc->tty != currtty)
635 return;
637 char c = getkey ();
639 if (c) {
640 if (i > 0 && c != '\b')
641 tty_write (proc->tty, &c, 1);
643 if (c == '\n')
644 break;
645 else if (i == 1)
646 s = c;
648 if (c == '\b') {
649 if (i > 1) {
650 i --;
651 tty_write (proc->tty, "\b", 1);
653 } else
654 i ++;
658 *memptr = (int) s;
661 void sys_threadopen (struct regs *r)
663 void *ptr = (void *) r->ebx;
665 unsigned m = *SYSV_THREADOPEN;
667 *SYSV_THREADOPEN = proc_thread_create (ptr, (void *) m);
670 void sys_threadclose (struct regs *r)
672 proc_t *proc = proc_find (_curr_task);
674 if (!proc)
675 return;
677 task_t *task = _curr_task;
679 /* free child process thread */
680 *SYSV_THREADCLOSE = proc_thread_destroy (proc, task);
682 task = proc->tty->task;
684 if (int_disable ())
685 longjmp (task->state, 1);
686 else
687 for (;;)
688 schedule ();
691 void sys_ioctl (struct regs *r)
693 void *s = (void *) r->ebx;
694 unsigned id = r->ecx;
695 int l = r->edx;
697 *SYSV_IOCTL = ioctl_call (id, s, l);
700 void sys_getpid (struct regs *r)
702 proc_t *proc = proc_find (_curr_task);
704 if (!proc)
705 return;
707 r->eax = (int) &proc->pid;
710 void sys_lseek (struct regs *r)
712 int fd = r->ebx;
713 long offset = r->ecx;
714 int whence = r->edx;
716 *SYSV_LSEEK = lseek (fd, offset, whence);
719 void sys_pipe (struct regs *r)
721 int *p = (int *) r->ebx;
723 int ret = pipe (p);
725 r->eax = (int) &ret;
728 void sys_creat (struct regs *r)
730 char *file = (char *) r->ebx;
731 unsigned mode = r->ecx; /* TODO: mode */
733 int ret = -1;
735 if (file) {
736 if (mode == O_CREAT)
737 ret = (touch (file) == 1) ? 0 : -1;
738 } else
739 errno_set (EFAULT);
741 r->eax = (int) &ret;
744 void sys_mkdir (struct regs *r)
746 char *dir = (char *) r->ebx;
747 unsigned mode = r->ecx; /* TODO: mode */
749 int ret = -1;
751 if (dir) {
752 if (mode)
753 ret = (mkdir (dir) == 1) ? 0 : -1;
754 } else
755 errno_set (EFAULT);
757 r->eax = (int) &ret;
760 void sys_rmdir (struct regs *r)
762 char *dir = (char *) r->ebx;
764 int ret = -1;
766 if (dir) {
767 ret = (rm (dir) == 1) ? 0 : -1;
768 } else
769 errno_set (EFAULT);
771 r->eax = (int) &ret;
774 void sys_sndopen (struct regs *r)
776 snd_cfg_t *cfg = (snd_cfg_t *) r->ebx;
778 int ret = 0;
780 if (!cfg)
781 r->eax = (int) &ret;
782 else
783 r->eax = (int) audio_open (cfg);
786 void sys_sndclose (struct regs *r)
788 snd_audio_t *aud = (snd_audio_t *) r->ebx;
790 int ret = -1;
792 if (!aud)
793 r->eax = (int) &ret;
794 else
795 r->eax = (int) audio_close (aud);
798 void sys_sndwrite (struct regs *r)
800 snd_audio_t *aud = (snd_audio_t *) r->ebx;
801 char *buf = (char *) r->ecx;
802 unsigned len = (unsigned) r->edx;
804 int ret = -1;
806 if (!aud)
807 r->eax = (int) &ret;
808 else
809 r->eax = (int) audio_write (aud, buf, len);
812 void sys_remove (struct regs *r)
814 char *file = (char *) r->ebx;
816 int ret = -1;
818 if (file) {
819 ret = (vfs_rm (file, strlen (file)) == 1) ? 0 : -1;
820 } else
821 errno_set (EFAULT);
823 r->eax = (int) &ret;
826 void sys_rename (struct regs *r)
828 char *file = (char *) r->ebx;
829 char *file2 = (char *) r->ecx;
831 int ret = 0;
833 if (file) {
834 if (cp (file, file2) != 1)
835 ret = -1;
837 if (!ret && rm (file) != 1)
838 ret = -1;
839 } else
840 errno_set (EFAULT);
842 r->eax = (int) &ret;
845 void syscall_handler (struct regs *r)
847 switch (r->eax) {
848 case 1:
849 return sys_exit (r);
850 case 2:
851 return sys_getch (r);
852 case 3:
853 return sys_sleep (r);
854 case 4:
855 return sys_putch (r);
856 case 5:
857 return sys_color (r);
858 case 6:
859 return sys_cls (r);
860 case 7:
861 return sys_getkey (r);
862 case 8:
863 return sys_gotoxy (r);
864 case 9:
865 return sys_fork (r);
866 case 10:
867 return sys_schedule (r);
868 case 11:
869 return sys_write (r);
870 case 12:
871 return sys_socket (r);
872 case 13:
873 return sys_connect (r);
874 case 14:
875 return sys_malloc (r);
876 case 15:
877 return sys_send (r);
878 case 16:
879 return sys_recv (r);
880 case 17:
881 return sys_close (r);
882 case 18:
883 return sys_open (r);
884 case 19:
885 return sys_pcspk (r);
886 case 20:
887 return sys_usleep (r);
888 case 21:
889 return sys_read (r);
890 case 22:
891 return sys_time (r);
892 case 23:
893 return sys_system (r);
894 case 24:
895 return sys_chdir (r);
896 case 25:
897 return sys_getdir (r);
898 case 26:
899 return sys_procarg (r);
900 case 27:
901 return sys_signal (r);
902 case 28:
903 return sys_mount (r);
904 case 29:
905 return sys_kputs (r);
906 case 30:
907 return sys_bind (r);
908 case 31:
909 return sys_listen (r);
910 case 32:
911 return sys_accept (r);
912 case 33:
913 return sys_fcntl (r);
914 case 34:
915 return sys_gvgafb (r);
916 case 35:
917 return sys_gcls (r);
918 case 36:
919 return sys_gfbswap (r);
920 case 37:
921 return sys_rs232read (r);
922 case 38:
923 return sys_rs232write (r);
924 case 39:
925 return sys_gttyexit (r);
926 case 40:
927 return sys_gexit (r);
928 case 41:
929 return sys_gttyinit (r);
930 case 42:
931 return sys_getenv (r);
932 case 43:
933 return sys_free (r);
934 case 44:
935 return sys_realloc (r);
936 case 45:
937 return sys_gethostbyname (r);
938 case 46:
939 return sys_vfsent (r);
940 case 47:
941 return sys_sendto (r);
942 case 48:
943 return sys_recvfrom (r);
944 case 49:
945 return sys_getchar (r);
946 case 50:
947 return sys_threadopen (r);
948 case 51:
949 return sys_threadclose (r);
950 case 52:
951 return sys_ioctl (r);
952 case 53:
953 return sys_getpid (r);
954 case 54:
955 return sys_lseek (r);
956 case 55:
957 return sys_pipe (r);
958 case 56:
959 return sys_creat (r);
960 case 57:
961 return sys_mkdir (r);
962 case 58:
963 return sys_rmdir (r);
964 case 59:
965 return sys_sndopen (r);
966 case 60:
967 return sys_sndclose (r);
968 case 61:
969 return sys_sndwrite (r);
970 case 62:
971 return sys_remove (r);
972 case 63:
973 return sys_rename (r);