All user-space apps ware moved to 8MB virtual address address (link.ld changes);...
[ZeXOS.git] / kernel / arch / i386 / syscall.c
blobee1e0cf9dc074bc4e822d58338abf06150d8a139
1 /*
2 * ZeX/OS
3 * Copyright (C) 2007 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
4 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
5 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
6 * Copyright (C) 2009 Martin 'povik' Poviser (martin.povik@gmail.com)
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include <system.h>
24 #include <arch/io.h>
25 #include <string.h>
26 #include <tty.h>
27 #include <proc.h>
28 #include <net/socket.h>
29 #include <file.h>
30 #include <signal.h>
31 #include <module.h>
32 #include <rs232.h>
33 #include <ioctl.h>
34 #include <fd.h>
35 #include <paging.h>
36 #include <pipe.h>
37 #include <errno.h>
39 extern task_t *_curr_task;
41 void sys_exit (struct regs *r)
43 task_t *taskc = task_find (0);
45 if (!taskc)
46 return;
48 page_dir_switch (taskc->page_cover->page_dir);
50 proc_t *proc = proc_find (_curr_task);
52 if (!proc)
53 return;
55 task_t *task = proc->tty->task;
57 proc->pid = 0;
59 if (int_disable ())
60 longjmp (task->state, 1);
61 else
62 while (1)
63 schedule ();
66 void sys_getch (struct regs *r)
68 proc_t *proc = proc_find (_curr_task);
70 if (!proc)
71 return;
73 if (proc->tty != currtty)
74 return;
76 unsigned char c = (unsigned char) getkey ();
78 if (c)
79 setkey (0);
81 //r->eax = (unsigned) &c;
83 unsigned char *memptr = (unsigned char *) 0x905d;
84 *memptr = c;
87 extern unsigned long timer_ticks;
88 void sys_sleep (struct regs *r)
90 unsigned long timer_start = timer_ticks + ((unsigned) r->ebx * 1000);
92 while (timer_start > timer_ticks)
93 schedule ();
96 void sys_putch (struct regs *r)
98 task_t *taskc = task_find (0);
100 if (!taskc)
101 return;
103 //page_dir_switch (taskc->page_cover->page_dir);
105 proc_t *proc = proc_find (_curr_task);
107 if (!proc)
108 return;
110 int c = r->ebx;
112 tty_putnch (proc->tty, c);
114 //page_dir_switch (proc->task->page_cover->page_dir);
117 void sys_color (struct regs *r)
119 video_color (r->ebx, r->ecx);
123 void sys_cls (struct regs *r)
125 proc_t *proc = proc_find (_curr_task);
127 if (!proc)
128 return;
130 if (proc->tty != currtty)
131 return;
133 /* NOTE: Why we should disable interrupts ? Nobody know, but works better */
134 if (int_disable ()) {
135 tty_cls (proc->tty);
136 int_enable ();
140 extern unsigned char scancode;
141 void sys_getkey (struct regs *r)
143 proc_t *proc = proc_find (_curr_task);
145 if (!proc)
146 return;
148 if (proc->tty != currtty)
149 return;
151 unsigned char c = (unsigned char) scancode;
153 scancode = 0;
155 unsigned char *memptr = (unsigned char *) 0x9060;
156 *memptr = c;
159 void sys_gotoxy (struct regs *r)
161 proc_t *proc = proc_find (_curr_task);
163 if (!proc)
164 return;
166 tty_gotoxy (proc->tty, r->ebx, r->ecx);
169 void sys_fork (struct regs *r)
171 unsigned short *where;
172 unsigned char c = (unsigned char) fork ();
174 unsigned short *memptr = (unsigned short *) 0x9000;
175 where = memptr;
176 *where = c;
179 void sys_schedule (struct regs *r)
181 schedule ();
184 extern kbd_quaue kbd_q;
185 void sys_write (struct regs *r)
187 unsigned len = r->ecx;
188 unsigned fd = r->edx;
190 unsigned char *buf = (unsigned char *) r->ebx;
192 if (!buf)
193 return;
195 // kprintf ("#buf: 0x%x / '%s'\n", buf, buf);
197 /*char buf[len+1];
198 if (!memcpy_to_user (&buf, (char *) r->ebx, len))
199 return;*/
201 int ret = 0;
203 proc_t *proc = 0;
204 char *mem = 0;
206 switch (fd) {
207 case 0:
208 proc = proc_find (_curr_task);
210 if (!proc) {
211 ret = -1;
212 break;
215 //if (buf >= proc->data && buf < (proc->data+proc->data_off)) {
216 // kprintf ("Je to staticky retezec :) - 0x%x - '%s'\n", buf+proc->code, buf+proc->code);
219 mem = (char *) buf;//vmem_proc_check (proc, buf);
221 //if (proc->tty != currtty)
222 // return;
224 //printf ("data: 0x%x | 0x%x\n", buf, proc->data);
226 //if (!memtest_data (buf, (void *) proc->data, proc->data_off))
227 tty_write (proc->tty, (char *) mem, len);
228 //else {
229 // tty_write (proc->tty, (char *) buf+proc->code, len);
231 ret = len;
232 //timer_wait (5000);
234 break;
235 case 1:
236 proc = proc_find (_curr_task);
238 if (!proc) {
239 ret = -1;
240 break;
243 if (len > KBD_MAX_QUAUE)
244 len = KBD_MAX_QUAUE;
246 mem = (char *) buf;
248 int i = 0;
249 for (i = len; i >= 0; i --)
250 setkey (buf[i]);
252 mem[len] = '\0';
254 ret = len;
255 break;
256 default:
257 mem = (char *) buf;
258 //printf ("hehe: 0x%x / '%s' len: %d\n", mem, mem, len);
259 ret = write (fd, (char *) mem, len);
260 break;
263 int *memptr = (int *) 0x9000;
264 *memptr = ret;
267 void sys_socket (struct regs *r)
269 int ret = socket (r->ebx, r->ecx, r->edx);
271 int *memptr = (int *) 0x9000;
272 *memptr = ret;
275 void sys_connect (struct regs *r)
277 sockaddr *addr = (sockaddr *) r->ebx;
279 int ret = connect (r->ecx, addr, r->edx);
281 int *memptr = (int *) 0x9000;
282 *memptr = ret;
285 void sys_malloc (struct regs *r)
287 proc_t *proc = proc_find (_curr_task);
289 paging_disable ();
290 r->eax = (unsigned) umalloc (proc, (int) r->ebx);
291 paging_enable ();
293 DPRINT ("malloc (): 0x%x", r->eax);
296 void sys_send (struct regs *r)
298 /* char msg[r->edx+1];
299 if (!memcpy_to_user (&msg, (char *) r->ebx, r->edx))
300 return;*/
302 int ret = send ((int) r->ecx, (char *) r->ebx, (unsigned) r->edx, 0);
304 int *memptr = (int *) 0x9000;
305 *memptr = ret;
308 void sys_recv (struct regs *r)
310 unsigned char *msg = (unsigned char *) r->ebx;
311 unsigned size = (unsigned) r->edx;
312 int fd = (int) r->ecx;
314 int ret = recv (fd, (char *) msg, size, 0);
316 /* if (ret > 0) {
317 printf ("recv> r->ebx: %d, r->edx: %u, ret: %d\n", (int) r->ecx, (unsigned) r->edx, ret);
320 //printf ("recv> r->ebx: %d, r->edx: %u, ret: %d\n", (int) r->ecx, (unsigned) r->edx, ret);
322 int *memptr = (int *) 0x9030;
323 *memptr = ret;
326 void sys_close (struct regs *r)
328 close (r->ebx);
331 void sys_open (struct regs *r)
333 unsigned char *pathname = (unsigned char *) r->ebx;
335 int ret = open ((char *) pathname, (unsigned) r->ecx);
337 // printf ("%d = sys_open (%s, %u)\n", ret, (char *) pathname, (unsigned) r->ecx);
339 int *memptr = (int *) 0x9000;
340 *memptr = ret;
343 void sys_pcspk (struct regs *r)
345 dev_t *dev = dev_find ("/dev/pcspk");
347 if (dev)
348 dev->handler (DEV_ACT_PLAY, (unsigned) r->ebx);
351 void sys_usleep (struct regs *r)
353 //unsigned long timer_start = timer_ticks + ((unsigned) r->ebx);
355 //while (timer_start > timer_ticks)
356 // schedule ();
357 usleep ((unsigned) r->ebx);
360 void sys_read (struct regs *r)
362 unsigned fd = r->ecx;
363 unsigned len = r->edx;
365 unsigned char *buf = (unsigned char *) r->ebx;
367 int ret = 0;
369 proc_t *proc = 0;
371 switch (fd) {
372 case 0:
373 break;
374 case 1:
375 proc = proc_find (_curr_task);
377 if (!proc)
378 break;
380 //if (proc->tty != currtty)
381 // return;
383 ret = tty_read (proc->tty, (char *) buf, len);
384 break;
385 default:
386 ret = read (fd, (char *) buf, len);
387 break;
390 int *memptr = (int *) 0x9000;
391 *memptr = ret;
394 void sys_time (struct regs *r)
396 time_t *memptr = (time_t *) 0x9005;
398 tm *t = rtc_getcurrtime ();
400 if (t)
401 *memptr = (time_t) t->__tm_gmtoff;
404 void sys_system (struct regs *r)
406 task_t *task = task_find (0);
408 if (!task)
409 return;
411 proc_t *proc = proc_find (_curr_task);
413 if (!proc)
414 return;
416 task_t *oldtask = _curr_task;
418 page_dir_switch (task->page_cover->page_dir);
420 unsigned char *cmd = (unsigned char *) r->ebx;
422 command_parser ((char *) cmd, strlen (cmd));
424 page_dir_switch (oldtask->page_cover->page_dir);
426 /* needed for correct scheduling (when you execute new process, _curr_task is tasj of current tty) */
427 _curr_task = oldtask;
429 schedule ();
433 void sys_chdir (struct regs *r)
435 unsigned char *dir = (unsigned char *) r->ebx;
437 cd ((char *) dir);
440 void sys_getdir (struct regs *r)
442 r->eax = (unsigned) vfs_dirent ();
445 void sys_procarg (struct regs *r)
447 proc_t *proc = proc_find (_curr_task);
449 if (!proc)
450 return;
452 switch (r->ecx) {
453 case 0:
454 r->eax = (unsigned) proc->argv;
455 break;
456 case 1:
457 r->eax = (unsigned) proc->argc;
458 break;
459 default:
460 r->eax = 0;
464 void sys_signal (struct regs *r)
466 signal (r->ebx, (sighandler_t) r->ecx);
469 void sys_mount (struct regs *r)
471 partition_t *p = partition_find ((char *) r->ebx);
473 if (p) {
474 mount (p, "", (char *) r->ecx);
475 r->eax = 1;
476 } else
477 r->eax = 0;
480 void sys_kputs (struct regs *r)
482 int_disable ();
484 module_t *kmod = module_find (_curr_task);
486 if (!kmod)
487 return;
489 if (kmod->task != _curr_task)
490 return;
492 unsigned char *buf = (unsigned char *) r->ebx;
493 kprintf (buf);
495 //kprintf ("yeah, sys_kputs: '%s' '0x%x'\n", buf, buf);
497 int_enable ();
500 void sys_bind (struct regs *r)
502 int ret = bind (r->ecx, (sockaddr *) r->ebx, r->edx);
504 int *memptr = (int *) 0x9000;
505 *memptr = ret;
508 void sys_listen (struct regs *r)
510 int ret = listen (r->ebx, r->ecx);
512 int *memptr = (int *) 0x9000;
513 *memptr = ret;
516 void sys_accept (struct regs *r)
518 int ret = accept (r->ecx, r->ebx, r->edx);
520 int *memptr = (int *) 0x9000;
521 *memptr = ret;
524 void sys_fcntl (struct regs *r)
526 int ret = fcntl (r->ebx, r->ecx, r->edx);
528 int *memptr = (int *) 0x9000;
529 *memptr = ret;
532 void sys_gvgafb (struct regs *r)
534 proc_t *proc = proc_find (_curr_task);
536 if (!proc)
537 return;
539 if (vgagui != 2) {
540 printf ("Please start this program in graphical VESA mode\n");
541 sys_exit (r);
542 return;
545 unsigned *memptr = (unsigned *) 0x900a;
546 *memptr = (unsigned) init_vgafb ();
549 void sys_gcls (struct regs *r)
551 //gcls (r->ebx);
554 void sys_gfbswap (struct regs *r)
556 proc_t *proc = proc_find (_curr_task);
558 if (!proc)
559 return;
561 if (proc->tty == currtty)
562 video_gfx_fbswap ();
564 schedule ();
567 void sys_rs232read (struct regs *r)
569 char *memptr = (char *) 0x9000;
570 *memptr = rs232_read ();
573 void sys_rs232write (struct regs *r)
575 rs232_write ((char) r->ebx);
578 void sys_gttyexit (struct regs *r)
580 proc_t *proc = proc_find (_curr_task);
582 if (!proc)
583 return;
585 tty_change (proc->tty);
588 void sys_gexit (struct regs *r)
590 video_gfx_exit ();
593 extern unsigned char vgagui;
594 extern tty_t *gtty;
595 void sys_gttyinit (struct regs *r)
597 tty_t *tty = gtty_init ();
599 if (!tty)
600 return;
602 r->eax = (unsigned) &tty->screen;
605 void sys_free (struct regs *r)
607 proc_t *proc = proc_find (_curr_task);
609 paging_disable ();
611 ufree (proc, (void *) r->ebx);
613 DPRINT ("free (): 0x%x", r->ebx);
615 paging_enable ();
618 void sys_realloc (struct regs *r)
620 proc_t *proc = proc_find (_curr_task);
622 paging_disable ();
624 r->eax = (unsigned) urealloc (proc, (void *) r->ebx, (size_t) r->ecx);
626 DPRINT ("realloc (): 0x%x", r->eax);
628 paging_enable ();
631 void sys_gethostbyname (struct regs *r)
633 char *buf = (char *) r->ebx;
635 if (!buf) {
636 r->eax = 0;
637 return;
640 r->eax = (unsigned) gethostbyname (buf);
643 void sys_procmap (struct regs *r)
645 proc_t *proc = proc_find (_curr_task);
647 if (!proc)
648 return;
650 printf ("LOL: '%s'\n", proc->data-0x1000);
651 //proc_vmem_map (proc);
654 void sys_sendto (struct regs *r)
656 /* HACK: bleeh, there is problem with fourth argument,
657 so we need to use another way to getting address */
658 unsigned *addr = (unsigned *) 0x9020;
660 sockaddr_in *to = (sockaddr_in *) *addr;
662 int ret = sendto ((int) r->ecx, (char *) r->ebx, (unsigned) r->edx, 0, to, 0);
664 int *memptr = (int *) 0x9000;
665 *memptr = ret;
668 void sys_recvfrom (struct regs *r)
670 unsigned char *msg = (unsigned char *) r->ebx;
672 /* HACK: bleeh, there is problem with fourth argument,
673 so we need to use another way to getting address */
674 unsigned *addr = (unsigned *) 0x9010;
676 sockaddr_in *from = (sockaddr_in *) *addr;
678 int ret = recvfrom ((int) r->ecx, (char *) msg, (unsigned) r->edx, 0, from, 0);
680 int *memptr = (int *) 0x9000;
681 *memptr = ret;
684 void sys_getchar (struct regs *r)
686 proc_t *proc = proc_find (_curr_task);
688 int i = 1;
689 unsigned char s = '\n';
691 int *memptr = (int *) 0x9064;
693 /* non-blocking mode */
694 if (stdin->flags & O_NONBLOCK) {
695 if (!proc)
696 return;
698 if (proc->tty != currtty)
699 return;
701 unsigned char c = getkey ();
703 if (!c) {
704 *memptr = -1;
705 return;
708 tty_putnch (proc->tty, c);
710 *memptr = c;
712 return;
715 /* blocking - clasical mode */
716 while (1) {
717 if (!proc)
718 return;
720 if (proc->tty != currtty)
721 return;
723 char c = getkey ();
725 if (c) {
726 if (i > 0 && c != '\b')
727 tty_write (proc->tty, &c, 1);
729 if (c == '\n')
730 break;
731 else if (i == 1)
732 s = c;
734 if (c == '\b') {
735 if (i > 1) {
736 i --;
737 tty_write (proc->tty, "\b", 1);
739 } else
740 i ++;
744 *memptr = (int) s;
747 void sys_threadopen (struct regs *r)
749 void *ptr = (void *) r->ebx;
751 unsigned *memptr = (unsigned *) 0x9050;
753 unsigned ret = proc_thread_create (ptr, (void *) *memptr);
755 *memptr = ret;
758 void sys_threadclose (struct regs *r)
760 proc_t *proc = proc_find (_curr_task);
762 if (!proc)
763 return;
765 unsigned *memptr = (unsigned *) 0x9050;
767 task_t *task = _curr_task;
769 /* free child process thread */
770 *memptr = proc_thread_destroy (proc, task);
772 task = proc->tty->task;
774 if (int_disable ())
775 longjmp (task->state, 1);
776 else
777 while (1)
778 schedule ();
782 void sys_ioctl (struct regs *r)
784 void *s = (void *) r->ebx;
785 unsigned id = r->ecx;
786 int l = r->edx;
788 int ret = ioctl_call (id, s, l);
790 r->eax = (int) &ret;
793 void sys_getpid (struct regs *r)
795 proc_t *proc = proc_find (_curr_task);
797 if (!proc)
798 return;
800 r->eax = (int) &proc->pid;
803 void sys_lseek (struct regs *r)
805 int fd = r->ebx;
806 long offset = r->ecx;
807 int whence = r->edx;
809 long ret = lseek (fd, offset, whence);
811 long *memptr = (long *) 0x9006;
813 *memptr = ret;
816 void sys_pipe (struct regs *r)
818 int *p = (int *) r->ebx;
820 int ret = pipe (p);
822 r->eax = (int) &ret;
825 void sys_creat (struct regs *r)
827 char *file = (char *) r->ebx;
828 unsigned mode = r->ecx; /* TODO: mode */
830 int ret = -1;
832 if (file) {
833 if (mode == O_CREAT)
834 ret = (touch (file) == 1) ? 0 : -1;
835 } else
836 errno_set (EFAULT);
838 r->eax = (int) &ret;
841 void sys_mkdir (struct regs *r)
843 char *dir = (char *) r->ebx;
844 unsigned mode = r->ecx; /* TODO: mode */
846 int ret = -1;
848 if (dir) {
849 if (mode)
850 ret = (mkdir (dir) == 1) ? 0 : -1;
851 } else
852 errno_set (EFAULT);
854 r->eax = (int) &ret;
857 void sys_rmdir (struct regs *r)
859 char *dir = (char *) r->ebx;
861 int ret = -1;
863 if (dir) {
864 ret = (rm (dir) == 1) ? 0 : -1;
865 } else
866 errno_set (EFAULT);
868 r->eax = (int) &ret;
871 void syscall_handler (struct regs *r)
873 switch (r->eax) {
874 case 1:
875 return sys_exit (r);
876 case 2:
877 return sys_getch (r);
878 case 3:
879 return sys_sleep (r);
880 case 4:
881 return sys_putch (r);
882 case 5:
883 return sys_color (r);
884 case 6:
885 return sys_cls (r);
886 case 7:
887 return sys_getkey (r);
888 case 8:
889 return sys_gotoxy (r);
890 case 9:
891 return sys_fork (r);
892 case 10:
893 return sys_schedule (r);
894 case 11:
895 return sys_write (r);
896 case 12:
897 return sys_socket (r);
898 case 13:
899 return sys_connect (r);
900 case 14:
901 return sys_malloc (r);
902 case 15:
903 return sys_send (r);
904 case 16:
905 return sys_recv (r);
906 case 17:
907 return sys_close (r);
908 case 18:
909 return sys_open (r);
910 case 19:
911 return sys_pcspk (r);
912 case 20:
913 return sys_usleep (r);
914 case 21:
915 return sys_read (r);
916 case 22:
917 return sys_time (r);
918 case 23:
919 return sys_system (r);
920 case 24:
921 return sys_chdir (r);
922 case 25:
923 return sys_getdir (r);
924 case 26:
925 return sys_procarg (r);
926 case 27:
927 return sys_signal (r);
928 case 28:
929 return sys_mount (r);
930 case 29:
931 return sys_kputs (r);
932 case 30:
933 return sys_bind (r);
934 case 31:
935 return sys_listen (r);
936 case 32:
937 return sys_accept (r);
938 case 33:
939 return sys_fcntl (r);
940 case 34:
941 return sys_gvgafb (r);
942 case 35:
943 return sys_gcls (r);
944 case 36:
945 return sys_gfbswap (r);
946 case 37:
947 return sys_rs232read (r);
948 case 38:
949 return sys_rs232write (r);
950 case 39:
951 return sys_gttyexit (r);
952 case 40:
953 return sys_gexit (r);
954 case 41:
955 return sys_gttyinit (r);
956 case 42:
957 return;
958 case 43:
959 return sys_free (r);
960 case 44:
961 return sys_realloc (r);
962 case 45:
963 return sys_gethostbyname (r);
964 case 46:
965 return sys_procmap (r);
966 case 47:
967 return sys_sendto (r);
968 case 48:
969 return sys_recvfrom (r);
970 case 49:
971 return sys_getchar (r);
972 case 50:
973 return sys_threadopen (r);
974 case 51:
975 return sys_threadclose (r);
976 case 52:
977 return sys_ioctl (r);
978 case 53:
979 return sys_getpid (r);
980 case 54:
981 return sys_lseek (r);
982 case 55:
983 return sys_pipe (r);
984 case 56:
985 return sys_creat (r);
986 case 57:
987 return sys_mkdir (r);
988 case 58:
989 return sys_rmdir (r);