int netbsd32_md_ioctl(struct file *fp, netbsd32_u_long cmd, void *data32, struct lwp *l) { u_int size; void *data, *memp = NULL; #define STK_PARAMS 128 u_long stkbuf[STK_PARAMS/sizeof(u_long)]; int error; switch (cmd) { case FBIOPUTCMAP32: IOCTL_STRUCT_CONV_TO(FBIOPUTCMAP, fbcmap); case FBIOGETCMAP32: IOCTL_STRUCT_CONV_TO(FBIOGETCMAP, fbcmap); case FBIOSCURSOR32: IOCTL_STRUCT_CONV_TO(FBIOSCURSOR, fbcursor); case FBIOGCURSOR32: IOCTL_STRUCT_CONV_TO(FBIOGCURSOR, fbcursor); case OPIOCGET32: IOCTL_STRUCT_CONV_TO(OPIOCGET, opiocdesc); case OPIOCSET32: IOCTL_STRUCT_CONV_TO(OPIOCSET, opiocdesc); case OPIOCNEXTPROP32: IOCTL_STRUCT_CONV_TO(OPIOCNEXTPROP, opiocdesc); default: error = (*fp->f_ops->fo_ioctl)(fp, cmd, data32); } if (memp) kmem_free(memp, size); return (error); }
/* * main ioctl syscall. * * ok, here we are in the biggy. we have to do fix ups depending * on the ioctl command before and afterwards. */ int netbsd32_ioctl(struct lwp *l, const struct netbsd32_ioctl_args *uap, register_t *retval) { /* { syscallarg(int) fd; syscallarg(netbsd32_u_long) com; syscallarg(netbsd32_voidp) data; } */ struct proc *p = l->l_proc; struct file *fp; struct filedesc *fdp; u_long com; int error = 0; u_int size, size32; void *data, *memp = NULL; void *data32, *memp32 = NULL; unsigned fd; fdfile_t *ff; int tmp; #define STK_PARAMS 128 u_long stkbuf[STK_PARAMS/sizeof(u_long)]; u_long stkbuf32[STK_PARAMS/sizeof(u_long)]; /* * we need to translate some commands (_IOW) before calling sys_ioctl, * some after (_IOR), and some both (_IOWR). */ #if 0 { char *dirs[8] = { "NONE!", "VOID", "OUT", "VOID|OUT!", "IN", "VOID|IN!", "INOUT", "VOID|IN|OUT!" }; printf("netbsd32_ioctl(%d, %x, %x): %s group %c base %d len %d\n", SCARG(uap, fd), SCARG(uap, com), SCARG(uap, data), dirs[((SCARG(uap, com) & IOC_DIRMASK)>>29)], IOCGROUP(SCARG(uap, com)), IOCBASECMD(SCARG(uap, com)), IOCPARM_LEN(SCARG(uap, com))); } #endif fdp = p->p_fd; fd = SCARG(uap, fd); if ((fp = fd_getfile(fd)) == NULL) return (EBADF); if ((fp->f_flag & (FREAD | FWRITE)) == 0) { error = EBADF; goto out; } ff = fdp->fd_ofiles[SCARG(uap, fd)]; switch (com = SCARG(uap, com)) { case FIOCLEX: ff->ff_exclose = true; fdp->fd_exclose = true; goto out; case FIONCLEX: ff->ff_exclose = false; goto out; } /* * Interpret high order word to find amount of data to be * copied to/from the user's address space. */ size = 0; size32 = IOCPARM_LEN(com); if (size32 > IOCPARM_MAX) { error = ENOTTY; goto out; } if (size32 > sizeof(stkbuf)) { memp32 = kmem_alloc((size_t)size32, KM_SLEEP); data32 = memp32; } else data32 = (void *)stkbuf32; if (com&IOC_IN) { if (size32) { error = copyin(SCARG_P32(uap, data), data32, size32); if (error) { if (memp32) kmem_free(memp32, (size_t)size32); goto out; } ktrgenio(fd, UIO_WRITE, SCARG_P32(uap, data), size32, 0); } else *(void **)data32 = SCARG_P32(uap, data); } else if ((com&IOC_OUT) && size32) /* * Zero the buffer so the user always * gets back something deterministic. */ memset(data32, 0, size32); else if (com&IOC_VOID) *(void **)data32 = SCARG_P32(uap, data); /* * convert various structures, pointers, and other objects that * change size from 32 bit -> 64 bit, for all ioctl commands. */ switch (SCARG(uap, com)) { case FIONBIO: mutex_enter(&fp->f_lock); if ((tmp = *(int *)data32) != 0) fp->f_flag |= FNONBLOCK; else fp->f_flag &= ~FNONBLOCK; mutex_exit(&fp->f_lock); error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (void *)&tmp); break; case FIOASYNC: mutex_enter(&fp->f_lock); if ((tmp = *(int *)data32) != 0) fp->f_flag |= FASYNC; else fp->f_flag &= ~FASYNC; mutex_exit(&fp->f_lock); error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (void *)&tmp); break; case DIOCGPART32: IOCTL_STRUCT_CONV_TO(DIOCGPART, partinfo); #if 0 /* not implemented by anything */ case DIOCRFORMAT32: IOCTL_STRUCT_CONV_TO(DIOCRFORMAT, format_op); case DIOCWFORMAT32: IOCTL_STRUCT_CONV_TO(DIOCWFORMAT, format_op); #endif /* * only a few ifreq syscalls need conversion and those are * all driver specific... XXX */ #if 0 case SIOCGADDRROM3232: IOCTL_STRUCT_CONV_TO(SIOCGADDRROM32, ifreq); case SIOCGCHIPID32: IOCTL_STRUCT_CONV_TO(SIOCGCHIPID, ifreq); case SIOCSIFADDR32: IOCTL_STRUCT_CONV_TO(SIOCSIFADDR, ifreq); case OSIOCGIFADDR32: IOCTL_STRUCT_CONV_TO(OSIOCGIFADDR, ifreq); case SIOCGIFADDR32: IOCTL_STRUCT_CONV_TO(SIOCGIFADDR, ifreq); case SIOCSIFDSTADDR32: IOCTL_STRUCT_CONV_TO(SIOCSIFDSTADDR, ifreq); case OSIOCGIFDSTADDR32: IOCTL_STRUCT_CONV_TO(OSIOCGIFDSTADDR, ifreq); case SIOCGIFDSTADDR32: IOCTL_STRUCT_CONV_TO(SIOCGIFDSTADDR, ifreq); case OSIOCGIFBRDADDR32: IOCTL_STRUCT_CONV_TO(OSIOCGIFBRDADDR, ifreq); case SIOCGIFBRDADDR32: IOCTL_STRUCT_CONV_TO(SIOCGIFBRDADDR, ifreq); case SIOCSIFBRDADDR32: IOCTL_STRUCT_CONV_TO(SIOCSIFBRDADDR, ifreq); case OSIOCGIFNETMASK32: IOCTL_STRUCT_CONV_TO(OSIOCGIFNETMASK, ifreq); case SIOCGIFNETMASK32: IOCTL_STRUCT_CONV_TO(SIOCGIFNETMASK, ifreq); case SIOCSIFNETMASK32: IOCTL_STRUCT_CONV_TO(SIOCSIFNETMASK, ifreq); case SIOCGIFMETRIC32: IOCTL_STRUCT_CONV_TO(SIOCGIFMETRIC, ifreq); case SIOCSIFMETRIC32: IOCTL_STRUCT_CONV_TO(SIOCSIFMETRIC, ifreq); case SIOCDIFADDR32: IOCTL_STRUCT_CONV_TO(SIOCDIFADDR, ifreq); case SIOCADDMULTI32: IOCTL_STRUCT_CONV_TO(SIOCADDMULTI, ifreq); case SIOCDELMULTI32: IOCTL_STRUCT_CONV_TO(SIOCDELMULTI, ifreq); case SIOCSIFMEDIA32: IOCTL_STRUCT_CONV_TO(SIOCSIFMEDIA, ifreq); case SIOCSIFMTU32: IOCTL_STRUCT_CONV_TO(SIOCSIFMTU, ifreq); case SIOCGIFMTU32: IOCTL_STRUCT_CONV_TO(SIOCGIFMTU, ifreq); case BIOCGETIF32: IOCTL_STRUCT_CONV_TO(BIOCGETIF, ifreq); case BIOCSETIF32: IOCTL_STRUCT_CONV_TO(BIOCSETIF, ifreq); case SIOCPHASE132: IOCTL_STRUCT_CONV_TO(SIOCPHASE1, ifreq); case SIOCPHASE232: IOCTL_STRUCT_CONV_TO(SIOCPHASE2, ifreq); #endif case OOSIOCGIFCONF32: IOCTL_STRUCT_CONV_TO(OOSIOCGIFCONF, ifconf); case OSIOCGIFCONF32: IOCTL_STRUCT_CONV_TO(OSIOCGIFCONF, ifconf); case SIOCGIFCONF32: IOCTL_STRUCT_CONV_TO(SIOCGIFCONF, ifconf); case SIOCGIFFLAGS32: IOCTL_STRUCT_CONV_TO(SIOCGIFFLAGS, ifreq); case SIOCSIFFLAGS32: IOCTL_STRUCT_CONV_TO(SIOCSIFFLAGS, ifreq); case SIOCGIFMEDIA32: IOCTL_STRUCT_CONV_TO(SIOCGIFMEDIA, ifmediareq); case SIOCSDRVSPEC32: IOCTL_STRUCT_CONV_TO(SIOCSDRVSPEC, ifdrv); case SIOCGETVIFCNT32: IOCTL_STRUCT_CONV_TO(SIOCGETVIFCNT, sioc_vif_req); case SIOCGETSGCNT32: IOCTL_STRUCT_CONV_TO(SIOCGETSGCNT, sioc_sg_req); default: #ifdef NETBSD32_MD_IOCTL error = netbsd32_md_ioctl(fp, com, data32, l); #else error = (*fp->f_ops->fo_ioctl)(fp, com, data32); #endif break; } if (error == EPASSTHROUGH) error = ENOTTY; /* * Copy any data to user, size was * already set and checked above. */ if (error == 0 && (com&IOC_OUT) && size32) { error = copyout(data32, SCARG_P32(uap, data), size32); ktrgenio(fd, UIO_READ, SCARG_P32(uap, data), size32, error); } /* if we malloced data, free it here */ if (memp32) kmem_free(memp32, (size_t)size32); if (memp) kmem_free(memp, (size_t)size); out: fd_putfile(fd); return (error); }