]> Zhao Yanbai Git Server - minix.git/commitdiff
- Kernel call handlers cleaned up. More strict checking of input parameters.
authorJorrit Herder <jnherder@minix3.org>
Fri, 29 Jul 2005 15:26:23 +0000 (15:26 +0000)
committerJorrit Herder <jnherder@minix3.org>
Fri, 29 Jul 2005 15:26:23 +0000 (15:26 +0000)
- Moved generic_handler() from system.c to system/do_irqctl.c.
- Set privileges of system processes somewhat stricter.

25 files changed:
kernel/glo.h
kernel/ipc.h
kernel/main.c
kernel/proto.h
kernel/system.c
kernel/system/Makefile
kernel/system/do_abort.c
kernel/system/do_endksig.c
kernel/system/do_fork.c
kernel/system/do_getinfo.c
kernel/system/do_irqctl.c
kernel/system/do_kill.c
kernel/system/do_memset.c
kernel/system/do_newmap.c
kernel/system/do_nice.c
kernel/system/do_privctl.c
kernel/system/do_sdevio.c
kernel/system/do_setalarm.c [moved from kernel/system/do_alarm.c with 93% similarity]
kernel/system/do_sigreturn.c
kernel/system/do_sigsend.c
kernel/system/do_trace.c
kernel/system/do_vcopy.c
kernel/system/do_vdevio.c
kernel/table.c
kernel/type.h

index 9cde441f0b454f894523ba3acc998af2620445a3..a80b84dc6b27e40302ec4005a6ab06673a428b21 100755 (executable)
@@ -47,7 +47,7 @@ EXTERN reg_t mon_ss, mon_sp;          /* boot monitor stack */
 EXTERN int mon_return;                 /* true if we can return to monitor */
 
 /* Variables that are initialized elsewhere are just extern here. */
-extern struct system_image image[];    /* system image processes */
+extern struct boot_image image[];      /* system image processes */
 extern char *t_stack[];                        /* task stack space */
 extern struct segdesc_s gdt[];         /* global descriptor table */
 
index cd414619e41a983fe8c92ed8327a4bbc2234ab98..ffff3cf2c11a9e9113003240dd8bfcba1b1eb312 100644 (file)
@@ -30,6 +30,7 @@
  */
 #define EMPTY_MASK             (0)
 #define FILLED_MASK            (~0)
+#define TASK_CALL_MASK         (1 << RECEIVE)
 #define USER_CALL_MASK         ((1 << SENDREC) | (1 << ECHO))
 
 /* Send masks determine to whom processes can send messages or notifications. 
index bdc63580e23897be6344e0f8deb7cad5789b30c2..51d94306572dfa89ed963411915da6f43ad2c52d 100755 (executable)
@@ -25,8 +25,6 @@
 FORWARD _PROTOTYPE( void announce, (void));    
 FORWARD _PROTOTYPE( void shutdown, (timer_t *tp));
 
-#define SHUTDOWN_TICKS 5       /* time allowed to do cleanup */
-
 
 /*===========================================================================*
  *                                   main                                    *
@@ -34,7 +32,7 @@ FORWARD _PROTOTYPE( void shutdown, (timer_t *tp));
 PUBLIC void main()
 {
 /* Start the ball rolling. */
-  struct system_image *ip;     /* boot image pointer */
+  struct boot_image *ip;       /* boot image pointer */
   register struct proc *rp;    /* process pointer */
   register struct priv *sp;    /* privilege structure pointer */
   register int i, s;
@@ -188,8 +186,8 @@ PUBLIC void prepare_shutdown(how)
 int how;
 {
 /* This function prepares to shutdown MINIX. */
-  register struct proc *rp; 
   static timer_t shutdown_timer;
+  register struct proc *rp; 
   message m;
 
   /* Show debugging dumps on panics. Make sure that the TTY task is still 
@@ -221,7 +219,7 @@ int how;
    */
   kprintf("MINIX will now be shut down ...\n");
   tmr_arg(&shutdown_timer)->ta_int = how;
-  set_timer(&shutdown_timer, get_uptime() + SHUTDOWN_TICKS, shutdown);
+  set_timer(&shutdown_timer, get_uptime() + HZ, shutdown);
 }
 
 
index c70db811cdad39f896d6ae533c22dfe3a901f297..2cb05fa6f0c270e968ff3c3dbf15d8d00f3fb4ae 100755 (executable)
@@ -51,7 +51,6 @@ _PROTOTYPE( phys_bytes umap_remote, (struct proc *rp, int seg,
                vir_bytes vir_addr, vir_bytes bytes)                    );
 _PROTOTYPE( phys_bytes umap_bios, (struct proc *rp, vir_bytes vir_addr,
                vir_bytes bytes)                                        );
-_PROTOTYPE( int generic_handler, (irq_hook_t *hook)                    );
 
 #if (CHIP == INTEL)
 
index b4f19d01670b0dee714de69fd8407cd668235a1c..714bf37327b9a7e41c677c742ddc098fad605daa 100755 (executable)
  *   numap_local:      umap_local D segment from proc nr instead of pointer
  *   virtual_copy:     copy bytes from one virtual address to another 
  *   get_randomness:   accumulate randomness in a buffer
