Added pipe() syscall; Fixed some memleaks;
[ZeXOS.git] / kernel / arch / i386 / syscall.c
blobabad088297476e2d0d395b2fca9a39a30fc83738
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)
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include <system.h>
23 #include <arch/io.h>
24 #include <string.h>
25 #include <tty.h>
26 #include <proc.h>
27 #include <net/socket.h>
28 #include <file.h>
29 #include <signal.h>
30 #include <module.h>
31 #include <rs232.h>
32 #include <ioctl.h>
33 #include <fd.h>
34 #include <paging.h>
35 #include <pipe.h>
37 extern task_t *_curr_task;
39 void sys_exit (struct regs *r)
41 task_t *taskc = task_find (0);
43 if (!taskc)
44 return;
46 page_dir_switch (taskc->page_cover->page_dir);
48 proc_t *proc = proc_find (_curr_task);
50 if (!proc)
51 return;
53 task_t *task = proc->tty->task;
55 proc->pid = 0;
57 if (int_disable ())
58 longjmp (task->state, 1);
59 else
60 while (1)
61 schedule ();
64 void sys_getch (struct regs *r)
66 proc_t *proc = proc_find (_curr_task);
68 if (!proc)
69 return;
71 if (proc->tty != currtty)
72 return;
74 unsigned char c = (unsigned char) getkey ();
76 if (c)
77 setkey (0);
79 //r->eax = (unsigned) &c;
81 unsigned char *memptr = (unsigned char *) 0x905d;
82 *memptr = c;
85 extern unsigned long timer_ticks;
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 task_t *taskc = task_find (0);
98 if (!taskc)
99 return;
101 //page_dir_switch (taskc->page_cover->page_dir);
103 proc_t *proc = proc_find (_curr_task);
105 if (!proc)
106 return;
108 int c = r->ebx;
110 tty_putnch (proc->tty, c);
112 //page_dir_switch (proc->task->page_cover->page_dir);
115 void sys_color (struct regs *r)
117 video_color (r->ebx, r->ecx);
121 void sys_cls (struct regs *r)
123 proc_t *proc = proc_find (_curr_task);
125 if (!proc)
126 return;
128 if (proc->tty != currtty)
129 return;
131 /* NOTE: Why we should disable interrupts ? Nobody know, but works better */
132 if (int_disable ()) {
133 tty_cls (proc->tty);
134 int_enable ();
138 extern unsigned char scancode;
139 void sys_getkey (struct regs *r)
141 proc_t *proc = proc_find (_curr_task);
143 if (!proc)
144 return;
146 if (proc->tty != currtty)
147 return;
149 unsigned char c = (unsigned char) scancode;
151 scancode = 0;
153 unsigned char *memptr = (unsigned char *) 0x9060;
154 *memptr = c;
157 void sys_gotoxy (struct regs *r)
159 proc_t *proc = proc_find (_curr_task);
161 if (!proc)
162 return;
164 tty_gotoxy (proc->tty, r->ebx, r->ecx);
167 void sys_fork (struct regs *r)
169 unsigned short *where;
170 unsigned char c = (unsigned char) fork ();
172 unsigned short *memptr = (unsigned short *) 0x9000;
173 where = memptr;
174 *where = c;
177 void sys_schedule (struct regs *r)
179 schedule ();
182 extern kbd_quaue kbd_q;
183 void sys_write (struct regs *r)
185 unsigned len = r->ecx;
186 unsigned fd = r->edx;
188 unsigned char *buf = (unsigned char *) r->ebx;
190 if (!buf)
191 return;
193 // kprintf ("#buf: 0x%x / '%s'\n", buf, buf);
195 /*char buf[len+1];
196 if (!memcpy_to_user (&buf, (char *) r->ebx, len))
197 return;*/
199 int ret = 0;
201 proc_t *proc = 0;
202 char *mem = 0;
204 switch (fd) {
205 case 0:
206 proc = proc_find (_curr_task);
208 if (!proc) {
209 ret = -1;
210 break;
213 //if (buf >= proc->data && buf < (proc->data+proc->data_off)) {
214 // kprintf ("Je to staticky retezec :) - 0x%x - '%s'\n", buf+proc->code, buf+proc->code);
217 mem = (char *) buf;//vmem_proc_check (proc, buf);
219 //if (proc->tty != currtty)
220 // return;
222 //printf ("data: 0x%x | 0x%x\n", buf, proc->data);
224 //if (!memtest_data (buf, (void *) proc->data, proc->data_off))
225 tty_write (proc->tty, (char *) mem, len);
226 //else {
227 // tty_write (proc->tty, (char *) buf+proc->code, len);
229 ret = len;
230 //timer_wait (5000);
232 break;
233 case 1:
234 proc = proc_find (_curr_task);
236 if (!proc) {
237 ret = -1;
238 break;
241 if (len > KBD_MAX_QUAUE)
242 len = KBD_MAX_QUAUE;
244 mem = (char *) buf;
246 int i = 0;
247 for (i = len; i >= 0; i --)
248 setkey (buf[i]);
250 mem[len] = '\0';
252 ret = len;
253 break;
254 default:
255 mem = (char *) buf; //vmem_proc_check (proc, buf);
256 //printf ("hehe: 0x%x / '%s' len: %d\n", mem, mem, len);
257 ret = write (fd, (char *) mem, len);
258 break;
261 int *where;
262 int *memptr = (int *) 0x9000;
263 where = memptr;
264 *where = ret;
267 void sys_socket (struct regs *r)
269 int ret = socket (r->ebx, r->ecx, r->edx);
271 int *where;
272 int *memptr = (int *) 0x9000;
273 where = memptr;
274 *where = ret;
277 void sys_connect (struct regs *r)
279 sockaddr *addr = (sockaddr *) r->ebx;
281 int ret = connect (r->ecx, addr, r->edx);
283 int *where;
284 int *memptr = (int *) 0x9000;
285 where = memptr;
286 *where = ret;
289 void sys_malloc (struct regs *r)
291 paging_disable ();
292 r->eax = (unsigned) kmalloc ((int) r->ebx);
293 paging_enable ();
295 DPRINT ("malloc (): 0x%x\n", r->eax);
298 void sys_send (struct regs *r)
300 /* char msg[r->edx+1];
301 if (!memcpy_to_user (&msg, (char *) r->ebx, r->edx))
302 return;*/
304 int ret = send ((int) r->ecx, (char *) r->ebx, (unsigned) r->edx, 0);
306 int *where;
307 int *memptr = (int *) 0x9040;
308 where = memptr;
309 *where = ret;
312 void sys_recv (struct regs *r)
314 unsigned char *msg = (unsigned char *) r->ebx;
315 unsigned size = (unsigned) r->edx;
316 int fd = (int) r->ecx;
318 int ret = recv (fd, (char *) msg, size, 0);
320 /* if (ret > 0) {
321 printf ("recv> r->ebx: %d, r->edx: %u, ret: %d\n", (int) r->ecx, (unsigned) r->edx, ret);
324 //printf ("recv> r->ebx: %d, r->edx: %u, ret: %d\n", (int) r->ecx, (unsigned) r->edx, ret);
326 int *memptr = (int *) 0x9030;
327 *memptr = ret;
330 void sys_close (struct regs *r)
332 close (r->ebx);
335 void sys_open (struct regs *r)
337 unsigned char *pathname = (unsigned char *) r->ebx;
339 int ret = open ((char *) pathname, (unsigned) r->ecx);
341 // printf ("%d = sys_open (%s, %u)\n", ret, (char *) pathname, (unsigned) r->ecx);
343 int *where;
344 int *memptr = (int *) 0x9000;
345 where = memptr;
346 *where = ret;
349 void sys_pcspk (struct regs *r)
351 dev_t *dev = dev_find ("/dev/pcspk");
353 if (dev)
354 dev->handler (DEV_ACT_PLAY, (unsigned) r->ebx);
357 void sys_usleep (struct regs *r)
359 //unsigned long timer_start = timer_ticks + ((unsigned) r->ebx);
361 //while (timer_start > timer_ticks)
362 // schedule ();
363 usleep ((unsigned) r->ebx);
366 void sys_read (struct regs *r)
368 unsigned fd = r->ecx;
369 unsigned len = r->edx;
371 unsigned char *buf = (unsigned char *) r->ebx;
373 int ret = 0;
375 proc_t *proc = 0;
377 switch (fd) {
378 case 0:
379 break;
380 case 1:
381 proc = proc_find (_curr_task);
383 if (!proc)
384 break;
386 //if (proc->tty != currtty)
387 // return;
389 ret = tty_read (proc->tty, (char *) buf, len);
390 break;
391 default:
392 ret = read (fd, (char *) buf, len);
393 break;
396 int *where;
397 int *memptr = (int *) 0x9000;
398 where = memptr;
399 *where = ret;
402 void sys_time (struct regs *r)
404 time_t *memptr = (time_t *) 0x9005;
406 tm *t = rtc_getcurrtime ();
408 if (t)
409 *memptr = (time_t) t->__tm_gmtoff;
412 void sys_system (struct regs *r)
414 task_t *task = task_find (0);
416 if (!task)
417 return;
419 proc_t *proc = proc_find (_curr_task);
421 if (!proc)
422 return;
424 task_t *oldtask = _curr_task;
426 page_dir_switch (task->page_cover->page_dir);
428 unsigned char *cmd = (unsigned char *) r->ebx;
430 command_parser ((char *) cmd, strlen (cmd));
432 page_dir_switch (oldtask->page_cover->page_dir);
434 /* needed for correct scheduling (when you execute new process, _curr_task is tasj of current tty) */
435 _curr_task = oldtask;
437 schedule ();
441 void sys_chdir (struct regs *r)
443 unsigned char *dir = (unsigned char *) r->ebx;
445 cd ((char *) dir);
448 void sys_getdir (struct regs *r)
450 r->eax = (unsigned) vfs_dirent ();
453 void sys_procarg (struct regs *r)
455 proc_t *proc = proc_find (_curr_task);
457 if (!proc)
458 return;
460 switch (r->ecx) {
461 case 0:
462 r->eax = (unsigned) proc->argv;
463 break;
464 case 1:
465 r->eax = (unsigned) proc->argc;
466 break;
467 default:
468 r->eax = 0;
472 void sys_signal (struct regs *r)
474 signal (r->ebx, (sighandler_t) r->ecx);
477 void sys_mount (struct regs *r)
479 partition_t *p = partition_find ((char *) r->ebx);
481 if (p) {
482 mount (p, "", (char *) r->ecx);
483 r->eax = 1;
484 } else
485 r->eax = 0;
488 void sys_kputs (struct regs *r)
490 int_disable ();
492 module_t *kmod = module_find (_curr_task);
494 if (!kmod)
495 return;
497 if (kmod->task != _curr_task)
498 return;
500 unsigned char *buf = (unsigned char *) r->ebx;
501 kprintf (buf);
503 //kprintf ("yeah, sys_kputs: '%s' '0x%x'\n", buf, buf);
505 int_enable ();
508 void sys_bind (struct regs *r)
510 int ret = bind (r->ecx, (sockaddr *) r->ebx, r->edx);
512 int *where;
513 int *memptr = (int *) 0x9000;
514 where = memptr;
515 *where = ret;
518 void sys_listen (struct regs *r)
520 int ret = listen (r->ebx, r->ecx);
522 int *where;
523 int *memptr = (int *) 0x9000;
524 where = memptr;
525 *where = ret;
528 void sys_accept (struct regs *r)
530 int ret = accept (r->ecx, r->ebx, r->edx);
532 int *where;
533 int *memptr = (int *) 0x9000;
534 where = memptr;
535 *where = ret;
538 void sys_fcntl (struct regs *r)
540 int ret = fcntl (r->ebx, r->ecx, r->edx);
542 int *where;
543 int *memptr = (int *) 0x9000;
544 where = memptr;
545 *where = ret;
548 void sys_gvgafb (struct regs *r)
550 proc_t *proc = proc_find (_curr_task);
552 if (!proc)
553 return;
555 if (vgagui != 2) {
556 printf ("Please start this program in graphical VESA mode\n");
557 sys_exit (r);
558 return;
561 unsigned p = (unsigned) palign ((void *) (proc->end - proc->start));
563 unsigned *memptr = (unsigned *) 0x900a;
564 *memptr = (unsigned) init_vgafb () + p;
567 void sys_gcls (struct regs *r)
569 //gcls (r->ebx);
572 void sys_gfbswap (struct regs *r)
574 proc_t *proc = proc_find (_curr_task);
576 if (!proc)
577 return;
579 if (proc->tty == currtty)
580 video_gfx_fbswap ();
582 schedule ();
585 void sys_rs232read (struct regs *r)
587 char *where;
588 char *memptr = (char *) 0x9000;
589 where = memptr;
590 *where = rs232_read ();
593 void sys_rs232write (struct regs *r)
595 rs232_write ((char) r->ebx);
598 void sys_gttyexit (struct regs *r)
600 proc_t *proc = proc_find (_curr_task);
602 if (!proc)
603 return;
605 tty_change (proc->tty);
608 void sys_gexit (struct regs *r)
610 video_gfx_exit ();
613 extern unsigned char vgagui;
614 extern tty_t *gtty;
615 void sys_gttyinit (struct regs *r)
617 tty_t *tty = gtty_init ();
619 if (!tty)
620 return;
622 r->eax = (unsigned) &tty->screen;
625 void sys_mkdir (struct regs *r)
627 unsigned char *dir = (unsigned char *) r->ebx;
629 mkdir ((char *) dir);
632 void sys_free (struct regs *r)
634 paging_disable ();
636 kfree ((void *) r->ebx);
638 DPRINT ("free (): 0x%x\n", r->ebx);
640 paging_enable ();
643 void sys_realloc (struct regs *r)
645 r->eax = (unsigned) krealloc ((void *) r->ebx, (size_t) r->ecx);
647 DPRINT ("realloc (): 0x%x\n", r->eax);
650 void sys_gethostbyname (struct regs *r)
652 char *buf = (char *) r->ebx;
654 if (!buf) {
655 r->eax = 0;
656 return;
659 r->eax = (unsigned) gethostbyname (buf);
662 void sys_procmap (struct regs *r)
664 proc_t *proc = proc_find (_curr_task);
666 if (!proc)
667 return;
669 printf ("LOL: '%s'\n", proc->data-0x1000);
670 //proc_vmem_map (proc);
673 void sys_sendto (struct regs *r)
675 /* HACK: bleeh, there is problem with fourth argument,
676 so we need to use another way to getting address */
677 unsigned *addr = (unsigned *) 0x9020;
679 sockaddr_in *to = (sockaddr_in *) *addr;
681 int ret = sendto ((int) r->ecx, (char *) r->ebx, (unsigned) r->edx, 0, to, 0);
683 int *where;
684 int *memptr = (int *) 0x9000;
685 where = memptr;
686 *where = ret;
689 void sys_recvfrom (struct regs *r)
691 unsigned char *msg = (unsigned char *) r->ebx;
693 /* HACK: bleeh, there is problem with fourth argument,
694 so we need to use another way to getting address */
695 unsigned *addr = (unsigned *) 0x9010;
697 sockaddr_in *from = (sockaddr_in *) *addr;
699 int ret = recvfrom ((int) r->ecx, (char *) msg, (unsigned) r->edx, 0, from, 0);
701 int *where;
702 int *memptr = (int *) 0x9000;
703 where = memptr;
704 *where = ret;
707 void sys_getchar (struct regs *r)
709 proc_t *proc = proc_find (_curr_task);
711 int i = 1;
712 unsigned char s = '\n';
714 int *memptr = (int *) 0x9064;
716 /* non-blocking mode */
717 if (stdin->flags & O_NONBLOCK) {
718 if (!proc)
719 return;
721 if (proc->tty != currtty)
722 return;
724 char c = getkey ();
726 if (!c) {
727 c = -1;
728 *memptr = c;
729 return;
732 tty_write (proc->tty, &c, 1);
734 *memptr = c;
736 return;
739 /* blocking - clasical mode */
740 while (1) {
741 if (!proc)
742 return;
744 if (proc->tty != currtty)
745 return;
747 char c = getkey ();
749 if (c) {
750 if (i > 0 && c != '\b')
751 tty_write (proc->tty, &c, 1);
753 if (c == '\n')
754 break;
755 else if (i == 1)
756 s = c;
758 if (c == '\b') {
759 if (i > 1) {
760 i --;
761 tty_write (proc->tty, "\b", 1);
763 } else
764 i ++;
768 *memptr = (int) s;
771 void sys_threadopen (struct regs *r)
773 void *ptr = (void *) r->ebx;
775 unsigned *memptr = (unsigned *) 0x9050;
777 unsigned ret = proc_thread_create (ptr, (void *) *memptr);
779 *memptr = ret;
782 void sys_threadclose (struct regs *r)
784 proc_t *proc = proc_find (_curr_task);
786 if (!proc)
787 return;
789 unsigned *memptr = (unsigned *) 0x9050;
791 task_t *task = _curr_task;
793 /* free child process thread */
794 *memptr = proc_thread_destroy (proc, task);
796 task = proc->tty->task;
798 if (int_disable ())
799 longjmp (task->state, 1);
800 else
801 while (1)
802 schedule ();
806 void sys_ioctl (struct regs *r)
808 void *s = (void *) r->ebx;
809 unsigned id = r->ecx;
810 int l = r->edx;
812 int ret = ioctl_call (id, s, l);
814 r->eax = (int) &ret;
817 void sys_getpid (struct regs *r)
819 proc_t *proc = proc_find (_curr_task);
821 if (!proc)
822 return;
824 r->eax = (int) &proc->pid;
827 void sys_lseek (struct regs *r)
829 int fd = r->ebx;
830 long offset = r->ecx;
831 int whence = r->edx;
833 long ret = lseek (fd, offset, whence);
835 long *memptr = (long *) 0x9006;
837 *memptr = ret;
840 void sys_pipe (struct regs *r)
842 int *p = (int *) r->ebx;
844 r->eax = pipe (p);
848 void syscall_handler (struct regs *r)
850 switch (r->eax) {
851 case 1:
852 return sys_exit (r);
853 case 2:
854 return sys_getch (r);
855 case 3:
856 return sys_sleep (r);
857 case 4:
858 return sys_putch (r);
859 case 5:
860 return sys_color (r);
861 case 6:
862 return sys_cls (r);
863 case 7:
864 return sys_getkey (r);
865 case 8:
866 return sys_gotoxy (r);
867 case 9:
868 return sys_fork (r);
869 case 10:
870 return sys_schedule (r);
871 case 11:
872 return sys_write (r);
873 case 12:
874 return sys_socket (r);
875 case 13:
876 return sys_connect (r);
877 case 14:
878 return sys_malloc (r);
879 case 15:
880 return sys_send (r);
881 case 16:
882 return sys_recv (r);
883 case 17:
884 return sys_close (r);
885 case 18:
886 return sys_open (r);
887 case 19:
888 return sys_pcspk (r);
889 case 20:
890 return sys_usleep (r);
891 case 21:
892 return sys_read (r);
893 case 22:
894 return sys_time (r);
895 case 23:
896 return sys_system (r);
897 case 24:
898 return sys_chdir (r);
899 case 25:
900 return sys_getdir (r);
901 case 26:
902 return sys_procarg (r);
903 case 27:
904 return sys_signal (r);
905 case 28:
906 return sys_mount (r);
907 case 29:
908 return sys_kputs (r);
909 case 30:
910 return sys_bind (r);
911 case 31:
912 return sys_listen (r);
913 case 32:
914 return sys_accept (r);
915 case 33:
916 return sys_fcntl (r);
917 case 34:
918 return sys_gvgafb (r);
919 case 35:
920 return sys_gcls (r);
921 case 36:
922 return sys_gfbswap (r);
923 case 37:
924 return sys_rs232read (r);
925 case 38:
926 return sys_rs232write (r);
927 case 39:
928 return sys_gttyexit (r);
929 case 40:
930 return sys_gexit (r);
931 case 41:
932 return sys_gttyinit (r);
933 case 42:
934 return sys_mkdir (r);
935 case 43:
936 return sys_free (r);
937 case 44:
938 return sys_realloc (r);
939 case 45:
940 return sys_gethostbyname (r);
941 case 46:
942 return sys_procmap (r);
943 case 47:
944 return sys_sendto (r);
945 case 48:
946 return sys_recvfrom (r);
947 case 49:
948 return sys_getchar (r);
949 case 50:
950 return sys_threadopen (r);
951 case 51:
952 return sys_threadclose (r);
953 case 52:
954 return sys_ioctl (r);
955 case 53:
956 return sys_getpid (r);
957 case 54:
958 return sys_lseek (r);
959 case 55:
960 return sys_pipe (r);