2009-01-26 18:43:59 +01:00
|
|
|
/* The kernel call implemented in this file:
|
2013-09-21 00:58:46 +02:00
|
|
|
* m_type: SYS_DIAGCTL
|
2009-01-26 18:43:59 +01:00
|
|
|
*
|
|
|
|
* The parameters for this kernel call are:
|
2013-09-21 00:58:46 +02:00
|
|
|
* DIAGCTL_CODE request
|
|
|
|
* and then request-specific arguments in DIAGCTL_ARG1 and DIAGCTL_ARG2.
|
2009-01-26 18:43:59 +01:00
|
|
|
*/
|
|
|
|
|
2010-04-02 00:22:33 +02:00
|
|
|
#include "kernel/system.h"
|
2009-01-26 18:43:59 +01:00
|
|
|
|
|
|
|
|
|
|
|
/*===========================================================================*
|
2013-09-21 00:58:46 +02:00
|
|
|
* do_diagctl *
|
2009-01-26 18:43:59 +01:00
|
|
|
*===========================================================================*/
|
2013-09-21 00:58:46 +02:00
|
|
|
int do_diagctl(struct proc * caller, message * m_ptr)
|
2009-01-26 18:43:59 +01:00
|
|
|
{
|
|
|
|
vir_bytes len, buf;
|
|
|
|
static char mybuf[DIAG_BUFSIZE];
|
2009-01-27 13:54:33 +01:00
|
|
|
int s, i, proc_nr;
|
2009-01-26 18:43:59 +01:00
|
|
|
|
2013-09-21 00:58:46 +02:00
|
|
|
switch (m_ptr->DIAGCTL_CODE) {
|
|
|
|
case DIAGCTL_CODE_DIAG:
|
|
|
|
buf = (vir_bytes) m_ptr->DIAGCTL_ARG1;
|
|
|
|
len = (vir_bytes) m_ptr->DIAGCTL_ARG2;
|
2009-01-26 18:43:59 +01:00
|
|
|
if(len < 1 || len > DIAG_BUFSIZE) {
|
2013-09-21 00:58:46 +02:00
|
|
|
printf("do_diagctl: diag for %d: len %d out of range\n",
|
2009-01-26 18:43:59 +01:00
|
|
|
caller->p_endpoint, len);
|
|
|
|
return EINVAL;
|
|
|
|
}
|
2010-02-09 16:20:09 +01:00
|
|
|
if((s=data_copy_vmcheck(caller, caller->p_endpoint, buf, KERNEL,
|
2010-02-03 10:04:48 +01:00
|
|
|
(vir_bytes) mybuf, len)) != OK) {
|
2013-09-21 00:58:46 +02:00
|
|
|
printf("do_diagctl: diag for %d: len %d: copy failed: %d\n",
|
2009-01-26 18:43:59 +01:00
|
|
|
caller->p_endpoint, len, s);
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
for(i = 0; i < len; i++)
|
|
|
|
kputc(mybuf[i]);
|
|
|
|
kputc(END_OF_KMESS);
|
|
|
|
return OK;
|
2013-09-21 00:58:46 +02:00
|
|
|
case DIAGCTL_CODE_STACKTRACE:
|
|
|
|
if(!isokendpt(m_ptr->DIAGCTL_ARG2, &proc_nr))
|
2009-01-27 13:54:33 +01:00
|
|
|
return EINVAL;
|
|
|
|
proc_stacktrace(proc_addr(proc_nr));
|
|
|
|
return OK;
|
2013-09-21 15:03:20 +02:00
|
|
|
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;
|
2009-01-26 18:43:59 +01:00
|
|
|
default:
|
2013-09-21 00:58:46 +02:00
|
|
|
printf("do_diagctl: invalid request %d\n", m_ptr->DIAGCTL_CODE);
|
2009-01-26 18:43:59 +01:00
|
|
|
return(EINVAL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|