- *   generic_handler:  interrupt handler for user-level device drivers
  *
  * Changes:
- *   Apr 25, 2005   made mapping of call vector explicit  (Jorrit N. Herder)
- *   Oct 17, 2004   generic handler and IRQ policies  (Jorrit N. Herder)
  *   Oct 10, 2004   dispatch system calls from call vector  (Jorrit N. Herder)
  *   Sep 30, 2004   source code documentation updated  (Jorrit N. Herder)
- *   Sep 10, 2004   system call functions in library  (Jorrit N. Herder)
- *   2004 to 2005   various new syscalls (see syslib.h)  (Jorrit N. Herder)
+ *   2004 to 2005   various new syscalls (see system.h)  (Jorrit N. Herder)
  */
 
 #include "kernel.h"
@@ -184,6 +180,7 @@ int proc_type;                              /* system or user process flag */
       if (sp->s_proc_nr != NONE) return(ENOSPC);
       rc->p_priv = sp;                         /* assign new slot */
       rc->p_priv->s_proc_nr = proc_nr(rc);     /* set association */
+      rc->p_priv->s_flags = SYS_PROC;          /* mark as privileged */
   } else {
       rc->p_priv = &priv[USER_PRIV_ID];                /* use shared slot */
       rc->p_priv->s_proc_nr = INIT_PROC_NR;    /* set association */
@@ -228,34 +225,6 @@ int source;
 }
 
 
-/*===========================================================================*
- *                            generic_handler                               *
- *===========================================================================*/
-PUBLIC int generic_handler(hook)
-irq_hook_t *hook;      
-{
-/* This function handles hardware interrupt in a simple and generic way. All
- * interrupts are transformed into messages to a driver. The IRQ line will be
- * reenabled if the policy says so.
- */
-
-  /* As a side-effect, the interrupt handler gathers random information by 
-   * timestamping the interrupt events. This is used for /dev/random.
-   */
-  get_randomness(hook->irq);
-
-  /* Add a bit for this interrupt to the process' pending interrupts. When 
-   * sending the notification message, this bit map will be magically set
-   * as an argument. 
-   */
-  priv(proc_addr(hook->proc_nr))->s_int_pending |= (1 << hook->notify_id);
-
-  /* Build notification message and return. */
-  lock_notify(HARDWARE, hook->proc_nr);
-  return(hook->policy & IRQ_REENABLE);
-}
-
-
 /*===========================================================================*
  *                             send_sig                                     *
  *===========================================================================*/
index 96e2c53d5f8ffc687e9e9d36198b83af28c2fc06..f852ae6667ddc1e5580b7e1cfbb96ae78bac8c72 100644 (file)
@@ -25,7 +25,7 @@ OBJECTS       = \
        $(SYSTEM)(do_trace.o) \
        $(SYSTEM)(do_nice.o) \
        $(SYSTEM)(do_times.o) \
-       $(SYSTEM)(do_alarm.o) \
+       $(SYSTEM)(do_setalarm.o) \
        $(SYSTEM)(do_irqctl.o) \
        $(SYSTEM)(do_devio.o) \
        $(SYSTEM)(do_vdevio.o) \
@@ -82,8 +82,8 @@ $(SYSTEM)(do_nice.o): do_nice.c
 $(SYSTEM)(do_times.o): do_times.c
        $(CC) do_times.c
 
-$(SYSTEM)(do_alarm.o): do_alarm.c
-       $(CC) do_alarm.c
+$(SYSTEM)(do_setalarm.o):      do_setalarm.c
+       $(CC) do_setalarm.c
 
 $(SYSTEM)(do_irqctl.o):        do_irqctl.c
        $(CC) do_irqctl.c
