SimpleOS

LXR

Navigation



Site hébergé par : enix

The LXR Cross Referencer for SOS

source navigation ]
diff markup ]
identifier search ]
general search ]
 
 
Article:1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 6.5 ] [ 7 ] [ 7.5 ] [ 8 ] [ 9 ] [ 9.5 ]

001 /* Copyright (C) 2005  David Decotigny
002 
003    This program is free software; you can redistribute it and/or
004    modify it under the terms of the GNU General Public License
005    as published by the Free Software Foundation; either version 2
006    of the License, or (at your option) any later version.
007    
008    This program is distributed in the hope that it will be useful,
009    but WITHOUT ANY WARRANTY; without even the implied warranty of
010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
011    GNU General Public License for more details.
012    
013    You should have received a copy of the GNU General Public License
014    along with this program; if not, write to the Free Software
015    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
016    USA. 
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  * THE syscall entry point
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; /* Not reached */
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         /* Duplicate the current process (and its address space) */
063         new_proc = sos_process_create(NULL, TRUE);
064         if (! new_proc)
065           {
066             retval = -SOS_ENOMEM;
067             break;
068           }
069         
070         /* Create *the* thread in this new processs, copy of the
071            current user thread (same registers, EXCEPT eax which is
072            set to 0) */
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         /* Return to the "parent" thread with a value different from
088            0. Unix says it should be the "PID" of the child. We don't
089            have such a "PID" notion for now */
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         /* Make sure the process has exactly 1 thread in it */
107         if (sos_process_get_nb_threads(proc) != 1)
108           {
109             retval = -SOS_EBUSY;
110             break;
111           }
112 
113         /* Get the user arguments */
114         retval = sos_syscall_get2args(user_ctxt, & user_str, & len);
115         if (SOS_OK != retval)
116           break;
117 
118         /* Copy the program name into kernel sppace */
119         retval = sos_strndup_from_user(& str, user_str, len + 1, 0);
120         if (SOS_OK != retval)
121           {
122             break;
123           }
124 
125         /* Create a new empty address space to map the program */
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         /* Map the program in it */
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         /* Allocate space for the user stack (8MB) */
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                                   /* PRIVATE */ 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         /* Now create the user thread */
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         /* Switch to this address space */
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         /* The current thread must exit now */
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         /* Allocate the stack */
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                                   /* PRIVATE */ 0);
325         if (SOS_OK != retval)
326           break;
327 
328         /* Now create the user thread */
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        * File system interface
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         /* Retrieve the value for "buflen" */
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         /* Do the actual reading */
634         retval = sos_fs_read(of, uaddr_buf, & kernel_buflen);
635         
636         /* Send successful number of bytes read to user */
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         /* Do the actual readdir */
666         retval = sos_fs_readdir(of, & direntry);
667         if (SOS_OK != retval)
668           break;
669         
670         /* Send direntry structure to user */
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         /* Retrieve the value for "buflen" */
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         /* Do the actual writing */
713         retval = sos_fs_write(of, uaddr_buf, & kernel_buflen);
714         
715         /* Send successful number of bytes written to user */
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         /* Retrieve the value for "buflen" */
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         /* Do the actual seek */
757         retval = sos_fs_seek(of, kernel_offset, whence, & result_position);
758         
759         /* Send successful number of bytes written to user */
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         /* Do the actual trunc */
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         /* Compute 64 bits offset value */
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         /* Do the actual sync */
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         /* Do the actual fcntl */
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         /* Do the actual ioctl */
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         /* Duplicate this FD */
1287         retval = sos_fs_duplicate_opened_file(of, proc, & new_of);
1288         if (SOS_OK != retval)
1289           break;
1290 
1291         /* Do the actual chdir */
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        * Debug syscalls (will be removed in the future)
1327        */
1328 
1329 
1330       /**
1331        * Syscall 4012: hexdump of a user-space memory region
1332        * args: addr_start size, retval=ignored
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        * Syscall 4004: lists the VR of the current thread's address space
1374        * args: debug_string, retval=ignored
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        * Syscall 4008: dump the list of processes in the system
1401        * args: none, retval=ignored
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 }

source navigation ] diff markup ] identifier search ] general search ]