xref: /minix/minix/kernel/system/do_getinfo.c (revision 0a6a1f1d)
1 /* The kernel call implemented in this file:
2  *   m_type:	SYS_GETINFO
3  *
4  * The parameters for this kernel call are:
5  *   m_lsys_krn_sys_getinfo.request	(what info to get)
6  *   m_lsys_krn_sys_getinfo.val_ptr 	(where to put it)
7  *   m_lsys_krn_sys_getinfo.val_len 	(maximum length expected, optional)
8  *   m_lsys_krn_sys_getinfo.val_ptr2	(second, optional pointer)
9  *   m_lsys_krn_sys_getinfo.val_len2_e	(second length or process nr)
10  *
11  * Upon return of the GETWHOAMI request the following parameters are used:
12  *   m_krn_lsys_sys_getwhoami.endpt	(the caller endpoint)
13  *   m_krn_lsys_sys_getwhoami.privflags	(the caller priviledes)
14  *   m_krn_lsys_sys_getwhoami.initflags (the caller initflags)
15  *   m_krn_lsys_sys_getwhoami.name	(the caller process name)
16  *
17  */
18 
19 #include <string.h>
20 
21 #include "kernel/system.h"
22 
23 
24 #if USE_GETINFO
25 
26 #include <minix/u64.h>
27 #include <sys/resource.h>
28 
29 /*===========================================================================*
30  *			        update_idle_time			     *
31  *===========================================================================*/
32 static void update_idle_time(void)
33 {
34 	int i;
35 	struct proc * idl = proc_addr(IDLE);
36 
37 	idl->p_cycles = make64(0, 0);
38 
39 	for (i = 0; i < CONFIG_MAX_CPUS ; i++) {
40 		idl->p_cycles += get_cpu_var(i, idle_proc).p_cycles;
41 	}
42 }
43 
44 /*===========================================================================*
45  *			        do_getinfo				     *
46  *===========================================================================*/
47 int do_getinfo(struct proc * caller, message * m_ptr)
48 {
49 /* Request system information to be copied to caller's address space. This
50  * call simply copies entire data structures to the caller.
51  */
52   size_t length;
53   vir_bytes src_vir;
54   int nr_e, nr, r;
55   int wipe_rnd_bin = -1;
56   struct proc *p;
57   struct rusage r_usage;
58 
59   /* Set source address and length based on request type. */
60   switch (m_ptr->m_lsys_krn_sys_getinfo.request) {
61     case GET_MACHINE: {
62         length = sizeof(struct machine);
63         src_vir = (vir_bytes) &machine;
64         break;
65     }
66     case GET_KINFO: {
67         length = sizeof(struct kinfo);
68         src_vir = (vir_bytes) &kinfo;
69         break;
70     }
71     case GET_LOADINFO: {
72         length = sizeof(struct loadinfo);
73         src_vir = (vir_bytes) &kloadinfo;
74         break;
75     }
76     case GET_CPUINFO: {
77         length = sizeof(cpu_info);
78         src_vir = (vir_bytes) &cpu_info;
79         break;
80     }
81     case GET_HZ: {
82         length = sizeof(system_hz);
83         src_vir = (vir_bytes) &system_hz;
84         break;
85     }
86     case GET_IMAGE: {
87         length = sizeof(struct boot_image) * NR_BOOT_PROCS;
88         src_vir = (vir_bytes) image;
89         break;
90     }
91     case GET_IRQHOOKS: {
92         length = sizeof(struct irq_hook) * NR_IRQ_HOOKS;
93         src_vir = (vir_bytes) irq_hooks;
94         break;
95     }
96     case GET_PROCTAB: {
97 	update_idle_time();
98         length = sizeof(struct proc) * (NR_PROCS + NR_TASKS);
99         src_vir = (vir_bytes) proc;
100         break;
101     }
102     case GET_PRIVTAB: {
103         length = sizeof(struct priv) * (NR_SYS_PROCS);
104         src_vir = (vir_bytes) priv;
105         break;
106     }
107     case GET_PROC: {
108         nr_e = (m_ptr->m_lsys_krn_sys_getinfo.val_len2_e == SELF) ?
109 		caller->p_endpoint : m_ptr->m_lsys_krn_sys_getinfo.val_len2_e;
110 	if(!isokendpt(nr_e, &nr)) return EINVAL; /* validate request */
111         length = sizeof(struct proc);
112         src_vir = (vir_bytes) proc_addr(nr);
113         break;
114     }
115     case GET_PRIV: {
116         nr_e = (m_ptr->m_lsys_krn_sys_getinfo.val_len2_e == SELF) ?
117             caller->p_endpoint : m_ptr->m_lsys_krn_sys_getinfo.val_len2_e;
118         if(!isokendpt(nr_e, &nr)) return EINVAL; /* validate request */
119         length = sizeof(struct priv);
120         src_vir = (vir_bytes) priv_addr(nr_to_id(nr));
121         break;
122     }
123     case GET_REGS: {
124         nr_e = (m_ptr->m_lsys_krn_sys_getinfo.val_len2_e == SELF) ?
125             caller->p_endpoint : m_ptr->m_lsys_krn_sys_getinfo.val_len2_e;
126         if(!isokendpt(nr_e, &nr)) return EINVAL; /* validate request */
127         p = proc_addr(nr);
128         length = sizeof(p->p_reg);
129         src_vir = (vir_bytes) &p->p_reg;
130         break;
131     }
132     case GET_WHOAMI: {
133 	int len;
134 	m_ptr->m_krn_lsys_sys_getwhoami.endpt = caller->p_endpoint;
135 	len = MIN(sizeof(m_ptr->m_krn_lsys_sys_getwhoami.name),
136 		sizeof(caller->p_name))-1;
137 	strncpy(m_ptr->m_krn_lsys_sys_getwhoami.name, caller->p_name, len);
138 	m_ptr->m_krn_lsys_sys_getwhoami.name[len] = '\0';
139 	m_ptr->m_krn_lsys_sys_getwhoami.privflags = priv(caller)->s_flags;
140         m_ptr->m_krn_lsys_sys_getwhoami.initflags = priv(caller)->s_init_flags;
141 	return OK;
142     }
143     case GET_MONPARAMS: {
144         src_vir = (vir_bytes) kinfo.param_buf;
145 	length = sizeof(kinfo.param_buf);
146         break;
147     }
148     case GET_RANDOMNESS: {
149         static struct k_randomness copy;	/* copy to keep counters */
150 	int i;
151 
152         copy = krandom;
153         for (i= 0; i<RANDOM_SOURCES; i++) {
154   		krandom.bin[i].r_size = 0;	/* invalidate random data */
155   		krandom.bin[i].r_next = 0;
156 	}
157     	length = sizeof(copy);
158     	src_vir = (vir_bytes) &copy;
159     	break;
160     }
161     case GET_RANDOMNESS_BIN: {
162 	int bin = m_ptr->m_lsys_krn_sys_getinfo.val_len2_e;
163 
164 	if(bin < 0 || bin >= RANDOM_SOURCES) {
165 		printf("SYSTEM: GET_RANDOMNESS_BIN: %d out of range\n", bin);
166 		return EINVAL;
167 	}
168 
169 	if(krandom.bin[bin].r_size < RANDOM_ELEMENTS)
170 		return ENOENT;
171 
172     	length = sizeof(krandom.bin[bin]);
173     	src_vir = (vir_bytes) &krandom.bin[bin];
174 
175 	wipe_rnd_bin = bin;
176 
177     	break;
178     }
179     case GET_IRQACTIDS: {
180         length = sizeof(irq_actids);
181         src_vir = (vir_bytes) irq_actids;
182         break;
183     }
184     case GET_IDLETSC: {
185 	struct proc * idl;
186 	update_idle_time();
187 	idl = proc_addr(IDLE);
188         length = sizeof(idl->p_cycles);
189         src_vir = (vir_bytes) &idl->p_cycles;
190         break;
191     }
192     default:
193 	printf("do_getinfo: invalid request %d\n",
194 		m_ptr->m_lsys_krn_sys_getinfo.request);
195         return(EINVAL);
196   }
197 
198   /* Try to make the actual copy for the requested data. */
199   if (m_ptr->m_lsys_krn_sys_getinfo.val_len > 0 &&
200 	length > m_ptr->m_lsys_krn_sys_getinfo.val_len)
201 	return (E2BIG);
202 
203   r = data_copy_vmcheck(caller, KERNEL, src_vir, caller->p_endpoint,
204 	m_ptr->m_lsys_krn_sys_getinfo.val_ptr, length);
205 
206   if(r != OK) return r;
207 
208 	if(wipe_rnd_bin >= 0 && wipe_rnd_bin < RANDOM_SOURCES) {
209 		krandom.bin[wipe_rnd_bin].r_size = 0;
210 		krandom.bin[wipe_rnd_bin].r_next = 0;
211 	}
212 
213   return(OK);
214 }
215 
216 #endif /* USE_GETINFO */
217 
218