No empty .Rs/.Re
[netbsd-mini2440.git] / sys / compat / irix / irix_syssgi.c
blob9fa2b9d2509401cbfdba3525644ecac25c6b1b3a
1 /* $NetBSD: irix_syssgi.c,v 1.49 2009/01/11 20:00:06 rumble Exp $ */
3 /*-
4 * Copyright (c) 2001, 2002, 2008 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Emmanuel Dreyfus.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: irix_syssgi.c,v 1.49 2009/01/11 20:00:06 rumble Exp $");
35 #if defined(_KERNEL_OPT)
36 #include "opt_ddb.h"
37 #endif
39 #ifndef ELFSIZE
40 #ifdef _LP64
41 #define ELFSIZE 64
42 #else
43 #define ELFSIZE 32
44 #endif
45 #endif
47 /* round up and down to page boundaries. Borrowed from sys/kern/exec_elf32.c */
48 #define ELF_ROUND(a, b) (((a) + (b) - 1) & ~((b) - 1))
49 #define ELF_TRUNC(a, b) ((a) & ~((b) - 1))
51 #include <sys/types.h>
52 #include <sys/param.h>
53 #include <sys/kernel.h>
54 #include <sys/malloc.h>
55 #include <sys/systm.h>
56 #include <sys/filedesc.h>
57 #include <sys/buf.h>
58 #include <sys/vnode.h>
59 #include <sys/file.h>
60 #include <sys/resourcevar.h>
61 #include <sys/sysctl.h>
62 #include <sys/exec.h>
63 #include <sys/exec_elf.h>
64 #include <sys/mount.h>
65 #include <sys/syscallargs.h>
67 #include <uvm/uvm_extern.h>
69 #include <compat/common/compat_util.h>
71 #include <compat/svr4/svr4_types.h>
73 #include <compat/irix/irix_types.h>
74 #include <compat/irix/irix_signal.h>
75 #include <compat/irix/irix_exec.h>
76 #include <compat/irix/irix_prctl.h>
77 #include <compat/irix/irix_syscall.h>
78 #include <compat/irix/irix_syscallargs.h>
79 #include <compat/irix/irix_syssgi.h>
81 /* In sys/kern/exec_elf32.c */
82 void ELFNAME(load_psection)(struct exec_vmcmd_set *, struct vnode *,
83 const Elf_Phdr *, Elf_Addr *, u_long *, int *, int);
85 static int irix_syssgi_mapelf(int, Elf_Phdr *, int,
86 struct lwp *, register_t *);
87 static int irix_syssgi_sysconf(int name, struct lwp *, register_t *);
88 static int irix_syssgi_pathconf(char *, int, struct lwp *, register_t *);
90 int
91 irix_sys_syssgi(struct lwp *l, const struct irix_sys_syssgi_args *uap, register_t *retval)
93 /* {
94 syscallarg(int) request;
95 syscallarg(void *) arg1;
96 syscallarg(void *) arg2;
97 syscallarg(void *) arg3;
98 syscallarg(void *) arg4;
99 syscallarg(void *) arg5;
100 } */
101 struct proc *p = l->l_proc;
102 int request = SCARG(uap, request);
103 void *arg1, *arg2, *arg3;
105 #ifdef DEBUG_IRIX
106 printf("irix_sys_syssgi(): request = %d\n", request);
107 #endif
108 switch(request) {
109 case IRIX_SGI_SYSID: /* Get HostID */
110 *retval = (register_t)hostid;
111 break;
113 case IRIX_SGI_SETGROUPS: { /* setgroups(2) */
114 struct sys_setgroups_args cup;
116 SCARG(&cup, gidsetsize) = (intptr_t)SCARG(uap, arg1);
117 SCARG(&cup, gidset) = (gid_t *)SCARG(uap, arg2);
118 return (sys_setgroups(l, &cup, retval));
119 break;
122 case IRIX_SGI_GETGROUPS: { /* getgroups(2) */
123 struct sys_getgroups_args cup;
125 SCARG(&cup, gidsetsize) = (intptr_t)SCARG(uap, arg1);
126 SCARG(&cup, gidset) = (gid_t *)SCARG(uap, arg2);
127 return (sys_getgroups(l, &cup, retval));
128 break;
131 case IRIX_SGI_SETSID: /* Set session ID: setsid(2) */
132 return (sys_setsid(l, NULL, retval));
133 break;
135 case IRIX_SGI_GETSID: { /* Get session ID: getsid(2) */
136 struct sys_getsid_args cup;
138 SCARG(&cup, pid) = (pid_t)(intptr_t)SCARG(uap, arg1);
139 return (sys_getsid(l, &cup, retval));
140 break;
143 case IRIX_SGI_GETPGID: {/* Get parent process GID: getpgid(2) */
144 struct sys_getpgid_args cup;
146 SCARG(&cup, pid) = (pid_t)(intptr_t)SCARG(uap, arg1);
147 return (sys_getpgid(l, &cup, retval));
148 break;
151 case IRIX_SGI_SETPGID: {/* Get parent process GID: setpgid(2) */
152 struct sys_setpgid_args cup;
154 SCARG(&cup, pid) = (pid_t)(intptr_t)SCARG(uap, arg1);
155 SCARG(&cup, pgid) = (pid_t)(intptr_t)SCARG(uap, arg2);
156 return (sys_setpgid(l, &cup, retval));
157 break;
160 case IRIX_SGI_PATHCONF: /* Get file limits: pathconf(3) */
161 return irix_syssgi_pathconf((char *)SCARG(uap, arg1),
162 (intptr_t)SCARG(uap, arg2), l, retval);
163 break;
165 case IRIX_SGI_RUSAGE: { /* BSD getrusage(2) */
166 struct compat_50_sys_getrusage_args cup;
168 SCARG(&cup, who) = (intptr_t)SCARG(uap, arg1);
169 SCARG(&cup, rusage) = (struct rusage50 *)SCARG(uap, arg2);
170 return compat_50_sys_getrusage(l, &cup, retval);
173 case IRIX_SGI_NUM_MODULES: /* <sys/systeminfo.h> get_num_modules() */
174 *retval = 1;
175 return 0;
176 break;
178 case IRIX_SGI_MODULE_INFO: { /* <sys/systeminfo.h> get_module_info() */
179 int module_num = (intptr_t)SCARG(uap, arg1);
180 struct irix_module_info_s *imip = SCARG(uap, arg2);
181 int mss = (intptr_t)SCARG(uap, arg3);
182 struct irix_module_info_s imi;
183 char *idx;
185 if (module_num != 0)
186 return EINVAL;
188 imi.serial_num = (u_int64_t)hostid;
189 imi.mod_num = 0;
190 (void)snprintf(imi.serial_str, IRIX_MAX_SERIAL_SIZE,
191 "0800%08x", (u_int32_t)hostid);
193 /* Convert to upper case */
194 for (idx = imi.serial_str; *idx; idx++)
195 if (*idx >= 'a' && *idx <= 'f')
196 *idx += ('A' - 'a');
198 /* Don't copyout irrelevant data on user request */
199 if (mss > sizeof(struct irix_module_info_s))
200 mss = sizeof(struct irix_module_info_s);
202 return copyout(&imi, imip, mss);
203 break;
206 case IRIX_SGI_RDNAME: { /* Read Processes' name */
207 struct proc *tp;
209 arg1 = SCARG(uap, arg1); /* PID of the process */
210 arg2 = SCARG(uap, arg2); /* Address of user buffer */
211 arg3 = SCARG(uap, arg3); /* Length of user buffer */
212 tp = pfind((pid_t)(intptr_t)arg1);
213 if (tp == NULL || \
214 tp->p_psstr == NULL || \
215 tp->p_psstr->ps_argvstr == NULL || \
216 tp->p_psstr->ps_argvstr[0] == NULL)
217 return 0;
219 *retval = (register_t)copyout(tp->p_psstr->ps_argvstr[0],
220 (void *)arg2, (size_t)arg3);
222 break;
224 case IRIX_SGI_TUNE: /* Tune system variables */
225 case IRIX_SGI_IDBG: /* Kernel debugging */
226 case IRIX_SGI_INVENT: /* Get system inventory */
227 case IRIX_SGI_SETLED: /* Turn on/off LEDs */
228 case IRIX_SGI_SETNVRAM: /* Sets a NVRAM variable value */
229 case IRIX_SGI_GETNVRAM: /* Gets a NVRAM variable value */
230 return EINVAL;
231 break;
233 case IRIX_SGI_ELFMAP: /* Maps an ELF image */
234 arg1 = SCARG(uap, arg1); /* file descriptor */
235 arg2 = SCARG(uap, arg2); /* ptr to ELF program header array */
236 arg3 = SCARG(uap, arg3); /* array's length */
237 return irix_syssgi_mapelf((intptr_t)arg1, (Elf_Phdr *)arg2,
238 (intptr_t)arg3, l, retval);
239 break;
241 case IRIX_SGI_USE_FP_BCOPY: /* bcopy and bzero can use FPU or not */
243 * Our kernel does not use FPU, hence we do nothing.
245 break;
247 case IRIX_SGI_TOSSTSAVE: /* Kill saved pregions */
249 * Our kernel does not seem to save such "pregions",
250 * therefore we do not have to do anything.
252 break;
254 case IRIX_SGI_SYSCONF: /* POSIX sysconf */
255 arg1 = SCARG(uap, arg1); /* system variable name */
256 return irix_syssgi_sysconf((intptr_t)arg1, l, retval);
257 break;
259 case IRIX_SGI_SATCTL: /* control audit stream */
260 case IRIX_SGI_RXEV_GET: /* Trusted IRIX call */
261 /* Undocumented (?) and unimplemented */
262 return 0;
263 break;
265 case IRIX_SGI_FDHI: /* getdtablehi(3): get higher open fd + 1 */
266 *retval = (register_t)(p->p_fd->fd_lastfile + 1);
267 return 0;
268 break;
270 default:
271 printf("Warning: call to unimplemented syssgi() command %d\n",
272 request);
273 return EINVAL;
274 break;
277 return 0;
280 static int
281 irix_syssgi_mapelf(int fd, Elf_Phdr *ph, int count, struct lwp *l, register_t *retval)
283 Elf_Phdr *kph;
284 Elf_Phdr *pht;
285 int error = 0;
286 int i,j;
287 int prot;
288 int flags;
289 u_long size;
290 Elf_Addr uaddr;
291 Elf_Addr reloc_offset;
292 file_t *fp;
293 struct exec_vmcmd_set vcset;
294 struct exec_vmcmd *base_vcp = NULL;
295 struct vnode *vp;
296 struct vm_map_entry *ret;
297 struct exec_vmcmd *vcp;
298 int need_relocation;
300 vcset.evs_cnt = 0;
301 vcset.evs_used = 0;
303 kph = (Elf_Phdr *)malloc(sizeof(Elf_Phdr) * count, M_TEMP, M_WAITOK);
304 error = copyin(ph, kph, sizeof(Elf_Phdr) * count);
305 if (error)
306 goto bad;
308 pht = kph;
309 need_relocation = 0;
310 for (i = 0; i < count; i++) {
311 /* Check that each ELF sections is loadable */
312 if (pht->p_type != PT_LOAD) {
313 error = ENOEXEC;
314 goto bad;
318 * Check that the section load addresses are increasing
319 * with the section in the program header array. We do
320 * not support any other situation.
322 if (pht->p_vaddr < kph->p_vaddr) {
323 #ifdef DEBUG_IRIX
324 printf("mapelf: unsupported psection order\n");
325 #endif
326 error = EINVAL;
327 goto bad;
331 * Check that the default load addresses are free.
332 * If not, we will have to perform a relocation
334 ret = uvm_map_findspace(&l->l_proc->p_vmspace->vm_map,
335 pht->p_vaddr, pht->p_memsz, (vaddr_t *)(void *)&uaddr,
336 NULL, 0, 0, UVM_FLAG_FIXED);
337 if (ret == NULL)
338 need_relocation = 1;
339 pht++;
343 * Perform a relocation
345 if (need_relocation) {
347 * compute the size needed by the section union. This
348 * assumes that the section load addresses are increasing.
349 * (And also that the sections are not overlapping)
351 pht--;
352 size = ELF_ROUND((pht->p_vaddr + pht->p_memsz), pht->p_align) -
353 ELF_TRUNC(kph->p_vaddr, kph->p_align);
355 /* Find a free place for the sections */
356 ret = uvm_map_findspace(&l->l_proc->p_vmspace->vm_map,
357 IRIX_MAPELF_RELOCATE, size, (vaddr_t *)(void *)&uaddr,
358 NULL, 0, kph->p_align, 0);
360 if (ret == NULL) {
361 error = ENOMEM;
362 goto bad;
366 * Relocate the sections, all with the same offset.
368 reloc_offset = uaddr - kph->p_vaddr;
369 pht = kph;
370 for (i = 0; i < count; i++) {
371 #ifdef DEBUG_IRIX
372 printf("mapelf: relocating section %d from %p to %p\n",
373 i, (void *)pht->p_vaddr,
374 (void *)(pht->p_vaddr + reloc_offset));
375 #endif
376 pht->p_vaddr += reloc_offset;
377 pht++;
381 /* Find the file's vnode */
382 fp = fd_getfile(fd);
383 if (fp == NULL) {
384 error = EBADF;
385 goto bad;
387 vp = fp->f_data;
389 error = vn_marktext(vp);
390 if (error)
391 goto bad_unuse;
394 * Load the sections
396 pht = kph;
397 for (i = 0; i < count; i++) {
398 #ifdef DEBUG_IRIX
399 printf("mapelf: loading section %d (len 0x%08lx) at %p\n",
400 i, (long)pht->p_memsz, (void *)pht->p_vaddr);
401 #endif
402 /* Build the vmcmds for loading the section */
403 kill_vmcmds(&vcset);
404 uaddr = pht->p_vaddr;
405 size = 0;
406 prot = 0;
407 flags = VMCMD_BASE;
409 ELFNAME(load_psection)(&vcset, vp, pht, &uaddr,
410 &size, &prot, flags);
412 /* Execute the vmcmds */
413 for (j = 0; j < vcset.evs_used && !error; j++) {
414 vcp = &vcset.evs_cmds[j];
415 if (vcp->ev_flags & VMCMD_RELATIVE) {
416 if (base_vcp == NULL)
417 panic("irix_syssgi_mapelf(): bad vmcmd base");
419 vcp->ev_addr += base_vcp->ev_addr;
421 IRIX_VM_SYNC(l->l_proc, error = (*vcp->ev_proc)(l, vcp));
422 if (error)
423 goto bad_unuse;
425 pht++;
428 *retval = (register_t)kph->p_vaddr;
430 bad_unuse:
431 fd_putfile(fd);
432 bad:
433 free(kph, M_TEMP);
434 return error;
439 static int
440 irix_syssgi_sysconf(int name, struct lwp *l, register_t *retval)
442 struct proc *p = l->l_proc;
443 int error = 0;
444 int mib[2], value;
445 size_t len = sizeof(value);
447 switch (name) {
448 case IRIX_SC_ARG_MAX:
449 mib[0] = CTL_KERN;
450 mib[1] = KERN_ARGMAX;
451 break;
452 case IRIX_SC_CHILD_MAX:
453 *retval = (register_t)p->p_rlimit[RLIMIT_NPROC].rlim_cur;
454 return 0;
455 break;
456 case IRIX_SC_CLK_TCK:
457 *retval = hz;
458 return 0;
459 break;
460 case IRIX_SC_NGROUPS_MAX:
461 mib[0] = CTL_KERN;
462 mib[1] = KERN_NGROUPS;
463 break;
464 case IRIX_SC_OPEN_MAX:
465 *retval = (register_t)p->p_rlimit[RLIMIT_NOFILE].rlim_cur;
466 return 0;
467 break;
468 case IRIX_SC_JOB_CONTROL:
469 mib[0] = CTL_KERN;
470 mib[1] = KERN_JOB_CONTROL;
471 break;
472 case IRIX_SC_SAVED_IDS:
473 mib[0] = CTL_KERN;
474 mib[1] = KERN_SAVED_IDS;
475 break;
476 case IRIX_SC_IP_SECOPTS:/* IP security options */
477 /* Trusted IRIX capabilities are unsupported */
478 case IRIX_SC_ACL: /* ACcess Lists */
479 case IRIX_SC_AUDIT: /* Audit */
480 case IRIX_SC_INF: /* Information labels */
481 case IRIX_SC_MAC: /* Mandatory Access Control */
482 case IRIX_SC_CAP: /* Capabilities */
483 *retval = 0;
484 return 0;
485 break;
486 case IRIX_SC_PAGESIZE:
487 mib[0] = CTL_HW;
488 mib[1] = HW_PAGESIZE;
489 break;
491 case IRIX_SC_PASS_MAX:
492 case IRIX_SC_VERSION:
493 default:
494 printf("Warning: syssgi(SYSCONF) unsupported variable %d\n",
495 name);
496 return EINVAL;
497 break;
501 * calling into sysctl with superuser privs, but we don't mind
502 * 'cause we're only querying a value.
504 error = old_sysctl(&mib[0], 2, &value, &len, NULL, 0, NULL);
505 if (error == 0)
506 *retval = value;
507 return (error);
510 static int
511 irix_syssgi_pathconf(char *path, int name, struct lwp *l, register_t *retval)
513 struct sys_pathconf_args cup;
514 int bname;
516 switch (name) {
517 case IRIX_PC_LINK_MAX:
518 case IRIX_PC_MAX_CANON:
519 case IRIX_PC_MAX_INPUT:
520 case IRIX_PC_NAME_MAX:
521 case IRIX_PC_PATH_MAX:
522 case IRIX_PC_PIPE_BUF:
523 case IRIX_PC_CHOWN_RESTRICTED:
524 case IRIX_PC_NO_TRUNC:
525 case IRIX_PC_VDISABLE:
526 case IRIX_PC_SYNC_IO:
527 bname = name;
528 break;
529 case IRIX_PC_FILESIZEBITS:
530 bname = _PC_FILESIZEBITS;
531 break;
532 case IRIX_PC_PRIO_IO:
533 case IRIX_PC_ASYNC_IO:
534 case IRIX_PC_ABI_ASYNC_IO:
535 case IRIX_PC_ABI_AIO_XFER_MAX:
536 default:
537 printf("Warning: unimplemented IRIX pathconf() command %d\n",
538 name);
539 *retval = 0;
540 return 0;
541 break;
543 SCARG(&cup, path) = path;
544 SCARG(&cup, name) = bname;
545 return sys_pathconf(l, &cup, retval);