index 8b2c247b4f78aa30493b4e08521fe0ddefbba262..3f9670fb379f5285e0b7d43f94732c28fe3fbb6b 100644 (file)
@@ -20,23 +20,25 @@ PUBLIC int do_abort(m_ptr)
 message *m_ptr;                        /* pointer to request message */
 {
 /* Handle sys_abort. MINIX is unable to continue. This can originate in the
- * PM (normal abort or panic) or FS (panic), or TTY (user issued CTRL-ALT-DEL 
- * or ESC after debugging dumps).
+ * PM (normal abort or panic) or FS (panic), or TTY (after CTRL-ALT-DEL). 
  */
   int how = m_ptr->ABRT_HOW;
+  int proc_nr;
+  int length;
+  phys_bytes src_phys;
 
   /* See if the monitor is to run the specified instructions. */
   if (how == RBT_MONITOR) {
-      int proc_nr = m_ptr->ABRT_MON_PROC;
-      int length = m_ptr->ABRT_MON_LEN + 1;
-      vir_bytes src_vir = (vir_bytes) m_ptr->ABRT_MON_ADDR;
-      phys_bytes src_phys = numap_local(proc_nr, src_vir, length);
-
-      /* Validate length and address of shutdown code before copying. */
-      if (length > kinfo.params_size || src_phys == 0)
-          phys_copy(vir2phys("delay;boot"), kinfo.params_base, 11);
-      else
-          phys_copy(src_phys, kinfo.params_base, (phys_bytes) length);
+
+      proc_nr = m_ptr->ABRT_MON_PROC;
+      if (! isokprocn(proc_nr)) return(EINVAL);
+      length = m_ptr->ABRT_MON_LEN + 1;
+      if (length > kinfo.params_size) return(E2BIG);
+      src_phys = numap_local(proc_nr,(vir_bytes)m_ptr->ABRT_MON_ADDR,length);
+      if (! src_phys) return(EFAULT);
+
+      /* Parameters seem ok, copy them and prepare shutting down. */
+      phys_copy(src_phys, kinfo.params_base, (phys_bytes) length);
   }
 
   /* Now prepare to shutdown MINIX. */
index 6f046364d461ae820338f0e14bd603e636e1feb0..5311bf570bb685a2e41fbb3ca801c87fa3909161 100644 (file)
@@ -23,8 +23,11 @@ message *m_ptr;                      /* pointer to request message */
  */
   register struct proc *rp;
 
+  /* Get process pointer and verify that it had signals pending. If the 
+   * process is already dead its flags will be reset. 
+   */
   rp = proc_addr(m_ptr->SIG_PROC);
-  if (isemptyp(rp)) return(EINVAL);            /* process already dead? */
+  if (! (rp->p_rts_flags & SIG_PENDING)) return(EINVAL);
 
   /* PM has finished one kernel signal. Perhaps process is ready now? */
   if (! (rp->p_rts_flags & SIGNALED))          /* new signal arrived */
index 8ae1df01c2c1aa5d848f14e99f835fc4fb8c549a..a342d2e6b7c82f0cf532e9c55eabc69c0e463bd8 100644 (file)
@@ -4,7 +4,6 @@
  * The parameters for this system call are:
  *    m1_i1:   PR_PROC_NR      (child's process table slot)    
  *    m1_i2:   PR_PPROC_NR     (parent, process that forked)   
- *    m1_i3:   PR_PID          (child pid received from PM)
  */
 
 #include "../system.h"
@@ -33,6 +32,18 @@ register message *m_ptr;     /* pointer to request message */
   rpc = proc_addr(m_ptr->PR_PROC_NR);
   if (isemptyp(rpp) || ! isemptyp(rpc)) return(EINVAL);
 
+  /* If this is a system process, make sure the child process gets its own
+   * privilege structure for accounting. This is the only part that can fail,
+   * so do this before allocating the process table slot.
+   */
+  if (priv(rpc)->s_flags & SYS_PROC) {
+      if (OK != (i=get_priv(rpc, SYS_PROC))) return(i);        /* get structure */
+      for (i=0; i< BITMAP_CHUNKS(NR_SYS_PROCS); i++)   /* remove pending: */
+          priv(rpc)->s_notify_pending.chunk[i] = 0;    /* - notifications */
+      priv(rpc)->s_int_pending = 0;                    /* - interrupts */
+      sigemptyset(&priv(rpc)->s_sig_pending);          /* - signals */
+  }
+
   /* Copy parent 'proc' struct to child. And reinitialize some fields. */
 #if (CHIP == INTEL)
   old_ldt_sel = rpc->p_ldt_sel;                /* backup local descriptors */
@@ -52,16 +63,6 @@ register message *m_ptr;     /* pointer to request message */
   rpc->p_user_time = 0;                /* set all the accounting times to 0 */
   rpc->p_sys_time = 0;
 
-  /* If this is a system process, make sure the child process gets its own
-   * privilege structure for accounting.
-   */
-  if (priv(rpc)->s_flags & SYS_PROC) {
-      if (OK != (i=get_priv(rpc, SYS_PROC))) return(i);        /* get structure */
-      for (i=0; i< BITMAP_CHUNKS(NR_SYS_PROCS); i++)   /* remove pending: */
-          priv(rpc)->s_notify_pending.chunk[i] = 0;    /* - notifications */
-      priv(rpc)->s_int_pending = 0;                    /* - interrupts */
-      sigemptyset(&priv(rpc)->s_sig_pending);          /* - signals */
-  }
   return(OK);
 }
 
index a7cbb2644f320b74df317ab7e57079e5ff2a861f..8b09f572d0c8a182573b5126c2f3de2e8bcfc064 100644 (file)
@@ -3,7 +3,6 @@
  *
  * The parameters for this system call are:
  *    m1_i3:   I_REQUEST       (what info to get)      
- *    m1_i4:   I_PROC_NR       (process to store value at)     
  *    m1_p1:   I_VAL_PTR       (where to put it)       
  *    m1_i1:   I_VAL_LEN       (maximum length expected, optional)     
  *    m1_p2:   I_VAL_PTR2      (second, optional pointer)      
@@ -47,7 +46,7 @@ register message *m_ptr;      /* pointer to request message */
         break;
     }
     case GET_IMAGE: {
-        length = sizeof(struct system_image) * NR_BOOT_PROCS;
+        length = sizeof(struct boot_image) * NR_BOOT_PROCS;
         src_phys = vir2phys(image);
         break;
     }
