1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 2008 David E. O'Brien 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the author nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 __FBSDID("$FreeBSD$"); 34 35 #include <sys/param.h> 36 #include <sys/capsicum.h> 37 #include <sys/cdio.h> 38 #include <sys/fcntl.h> 39 #include <sys/filio.h> 40 #include <sys/file.h> 41 #include <sys/ioccom.h> 42 #include <sys/malloc.h> 43 #include <sys/memrange.h> 44 #include <sys/pciio.h> 45 #include <sys/proc.h> 46 #include <sys/syscall.h> 47 #include <sys/syscallsubr.h> 48 #include <sys/sysctl.h> 49 #include <sys/sysent.h> 50 #include <sys/sysproto.h> 51 #include <sys/systm.h> 52 #include <sys/uio.h> 53 54 #include <compat/freebsd32/freebsd32.h> 55 #include <compat/freebsd32/freebsd32_ioctl.h> 56 #include <compat/freebsd32/freebsd32_misc.h> 57 #include <compat/freebsd32/freebsd32_proto.h> 58 59 CTASSERT(sizeof(struct mem_range_op32) == 12); 60 61 static int 62 freebsd32_ioctl_memrange(struct thread *td, 63 struct freebsd32_ioctl_args *uap, struct file *fp) 64 { 65 struct mem_range_op mro; 66 struct mem_range_op32 mro32; 67 int error; 68 u_long com; 69 70 if ((error = copyin(uap->data, &mro32, sizeof(mro32))) != 0) 71 return (error); 72 73 PTRIN_CP(mro32, mro, mo_desc); 74 CP(mro32, mro, mo_arg[0]); 75 CP(mro32, mro, mo_arg[1]); 76 77 com = 0; 78 switch (uap->com) { 79 case MEMRANGE_GET32: 80 com = MEMRANGE_GET; 81 break; 82 83 case MEMRANGE_SET32: 84 com = MEMRANGE_SET; 85 break; 86 87 default: 88 panic("%s: unknown MEMRANGE %#x", __func__, uap->com); 89 } 90 91 if ((error = fo_ioctl(fp, com, (caddr_t)&mro, td->td_ucred, td)) != 0) 92 return (error); 93 94 if ( (com & IOC_OUT) ) { 95 CP(mro, mro32, mo_arg[0]); 96 CP(mro, mro32, mo_arg[1]); 97 98 error = copyout(&mro32, uap->data, sizeof(mro32)); 99 } 100 101 return (error); 102 } 103 104 static int 105 freebsd32_ioctl_barmmap(struct thread *td, 106 struct freebsd32_ioctl_args *uap, struct file *fp) 107 { 108 struct pci_bar_mmap32 pbm32; 109 struct pci_bar_mmap pbm; 110 int error; 111 112 error = copyin(uap->data, &pbm32, sizeof(pbm32)); 113 if (error != 0) 114 return (error); 115 PTRIN_CP(pbm32, pbm, pbm_map_base); 116 CP(pbm32, pbm, pbm_sel); 117 CP(pbm32, pbm, pbm_reg); 118 CP(pbm32, pbm, pbm_flags); 119 CP(pbm32, pbm, pbm_memattr); 120 pbm.pbm_bar_length = PAIR32TO64(uint64_t, pbm32.pbm_bar_length); 121 error = fo_ioctl(fp, PCIOCBARMMAP, (caddr_t)&pbm, td->td_ucred, td); 122 if (error == 0) { 123 PTROUT_CP(pbm, pbm32, pbm_map_base); 124 CP(pbm, pbm32, pbm_map_length); 125 #if BYTE_ORDER == LITTLE_ENDIAN 126 pbm32.pbm_bar_length1 = pbm.pbm_bar_length; 127 pbm32.pbm_bar_length2 = pbm.pbm_bar_length >> 32; 128 #else 129 pbm32.pbm_bar_length1 = pbm.pbm_bar_length >> 32; 130 pbm32.pbm_bar_length2 = pbm.pbm_bar_length; 131 #endif 132 CP(pbm, pbm32, pbm_bar_off); 133 error = copyout(&pbm32, uap->data, sizeof(pbm32)); 134 } 135 return (error); 136 } 137 138 static int 139 freebsd32_ioctl_sg(struct thread *td, 140 struct freebsd32_ioctl_args *uap, struct file *fp) 141 { 142 struct sg_io_hdr io; 143 struct sg_io_hdr32 io32; 144 int error; 145 146 if ((error = copyin(uap->data, &io32, sizeof(io32))) != 0) 147 return (error); 148 149 CP(io32, io, interface_id); 150 CP(io32, io, dxfer_direction); 151 CP(io32, io, cmd_len); 152 CP(io32, io, mx_sb_len); 153 CP(io32, io, iovec_count); 154 CP(io32, io, dxfer_len); 155 PTRIN_CP(io32, io, dxferp); 156 PTRIN_CP(io32, io, cmdp); 157 PTRIN_CP(io32, io, sbp); 158 CP(io32, io, timeout); 159 CP(io32, io, flags); 160 CP(io32, io, pack_id); 161 PTRIN_CP(io32, io, usr_ptr); 162 CP(io32, io, status); 163 CP(io32, io, masked_status); 164 CP(io32, io, msg_status); 165 CP(io32, io, sb_len_wr); 166 CP(io32, io, host_status); 167 CP(io32, io, driver_status); 168 CP(io32, io, resid); 169 CP(io32, io, duration); 170 CP(io32, io, info); 171 172 if ((error = fo_ioctl(fp, SG_IO, (caddr_t)&io, td->td_ucred, td)) != 0) 173 return (error); 174 175 CP(io, io32, interface_id); 176 CP(io, io32, dxfer_direction); 177 CP(io, io32, cmd_len); 178 CP(io, io32, mx_sb_len); 179 CP(io, io32, iovec_count); 180 CP(io, io32, dxfer_len); 181 PTROUT_CP(io, io32, dxferp); 182 PTROUT_CP(io, io32, cmdp); 183 PTROUT_CP(io, io32, sbp); 184 CP(io, io32, timeout); 185 CP(io, io32, flags); 186 CP(io, io32, pack_id); 187 PTROUT_CP(io, io32, usr_ptr); 188 CP(io, io32, status); 189 CP(io, io32, masked_status); 190 CP(io, io32, msg_status); 191 CP(io, io32, sb_len_wr); 192 CP(io, io32, host_status); 193 CP(io, io32, driver_status); 194 CP(io, io32, resid); 195 CP(io, io32, duration); 196 CP(io, io32, info); 197 198 error = copyout(&io32, uap->data, sizeof(io32)); 199 200 return (error); 201 } 202 203 int 204 freebsd32_ioctl(struct thread *td, struct freebsd32_ioctl_args *uap) 205 { 206 struct ioctl_args ap /*{ 207 int fd; 208 u_long com; 209 caddr_t data; 210 }*/ ; 211 struct file *fp; 212 cap_rights_t rights; 213 int error; 214 215 error = fget(td, uap->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); 216 if (error != 0) 217 return (error); 218 if ((fp->f_flag & (FREAD | FWRITE)) == 0) { 219 fdrop(fp, td); 220 return (EBADF); 221 } 222 223 switch (uap->com) { 224 case MEMRANGE_GET32: /* FALLTHROUGH */ 225 case MEMRANGE_SET32: 226 error = freebsd32_ioctl_memrange(td, uap, fp); 227 break; 228 229 case SG_IO_32: 230 error = freebsd32_ioctl_sg(td, uap, fp); 231 break; 232 233 case PCIOCBARMMAP_32: 234 error = freebsd32_ioctl_barmmap(td, uap, fp); 235 break; 236 237 default: 238 fdrop(fp, td); 239 ap.fd = uap->fd; 240 ap.com = uap->com; 241 PTRIN_CP(*uap, ap, data); 242 return sys_ioctl(td, &ap); 243 } 244 245 fdrop(fp, td); 246 return (error); 247 } 248