The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/compat/irix/irix_syssgi.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: irix_syssgi.c,v 1.48 2008/04/28 20:23:42 martin Exp $ */
    2 
    3 /*-
    4  * Copyright (c) 2001, 2002, 2008 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Emmanuel Dreyfus.
    9  *
   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.
   18  *
   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.
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __KERNEL_RCSID(0, "$NetBSD: irix_syssgi.c,v 1.48 2008/04/28 20:23:42 martin Exp $");
   34 
   35 #if defined(_KERNEL_OPT)
   36 #include "opt_ddb.h"
   37 #endif
   38 
   39 #ifndef ELFSIZE
   40 #define ELFSIZE 32
   41 #endif
   42 
   43 /* round up and down to page boundaries. Borrowed from sys/kern/exec_elf32.c */
   44 #define ELF_ROUND(a, b)         (((a) + (b) - 1) & ~((b) - 1))
   45 #define ELF_TRUNC(a, b)         ((a) & ~((b) - 1))
   46 
   47 #include <sys/types.h>
   48 #include <sys/param.h>
   49 #include <sys/kernel.h>
   50 #include <sys/malloc.h>
   51 #include <sys/systm.h>
   52 #include <sys/filedesc.h>
   53 #include <sys/buf.h>
   54 #include <sys/vnode.h>
   55 #include <sys/file.h>
   56 #include <sys/resourcevar.h>
   57 #include <sys/sysctl.h>
   58 #include <sys/exec.h>
   59 #include <sys/exec_elf.h>
   60 #include <sys/mount.h>
   61 #include <sys/syscallargs.h>
   62 
   63 #include <uvm/uvm_extern.h>
   64 
   65 #include <compat/common/compat_util.h>
   66 
   67 #include <compat/svr4/svr4_types.h>
   68 
   69 #include <compat/irix/irix_types.h>
   70 #include <compat/irix/irix_signal.h>
   71 #include <compat/irix/irix_exec.h>
   72 #include <compat/irix/irix_prctl.h>
   73 #include <compat/irix/irix_syscall.h>
   74 #include <compat/irix/irix_syscallargs.h>
   75 #include <compat/irix/irix_syssgi.h>
   76 
   77 /* In sys/kern/exec_elf32.c */
   78 void    ELFNAME(load_psection)(struct exec_vmcmd_set *, struct vnode *,
   79             const Elf_Phdr *, Elf_Addr *, u_long *, int *, int);
   80 
   81 static int irix_syssgi_mapelf(int, Elf_Phdr *, int,
   82     struct lwp *, register_t *);
   83 static int irix_syssgi_sysconf(int name, struct lwp *, register_t *);
   84 static int irix_syssgi_pathconf(char *, int, struct lwp *, register_t *);
   85 
   86 int
   87 irix_sys_syssgi(struct lwp *l, const struct irix_sys_syssgi_args *uap, register_t *retval)
   88 {
   89         /* {
   90                 syscallarg(int) request;
   91                 syscallarg(void *) arg1;
   92                 syscallarg(void *) arg2;
   93                 syscallarg(void *) arg3;
   94                 syscallarg(void *) arg4;
   95                 syscallarg(void *) arg5;
   96         } */
   97         struct proc *p = l->l_proc;
   98         int request = SCARG(uap, request);
   99         void *arg1, *arg2, *arg3;
  100 
  101 #ifdef DEBUG_IRIX
  102         printf("irix_sys_syssgi(): request = %d\n", request);
  103 #endif
  104         switch(request) {
  105         case IRIX_SGI_SYSID:    /* Get HostID */
  106                 *retval = (register_t)hostid;
  107                 break;
  108 
  109         case IRIX_SGI_SETGROUPS: {      /* setgroups(2) */
  110                 struct sys_setgroups_args cup;
  111 
  112                 SCARG(&cup, gidsetsize) = (int)SCARG(uap, arg1);
  113                 SCARG(&cup, gidset) = (gid_t *)SCARG(uap, arg2);
  114                 return (sys_setgroups(l, &cup, retval));
  115                 break;
  116         }
  117 
  118         case IRIX_SGI_GETGROUPS: {      /* getgroups(2) */
  119                 struct sys_getgroups_args cup;
  120 
  121                 SCARG(&cup, gidsetsize) = (int)SCARG(uap, arg1);
  122                 SCARG(&cup, gidset) = (gid_t *)SCARG(uap, arg2);
  123                 return (sys_getgroups(l, &cup, retval));
  124                 break;
  125         }
  126 
  127         case IRIX_SGI_SETSID:   /* Set session ID: setsid(2) */
  128                 return (sys_setsid(l, NULL, retval));
  129                 break;
  130 
  131         case IRIX_SGI_GETSID: { /* Get session ID: getsid(2) */
  132                 struct sys_getsid_args cup;
  133 
  134                 SCARG(&cup, pid) = (pid_t)SCARG(uap, arg1);
  135                 return (sys_getsid(l, &cup, retval));
  136                 break;
  137         }
  138 
  139         case IRIX_SGI_GETPGID: {/* Get parent process GID: getpgid(2) */
  140                 struct sys_getpgid_args cup;
  141 
  142                 SCARG(&cup, pid) = (pid_t)SCARG(uap, arg1);
  143                 return (sys_getpgid(l, &cup, retval));
  144                 break;
  145         }
  146 
  147         case IRIX_SGI_SETPGID: {/* Get parent process GID: setpgid(2) */
  148                 struct sys_setpgid_args cup;
  149 
  150                 SCARG(&cup, pid) = (pid_t)SCARG(uap, arg1);
  151                 SCARG(&cup, pgid) = (pid_t)SCARG(uap, arg2);
  152                 return (sys_setpgid(l, &cup, retval));
  153                 break;
  154         }
  155 
  156         case IRIX_SGI_PATHCONF: /* Get file limits: pathconf(3) */
  157                 return irix_syssgi_pathconf((char *)SCARG(uap, arg1),
  158                     (int)SCARG(uap, arg2), l, retval);
  159                 break;
  160 
  161         case IRIX_SGI_RUSAGE: { /* BSD getrusage(2) */
  162                 struct sys_getrusage_args cup;
  163 
  164                 SCARG(&cup, who) = (int)SCARG(uap, arg1);
  165                 SCARG(&cup, rusage) = (struct rusage *)SCARG(uap, arg2);
  166                 return sys_getrusage(l, &cup, retval);
  167                 break;
  168         }
  169 
  170         case IRIX_SGI_NUM_MODULES: /* <sys/systeminfo.h> get_num_modules() */
  171                 *retval = 1;
  172                 return 0;
  173                 break;
  174 
  175         case IRIX_SGI_MODULE_INFO: { /* <sys/systeminfo.h> get_module_info() */
  176                 int module_num = (int)SCARG(uap, arg1);
  177                 struct irix_module_info_s *imip = SCARG(uap, arg2);
  178                 int mss = (int)SCARG(uap, arg3);
  179                 struct irix_module_info_s imi;
  180                 char *idx;
  181 
  182                 if (module_num != 0)
  183                         return EINVAL;
  184 
  185                 imi.serial_num = (u_int64_t)hostid;
  186                 imi.mod_num = 0;
  187                 (void)snprintf(imi.serial_str, IRIX_MAX_SERIAL_SIZE,
  188                     "0800%08x", (u_int32_t)hostid);
  189 
  190                 /* Convert to upper case */
  191                 for (idx = imi.serial_str; *idx; idx++)
  192                         if (*idx >= 'a' && *idx <= 'f')
  193                                 *idx += ('A' - 'a');
  194 
  195                 /* Don't copyout irrelevant data on user request */
  196                 if (mss > sizeof(struct irix_module_info_s))
  197                         mss = sizeof(struct irix_module_info_s);
  198 
  199                 return copyout(&imi, imip, mss);
  200                 break;
  201         }
  202 
  203         case IRIX_SGI_RDNAME: { /* Read Processes' name */
  204                 struct proc *tp;
  205 
  206                 arg1 = SCARG(uap, arg1); /* PID of the process */
  207                 arg2 = SCARG(uap, arg2); /* Address of user buffer */
  208                 arg3 = SCARG(uap, arg3); /* Length of user buffer */
  209                 tp = pfind((pid_t)arg1);
  210                 if (tp == NULL || \
  211                     tp->p_psstr == NULL || \
  212                     tp->p_psstr->ps_argvstr == NULL || \
  213                     tp->p_psstr->ps_argvstr[0] == NULL)
  214                         return 0;
  215 
  216                 *retval = (register_t)copyout(tp->p_psstr->ps_argvstr[0],
  217                     (void *)arg2, (size_t)arg3);
  218 
  219                 break;
  220         }
  221         case IRIX_SGI_TUNE:     /* Tune system variables */
  222         case IRIX_SGI_IDBG:     /* Kernel debugging */
  223         case IRIX_SGI_INVENT:   /* Get system inventory */
  224         case IRIX_SGI_SETLED:   /* Turn on/off LEDs */
  225         case IRIX_SGI_SETNVRAM: /* Sets a NVRAM variable value */
  226         case IRIX_SGI_GETNVRAM: /* Gets a NVRAM variable value */
  227                 return EINVAL;
  228                 break;
  229 
  230         case IRIX_SGI_ELFMAP:   /* Maps an ELF image */
  231                  arg1 = SCARG(uap, arg1); /* file descriptor  */
  232                  arg2 = SCARG(uap, arg2); /* ptr to ELF program header array */
  233                  arg3 = SCARG(uap, arg3); /* array's length */
  234                 return irix_syssgi_mapelf((int)arg1, (Elf_Phdr *)arg2,
  235                     (int)arg3, l, retval);
  236                 break;
  237 
  238         case IRIX_SGI_USE_FP_BCOPY:     /* bcopy and bzero can use FPU or not */
  239                 /*
  240                  * Our kernel does not use FPU, hence we do nothing.
  241                  */
  242                 break;
  243 
  244         case IRIX_SGI_TOSSTSAVE:        /* Kill saved pregions */
  245                 /*
  246                  * Our kernel does not seem to save such "pregions",
  247                  * therefore we do not have to do anything.
  248                  */
  249                 break;
  250 
  251         case IRIX_SGI_SYSCONF:          /* POSIX sysconf */
  252                 arg1 = SCARG(uap, arg1); /* system variable name */
  253                 return irix_syssgi_sysconf((int)arg1, l, retval);
  254                 break;
  255 
  256         case IRIX_SGI_SATCTL:           /* control audit stream */
  257         case IRIX_SGI_RXEV_GET:         /* Trusted IRIX call */
  258                 /* Undocumented (?) and unimplemented */
  259                 return 0;
  260                 break;
  261 
  262         case IRIX_SGI_FDHI:     /* getdtablehi(3): get higher open fd + 1 */
  263                 *retval = (register_t)(p->p_fd->fd_lastfile + 1);
  264                 return 0;
  265                 break;
  266 
  267         default:
  268                 printf("Warning: call to unimplemented syssgi() command %d\n",
  269                     request);
  270                     return EINVAL;
  271                 break;
  272         }
  273 
  274         return 0;
  275 }
  276 
  277 static int
  278 irix_syssgi_mapelf(int fd, Elf_Phdr *ph, int count, struct lwp *l, register_t *retval)
  279 {
  280         Elf_Phdr *kph;
  281         Elf_Phdr *pht;
  282         int error = 0;
  283         int i,j;
  284         int prot;
  285         int flags;
  286         u_long size;
  287         Elf_Addr uaddr;
  288         Elf_Addr reloc_offset;
  289         file_t *fp;
  290         struct exec_vmcmd_set vcset;
  291         struct exec_vmcmd *base_vcp = NULL;
  292         struct vnode *vp;
  293         struct vm_map_entry *ret;
  294         struct exec_vmcmd *vcp;
  295         int need_relocation;
  296 
  297         vcset.evs_cnt = 0;
  298         vcset.evs_used = 0;
  299 
  300         kph = (Elf_Phdr *)malloc(sizeof(Elf_Phdr) * count, M_TEMP, M_WAITOK);
  301         error = copyin(ph, kph, sizeof(Elf_Phdr) * count);
  302         if (error)
  303                 goto bad;
  304 
  305         pht = kph;
  306         need_relocation = 0;
  307         for (i = 0; i < count; i++) {
  308                 /* Check that each ELF sections is loadable */
  309                 if (pht->p_type != PT_LOAD) {
  310                         error = ENOEXEC;
  311                         goto bad;
  312                 }
  313 
  314                 /*
  315                  * Check that the section load addresses are increasing
  316                  * with the section in the program header array. We do
  317                  * not support any other situation.
  318                  */
  319                 if (pht->p_vaddr < kph->p_vaddr) {
  320 #ifdef DEBUG_IRIX
  321                         printf("mapelf: unsupported psection order\n");
  322 #endif
  323                         error = EINVAL;
  324                         goto bad;
  325                 }
  326 
  327                 /*
  328                  * Check that the default load addresses are free.
  329                  * If not, we will have to perform a relocation
  330                  */
  331                 ret = uvm_map_findspace(&l->l_proc->p_vmspace->vm_map,
  332                     pht->p_vaddr, pht->p_memsz, (vaddr_t *)(void *)&uaddr,
  333                     NULL, 0, 0, UVM_FLAG_FIXED);
  334                 if (ret == NULL)
  335                         need_relocation = 1;
  336                 pht++;
  337         }
  338 
  339         /*
  340          * Perform a relocation
  341          */
  342         if (need_relocation) {
  343                 /*
  344                  * compute the size needed by the section union. This
  345                  * assumes that the section load addresses are increasing.
  346                  * (And also that the sections are not overlapping)
  347                  */
  348                 pht--;
  349                 size = ELF_ROUND((pht->p_vaddr + pht->p_memsz), pht->p_align) -
  350                     ELF_TRUNC(kph->p_vaddr, kph->p_align);
  351 
  352                 /* Find a free place for the sections */
  353                 ret = uvm_map_findspace(&l->l_proc->p_vmspace->vm_map,
  354                     IRIX_MAPELF_RELOCATE, size, (vaddr_t *)(void *)&uaddr,
  355                         NULL, 0, kph->p_align, 0);
  356 
  357                 if (ret == NULL) {
  358                         error = ENOMEM;
  359                         goto bad;
  360                 }
  361 
  362                 /*
  363                  * Relocate the sections, all with the same offset.
  364                  */
  365                 reloc_offset = uaddr - kph->p_vaddr;
  366                 pht = kph;
  367                 for (i = 0; i < count; i++) {
  368 #ifdef DEBUG_IRIX
  369                         printf("mapelf: relocating section %d from %p to %p\n",
  370                             i, (void *)pht->p_vaddr,
  371                             (void *)(pht->p_vaddr + reloc_offset));
  372 #endif
  373                         pht->p_vaddr += reloc_offset;
  374                         pht++;
  375                 }
  376         }
  377 
  378         /* Find the file's vnode */
  379         fp = fd_getfile(fd);
  380         if (fp == NULL) {
  381                 error = EBADF;
  382                 goto bad;
  383         }
  384         vp = fp->f_data;
  385 
  386         error = vn_marktext(vp);
  387         if (error)
  388                 goto bad_unuse;
  389 
  390         /*
  391          * Load the sections
  392          */
  393         pht = kph;
  394         for (i = 0; i < count; i++) {
  395 #ifdef DEBUG_IRIX
  396                 printf("mapelf: loading section %d (len 0x%08lx) at %p\n",
  397                     i, (long)pht->p_memsz, (void *)pht->p_vaddr);
  398 #endif
  399                 /* Build the vmcmds for loading the section */
  400                 kill_vmcmds(&vcset);
  401                 uaddr = pht->p_vaddr;
  402                 size = 0;
  403                 prot = 0;
  404                 flags = VMCMD_BASE;
  405 
  406                 ELFNAME(load_psection)(&vcset, vp, pht, &uaddr,
  407                     &size, &prot, flags);
  408 
  409                 /* Execute the vmcmds */
  410                 for (j = 0; j < vcset.evs_used && !error; j++) {
  411                         vcp = &vcset.evs_cmds[j];
  412                         if (vcp->ev_flags & VMCMD_RELATIVE) {
  413                                 if (base_vcp == NULL)
  414                                         panic("irix_syssgi_mapelf():  bad vmcmd base");
  415 
  416                                 vcp->ev_addr += base_vcp->ev_addr;
  417                         }
  418                         IRIX_VM_SYNC(l->l_proc, error = (*vcp->ev_proc)(l, vcp));
  419                         if (error)
  420                                 goto bad_unuse;
  421                 }
  422                 pht++;
  423         }
  424 
  425         *retval = (register_t)kph->p_vaddr;
  426 
  427 bad_unuse:
  428         fd_putfile(fd);
  429 bad:
  430         free(kph, M_TEMP);
  431         return error;
  432 }
  433 
  434 
  435 
  436 static int
  437 irix_syssgi_sysconf(int name, struct lwp *l, register_t *retval)
  438 {
  439         struct proc *p = l->l_proc;
  440         int error = 0;
  441         int mib[2], value;
  442         size_t len = sizeof(value);
  443 
  444         switch (name) {
  445         case IRIX_SC_ARG_MAX:
  446                 mib[0] = CTL_KERN;
  447                 mib[1] = KERN_ARGMAX;
  448                 break;
  449         case IRIX_SC_CHILD_MAX:
  450                 *retval = (register_t)p->p_rlimit[RLIMIT_NPROC].rlim_cur;
  451                 return 0;
  452                 break;
  453         case IRIX_SC_CLK_TCK:
  454                 *retval = hz;
  455                 return 0;
  456                 break;
  457         case IRIX_SC_NGROUPS_MAX:
  458                 mib[0] = CTL_KERN;
  459                 mib[1] = KERN_NGROUPS;
  460                 break;
  461         case IRIX_SC_OPEN_MAX:
  462                 *retval = (register_t)p->p_rlimit[RLIMIT_NOFILE].rlim_cur;
  463                 return 0;
  464                 break;
  465         case IRIX_SC_JOB_CONTROL:
  466                 mib[0] = CTL_KERN;
  467                 mib[1] = KERN_JOB_CONTROL;
  468                 break;
  469         case IRIX_SC_SAVED_IDS:
  470                 mib[0] = CTL_KERN;
  471                 mib[1] = KERN_SAVED_IDS;
  472                 break;
  473         case IRIX_SC_IP_SECOPTS:/* IP security options */
  474         /* Trusted IRIX capabilities are unsupported */
  475         case IRIX_SC_ACL:       /* ACcess Lists */
  476         case IRIX_SC_AUDIT:     /* Audit */
  477         case IRIX_SC_INF:       /* Information labels */
  478         case IRIX_SC_MAC:       /* Mandatory Access Control */
  479         case IRIX_SC_CAP:       /* Capabilities */
  480                 *retval = 0;
  481                 return 0;
  482                 break;
  483         case IRIX_SC_PAGESIZE:
  484                 mib[0] = CTL_HW;
  485                 mib[1] = HW_PAGESIZE;
  486                 break;
  487 
  488         case IRIX_SC_PASS_MAX:
  489         case IRIX_SC_VERSION:
  490         default:
  491                 printf("Warning: syssgi(SYSCONF) unsupported variable %d\n",
  492                     name);
  493                 return EINVAL;
  494                 break;
  495         }
  496 
  497         /*
  498          * calling into sysctl with superuser privs, but we don't mind
  499          * 'cause we're only querying a value.
  500          */
  501         error = old_sysctl(&mib[0], 2, &value, &len, NULL, 0, NULL);
  502         if (error == 0)
  503                 *retval = value;
  504         return (error);
  505 }
  506 
  507 static int
  508 irix_syssgi_pathconf(char *path, int name, struct lwp *l, register_t *retval)
  509 {
  510         struct sys_pathconf_args cup;
  511         int bname;
  512 
  513         switch (name) {
  514         case IRIX_PC_LINK_MAX:
  515         case IRIX_PC_MAX_CANON:
  516         case IRIX_PC_MAX_INPUT:
  517         case IRIX_PC_NAME_MAX:
  518         case IRIX_PC_PATH_MAX:
  519         case IRIX_PC_PIPE_BUF:
  520         case IRIX_PC_CHOWN_RESTRICTED:
  521         case IRIX_PC_NO_TRUNC:
  522         case IRIX_PC_VDISABLE:
  523         case IRIX_PC_SYNC_IO:
  524                 bname = name;
  525                 break;
  526         case IRIX_PC_FILESIZEBITS:
  527                 bname = _PC_FILESIZEBITS;
  528                 break;
  529         case IRIX_PC_PRIO_IO:
  530         case IRIX_PC_ASYNC_IO:
  531         case IRIX_PC_ABI_ASYNC_IO:
  532         case IRIX_PC_ABI_AIO_XFER_MAX:
  533         default:
  534                 printf("Warning: unimplemented IRIX pathconf() command %d\n",
  535                     name);
  536                 *retval = 0;
  537                 return 0;
  538                 break;
  539         }
  540         SCARG(&cup, path) = path;
  541         SCARG(&cup, name) = bname;
  542         return sys_pathconf(l, &cup, retval);
  543 }

Cache object: 8ac31d59c24ef7f9b305c21c208d3448


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.