index 7d7d89f17876011458d31606f4940b852005dc3a..3833606ef91fb254617487a9887832607426946b 100644 (file)
@@ -5,7 +5,8 @@
  *    m5_c1:   IRQ_REQUEST     (control operation to perform)  
  *    m5_c2:   IRQ_VECTOR      (irq line that must be controlled)
  *    m5_i1:   IRQ_POLICY      (irq policy allows reenabling interrupts)
- *    m5_l3:   IRQ_HOOK_ID     (index of irq hook assigned at kernel)
+ *    m5_l3:   IRQ_HOOK_ID     (provides index to be returned on interrupt)
+ *      ,,          ,,          (returns index of irq hook assigned at kernel)
  *
  * Author:
  *    Jorrit N. Herder <jnherder@cs.vu.nl>
 
 #include "../system.h"
 
+
 #if USE_IRQCTL
 
+FORWARD _PROTOTYPE(int generic_handler, (irq_hook_t *hook));
+
 /*===========================================================================*
  *                             do_irqctl                                    *
  *===========================================================================*/
@@ -99,5 +103,33 @@ register message *m_ptr;    /* pointer to request message */
   return(r);
 }
 
+
+/*===========================================================================*
+ *                            generic_handler                               *
+ *===========================================================================*/
+PRIVATE int generic_handler(hook)
+irq_hook_t *hook;      
+{
+/* This function handles hardware interrupt in a simple and generic way. All
+ * interrupts are transformed into messages to a driver. The IRQ line will be
+ * reenabled if the policy says so.
+ */
+
+  /* As a side-effect, the interrupt handler gathers random information by 
+   * timestamping the interrupt events. This is used for /dev/random.
+   */
+  get_randomness(hook->irq);
+
+  /* Add a bit for this interrupt to the process' pending interrupts. When 
+   * sending the notification message, this bit map will be magically set
+   * as an argument. 
+   */
+  priv(proc_addr(hook->proc_nr))->s_int_pending |= (1 << hook->notify_id);
+
+  /* Build notification message and return. */
+  lock_notify(HARDWARE, hook->proc_nr);
+  return(hook->policy & IRQ_REENABLE);
+}
+
 #endif /* USE_IRQCTL */
 
index 9f8a248f47e362b3ab60e2f16159fed395f73665..442a0e4e898f36e119e3b7d7dda0db4a79914bc7 100644 (file)
@@ -30,6 +30,7 @@ message *m_ptr;                       /* pointer to request message */
   int sig_nr = m_ptr->SIG_NUMBER;
 
   if (! isokprocn(proc_nr) || sig_nr > _NSIG) return(EINVAL);
