208 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			208 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include "../kernel.h"
 | |
| #include "../system.h"
 | |
| #include <unistd.h>
 | |
| INIT_ASSERT
 | |
| 
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *			          do_unused				     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC int do_unused(m)
 | |
| message *m;				/* pointer to request message */
 | |
| {
 | |
|   kprintf("SYS task got illegal request from %d.", m->m_source);
 | |
|   return(EBADREQUEST);		/* illegal message type */
 | |
| }
 | |
| 
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *			          do_random				     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC int do_random(m)
 | |
| message *m;				/* pointer to request message */
 | |
| {
 | |
|   return(ENOSYS);			/* no yet implemented */
 | |
| }
 | |
| 
 | |
| 
 | |
| /* The system call implemented in this file:
 | |
|  *   m_type:	SYS_ABORT
 | |
|  *
 | |
|  * The parameters for this system call are:
 | |
|  *    m1_i1:	ABRT_HOW 	(how to abort, possibly fetch monitor params)	
 | |
|  *    m1_i2:	ABRT_MON_PROC 	(proc nr to get monitor params from)	
 | |
|  *    m1_i3:	ABRT_MON_LEN	(length of monitor params)
 | |
|  *    m1_p1:	ABRT_MON_ADDR 	(virtual address of params)	
 | |
|  */
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				do_abort				     *
 | |
|  *===========================================================================*/
 | |
| 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 (a CTRL-ALT-DEL or ESC
 | |
|  * after debugging dumps).
 | |
|  */
 | |
|   register struct proc *rp;
 | |
|   phys_bytes src_phys;
 | |
|   vir_bytes len;
 | |
|   int how = m_ptr->ABRT_HOW;
 | |
|   
 | |
|   rp = proc_addr(m_ptr->m_source);
 | |
| 
 | |
|   if (how == RBT_MONITOR) {
 | |
| 	/* The monitor is to run user specified instructions. */
 | |
| 	len = m_ptr->ABRT_MON_LEN + 1;
 | |
| 	assert(len <= kinfo.params_size);
 | |
| 	src_phys = numap_local(m_ptr->ABRT_MON_PROC, 
 | |
| 		(vir_bytes) m_ptr->ABRT_MON_ADDR, len);
 | |
| 	assert(src_phys != 0);
 | |
| 	phys_copy(src_phys, kinfo.params_base, (phys_bytes) len);
 | |
|   }
 | |
|   prepare_shutdown(how);
 | |
|   return(OK);				/* pro-forma (really EDISASTER) */
 | |
| }
 | |
| 
 | |
| /* The system call implemented in this file:
 | |
|  *   m_type:	SYS_GETINFO
 | |
|  *
 | |
|  * 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_KEY_PTR	(environment variable key)	
 | |
|  *    m1_i2:	I_KEY_LEN	(lenght of environment variable key)	
 | |
|  * 
 | |
|  * Author:
 | |
|  *    Jorrit N. Herder <jnherder@cs.vu.nl>
 | |
|  */
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *			        do_getinfo				     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC int do_getinfo(m_ptr)
 | |
| register message *m_ptr;	/* pointer to request message */
 | |
