001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018 #include <sos/thread.h>
019 #include <sos/kmalloc.h>
020 #include <sos/klibc.h>
021 #include <drivers/bochs.h>
022 #include <hwcore/paging.h>
023 #include <sos/physmem.h>
024 #include <sos/umem_vmm.h>
025 #include <drivers/zero.h>
026 #include <drivers/mem.h>
027 #include <sos/binfmt_elf32.h>
028
029 #include <hwcore/cpu_context.h>
030 #include <sos/uaccess.h>
031 #include "syscall.h"
032
033
034
035
036 sos_ret_t sos_do_syscall(int syscall_id,
037 const struct sos_cpu_state *user_ctxt)
038 {
039 sos_ret_t retval;
040
041 switch(syscall_id)
042 {
043 case SOS_SYSCALL_ID_EXIT:
044 {
045 unsigned int status;
046
047 retval = sos_syscall_get1arg(user_ctxt, & status);
048 if (SOS_OK != retval)
049 break;
050 sos_thread_exit();
051 retval = -SOS_EFATAL;
052 }
053 break;
054
055 case SOS_SYSCALL_ID_FORK:
056 {
057 struct sos_thread *cur_thr, *new_thr;
058 struct sos_process *new_proc;
059
060 cur_thr = sos_thread_get_current();
061
062
063 new_proc = sos_process_create(NULL, TRUE);
064 if (! new_proc)
065 {
066 retval = -SOS_ENOMEM;
067 break;
068 }
069
070
071
072
073 new_thr =
074 sos_duplicate_user_thread(NULL, new_proc,
075 cur_thr,
076 user_ctxt,
077 0);
078 if (! new_thr)
079 {
080 sos_process_unref(new_proc);
081 retval = -SOS_ENOMEM;
082 break;
083 }
084
085 sos_process_unref(new_proc);
086
087
088
089
090 retval = (sos_ui32_t)new_proc;
091 }
092 break;
093
094 case SOS_SYSCALL_ID_EXEC:
095 {
096 struct sos_thread *cur_thr, *new_thr;
097 struct sos_process * proc;
098 struct sos_umem_vmm_as *new_as;
099 sos_uaddr_t user_str, ustack, start_uaddr;
100 sos_size_t len;
101 char * str;
102
103 cur_thr = sos_thread_get_current();
104 proc = cur_thr->process;
105
106
107 if (sos_process_get_nb_threads(proc) != 1)
108 {
109 retval = -SOS_EBUSY;
110 break;
111 }
112
113
114 retval = sos_syscall_get2args(user_ctxt, & user_str, & len);
115 if (SOS_OK != retval)
116 break;
117
118
119 retval = sos_strndup_from_user(& str, user_str, len + 1, 0);
120 if (SOS_OK != retval)
121 {
122 break;
123 }
124
125
126 new_as = sos_umem_vmm_create_empty_as(proc);
127 if (! new_as)
128 {
129 sos_kfree((sos_vaddr_t)str);
130 retval = -SOS_ENOMEM;
131 break;
132 }
133
134
135 start_uaddr = sos_binfmt_elf32_map(new_as, str);
136 if (start_uaddr == (sos_uaddr_t)NULL)
137 {
138 sos_umem_vmm_delete_as(new_as);
139 sos_kfree((sos_vaddr_t)str);
140 retval = -SOS_ENOENT;
141 break;
142 }
143
144
145 #define SOS_DEFAULT_USER_STACK_SIZE (8 << 20)
146 ustack = (SOS_PAGING_TOP_USER_ADDRESS - SOS_DEFAULT_USER_STACK_SIZE)
147 + 1;
148 retval = sos_dev_zero_map(new_as, &ustack, SOS_DEFAULT_USER_STACK_SIZE,
149 SOS_VM_MAP_PROT_READ | SOS_VM_MAP_PROT_WRITE,
150 0);
151 if (SOS_OK != retval)
152 {
153 sos_umem_vmm_delete_as(new_as);
154 sos_kfree((sos_vaddr_t)str);
155 break;
156 }
157
158
159 new_thr = sos_create_user_thread(NULL,
160 proc,
161 start_uaddr,
162 0, 0,
163 ustack + SOS_DEFAULT_USER_STACK_SIZE
164 - 4,
165 SOS_SCHED_PRIO_TS_LOWEST);
166 if (! new_thr)
167 {
168 sos_umem_vmm_delete_as(new_as);
169 sos_kfree((sos_vaddr_t)str);
170 retval = -SOS_ENOMEM;
171 break;
172 }
173
174 sos_process_set_name(proc, str);
175
176
177 retval = sos_process_set_address_space(proc,
178 new_as);
179 if (SOS_OK != retval)
180 {
181 sos_umem_vmm_delete_as(new_as);
182 sos_kfree((sos_vaddr_t)str);
183 break;
184 }
185
186
187 sos_kfree((sos_vaddr_t)str);
188 sos_thread_exit();
189 retval = -SOS_EFATAL;
190 }
191 break;
192
193 case SOS_SYSCALL_ID_MUNMAP:
194 {
195 sos_uaddr_t start_uaddr;
196 sos_size_t size;
197 struct sos_umem_vmm_as * my_as;
198
199 my_as
200 = sos_process_get_address_space(sos_thread_get_current()->process);
201
202 retval = sos_syscall_get2args(user_ctxt,
203 (unsigned int*)& start_uaddr,
204 (unsigned int*)& size);
205 if (SOS_OK != retval)
206 break;
207
208 retval = sos_umem_vmm_unmap(my_as, start_uaddr, size);
209 }
210 break;
211
212 case SOS_SYSCALL_ID_MPROTECT:
213 {
214 sos_uaddr_t start_uaddr;
215 sos_size_t size;
216 sos_ui32_t new_access_rights;
217 struct sos_umem_vmm_as * my_as;
218
219 my_as
220 = sos_process_get_address_space(sos_thread_get_current()->process);
221
222 retval = sos_syscall_get3args(user_ctxt,
223 (unsigned int*)& start_uaddr,
224 (unsigned int*)& size,
225 (unsigned int*)& new_access_rights);
226 if (SOS_OK != retval)
227 break;
228
229 retval = sos_thread_prepare_user_space_access(NULL, (sos_vaddr_t)NULL);
230 if (SOS_OK != retval)
231 break;
232
233 retval = sos_umem_vmm_chprot(my_as, start_uaddr, size,
234 new_access_rights);
235
236 sos_thread_end_user_space_access();
237 }
238 break;
239
240 case SOS_SYSCALL_ID_MRESIZE:
241 {
242 sos_uaddr_t old_uaddr;
243 sos_size_t old_size;
244 sos_uaddr_t *uptr_new_uaddr;
245 sos_uaddr_t new_uaddr;
246 sos_size_t new_size;
247 sos_ui32_t flags;
248 struct sos_umem_vmm_as * my_as;
249
250 my_as
251 = sos_process_get_address_space(sos_thread_get_current()->process);
252
253 retval = sos_syscall_get5args(user_ctxt,
254 (unsigned int*)& old_uaddr,
255 (unsigned int*)& old_size,
256 (unsigned int*)& uptr_new_uaddr,
257 (unsigned int*)& new_size,
258 (unsigned int*)& flags);
259 if (SOS_OK != retval)
260 break;
261
262 if (sizeof(new_uaddr) != sos_memcpy_from_user((sos_vaddr_t)& new_uaddr,
263 (sos_uaddr_t)
264 uptr_new_uaddr,
265 sizeof(new_uaddr)))
266 {
267 retval = -SOS_EFAULT;
268 break;
269 }
270
271 retval = sos_thread_prepare_user_space_access(NULL, (sos_vaddr_t)NULL);
272 if (SOS_OK != retval)
273 break;
274
275 retval = sos_umem_vmm_resize(my_as, old_uaddr, old_size,
276 & new_uaddr, new_size, flags);
277 sos_thread_end_user_space_access();
278 if (SOS_OK != retval)
279 break;
280
281 if (sizeof(new_uaddr)
282 == sos_memcpy_to_user((sos_uaddr_t)uptr_new_uaddr,
283 (sos_vaddr_t)&new_uaddr,
284 sizeof(new_uaddr)))
285 {
286 retval = -SOS_EFAULT;
287 break;
288 }
289 }
290 break;
291
292 case SOS_SYSCALL_ID_NEW_THREAD:
293 {
294 sos_uaddr_t start_func;
295 sos_ui32_t start_arg1, start_arg2;
296 sos_size_t stack_size;
297 sos_uaddr_t stack_uaddr;
298
299 struct sos_thread * new_thr;
300 struct sos_umem_vmm_as * my_as;
301
302 my_as
303 = sos_process_get_address_space(sos_thread_get_current()->process);
304
305 retval = sos_syscall_get4args(user_ctxt,
306 (unsigned int*)& start_func,
307 (unsigned int*)& start_arg1,
308 (unsigned int*)& start_arg2,
309 (unsigned int*)& stack_size);
310 if (SOS_OK != retval)
311 break;
312
313 if (stack_size <= 0)
314 {
315 retval = -SOS_EINVAL;
316 break;
317 }
318
319
320 stack_uaddr = 0;
321 stack_size = SOS_PAGE_ALIGN_SUP(stack_size);
322 retval = sos_dev_zero_map(my_as, & stack_uaddr, stack_size,
323 SOS_VM_MAP_PROT_READ | SOS_VM_MAP_PROT_WRITE,
324 0);
325 if (SOS_OK != retval)
326 break;
327
328
329 new_thr = sos_create_user_thread(NULL,
330 sos_thread_get_current()->process,
331 start_func,
332 start_arg1,
333 start_arg2,
334 stack_uaddr + stack_size - 4,
335 SOS_SCHED_PRIO_TS_LOWEST);
336
337 if (! new_thr)
338 {
339 sos_umem_vmm_unmap(my_as, stack_uaddr, stack_size);
340 retval = -SOS_ENOMEM;
341 break;
342 }
343
344 }
345 break;
346
347 case SOS_SYSCALL_ID_NANOSLEEP:
348 {
349 struct sos_time delay;
350
351 retval = sos_syscall_get2args(user_ctxt,
352 (unsigned int*)& delay.sec,
353 (unsigned int*)& delay.nanosec);
354 if (SOS_OK != retval)
355 break;
356
357 retval = sos_thread_sleep(& delay);
358 }
359 break;
360
361 case SOS_SYSCALL_ID_BRK:
362 {
363 sos_uaddr_t new_top_heap;
364 struct sos_umem_vmm_as * my_as;
365
366 my_as
367 = sos_process_get_address_space(sos_thread_get_current()->process);
368
369 retval = sos_syscall_get1arg(user_ctxt,
370 (unsigned int*)& new_top_heap);
371 if (SOS_OK != retval)
372 break;
373
374 retval = sos_thread_prepare_user_space_access(NULL, (sos_vaddr_t)NULL);
375 if (SOS_OK != retval)
376 break;
377
378 retval = sos_umem_vmm_brk(my_as, new_top_heap);
379 sos_thread_end_user_space_access();
380 }
381 break;
382
383
384
385
386
387 case SOS_SYSCALL_ID_MOUNT:
388 {
389 sos_uaddr_t user_src;
390 sos_size_t srclen;
391 char * kernel_src = NULL;
392 sos_uaddr_t user_dst;
393 sos_size_t dstlen;
394 char * kernel_dst;
395 sos_ui32_t mountflags;
396 sos_uaddr_t user_fstype;
397 char * kernel_fstype;
398 sos_uaddr_t user_args;
399 char * kernel_args = NULL;
400 struct sos_process * proc;
401
402 proc = sos_thread_get_current()->process;
403 retval = sos_syscall_get7args(user_ctxt,
404 (unsigned int*)& user_src,
405 (unsigned int*)& srclen,
406 (unsigned int*)& user_dst,
407 (unsigned int*)& dstlen,
408 (unsigned int*)& user_fstype,
409 (unsigned int*)& mountflags,
410 (unsigned int*)& user_args);
411 if (SOS_OK != retval)
412 break;
413
414 if (user_src != (sos_uaddr_t)NULL)
415 {
416 retval = sos_strndup_from_user(&kernel_src, user_src, srclen, 0);
417 if (SOS_OK != retval)
418 break;
419 }
420
421 retval = sos_strndup_from_user(&kernel_dst, user_dst, dstlen, 0);
422 if (SOS_OK != retval)
423 {
424 if (kernel_src)
425 sos_kfree((sos_vaddr_t)kernel_src);
426 break;
427 }
428
429 retval = sos_strndup_from_user(& kernel_fstype, user_fstype, 256, 0);
430 if (SOS_OK != retval)
431 {
432 if (kernel_src)
433 sos_kfree((sos_vaddr_t)kernel_src);
434 sos_kfree((sos_vaddr_t)kernel_dst);
435 break;
436 }
437
438 if (user_args != (sos_uaddr_t)NULL)
439 {
440 retval = sos_strndup_from_user(& kernel_args, user_args, 1024, 0);
441 if (SOS_OK != retval)
442 {
443 if (kernel_src)
444 sos_kfree((sos_vaddr_t)kernel_src);
445 sos_kfree((sos_vaddr_t)kernel_dst);
446 sos_kfree((sos_vaddr_t)kernel_fstype);
447 break;
448 }
449 }
450
451 retval = sos_fs_mount(proc, kernel_src, srclen,
452 kernel_dst, dstlen,
453 kernel_fstype,
454 mountflags,
455 kernel_args,
456 NULL);
457 if (kernel_src)
458 sos_kfree((sos_vaddr_t)kernel_src);
459 sos_kfree((sos_vaddr_t)kernel_dst);
460 sos_kfree((sos_vaddr_t)kernel_fstype);
461 if (kernel_args)
462 sos_kfree((sos_vaddr_t)kernel_args);
463 }
464 break;
465
466 case SOS_SYSCALL_ID_UMOUNT:
467 {
468 sos_uaddr_t user_str;
469 sos_size_t len;
470 char * path;
471 struct sos_process * proc;
472
473 proc = sos_thread_get_current()->process;
474 retval = sos_syscall_get2args(user_ctxt,
475 (unsigned int*)& user_str,
476 (unsigned int*)& len);
477 if (SOS_OK != retval)
478 break;
479
480 retval = sos_strndup_from_user(&path, user_str, len, 0);
481 if (SOS_OK != retval)
482 break;
483
484 retval = sos_fs_umount(proc,
485 path, len);
486 sos_kfree((sos_vaddr_t)path);
487 }
488 break;
489
490 case SOS_SYSCALL_ID_SYNC:
491 {
492 sos_fs_sync_all_fs();
493 retval = SOS_OK;
494 }
495 break;
496
497 case SOS_SYSCALL_ID_VFSTAT64:
498 {
499 sos_uaddr_t user_str;
500 sos_size_t len;
501 sos_uaddr_t user_vfstat_struct;
502 struct sos_fs_statfs kernel_vfstat_struct;
503 char * path;
504 struct sos_process * proc;
505
506 proc = sos_thread_get_current()->process;
507 retval = sos_syscall_get3args(user_ctxt,
508 (unsigned int*)& user_str,
509 (unsigned int*)& len,
510 (unsigned int*)& user_vfstat_struct);
511 if (SOS_OK != retval)
512 break;
513
514 retval = sos_strndup_from_user(&path, user_str, len, 0);
515 if (SOS_OK != retval)
516 break;
517
518 retval = sos_fs_vfstat(proc, path, len, & kernel_vfstat_struct);
519 sos_kfree((sos_vaddr_t)path);
520 if (SOS_OK != retval)
521 break;
522
523 if (sizeof(kernel_vfstat_struct)
524 != sos_memcpy_to_user(user_vfstat_struct,
525 (sos_vaddr_t) & kernel_vfstat_struct,
526 sizeof(kernel_vfstat_struct)))
527 retval = -SOS_EFAULT;
528 }
529 break;
530
531 case SOS_SYSCALL_ID_OPEN:
532 {
533 sos_uaddr_t user_str;
534 sos_size_t len;
535 sos_ui32_t open_flags;
536 sos_ui32_t access_rights;
537 char * path;
538 struct sos_fs_opened_file * of;
539 struct sos_process * proc;
540
541 proc = sos_thread_get_current()->process;
542 retval = sos_syscall_get4args(user_ctxt,
543 (unsigned int*)& user_str,
544 (unsigned int*)& len,
545 (unsigned int*)& open_flags,
546 (unsigned int*)& access_rights);
547 if (SOS_OK != retval)
548 break;
549
550 retval = sos_strndup_from_user(&path, user_str, len, 0);
551 if (SOS_OK != retval)
552 break;
553
554 retval = sos_fs_open(proc,
555 path, len,
556 open_flags,
557 access_rights,
558 & of);
559 sos_kfree((sos_vaddr_t)path);
560 if (SOS_OK != retval)
561 break;
562
563 retval = sos_process_register_opened_file(proc, of);
564 if (retval < 0)
565 {
566 sos_fs_close(of);
567 break;
568 }
569 }
570 break;
571
572 case SOS_SYSCALL_ID_CLOSE:
573 {
574 struct sos_fs_opened_file * of;
575 struct sos_process * proc;
576 int fd;
577
578 proc = sos_thread_get_current()->process;
579 retval = sos_syscall_get1arg(user_ctxt,
580 (unsigned int*)& fd);
581 if (SOS_OK != retval)
582 break;
583
584 of = sos_process_get_opened_file(proc, fd);
585 if (NULL == of)
586 {
587 retval = -SOS_EBADF;
588 break;
589 }
590
591 retval = sos_process_unregister_opened_file(proc, fd);
592 if (SOS_OK != retval)
593 break;
594
595 retval = sos_fs_close(of);
596 }
597 break;
598
599 case SOS_SYSCALL_ID_READ:
600 {
601 struct sos_fs_opened_file * of;
602 struct sos_process * proc;
603 sos_uaddr_t uaddr_buf;
604 sos_uaddr_t uaddr_buflen;
605 sos_size_t kernel_buflen;
606 int fd;
607
608 proc = sos_thread_get_current()->process;
609 retval = sos_syscall_get3args(user_ctxt,
610 (unsigned int*)& fd,
611 (unsigned int*)& uaddr_buf,
612 (unsigned int*)& uaddr_buflen);
613 if (SOS_OK != retval)
614 break;
615
616
617 retval = sos_memcpy_from_user((sos_vaddr_t)& kernel_buflen,
618 uaddr_buflen,
619 sizeof(kernel_buflen));
620 if (sizeof(kernel_buflen) != retval)
621 {
622 retval = -SOS_EFAULT;
623 break;
624 }
625
626 of = sos_process_get_opened_file(proc, fd);
627 if (NULL == of)
628 {
629 retval = -SOS_EBADF;
630 break;
631 }
632
633
634 retval = sos_fs_read(of, uaddr_buf, & kernel_buflen);
635
636
637 sos_memcpy_to_user(uaddr_buflen,
638 (sos_vaddr_t)& kernel_buflen,
639 sizeof(kernel_buflen));
640 }
641 break;
642
643 case SOS_SYSCALL_ID_READDIR:
644 {
645 struct sos_fs_opened_file * of;
646 struct sos_process * proc;
647 sos_uaddr_t uaddr_direntry;
648 struct sos_fs_dirent direntry;
649 int fd;
650
651 proc = sos_thread_get_current()->process;
652 retval = sos_syscall_get2args(user_ctxt,
653 (unsigned int*)& fd,
654 (unsigned int*)& uaddr_direntry);
655 if (SOS_OK != retval)
656 break;
657
658 of = sos_process_get_opened_file(proc, fd);
659 if (NULL == of)
660 {
661 retval = -SOS_EBADF;
662 break;
663 }
664
665
666 retval = sos_fs_readdir(of, & direntry);
667 if (SOS_OK != retval)
668 break;
669
670
671 if (sizeof(direntry) != sos_memcpy_to_user(uaddr_direntry,
672 (sos_vaddr_t)& direntry,
673 sizeof(direntry)))
674 retval = -SOS_EFAULT;
675 }
676 break;
677
678 case SOS_SYSCALL_ID_WRITE:
679 {
680 struct sos_fs_opened_file * of;
681 struct sos_process * proc;
682 sos_uaddr_t uaddr_buf;
683 sos_uaddr_t uaddr_buflen;
684 sos_size_t kernel_buflen;
685 int fd;
686
687 proc = sos_thread_get_current()->process;
688 retval = sos_syscall_get3args(user_ctxt,
689 (unsigned int*)& fd,
690 (unsigned int*)& uaddr_buf,
691 (unsigned int*)& uaddr_buflen);
692 if (SOS_OK != retval)
693 break;
694
695
696 retval = sos_memcpy_from_user((sos_vaddr_t)& kernel_buflen,
697 uaddr_buflen,
698 sizeof(kernel_buflen));
699 if (sizeof(kernel_buflen) != retval)
700 {
701 retval = -SOS_EFAULT;
702 break;
703 }
704
705 of = sos_process_get_opened_file(proc, fd);
706 if (NULL == of)
707 {
708 retval = -SOS_EBADF;
709 break;
710 }
711
712
713 retval = sos_fs_write(of, uaddr_buf, & kernel_buflen);
714
715
716 sos_memcpy_to_user(uaddr_buflen,
717 (sos_vaddr_t)& kernel_buflen,
718 sizeof(kernel_buflen));
719 }
720 break;
721
722 case SOS_SYSCALL_ID_SEEK64:
723 {
724 struct sos_fs_opened_file * of;
725 struct sos_process * proc;
726 sos_uaddr_t uaddr_offset;
727 sos_seek_whence_t whence;
728 sos_lsoffset_t kernel_offset, result_position;
729 int fd;
730
731 proc = sos_thread_get_current()->process;
732 retval = sos_syscall_get3args(user_ctxt,
733 (unsigned int*)& fd,
734 (unsigned int*)& uaddr_offset,
735 (unsigned int*)& whence);
736 if (SOS_OK != retval)
737 break;
738
739
740 retval = sos_memcpy_from_user((sos_vaddr_t)& kernel_offset,
741 uaddr_offset,
742 sizeof(kernel_offset));
743 if (sizeof(kernel_offset) != retval)
744 {
745 retval = -SOS_EFAULT;
746 break;
747 }
748
749 of = sos_process_get_opened_file(proc, fd);
750 if (NULL == of)
751 {
752 retval = -SOS_EBADF;
753 break;
754 }
755
756
757 retval = sos_fs_seek(of, kernel_offset, whence, & result_position);
758
759
760 sos_memcpy_to_user(uaddr_offset,
761 (sos_vaddr_t)& result_position,
762 sizeof(kernel_offset));
763 }
764 break;
765
766 case SOS_SYSCALL_ID_FTRUNCATE64:
767 {
768 struct sos_fs_opened_file * of;
769 struct sos_process * proc;
770 sos_lsoffset_t length;
771 int fd;
772
773 proc = sos_thread_get_current()->process;
774 retval = sos_syscall_get2args(user_ctxt,
775 (unsigned int*)& fd,
776 (unsigned int*)& length);
777 if (SOS_OK != retval)
778 break;
779
780 of = sos_process_get_opened_file(proc, fd);
781 if (NULL == of)
782 {
783 retval = -SOS_EBADF;
784 break;
785 }
786
787
788 retval = sos_fs_ftruncate(of, length);
789 }
790 break;
791
792 case SOS_SYSCALL_ID_FSMMAP:
793 {
794 sos_uaddr_t ptr_hint_uaddr;
795 sos_uaddr_t hint_uaddr;
796 sos_size_t length;
797 sos_ui32_t prot;
798 sos_ui32_t flags;
799 int fd;
800 sos_ui32_t offs64_hi;
801 sos_ui32_t offs64_lo;
802 sos_luoffset_t offset_in_resource;
803 struct sos_fs_opened_file * of;
804 struct sos_process * proc;
805
806 proc = sos_thread_get_current()->process;
807 retval = sos_syscall_get7args(user_ctxt,
808 (unsigned int*)& ptr_hint_uaddr,
809 (unsigned int*)& length,
810 (unsigned int*)& prot,
811 (unsigned int*)& flags,
812 (unsigned int*)& fd,
813 (unsigned int*)& offs64_hi,
814 (unsigned int*)& offs64_lo);
815 if (SOS_OK != retval)
816 break;
817
818 of = sos_process_get_opened_file(proc, fd);
819 if (NULL == of)
820 {
821 retval = -SOS_EBADF;
822 break;
823 }
824
825
826 offset_in_resource = offs64_hi;
827 offset_in_resource <<= 32;
828 offset_in_resource |= offs64_lo;
829
830 retval = sos_memcpy_from_user((sos_vaddr_t)& hint_uaddr,
831 ptr_hint_uaddr,
832 sizeof(hint_uaddr));
833 if (sizeof(hint_uaddr) != retval)
834 {
835 retval = -SOS_EFAULT;
836 break;
837 }
838
839 retval = sos_fs_mmap(of, & hint_uaddr, length, prot, flags,
840 offset_in_resource);
841 if (SOS_OK == retval)
842 {
843 if (sizeof(hint_uaddr)
844 != sos_memcpy_to_user(ptr_hint_uaddr,
845 (sos_vaddr_t)& hint_uaddr,
846 sizeof(hint_uaddr)))
847 {
848 sos_umem_vmm_unmap(sos_process_get_address_space(proc),
849 hint_uaddr, length);
850 retval = -SOS_EFAULT;
851 }
852 }
853
854 }
855 break;
856
857 case SOS_SYSCALL_ID_FSYNC:
858 {
859 struct sos_fs_opened_file * of;
860 struct sos_process * proc;
861 int fd;
862
863 proc = sos_thread_get_current()->process;
864 retval = sos_syscall_get1arg(user_ctxt,
865 (unsigned int*)& fd);
866 if (SOS_OK != retval)
867 break;
868
869 of = sos_process_get_opened_file(proc, fd);
870 if (NULL == of)
871 {
872 retval = -SOS_EBADF;
873 break;
874 }
875
876
877 retval = sos_fs_fsync(of);
878 }
879 break;
880
881 case SOS_SYSCALL_ID_FCNTL:
882 {
883 struct sos_fs_opened_file * of;
884 struct sos_process * proc;
885 sos_ui32_t cmd, arg;
886 int fd;
887
888 proc = sos_thread_get_current()->process;
889 retval = sos_syscall_get3args(user_ctxt,
890 (unsigned int*)& fd,
891 (unsigned int*)& cmd,
892 (unsigned int*)& arg);
893 if (SOS_OK != retval)
894 break;
895
896 of = sos_process_get_opened_file(proc, fd);
897 if (NULL == of)
898 {
899 retval = -SOS_EBADF;
900 break;
901 }
902
903
904 retval = sos_fs_fcntl(of, cmd, arg);
905 }
906 break;
907
908 case SOS_SYSCALL_ID_IOCTL:
909 {
910 struct sos_fs_opened_file * of;
911 struct sos_process * proc;
912 sos_ui32_t cmd, arg;
913 int fd;
914
915 proc = sos_thread_get_current()->process;
916 retval = sos_syscall_get3args(user_ctxt,
917 (unsigned int*)& fd,
918 (unsigned int*)& cmd,
919 (unsigned int*)& arg);
920 if (SOS_OK != retval)
921 break;
922
923 of = sos_process_get_opened_file(proc, fd);
924 if (NULL == of)
925 {
926 retval = -SOS_EBADF;
927 break;
928 }
929
930
931 retval = sos_fs_ioctl(of, cmd, arg);
932 }
933 break;
934
935 case SOS_SYSCALL_ID_CREAT:
936 {
937 sos_uaddr_t user_str;
938 sos_size_t len;
939 sos_ui32_t access_rights;
940 char * path;
941 struct sos_process * proc;
942
943 proc = sos_thread_get_current()->process;
944 retval = sos_syscall_get3args(user_ctxt,
945 (unsigned int*)& user_str,
946 (unsigned int*)& len,
947 (unsigned int*)& access_rights);
948 if (SOS_OK != retval)
949 break;
950
951 retval = sos_strndup_from_user(&path, user_str, len, 0);
952 if (SOS_OK != retval)
953 break;
954
955 retval = sos_fs_creat(proc,
956 path, len,
957 access_rights);
958 sos_kfree((sos_vaddr_t)path);
959 }
960 break;
961
962 case SOS_SYSCALL_ID_LINK:
963 case SOS_SYSCALL_ID_RENAME:
964 {
965 sos_uaddr_t user_oldpath, user_newpath;
966 sos_size_t oldpathlen, newpathlen;
967 char * kernel_oldpath, * kernel_newpath;
968 struct sos_process * proc;
969
970 proc = sos_thread_get_current()->process;
971 retval = sos_syscall_get4args(user_ctxt,
972 (unsigned int*)& user_oldpath,
973 (unsigned int*)& oldpathlen,
974 (unsigned int*)& user_newpath,
975 (unsigned int*)& newpathlen);
976 if (SOS_OK != retval)
977 break;
978
979 retval = sos_strndup_from_user(&kernel_oldpath,
980 user_oldpath,
981 oldpathlen, 0);
982 if (SOS_OK != retval)
983 break;
984
985 retval = sos_strndup_from_user(&kernel_newpath,
986 user_newpath,
987 newpathlen, 0);
988 if (SOS_OK != retval)
989 {
990 sos_kfree((sos_vaddr_t) kernel_oldpath);
991 break;
992 }
993
994 if (syscall_id == SOS_SYSCALL_ID_LINK)
995 retval = sos_fs_link(proc,
996 kernel_oldpath, oldpathlen,
997 kernel_newpath, newpathlen);
998 else
999 retval = sos_fs_rename(proc,
1000 kernel_oldpath, oldpathlen,
1001 kernel_newpath, newpathlen);
1002 sos_kfree((sos_vaddr_t)kernel_oldpath);
1003 sos_kfree((sos_vaddr_t)kernel_newpath);
1004 }
1005 break;
1006
1007 case SOS_SYSCALL_ID_UNLINK:
1008 {
1009 sos_uaddr_t user_str;
1010 sos_size_t len;
1011 char * path;
1012 struct sos_process * proc;
1013
1014 proc = sos_thread_get_current()->process;
1015 retval = sos_syscall_get2args(user_ctxt,
1016 (unsigned int*)& user_str,
1017 (unsigned int*)& len);
1018 if (SOS_OK != retval)
1019 break;
1020
1021 retval = sos_strndup_from_user(&path, user_str, len, 0);
1022 if (SOS_OK != retval)
1023 break;
1024
1025 retval = sos_fs_unlink(proc,
1026 path, len);
1027 sos_kfree((sos_vaddr_t)path);
1028 }
1029 break;
1030
1031 case SOS_SYSCALL_ID_SYMLINK:
1032 {
1033 sos_uaddr_t user_path, user_targetpath;
1034 sos_size_t pathlen, targetpathlen;
1035 char * kernel_path;
1036 struct sos_process * proc;
1037
1038 proc = sos_thread_get_current()->process;
1039 retval = sos_syscall_get4args(user_ctxt,
1040 (unsigned int*)& user_path,
1041 (unsigned int*)& pathlen,
1042 (unsigned int*)& user_targetpath,
1043 (unsigned int*)& targetpathlen);
1044 if (SOS_OK != retval)
1045 break;
1046
1047 retval = sos_strndup_from_user(&kernel_path,
1048 user_path,
1049 pathlen, 0);
1050 if (SOS_OK != retval)
1051 break;
1052
1053 retval = sos_fs_symlink(proc,
1054 kernel_path, pathlen,
1055 user_targetpath, targetpathlen);
1056 sos_kfree((sos_vaddr_t)kernel_path);
1057 }
1058 break;
1059
1060 case SOS_SYSCALL_ID_MKNOD:
1061 {
1062 sos_uaddr_t user_str;
1063 sos_size_t len;
1064 sos_ui32_t access_rights;
1065 int type;
1066 char * path;
1067 struct sos_fs_dev_id_t dev_id;
1068 struct sos_process * proc;
1069
1070 proc = sos_thread_get_current()->process;
1071 retval = sos_syscall_get6args(user_ctxt,
1072 (unsigned int*)& user_str,
1073 (unsigned int*)& len,
1074 (unsigned int*)& type,
1075 (unsigned int*)& access_rights,
1076 (unsigned int*)& dev_id.device_class,
1077 (unsigned int*)& dev_id.device_instance);
1078 if (SOS_OK != retval)
1079 break;
1080
1081 retval = sos_strndup_from_user(&path, user_str, len, 0);
1082 if (SOS_OK != retval)
1083 break;
1084
1085 switch (type)
1086 {
1087 case SOS_FS_NODE_REGULAR_FILE:
1088 retval = sos_fs_creat(proc, path, len, access_rights);
1089 break;
1090
1091 case SOS_FS_NODE_DIRECTORY:
1092 retval = sos_fs_mkdir(proc, path, len, access_rights);
1093 break;
1094
1095 case SOS_FS_NODE_SYMLINK:
1096 retval = -SOS_ENOSUP;
1097 break;
1098
1099 case SOS_FS_NODE_DEVICE_CHAR:
1100 retval = sos_fs_mknod(proc,
1101 path, len, type, access_rights, &dev_id);
1102 break;
1103
1104 default:
1105 retval = -SOS_EINVAL;
1106 break;
1107 }
1108
1109 sos_kfree((sos_vaddr_t)path);
1110 }
1111 break;
1112
1113 case SOS_SYSCALL_ID_MKDIR:
1114 {
1115 sos_uaddr_t user_str;
1116 sos_size_t len;
1117 sos_ui32_t access_rights;
1118 char * path;
1119 struct sos_process * proc;
1120
1121 proc = sos_thread_get_current()->process;
1122 retval = sos_syscall_get3args(user_ctxt,
1123 (unsigned int*)& user_str,
1124 (unsigned int*)& len,
1125 (unsigned int*)& access_rights);
1126 if (SOS_OK != retval)
1127 break;
1128
1129 retval = sos_strndup_from_user(&path, user_str, len, 0);
1130 if (SOS_OK != retval)
1131 break;
1132
1133 retval = sos_fs_mkdir(proc,
1134 path, len, access_rights);
1135 sos_kfree((sos_vaddr_t)path);
1136 }
1137 break;
1138
1139 case SOS_SYSCALL_ID_RMDIR:
1140 {
1141 sos_uaddr_t user_str;
1142 sos_size_t len;
1143 char * path;
1144 struct sos_process * proc;
1145
1146 proc = sos_thread_get_current()->process;
1147 retval = sos_syscall_get2args(user_ctxt,
1148 (unsigned int*)& user_str,
1149 (unsigned int*)& len);
1150 if (SOS_OK != retval)
1151 break;
1152
1153 retval = sos_strndup_from_user(&path, user_str, len, 0);
1154 if (SOS_OK != retval)
1155 break;
1156
1157 retval = sos_fs_rmdir(proc, path, len);
1158 sos_kfree((sos_vaddr_t)path);
1159 }
1160 break;
1161
1162 case SOS_SYSCALL_ID_CHMOD:
1163 {
1164 sos_uaddr_t user_str;
1165 sos_size_t len;
1166 sos_ui32_t access_rights;
1167 char * path;
1168 struct sos_process * proc;
1169
1170 proc = sos_thread_get_current()->process;
1171 retval = sos_syscall_get3args(user_ctxt,
1172 (unsigned int*)& user_str,
1173 (unsigned int*)& len,
1174 (unsigned int*)& access_rights);
1175 if (SOS_OK != retval)
1176 break;
1177
1178 retval = sos_strndup_from_user(&path, user_str, len, 0);
1179 if (SOS_OK != retval)
1180 break;
1181
1182 retval = sos_fs_chmod(proc, path, len, access_rights);
1183 sos_kfree((sos_vaddr_t)path);
1184 }
1185 break;
1186
1187 case SOS_SYSCALL_ID_STAT64:
1188 {
1189 sos_uaddr_t user_str;
1190 sos_size_t len;
1191 sos_uaddr_t user_stat_struct;
1192 struct sos_fs_stat kernel_stat_struct;
1193 int nofollow;
1194 char * path;
1195 struct sos_process * proc;
1196
1197 proc = sos_thread_get_current()->process;
1198 retval = sos_syscall_get4args(user_ctxt,
1199 (unsigned int*)& user_str,
1200 (unsigned int*)& len,
1201 (unsigned int*)& nofollow,
1202 (unsigned int*)& user_stat_struct);
1203 if (SOS_OK != retval)
1204 break;
1205
1206 retval = sos_strndup_from_user(&path, user_str, len, 0);
1207 if (SOS_OK != retval)
1208 break;
1209
1210 retval = sos_fs_stat(proc, path, len, nofollow, & kernel_stat_struct);
1211 sos_kfree((sos_vaddr_t)path);
1212 if (SOS_OK != retval)
1213 break;
1214
1215 if (sizeof(kernel_stat_struct)
1216 != sos_memcpy_to_user(user_stat_struct,
1217 (sos_vaddr_t) & kernel_stat_struct,
1218 sizeof(kernel_stat_struct)))
1219 retval = -SOS_EFAULT;
1220 }
1221 break;
1222
1223 case SOS_SYSCALL_ID_CHROOT:
1224 case SOS_SYSCALL_ID_CHDIR:
1225 {
1226 sos_uaddr_t user_str;
1227 sos_size_t len;
1228 char * path;
1229 struct sos_fs_opened_file * of, * old_of;
1230 struct sos_process * proc;
1231
1232 proc = sos_thread_get_current()->process;
1233 retval = sos_syscall_get2args(user_ctxt,
1234 (unsigned int*)& user_str,
1235 (unsigned int*)& len);
1236 if (SOS_OK != retval)
1237 break;
1238
1239 retval = sos_strndup_from_user(&path, user_str, len, 0);
1240 if (SOS_OK != retval)
1241 break;
1242
1243 retval = sos_fs_open(proc,
1244 path, len,
1245 SOS_FS_OPEN_DIRECTORY,
1246 SOS_FS_OPEN_READ,
1247 & of);
1248 sos_kfree((sos_vaddr_t)path);
1249 if (SOS_OK != retval)
1250 break;
1251
1252 if (syscall_id == SOS_SYSCALL_ID_CHROOT)
1253 retval = sos_process_chroot(proc, of, & old_of);
1254 else
1255 retval = sos_process_chdir(proc, of, & old_of);
1256
1257 if (retval < 0)
1258 {
1259 sos_fs_close(of);
1260 break;
1261 }
1262
1263 sos_fs_close(old_of);
1264 }
1265 break;
1266
1267 case SOS_SYSCALL_ID_FCHDIR:
1268 {
1269 struct sos_fs_opened_file * of, * new_of, * old_of;
1270 struct sos_process * proc;
1271 int fd;
1272
1273 proc = sos_thread_get_current()->process;
1274 retval = sos_syscall_get1arg(user_ctxt,
1275 (unsigned int*)& fd);
1276 if (SOS_OK != retval)
1277 break;
1278
1279 of = sos_process_get_opened_file(proc, fd);
1280 if (NULL == of)
1281 {
1282 retval = -SOS_EBADF;
1283 break;
1284 }
1285
1286
1287 retval = sos_fs_duplicate_opened_file(of, proc, & new_of);
1288 if (SOS_OK != retval)
1289 break;
1290
1291
1292 retval = sos_process_chdir(proc, new_of, & old_of);
1293 if (retval < 0)
1294 {
1295 sos_fs_close(new_of);
1296 break;
1297 }
1298
1299 sos_fs_close(old_of);
1300 }
1301 break;
1302
1303 case SOS_SYSCALL_ID_BOCHS_WRITE:
1304 {
1305 sos_uaddr_t user_str;
1306 sos_size_t len;
1307 char * str;
1308 retval = sos_syscall_get2args(user_ctxt, & user_str, & len);
1309 if (SOS_OK != retval)
1310 break;
1311
1312 retval = sos_strndup_from_user(& str, user_str, len + 1, 0);
1313 if (SOS_OK == retval)
1314 {
1315 sos_bochs_printf("THR 0x%x: ",
1316 (unsigned)sos_thread_get_current());
1317 retval = sos_bochs_putstring(str);
1318 retval = len;
1319 sos_kfree((sos_vaddr_t)str);
1320 }
1321 }
1322 break;
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334 case 4012:
1335 {
1336 sos_uaddr_t user_str;
1337 unsigned int len;
1338 unsigned char * str;
1339
1340 retval = sos_syscall_get2args(user_ctxt, & user_str, & len);
1341 if (SOS_OK != retval)
1342 break;
1343
1344 str = (unsigned char*)sos_kmalloc(len, 0);
1345 if (str)
1346 {
1347 int i;
1348 sos_bochs_printf("Hexdump(0x%x, %d):\n", user_str, len);
1349 retval = sos_memcpy_from_user((sos_vaddr_t) str, user_str, len);
1350 sos_bochs_printf(" (Successfully copied %d out of %d)\n",
1351 retval, len);
1352
1353 for (i = 0 ; i < retval ; i++)
1354 {
1355 if ((i % 32) == 0)
1356 sos_bochs_printf("%x:", i);
1357 sos_bochs_printf(" %x", str[i]);
1358 if (((i+1) % 32) == 0)
1359 sos_bochs_printf("\n");
1360 }
1361 if (i % 32)
1362 sos_bochs_printf("\n");
1363
1364 sos_kfree((sos_vaddr_t)str);
1365 }
1366 else
1367 retval = -SOS_ENOMEM;
1368 }
1369 break;
1370
1371
1372
1373
1374
1375
1376 case 4004:
1377 {
1378 sos_uaddr_t ustr;
1379 char * kstr;
1380 struct sos_umem_vmm_as * my_as;
1381
1382 retval = sos_syscall_get1arg(user_ctxt, & ustr);
1383 if (SOS_OK != retval)
1384 break;
1385
1386 retval = sos_strndup_from_user(& kstr, ustr, 256, 0);
1387 if (SOS_OK != retval)
1388 break;
1389
1390 extern void sos_dump_as(const struct sos_umem_vmm_as *, const char *);
1391 my_as
1392 = sos_process_get_address_space(sos_thread_get_current()->process);
1393 sos_dump_as(my_as, kstr);
1394 sos_kfree((sos_vaddr_t)kstr);
1395 }
1396 break;
1397
1398
1399
1400
1401
1402
1403 case 4008:
1404 {
1405 extern void sos_process_dumplist(void);
1406 sos_process_dumplist();
1407 retval = SOS_OK;
1408 }
1409 break;
1410
1411 default:
1412 sos_bochs_printf("Syscall: UNKNOWN[%d]\n", syscall_id);
1413 retval = -SOS_ENOSUP;
1414 }
1415
1416 return retval;
1417 }