+  if (iskerneln(proc_nr)) return(EPERM);
 
   if (m_ptr->m_source == PM_PROC_NR) {
       /* Directly send signal notification to a system process. */
index 360fdc4102d16871befb62163eb0371f2983625a..0235c2e11ec3483a26b3609f713939841171e13c 100644 (file)
@@ -2,9 +2,9 @@
  *   m_type:   SYS_MEMSET
  *
  * The parameters for this system call are:
- *    m1_p1:   MEM_PTR         (virtual address)       
- *    m1_i1:   MEM_COUNT       (returns physical address)      
- *    m1_i2:   MEM_PATTERN     (size of datastructure)         
+ *    m2_p1:   MEM_PTR         (virtual address)       
+ *    m2_l1:   MEM_COUNT       (returns physical address)      
+ *    m2_l2:   MEM_PATTERN     (size of datastructure)         
  */
 
 #include "../system.h"
index 74048d9d610a060d3800ef6073b7a852ca24c36f..c9d70ce7b0e2b539622b1a13486cccb6192e28be 100644 (file)
@@ -26,6 +26,7 @@ message *m_ptr;                       /* pointer to request message */
   caller = m_ptr->m_source;
   map_ptr = (struct mem_map *) m_ptr->PR_MEM_PTR;
   if (! isokprocn(m_ptr->PR_PROC_NR)) return(EINVAL);
+  if (iskerneln(m_ptr->PR_PROC_NR)) return(EPERM);
   rp = proc_addr(m_ptr->PR_PROC_NR);
 
   /* Copy the map from PM. */
index eaa539e022e7ea7dc204c284f278aa3034f25b41..879ae32ffc1e69f65fff72884f1af30773febdc9 100644 (file)
@@ -23,6 +23,7 @@ PUBLIC int do_nice(message *m_ptr)
   /* Extract the message parameters and do sanity checking. */
   proc_nr = m_ptr->PR_PROC_NR;
   if (! isokprocn(proc_nr)) return(EINVAL);
+  if (iskerneln(proc_nr)) return(EPERM);
   pri = m_ptr->PR_PRIORITY;
   if (pri < PRIO_MIN || pri > PRIO_MAX) return(EINVAL);
 
index ed4835faaf9f5eab5dd38b53713f8f7aea2b2864..0882569c8d534a3c719ea9be6cd02f9446b0b969 100644 (file)
@@ -33,7 +33,7 @@ message *m_ptr;                       /* pointer to request message */
 
   /* Make sure this process has its own privileges structure. */
   if (! (priv(rp)->s_flags & SYS_PROC)) 
-      get_priv(rp, SYS_PROC);
+      if ((i=get_priv(rp, SYS_PROC)) != OK) return(i);
 
   /* Now update the process' privileges as requested. */
   rp->p_priv->s_call_mask = FILLED_MASK;
index 58ea4fd570f6883f0a600a63d74d9148064bfbea..7ca526ddb8ddfce76298dd6b68e05cd06282c192 100644 (file)
@@ -26,10 +26,13 @@ register message *m_ptr;    /* pointer to request message */
   long port = m_ptr->DIO_PORT;
   phys_bytes phys_buf;
 
-  /* Check if process number is OK. */
+  /* Check if process number is OK. A process number is allowed here, because
+   * driver may directly provide a pointer to a buffer at the user-process
+   * that initiated the device I/O. Kernel processes, of course, are denied.
+   */
   if (proc_nr == SELF) proc_nr = m_ptr->m_source;
-  if (! isokprocn(proc_nr))
-      return(EINVAL);
+  if (! isokprocn(proc_nr)) return(EINVAL);
+  if (iskerneln(proc_nr)) return(EPERM);
 
   /* Get and check physical address. */
   if ((phys_buf = numap_local(proc_nr, (vir_bytes) m_ptr->DIO_VEC_ADDR, count)) == 0)
similarity index 93%
rename from kernel/system/do_alarm.c
rename to kernel/system/do_setalarm.c
index a57c00f1e8eefe9a809bb70a25d522542ddfce9e..ac5ec61c133c1acd520be13c956f3cb44a7ecbaa 100644 (file)
@@ -23,6 +23,7 @@ PUBLIC int do_setalarm(m_ptr)
 message *m_ptr;                        /* pointer to request message */
 {
 /* A process requests a synchronous alarm, or wants to cancel its alarm. */
+  register struct proc *rp;    /* pointer to requesting process */
   int proc_nr;                 /* which process wants the alarm */
   long exp_time;               /* expiration time for this alarm */
   int use_abs_time;            /* use absolute or relative time */
@@ -30,12 +31,14 @@ message *m_ptr;                     /* pointer to request message */
   clock_t uptime;              /* placeholder for current uptime */
 
   /* Extract shared parameters from the request message. */
-  proc_nr = m_ptr->m_source;           /* process to interrupt later */
   exp_time = m_ptr->ALRM_EXP_TIME;     /* alarm's expiration time */
   use_abs_time = m_ptr->ALRM_ABS_TIME; /* flag for absolute time */
+  proc_nr = m_ptr->m_source;           /* process to interrupt later */
+  rp = proc_addr(proc_nr);
+  if (! (priv(rp)->s_flags & SYS_PROC)) return(EPERM);
 
   /* Get the timer structure and set the parameters for this alarm. */
-  tp = &(proc_addr(proc_nr)->p_priv->s_alarm_timer);   
+  tp = &(priv(rp)->s_alarm_timer);     
   tmr_arg(tp)->ta_int = proc_nr;       
   tp->tmr_func = cause_alarm; 
 
index 576240ccec9b49d818dfb5daef1920d020f99ab0..b77fb2713645c8e2d28d337ff48e1797753041cb 100644 (file)
@@ -27,6 +27,8 @@ message *m_ptr;                       /* pointer to request message */
   register struct proc *rp;
   phys_bytes src_phys;
 
+  if (! isokprocn(m_ptr->SIG_PROC)) return(EINVAL);
+  if (iskerneln(m_ptr->SIG_PROC)) return(EPERM);
   rp = proc_addr(m_ptr->SIG_PROC);
 
   /* Copy in the sigcontext structure. */
index 33bd85bad8253c8805625d501a16033146e3424a..f370483888ebcdeb4be41049eeef71cfa7f11fae 100644 (file)
@@ -29,6 +29,8 @@ message *m_ptr;                       /* pointer to request message */
   struct sigcontext sc, *scp;
   struct sigframe fr, *frp;
 
+  if (! isokprocn(m_ptr->SIG_PROC)) return(EINVAL);
+  if (iskerneln(m_ptr->SIG_PROC)) return(EPERM);
   rp = proc_addr(m_ptr->SIG_PROC);
 
   /* Get the sigmsg structure into our address space.  */
index 4f559f3b5eba00d50ef892fc5b374d10eb271433..278ce9bd57bf95218b1fd04b56c78f073982ee2c 100644 (file)
@@ -47,6 +47,9 @@ register message *m_ptr;
   int tr_proc_nr = m_ptr->CTL_PROC_NR;
   int i;
 
+  if (! isokprocn(tr_proc_nr)) return(EINVAL);
+  if (iskerneln(tr_proc_nr)) return(EPERM);
+
   rp = proc_addr(tr_proc_nr);
   if (isemptyp(rp)) return(EIO);
   switch (tr_request) {
index 26323afd6398c283a7b9ffd8ae874e43ab53a97e..47260cfc57d9f3e0f2c6600b66ee7783e03476c0 100644 (file)
@@ -2,13 +2,9 @@
  *   m_type:   SYS_VIRVCOPY, SYS_PHYSVCOPY 
  *
  * The parameters for this system call are:
- *    m5_c1:   CP_SRC_SPACE
- *    m5_l1:   CP_SRC_ADDR
- *    m5_i1:   CP_SRC_PROC_NR  
- *    m5_c2:   CP_DST_SPACE
- *    m5_l2:   CP_DST_ADDR     
- *    m5_i2:   CP_DST_PROC_NR  
- *    m5_l3:   CP_NR_BYTES
+ *    m1_i3:   VCP_VEC_SIZE            size of copy request vector 
+ *    m1_p1:   VCP_VEC_ADDR            address of vector at caller 
+ *    m1_i2:   VCP_NR_OK               number of successfull copies    
  */
 
 #include "../system.h"
@@ -52,16 +48,17 @@ register message *m_ptr;    /* pointer to request message */
   phys_copy(caller_phys, kernel_phys, (phys_bytes) bytes);
 
   /* Assume vector with requests is correct. Try to copy everything. */
+  m_ptr->VCP_NR_OK = 0;
   for (i=0; i<nr_req; i++) {
 
       req = &vir_cp_req[i];
 
       /* Check if physical addressing is used without SYS_PHYSVCOPY. */
       if (((req->src.segment | req->dst.segment) & PHYS_SEG) &&
-              m_ptr->m_type != SYS_PHYSVCOPY) 
-          return(EPERM);
+              m_ptr->m_type != SYS_PHYSVCOPY) return(EPERM);
       if ((s=virtual_copy(&req->src, &req->dst, req->count)) != OK) 
           return(s);
+      m_ptr->VCP_NR_OK ++;
   }
   return(OK);
 }
index 9c455fcb69a421288ecd4e0575578582c242739c..dfc4a64052bc4dd17c282fd2c8f3509765ca2653 100644 (file)
 #if USE_VDEVIO
 
 /* Buffer for SYS_VDEVIO to copy (port,value)-pairs from/ to user. */
-PRIVATE char vdevio_pv_buf[VDEVIO_BUF_SIZE];      
+PRIVATE char vdevio_buf[VDEVIO_BUF_SIZE];      
+PRIVATE pvb_pair_t *pvb = (pvb_pair_t *) vdevio_buf;           
+PRIVATE pvw_pair_t *pvw = (pvw_pair_t *) vdevio_buf;      
+PRIVATE pvl_pair_t *pvl = (pvl_pair_t *) vdevio_buf;     
 
-/* SYS_VDEVIO sends a pointer to a (port,value)-pairs vector at the caller. 
- * Define the maximum number of (port,value)-pairs that can be handled in a 
- * in a single SYS_VDEVIO system call based on the struct definitions. 
- */
-#define MAX_PVB_PAIRS ((VDEVIO_BUF_SIZE * sizeof(char)) / sizeof(pvb_pair_t))
-#define MAX_PVW_PAIRS ((VDEVIO_BUF_SIZE * sizeof(char)) / sizeof(pvw_pair_t))
-#define MAX_PVL_PAIRS ((VDEVIO_BUF_SIZE * sizeof(char)) / sizeof(pvl_pair_t))
-       
 
 /*===========================================================================*
  *                             do_vdevio                                    *
@@ -37,88 +32,57 @@ register message *m_ptr;    /* pointer to request message */
  * that I/O batch from being interrrupted.
  * This is the counterpart of do_devio, which performs a single device I/O. 
  */ 
-    pvb_pair_t *pvb_pairs;      /* needed for byte values */
-    pvw_pair_t *pvw_pairs;      /* needed for word values */
-    pvl_pair_t *pvl_pairs;      /* needed for long values */
-    int i;
-    int caller_proc;            /* process number of caller */
-    size_t bytes;               /* # bytes to be copied */
-    vir_bytes caller_vir;       /* virtual address at caller */
-    phys_bytes caller_phys;     /* physical address at caller */
-    phys_bytes kernel_phys;     /* physical address in kernel */
-
-
-    /* Check if nr of ports is ok and get size of (port,value) data. */
-    if (m_ptr->DIO_VEC_SIZE <= 0) return(EINVAL);
-    switch(m_ptr->DIO_TYPE) {
-    case DIO_BYTE:
-        if (m_ptr->DIO_VEC_SIZE > MAX_PVB_PAIRS)  return(EINVAL);
-        bytes = (size_t) (m_ptr->DIO_VEC_SIZE * sizeof(pvb_pair_t));
-        break;
-    case DIO_WORD:
-        if (m_ptr->DIO_VEC_SIZE > MAX_PVW_PAIRS)  return(EINVAL);
-        bytes = (size_t) (m_ptr->DIO_VEC_SIZE * sizeof(pvw_pair_t));
-        break;
-    case DIO_LONG:
-        if (m_ptr->DIO_VEC_SIZE > MAX_PVL_PAIRS)  return(EINVAL);
-        bytes = (size_t) (m_ptr->DIO_VEC_SIZE * sizeof(pvl_pair_t));
-        break;
-    default:   /* this once and for all checks for a correct type */
-        return(EINVAL);
-    }
+  int vec_size;               /* size of vector */
+  int io_in;                  /* true if input */
+  size_t bytes;               /* # bytes to be copied */
+  int caller_proc;            /* process number of caller */
+  vir_bytes caller_vir;       /* virtual address at caller */
+  phys_bytes caller_phys;     /* physical address at caller */
+  int i;
+    
+  /* Get the request, size of the request vector, and check the values. */
+  if (m_ptr->DIO_REQUEST == DIO_INPUT) io_in = TRUE;
+  else if (m_ptr->DIO_REQUEST == DIO_OUTPUT) io_in = FALSE;
+  else return(EINVAL);
+  if ((vec_size = m_ptr->DIO_VEC_SIZE) <= 0) return(EINVAL);
+  switch (m_ptr->DIO_TYPE) {
+      case DIO_BYTE: bytes = vec_size * sizeof(pvb_pair_t); break;
+      case DIO_WORD: bytes = vec_size * sizeof(pvw_pair_t); break;
+      case DIO_LONG: bytes = vec_size * sizeof(pvl_pair_t); break;
+      default:  return(EINVAL);   /* check type once and for all */
+  }
+  if (bytes > sizeof(vdevio_buf))  return(E2BIG);
 
-    /* Calculate physical addresses and copy (port,value)-pairs from user. */
-    caller_proc = m_ptr->m_source; 
-    caller_vir = (vir_bytes) m_ptr->DIO_VEC_ADDR;
-    caller_phys = umap_local(proc_addr(caller_proc), D, caller_vir, bytes);
-    if (0 == caller_phys) return EFAULT;
-    kernel_phys = vir2phys(vdevio_pv_buf);
-    phys_copy(caller_phys, kernel_phys, (phys_bytes) bytes);
+  /* Calculate physical addresses and copy (port,value)-pairs from user. */
+  caller_proc = m_ptr->m_source; 
+  caller_vir = (vir_bytes) m_ptr->DIO_VEC_ADDR;
+  caller_phys = umap_local(proc_addr(caller_proc), D, caller_vir, bytes);
+  if (0 == caller_phys) return(EFAULT);
+  phys_copy(caller_phys, vir2phys(vdevio_buf), (phys_bytes) bytes);
 
-    /* Perform actual device I/O for byte, word, and long values. Note that 
-    * the entire switch is wrapped in lock() and unlock() to prevent the I/O
-    * batch from being interrupted. It may be cleaner to do this just around 
-    * the for loops, but this results in rather lenghty code.
-    */
-    lock(13, "do_vdevio");
-    switch (m_ptr->DIO_TYPE) {
-        case DIO_BYTE:                                          /* byte values */
-            pvb_pairs = (pvb_pair_t *) vdevio_pv_buf;
-            if (DIO_INPUT == m_ptr->DIO_REQUEST) { 
-                for (i=0; i < m_ptr->DIO_VEC_SIZE; i++) 
-                    pvb_pairs[i].value = inb(pvb_pairs[i].port); 
-            } else { 
-                for (i=0; i < m_ptr->DIO_VEC_SIZE; i++) 
-                    outb(pvb_pairs[i].port, pvb_pairs[i].value); 
-            } 
-            break; 
-        case DIO_WORD:                                   /* word values */
-            pvw_pairs = (pvw_pair_t *) vdevio_pv_buf;
-            if (DIO_INPUT == m_ptr->DIO_REQUEST) {
-                for (i=0; i < m_ptr->DIO_VEC_SIZE; i++) 
-                    pvw_pairs[i].value = inw(pvw_pairs[i].port);  
-            } else {
-                for (i=0; i < m_ptr->DIO_VEC_SIZE; i++) 
-                    outw(pvw_pairs[i].port, pvw_pairs[i].value); 
-            }
-            break; 
-       case DIO_LONG:                  /* fall through: long values */
-        default:  /* only DIO_LONG can arrive here, see above switch */
-            pvl_pairs = (pvl_pair_t *) vdevio_pv_buf;
-            if (DIO_INPUT == m_ptr->DIO_REQUEST) { 
-                for (i=0; i < m_ptr->DIO_VEC_SIZE; i++) 
-                    pvl_pairs[i].value = inl(pvl_pairs[i].port);  
-            } else {
-                for (i=0; i < m_ptr->DIO_VEC_SIZE; i++) 
-                    outl(pvb_pairs[i].port, pvl_pairs[i].value); 
-            }
-    }
-    unlock(13);
+  /* Perform actual device I/O for byte, word, and long values. Note that 
+   * the entire switch is wrapped in lock() and unlock() to prevent the I/O
+   * batch from being interrupted. 
+   */  
+  lock(13, "do_vdevio");
+  switch (m_ptr->DIO_TYPE) {
+  case DIO_BYTE:                                        /* byte values */
+      if (io_in) for (i=0; i<vec_size; i++)  pvb[i].value = inb(pvb[i].port); 
+      else       for (i=0; i<vec_size; i++)  outb(pvb[i].port, pvb[i].value); 
+      break; 
+  case DIO_WORD:                                         /* word values */
+      if (io_in) for (i=0; i<vec_size; i++)  pvw[i].value = inw(pvw[i].port);  
+      else       for (i=0; i<vec_size; i++)  outw(pvw[i].port, pvw[i].value); 
+      break; 
+  default:                                               /* long values */
+      if (io_in) for (i=0; i<vec_size; i++) pvl[i].value = inl(pvl[i].port);  
+      else       for (i=0; i<vec_size; i++) outl(pvb[i].port, pvl[i].value); 
+  }
+  unlock(13);
     
-    /* Almost done, copy back results for input requests. */
-    if (DIO_INPUT == m_ptr->REQUEST)
-        phys_copy(kernel_phys, caller_phys, (phys_bytes) bytes);
-    return(OK);
+  /* Almost done, copy back results for input requests. */
+  if (io_in) phys_copy(vir2phys(vdevio_buf), caller_phys, (phys_bytes) bytes);
+  return(OK);
 }
 
 #endif /* USE_VDEVIO */