| {
 | |
| /* Request system information to be copied to caller's address space. */
 | |
|   size_t length;
 | |
|   phys_bytes src_phys; 
 | |
|   phys_bytes dst_phys; 
 | |
|   int proc_nr, nr;
 | |
| 
 | |
|   /* Set source address and length based on request type. */      
 | |
|   switch (m_ptr->I_REQUEST) {	
 | |
|     case GET_MACHINE: {
 | |
|     	length = sizeof(struct machine);
 | |
|     	src_phys = vir2phys(&machine);
 | |
|     	break;
 | |
|     }
 | |
|     case GET_KINFO: {
 | |
|     	length = sizeof(struct kinfo);
 | |
|     	src_phys = vir2phys(&kinfo);
 | |
|     	break;
 | |
|     }
 | |
|     case GET_IMAGE: {
 | |
|     	length = sizeof(struct system_image) * IMAGE_SIZE;
 | |
|     	src_phys = vir2phys(image);
 | |
|         break;
 | |
|     }
 | |
|     case GET_IRQHOOKS: {
 | |
|     	length = sizeof(struct irq_hook) * NR_IRQ_HOOKS;
 | |
|     	src_phys = vir2phys(irq_hooks);
 | |
|         break;
 | |
|     }
 | |
|     case GET_MEMCHUNKS: {
 | |
|         length = sizeof(struct memory) * NR_MEMS;
 | |
|         src_phys = vir2phys(mem);
 | |
|         break;
 | |
|     }
 | |
|     case GET_SCHEDINFO: {
 | |
|         /* This is slightly complicated because we need two data structures
 | |
|          * at once, otherwise the scheduling information may be incorrect.
 | |
|          * Copy the queue heads and fall through to copy the process table. 
 | |
|          */
 | |
|         length = sizeof(struct proc *) * NR_SCHED_QUEUES;
 | |
|         src_phys = vir2phys(rdy_head);
 | |
|         dst_phys = numap_local(m_ptr->m_source, (vir_bytes) m_ptr->I_KEY_PTR,
 | |
|         	 length); 
 | |
|         if (src_phys == 0 || dst_phys == 0) return(EFAULT);
 | |
|         phys_copy(src_phys, dst_phys, length);
 | |
|     }
 | |
|     case GET_PROCTAB: {
 | |
|     	length = sizeof(struct proc) * (NR_PROCS + NR_TASKS);
 | |
|     	src_phys = vir2phys(proc);
 | |
|         break;
 | |
|     }
 | |
|     case GET_PROC: {
 | |
|     	nr = (m_ptr->I_KEY_LEN == SELF) ? m_ptr->m_source : m_ptr->I_KEY_LEN;
 | |
|     	if (! isokprocn(nr)) return(EINVAL);
 | |
|     	length = sizeof(struct proc);
 | |
|     	src_phys = vir2phys(proc_addr(nr));
 | |
|         break;
 | |
|     }
 | |
|     case GET_MONPARAMS: {
 | |
|     	src_phys = kinfo.params_base;	/* already is a physical address! */
 | |
|     	length = kinfo.params_size;
 | |
|     	break;
 | |
|     }
 | |
|     case GET_PROCNR: {
 | |
|         if (m_ptr->I_KEY_LEN == 0) {		/* get own process nr */
 | |
| #if DEAD_CODE
 | |
| 	/* GET_PROCNR functionality will be moved to the Process Manager! */
 | |
|         kprintf("GET_PROCNR (own) from %d\n", m_ptr->m_source);
 | |
| #endif
 | |
|             src_phys = vir2phys(&proc_nr);	
 | |
|             length = sizeof(int);
 | |
|         } else {				/* lookup nr by name */
 | |
|   	    int proc_found = FALSE;
 | |
|   	    struct proc *pp;
 | |
| 	    struct vir_addr vsrc, vdst;
 | |
|   	    char key[8];	/* storage for process name to lookup */
 | |
| #if DEAD_CODE
 | |
| 	/* GET_PROCNR functionality will be moved to the Process Manager! */
 | |
|         kprintf("GET_PROCNR (by name) from %d\n", m_ptr->m_source);
 | |
| #endif
 | |
|   proc_nr = m_ptr->m_source;	/* only caller can request copy */
 | |
|     	    if (m_ptr->I_KEY_LEN > sizeof(key)) return(EINVAL);
 | |
| 	    vsrc.proc_nr = proc_nr; vsrc.segment = D; vsrc.offset = (vir_bytes) m_ptr->I_KEY_PTR;
 | |
| 	    vdst.proc_nr = SYSTASK, vdst.segment = D; vdst.offset = (vir_bytes) key;
 | |
| 	    if (virtual_copy(&vsrc, &vdst, m_ptr->I_KEY_LEN) != OK) return(EFAULT);
 | |
| #if DEAD_CODE
 | |
|     	    if (vir_copy(proc_nr, (vir_bytes) m_ptr->I_KEY_PTR, SYSTASK,
 | |
|     	        (vir_bytes) key, m_ptr->I_KEY_LEN) != OK) return(EFAULT);
 | |
| #endif
 | |
|   	    for (pp=BEG_PROC_ADDR; pp<END_PROC_ADDR; pp++) {
 | |
| 		if (kstrncmp(pp->p_name, key, m_ptr->I_KEY_LEN) == 0) {
 | |
| 			src_phys = vir2phys(&(pp->p_nr));
 | |
|             		length = sizeof(int);
 | |
| 			proc_found = TRUE;
 | |
| 			break;
 | |
| 		}
 | |
| 	    }
 | |
| 	    if (! proc_found) return(ESRCH);
 | |
|         }
 | |
|         break;
 | |
|     }
 | |
|     case GET_KMESSAGES: {
 | |
|         length = sizeof(struct kmessages);
 | |
|         src_phys = vir2phys(&kmess);
 | |
|         break;
 | |
|     }
 | |
|     default:
 | |
|         return(EINVAL);
 | |
|   }
 | |
| 
 | |
|   /* Try to make the actual copy for the requested data. */
 | |
|   if (m_ptr->I_VAL_LEN > 0 && length > m_ptr->I_VAL_LEN) return (E2BIG);
 | |
|   proc_nr = m_ptr->m_source;	/* only caller can request copy */
 | |
|   dst_phys = numap_local(proc_nr, (vir_bytes) m_ptr->I_VAL_PTR, length); 
 | |
|   if (src_phys == 0 || dst_phys == 0) return(EFAULT);
 | |
|   phys_copy(src_phys, dst_phys, length);
 | |
|   return(OK);
 | |
| }
 | |
| 
 | |
| 
 | 
