/* The kernel call implemented in this file: * m_type: SYS_DIAGCTL * * The parameters for this kernel call are: * m_lsys_krn_sys_diagctl.code request * and then request-specific arguments in * m_lsys_krn_sys_diagctl.buf * m_lsys_krn_sys_diagctl.len * m_lsys_krn_sys_diagctl.endpt */ #include "kernel/system.h" /*===========================================================================* * do_diagctl * *===========================================================================*/ int do_diagctl(struct proc * caller, message * m_ptr) { vir_bytes len, buf; static char mybuf[DIAG_BUFSIZE]; int s, i, proc_nr; switch (m_ptr->m_lsys_krn_sys_diagctl.code) { case DIAGCTL_CODE_DIAG: buf = m_ptr->m_lsys_krn_sys_diagctl.buf; len = m_ptr->m_lsys_krn_sys_diagctl.len; if(len < 1 || len > DIAG_BUFSIZE) { printf("do_diagctl: diag for %d: len %d out of range\n", caller->p_endpoint, len); return EINVAL; } if((s=data_copy_vmcheck(caller, caller->p_endpoint, buf, KERNEL, (vir_bytes) mybuf, len)) != OK) { printf("do_diagctl: diag for %d: len %d: copy failed: %d\n", caller->p_endpoint, len, s); return s; } for(i = 0; i < len; i++) kputc(mybuf[i]); kputc(END_OF_KMESS); return OK; case DIAGCTL_CODE_STACKTRACE: if(!isokendpt(m_ptr->m_lsys_krn_sys_diagctl.endpt, &proc_nr)) return EINVAL; proc_stacktrace(proc_addr(proc_nr)); return OK; case DIAGCTL_CODE_REGISTER: if (!(priv(caller)->s_flags & SYS_PROC)) return EPERM; priv(caller)->s_diag_sig = TRUE; /* If the message log is not empty, send a first notification * immediately. After bootup the log is basically never empty. */ if (kmess.km_size > 0 && !kinfo.do_serial_debug) send_sig(caller->p_endpoint, SIGKMESS); return OK; case DIAGCTL_CODE_UNREGISTER: if (!(priv(caller)->s_flags & SYS_PROC)) return EPERM; priv(caller)->s_diag_sig = FALSE; return OK; default: printf("do_diagctl: invalid request %d\n", m_ptr->m_lsys_krn_sys_diagctl.code); return(EINVAL); } }