index c11ed4982c8975e6d7ae7434dcad6b97492662a6..7aad531145ae2b71eaf482798567a642a89e456e 100755 (executable)
@@ -19,7 +19,7 @@
  * or PRIVATE. The reason for this is that extern variables cannot have a  
  * default initialization. If such variables are shared, they must also be
  * declared in one of the *.h files without the initialization.  Examples 
- * include 'system_image' (this file) and 'idt' and 'gdt' (protect.c). 
+ * include 'boot_image' (this file) and 'idt' and 'gdt' (protect.c). 
  *
  * Changes:
  *    Nov 10, 2004   removed controller->driver mappings  (Jorrit N. Herder)
@@ -68,10 +68,10 @@ PUBLIC char *t_stack[TOT_STACK_SPACE / sizeof(char *)];
 #define USER_T          8              /* ticks */
 #define SYS_T          16              /* ticks */
 
-PUBLIC struct system_image image[] = {
+PUBLIC struct boot_image image[] = {
  { IDLE,    idle_task,  IDLE_F, IDLE_T,   IDLE_Q,  IDLE_S,    EMPTY_MASK, EMPTY_MASK,    "IDLE"    },
- { CLOCK,   clock_task, TASK_F, SYS_T,   TASK_Q, CLOCK_S,   FILLED_MASK, SYSTEM_SEND_MASK,   "CLOCK"   },
- { SYSTEM,  sys_task,   TASK_F, SYS_T,   TASK_Q, SYSTEM_S,     FILLED_MASK, SYSTEM_SEND_MASK,  "SYSTEM"     },
+ { CLOCK,   clock_task, TASK_F, SYS_T,   TASK_Q, CLOCK_S,   TASK_CALL_MASK, SYSTEM_SEND_MASK,   "CLOCK"   },
+ { SYSTEM,  sys_task,   TASK_F, SYS_T,   TASK_Q, SYSTEM_S,     TASK_CALL_MASK, SYSTEM_SEND_MASK,  "SYSTEM"     },
  { HARDWARE,   0,       TASK_F, SYS_T,   TASK_Q, HARDWARE_S, EMPTY_MASK, SYSTEM_SEND_MASK, "KERNEL" },
  { PM_PROC_NR, 0,       SYS_F, SYS_T, 3, 0,          FILLED_MASK,   SERVER_SEND_MASK,      "PM"      },
  { FS_PROC_NR, 0,       SYS_F, SYS_T, 4, 0,          FILLED_MASK,   SERVER_SEND_MASK,      "FS"      },
@@ -111,5 +111,5 @@ PUBLIC struct system_image image[] = {
  * a compile time error. Note that no space is allocated because 'dummy' is
  * declared extern.
   */
-extern int dummy[(NR_BOOT_PROCS==sizeof(image)/sizeof(struct system_image))?1:-1];
+extern int dummy[(NR_BOOT_PROCS==sizeof(image)/sizeof(struct boot_image))?1:-1];
 
index 4d9a8890af5c4dd70a604fd91146e1d0edd5e484..5db8942297dcfde35a0a9f19d94df47c76dc370c 100755 (executable)
@@ -10,7 +10,7 @@ typedef struct {                      /* bitmap for system indexes */
   bitchunk_t chunk[BITMAP_CHUNKS(NR_SYS_PROCS)];
 } sys_map_t;
 
-struct system_image {
+struct boot_image {
   proc_nr_t proc_nr;                   /* process number to use */
   task_t *initial_pc;                  /* start function for tasks */
   int flags;                           /* process flags */