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