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

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