2 * SPDX-License-Identifier: BSD-3-Clause
4 * Copyright (c) 2008 David E. O'Brien
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
35 #include "opt_compat.h"
37 #include <sys/param.h>
38 #include <sys/capsicum.h>
40 #include <sys/fcntl.h>
41 #include <sys/filio.h>
43 #include <sys/ioccom.h>
44 #include <sys/malloc.h>
45 #include <sys/mdioctl.h>
46 #include <sys/memrange.h>
47 #include <sys/pciio.h>
49 #include <sys/syscall.h>
50 #include <sys/syscallsubr.h>
51 #include <sys/sysctl.h>
52 #include <sys/sysent.h>
53 #include <sys/sysproto.h>
54 #include <sys/systm.h>
56 #include <compat/freebsd32/freebsd32.h>
57 #include <compat/freebsd32/freebsd32_ioctl.h>
58 #include <compat/freebsd32/freebsd32_proto.h>
60 CTASSERT((sizeof(struct md_ioctl32)) == 436);
61 CTASSERT(sizeof(struct ioc_read_toc_entry32) == 8);
62 CTASSERT(sizeof(struct mem_range_op32) == 12);
63 CTASSERT(sizeof(struct pci_conf_io32) == 36);
64 CTASSERT(sizeof(struct pci_match_conf32) == 44);
65 CTASSERT(sizeof(struct pci_conf32) == 44);
69 freebsd32_ioctl_md(struct thread *td, struct freebsd32_ioctl_args *uap,
73 struct md_ioctl32 md32;
77 if (uap->com & IOC_IN) {
78 if ((error = copyin(uap->data, &md32, sizeof(md32)))) {
81 CP(md32, mdv, md_version);
82 CP(md32, mdv, md_unit);
83 CP(md32, mdv, md_type);
84 PTRIN_CP(md32, mdv, md_file);
85 CP(md32, mdv, md_mediasize);
86 CP(md32, mdv, md_sectorsize);
87 CP(md32, mdv, md_options);
88 CP(md32, mdv, md_base);
89 CP(md32, mdv, md_fwheads);
90 CP(md32, mdv, md_fwsectors);
91 PTRIN_CP(md32, mdv, md_label);
92 } else if (uap->com & IOC_OUT) {
94 * Zero the buffer so the user always
95 * gets back something deterministic.
97 bzero(&mdv, sizeof mdv);
114 panic("%s: unknown MDIOC %#x", __func__, uap->com);
116 error = fo_ioctl(fp, com, (caddr_t)&mdv, td->td_ucred, td);
117 if (error == 0 && (com & IOC_OUT)) {
118 CP(mdv, md32, md_version);
119 CP(mdv, md32, md_unit);
120 CP(mdv, md32, md_type);
121 PTROUT_CP(mdv, md32, md_file);
122 CP(mdv, md32, md_mediasize);
123 CP(mdv, md32, md_sectorsize);
124 CP(mdv, md32, md_options);
125 CP(mdv, md32, md_base);
126 CP(mdv, md32, md_fwheads);
127 CP(mdv, md32, md_fwsectors);
128 PTROUT_CP(mdv, md32, md_label);
129 if (com == MDIOCLIST) {
131 * Use MDNPAD, and not MDNPAD32. Padding is
132 * allocated and used by compat32 ABI.
134 for (i = 0; i < MDNPAD; i++)
135 CP(mdv, md32, md_pad[i]);
137 error = copyout(&md32, uap->data, sizeof(md32));
144 freebsd32_ioctl_ioc_read_toc(struct thread *td,
145 struct freebsd32_ioctl_args *uap, struct file *fp)
147 struct ioc_read_toc_entry toce;
148 struct ioc_read_toc_entry32 toce32;
151 if ((error = copyin(uap->data, &toce32, sizeof(toce32))))
153 CP(toce32, toce, address_format);
154 CP(toce32, toce, starting_track);
155 CP(toce32, toce, data_len);
156 PTRIN_CP(toce32, toce, data);
158 if ((error = fo_ioctl(fp, CDIOREADTOCENTRYS, (caddr_t)&toce,
159 td->td_ucred, td))) {
160 CP(toce, toce32, address_format);
161 CP(toce, toce32, starting_track);
162 CP(toce, toce32, data_len);
163 PTROUT_CP(toce, toce32, data);
164 error = copyout(&toce32, uap->data, sizeof(toce32));
170 freebsd32_ioctl_fiodgname(struct thread *td,
171 struct freebsd32_ioctl_args *uap, struct file *fp)
173 struct fiodgname_arg fgn;
174 struct fiodgname_arg32 fgn32;
177 if ((error = copyin(uap->data, &fgn32, sizeof fgn32)) != 0)
180 PTRIN_CP(fgn32, fgn, buf);
181 error = fo_ioctl(fp, FIODGNAME, (caddr_t)&fgn, td->td_ucred, td);
186 freebsd32_ioctl_memrange(struct thread *td,
187 struct freebsd32_ioctl_args *uap, struct file *fp)
189 struct mem_range_op mro;
190 struct mem_range_op32 mro32;
194 if ((error = copyin(uap->data, &mro32, sizeof(mro32))) != 0)
197 PTRIN_CP(mro32, mro, mo_desc);
198 CP(mro32, mro, mo_arg[0]);
199 CP(mro32, mro, mo_arg[1]);
212 panic("%s: unknown MEMRANGE %#x", __func__, uap->com);
215 if ((error = fo_ioctl(fp, com, (caddr_t)&mro, td->td_ucred, td)) != 0)
218 if ( (com & IOC_OUT) ) {
219 CP(mro, mro32, mo_arg[0]);
220 CP(mro, mro32, mo_arg[1]);
222 error = copyout(&mro32, uap->data, sizeof(mro32));
229 freebsd32_ioctl_pciocgetconf(struct thread *td,
230 struct freebsd32_ioctl_args *uap, struct file *fp)
232 struct pci_conf_io pci;
233 struct pci_conf_io32 pci32;
234 struct pci_match_conf32 pmc32;
235 struct pci_match_conf32 *pmc32p;
236 struct pci_match_conf pmc;
237 struct pci_match_conf *pmcp;
238 struct pci_conf32 pc32;
239 struct pci_conf32 *pc32p;
241 struct pci_conf *pcp;
243 u_int32_t npat_to_convert;
244 u_int32_t nmatch_to_convert;
248 if ((error = copyin(uap->data, &pci32, sizeof(pci32))) != 0)
251 CP(pci32, pci, num_patterns);
252 CP(pci32, pci, offset);
253 CP(pci32, pci, generation);
255 npat_to_convert = pci32.pat_buf_len / sizeof(struct pci_match_conf32);
256 pci.pat_buf_len = npat_to_convert * sizeof(struct pci_match_conf);
258 nmatch_to_convert = pci32.match_buf_len / sizeof(struct pci_conf32);
259 pci.match_buf_len = nmatch_to_convert * sizeof(struct pci_conf);
262 if ((error = copyout_map(td, &addr, pci.pat_buf_len)) != 0)
264 pci.patterns = (struct pci_match_conf *)addr;
265 if ((error = copyout_map(td, &addr, pci.match_buf_len)) != 0)
267 pci.matches = (struct pci_conf *)addr;
269 npat_to_convert = min(npat_to_convert, pci.num_patterns);
271 for (i = 0, pmc32p = (struct pci_match_conf32 *)PTRIN(pci32.patterns),
273 i < npat_to_convert; i++, pmc32p++, pmcp++) {
274 if ((error = copyin(pmc32p, &pmc32, sizeof(pmc32))) != 0)
276 CP(pmc32,pmc,pc_sel);
277 strlcpy(pmc.pd_name, pmc32.pd_name, sizeof(pmc.pd_name));
278 CP(pmc32,pmc,pd_unit);
279 CP(pmc32,pmc,pc_vendor);
280 CP(pmc32,pmc,pc_device);
281 CP(pmc32,pmc,pc_class);
283 if ((error = copyout(&pmc, pmcp, sizeof(pmc))) != 0)
287 if ((error = fo_ioctl(fp, PCIOCGETCONF, (caddr_t)&pci,
288 td->td_ucred, td)) != 0)
291 nmatch_to_convert = min(nmatch_to_convert, pci.num_matches);
293 for (i = 0, pcp = pci.matches,
294 pc32p = (struct pci_conf32 *)PTRIN(pci32.matches);
295 i < nmatch_to_convert; i++, pcp++, pc32p++) {
296 if ((error = copyin(pcp, &pc, sizeof(pc))) != 0)
300 CP(pc,pc32,pc_subvendor);
301 CP(pc,pc32,pc_subdevice);
302 CP(pc,pc32,pc_vendor);
303 CP(pc,pc32,pc_device);
304 CP(pc,pc32,pc_class);
305 CP(pc,pc32,pc_subclass);
306 CP(pc,pc32,pc_progif);
307 CP(pc,pc32,pc_revid);
308 strlcpy(pc32.pd_name, pc.pd_name, sizeof(pc32.pd_name));
310 if ((error = copyout(&pc32, pc32p, sizeof(pc32))) != 0)
314 CP(pci, pci32, num_matches);
315 CP(pci, pci32, offset);
316 CP(pci, pci32, generation);
317 CP(pci, pci32, status);
319 error = copyout(&pci32, uap->data, sizeof(pci32));
323 copyout_unmap(td, (vm_offset_t)pci.patterns, pci.pat_buf_len);
325 copyout_unmap(td, (vm_offset_t)pci.matches, pci.match_buf_len);
331 freebsd32_ioctl_sg(struct thread *td,
332 struct freebsd32_ioctl_args *uap, struct file *fp)
335 struct sg_io_hdr32 io32;
338 if ((error = copyin(uap->data, &io32, sizeof(io32))) != 0)
341 CP(io32, io, interface_id);
342 CP(io32, io, dxfer_direction);
343 CP(io32, io, cmd_len);
344 CP(io32, io, mx_sb_len);
345 CP(io32, io, iovec_count);
346 CP(io32, io, dxfer_len);
347 PTRIN_CP(io32, io, dxferp);
348 PTRIN_CP(io32, io, cmdp);
349 PTRIN_CP(io32, io, sbp);
350 CP(io32, io, timeout);
352 CP(io32, io, pack_id);
353 PTRIN_CP(io32, io, usr_ptr);
354 CP(io32, io, status);
355 CP(io32, io, masked_status);
356 CP(io32, io, msg_status);
357 CP(io32, io, sb_len_wr);
358 CP(io32, io, host_status);
359 CP(io32, io, driver_status);
361 CP(io32, io, duration);
364 if ((error = fo_ioctl(fp, SG_IO, (caddr_t)&io, td->td_ucred, td)) != 0)
367 CP(io, io32, interface_id);
368 CP(io, io32, dxfer_direction);
369 CP(io, io32, cmd_len);
370 CP(io, io32, mx_sb_len);
371 CP(io, io32, iovec_count);
372 CP(io, io32, dxfer_len);
373 PTROUT_CP(io, io32, dxferp);
374 PTROUT_CP(io, io32, cmdp);
375 PTROUT_CP(io, io32, sbp);
376 CP(io, io32, timeout);
378 CP(io, io32, pack_id);
379 PTROUT_CP(io, io32, usr_ptr);
380 CP(io, io32, status);
381 CP(io, io32, masked_status);
382 CP(io, io32, msg_status);
383 CP(io, io32, sb_len_wr);
384 CP(io, io32, host_status);
385 CP(io, io32, driver_status);
387 CP(io, io32, duration);
390 error = copyout(&io32, uap->data, sizeof(io32));
396 freebsd32_ioctl(struct thread *td, struct freebsd32_ioctl_args *uap)
398 struct ioctl_args ap /*{
407 error = fget(td, uap->fd, cap_rights_init(&rights, CAP_IOCTL), &fp);
410 if ((fp->f_flag & (FREAD | FWRITE)) == 0) {
416 case MDIOCATTACH_32: /* FALLTHROUGH */
417 case MDIOCDETACH_32: /* FALLTHROUGH */
418 case MDIOCQUERY_32: /* FALLTHROUGH */
420 error = freebsd32_ioctl_md(td, uap, fp);
423 case CDIOREADTOCENTRYS_32:
424 error = freebsd32_ioctl_ioc_read_toc(td, uap, fp);
428 error = freebsd32_ioctl_fiodgname(td, uap, fp);
431 case MEMRANGE_GET32: /* FALLTHROUGH */
433 error = freebsd32_ioctl_memrange(td, uap, fp);
436 case PCIOCGETCONF_32:
437 error = freebsd32_ioctl_pciocgetconf(td, uap, fp);
441 error = freebsd32_ioctl_sg(td, uap, fp);
448 PTRIN_CP(*uap, ap, data);
449 return sys_ioctl(td, &ap);