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 /**
035  * THE syscall entry point
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; /* Not reached */
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         /* Duplicate the current process (and its address space) */
064         new_proc = sos_process_create(NULL, TRUE);
065         if (! new_proc)
066           {
067             retval = -SOS_ENOMEM;
068             break;
069           }
070         
071         /* Create *the* thread in this new processs, copy of the
072            current user thread (same registers, EXCEPT eax which is
073            set to 0) */
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         /* Return to the "parent" thread with a value different from
089            0. Unix says it should be the "PID" of the child. We don't
090            have such a "PID" notion for now */
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         /* Make sure the process has exactly 1 thread in it */
108         if (sos_process_get_nb_threads(proc) != 1)
109           {
110             retval = -SOS_EBUSY;
111             break;
112           }
113 
114         /* Get the user arguments */
115         retval = sos_syscall_get2args(user_ctxt, & user_str, & len);
116         if (SOS_OK != retval)
117           break;
118 
119         /* Copy the program name into kernel sppace */
120         retval = sos_strndup_from_user(& str, user_str, len + 1, 0);
121         if (SOS_OK != retval)
122           {
123             break;
124           }
125 
126         /* Create a new empty address space to map the program */
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         /* Map the program in it */
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         /* Allocate space for the user stack (8MB) */
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                                   /* PRIVATE */ 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         /* Now create the user thread */
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         /* Switch to this address space */
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         /* The current thread must exit now */
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         /* Compute 64 bits offset value */
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         /* Allocate the stack */
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                                   /* PRIVATE */ 0);
398         if (SOS_OK != retval)
399           break;
400 
401         /* Now create the user thread */
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        * File system interface
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         /* Retrieve the value for "buflen" */
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         /* Do the actual reading */
707         retval = sos_fs_read(of, uaddr_buf, & kernel_buflen);
708         
709         /* Send successful number of bytes read to user */
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         /* Do the actual readdir */
739         retval = sos_fs_readdir(of, & direntry);
740         if (SOS_OK != retval)
741           break;
742         
743         /* Send direntry structure to user */
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         /* Retrieve the value for "buflen" */
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         /* Do the actual writing */
786         retval = sos_fs_write(of, uaddr_buf, & kernel_buflen);
787         
788         /* Send successful number of bytes written to user */
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         /* Retrieve the value for "buflen" */
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         /* Do the actual seek */
830         retval = sos_fs_seek(of, kernel_offset, whence, & result_position);
831         
832         /* Send successful number of bytes written to user */
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         /* Do the actual trunc */
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         /* Compute 64 bits offset value */
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         /* Do the actual sync */
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         /* Do the actual fcntl */
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         /* Duplicate this FD */
1280         retval = sos_fs_duplicate_opened_file(of, proc, & new_of);
1281         if (SOS_OK != retval)
1282           break;
1283 
1284         /* Do the actual chdir */
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        * Debug syscalls (will be removed in the future)
1320        */
1321 
1322 
1323       /**
1324        * Syscall 4012: hexdump of a user-space memory region
1325        * args: addr_start size, retval=ignored
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        * Syscall 4004: lists the VR of the current thread's address space
1367        * args: debug_string, retval=ignored
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        * Syscall 4008: dump the list of processes in the system
1394        * args: none, retval=ignored
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 }

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