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