1 /* $NetBSD: irix_syssgi.c,v 1.49 2009/01/11 20:00:06 rumble Exp $ */
4 * Copyright (c) 2001, 2002, 2008 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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)
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>
58 #include <sys/vnode.h>
60 #include <sys/resourcevar.h>
61 #include <sys/sysctl.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
*);
91 irix_sys_syssgi(struct lwp
*l
, const struct irix_sys_syssgi_args
*uap
, register_t
*retval
)
94 syscallarg(int) request;
95 syscallarg(void *) arg1;
96 syscallarg(void *) arg2;
97 syscallarg(void *) arg3;
98 syscallarg(void *) arg4;
99 syscallarg(void *) arg5;
101 struct proc
*p
= l
->l_proc
;
102 int request
= SCARG(uap
, request
);
103 void *arg1
, *arg2
, *arg3
;
106 printf("irix_sys_syssgi(): request = %d\n", request
);
109 case IRIX_SGI_SYSID
: /* Get HostID */
110 *retval
= (register_t
)hostid
;
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
));
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
));
131 case IRIX_SGI_SETSID
: /* Set session ID: setsid(2) */
132 return (sys_setsid(l
, NULL
, retval
));
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
));
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
));
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
));
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
);
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() */
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
;
188 imi
.serial_num
= (u_int64_t
)hostid
;
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')
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
);
206 case IRIX_SGI_RDNAME
: { /* Read Processes' name */
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
);
214 tp
->p_psstr
== NULL
|| \
215 tp
->p_psstr
->ps_argvstr
== NULL
|| \
216 tp
->p_psstr
->ps_argvstr
[0] == NULL
)
219 *retval
= (register_t
)copyout(tp
->p_psstr
->ps_argvstr
[0],
220 (void *)arg2
, (size_t)arg3
);
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 */
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
);
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.
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.
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
);
259 case IRIX_SGI_SATCTL
: /* control audit stream */
260 case IRIX_SGI_RXEV_GET
: /* Trusted IRIX call */
261 /* Undocumented (?) and unimplemented */
265 case IRIX_SGI_FDHI
: /* getdtablehi(3): get higher open fd + 1 */
266 *retval
= (register_t
)(p
->p_fd
->fd_lastfile
+ 1);
271 printf("Warning: call to unimplemented syssgi() command %d\n",
281 irix_syssgi_mapelf(int fd
, Elf_Phdr
*ph
, int count
, struct lwp
*l
, register_t
*retval
)
291 Elf_Addr reloc_offset
;
293 struct exec_vmcmd_set vcset
;
294 struct exec_vmcmd
*base_vcp
= NULL
;
296 struct vm_map_entry
*ret
;
297 struct exec_vmcmd
*vcp
;
303 kph
= (Elf_Phdr
*)malloc(sizeof(Elf_Phdr
) * count
, M_TEMP
, M_WAITOK
);
304 error
= copyin(ph
, kph
, sizeof(Elf_Phdr
) * count
);
310 for (i
= 0; i
< count
; i
++) {
311 /* Check that each ELF sections is loadable */
312 if (pht
->p_type
!= PT_LOAD
) {
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
) {
324 printf("mapelf: unsupported psection order\n");
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
);
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)
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);
366 * Relocate the sections, all with the same offset.
368 reloc_offset
= uaddr
- kph
->p_vaddr
;
370 for (i
= 0; i
< count
; i
++) {
372 printf("mapelf: relocating section %d from %p to %p\n",
373 i
, (void *)pht
->p_vaddr
,
374 (void *)(pht
->p_vaddr
+ reloc_offset
));
376 pht
->p_vaddr
+= reloc_offset
;
381 /* Find the file's vnode */
389 error
= vn_marktext(vp
);
397 for (i
= 0; i
< count
; i
++) {
399 printf("mapelf: loading section %d (len 0x%08lx) at %p\n",
400 i
, (long)pht
->p_memsz
, (void *)pht
->p_vaddr
);
402 /* Build the vmcmds for loading the section */
404 uaddr
= pht
->p_vaddr
;
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
));
428 *retval
= (register_t
)kph
->p_vaddr
;
440 irix_syssgi_sysconf(int name
, struct lwp
*l
, register_t
*retval
)
442 struct proc
*p
= l
->l_proc
;
445 size_t len
= sizeof(value
);
448 case IRIX_SC_ARG_MAX
:
450 mib
[1] = KERN_ARGMAX
;
452 case IRIX_SC_CHILD_MAX
:
453 *retval
= (register_t
)p
->p_rlimit
[RLIMIT_NPROC
].rlim_cur
;
456 case IRIX_SC_CLK_TCK
:
460 case IRIX_SC_NGROUPS_MAX
:
462 mib
[1] = KERN_NGROUPS
;
464 case IRIX_SC_OPEN_MAX
:
465 *retval
= (register_t
)p
->p_rlimit
[RLIMIT_NOFILE
].rlim_cur
;
468 case IRIX_SC_JOB_CONTROL
:
470 mib
[1] = KERN_JOB_CONTROL
;
472 case IRIX_SC_SAVED_IDS
:
474 mib
[1] = KERN_SAVED_IDS
;
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 */
486 case IRIX_SC_PAGESIZE
:
488 mib
[1] = HW_PAGESIZE
;
491 case IRIX_SC_PASS_MAX
:
492 case IRIX_SC_VERSION
:
494 printf("Warning: syssgi(SYSCONF) unsupported variable %d\n",
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
);
511 irix_syssgi_pathconf(char *path
, int name
, struct lwp
*l
, register_t
*retval
)
513 struct sys_pathconf_args cup
;
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
:
529 case IRIX_PC_FILESIZEBITS
:
530 bname
= _PC_FILESIZEBITS
;
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
:
537 printf("Warning: unimplemented IRIX pathconf() command %d\n",
543 SCARG(&cup
, path
) = path
;
544 SCARG(&cup
, name
) = bname
;
545 return sys_pathconf(l
, &cup
, retval
);